1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Execution Server
3 * ---------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief ExecServer Tests.
22 *//*--------------------------------------------------------------------*/
26 #include "xsProtocol.hpp"
27 #include "deSocket.hpp"
28 #include "deRingBuffer.hpp"
29 #include "deFilePath.hpp"
30 #include "deBlockBuffer.hpp"
31 #include "deThread.hpp"
32 #include "deStringUtil.hpp"
35 #include "deProcess.h"
48 typedef std::auto_ptr<Message> ScopedMsgPtr;
50 class SocketError : public Error
53 SocketError (deSocketResult result, const char* message, const char* file, int line)
54 : Error (message, deGetSocketResultName(result), file, line)
59 deSocketResult getResult (void) const
65 deSocketResult m_result;
69 void sendMessage (de::Socket& socket, const Message& message)
77 while (pos < buf.size())
79 size_t numLeft = buf.size() - pos;
81 deSocketResult result = socket.send(&buf[pos], numLeft, &numSent);
83 if (result != DE_SOCKETRESULT_SUCCESS)
84 throw SocketError(result, "send() failed", __FILE__, __LINE__);
90 void readBytes (de::Socket& socket, vector<deUint8>& dst, size_t numBytes)
94 while (numRead < numBytes)
96 size_t numLeft = numBytes - numRead;
97 size_t curNumRead = 0;
98 deSocketResult result = socket.receive(&dst[numRead], numLeft, &curNumRead);
100 if (result != DE_SOCKETRESULT_SUCCESS)
101 throw SocketError(result, "receive() failed", __FILE__, __LINE__);
103 numRead += curNumRead;
107 Message* readMessage (de::Socket& socket)
110 vector<deUint8> header;
111 readBytes(socket, header, MESSAGE_HEADER_SIZE);
115 Message::parseHeader(&header[0], (int)header.size(), type, messageSize);
117 // Simple messages without any data.
120 case MESSAGETYPE_KEEPALIVE: return new KeepAliveMessage();
121 case MESSAGETYPE_PROCESS_STARTED: return new ProcessStartedMessage();
123 break; // Read message with data.
126 vector<deUint8> messageBuf;
127 readBytes(socket, messageBuf, messageSize-MESSAGE_HEADER_SIZE);
131 case MESSAGETYPE_HELLO: return new HelloMessage(&messageBuf[0], (int)messageBuf.size());
132 case MESSAGETYPE_TEST: return new TestMessage(&messageBuf[0], (int)messageBuf.size());
133 case MESSAGETYPE_PROCESS_LOG_DATA: return new ProcessLogDataMessage(&messageBuf[0], (int)messageBuf.size());
134 case MESSAGETYPE_INFO: return new InfoMessage(&messageBuf[0], (int)messageBuf.size());
135 case MESSAGETYPE_PROCESS_LAUNCH_FAILED: return new ProcessLaunchFailedMessage(&messageBuf[0], (int)messageBuf.size());
136 case MESSAGETYPE_PROCESS_FINISHED: return new ProcessFinishedMessage(&messageBuf[0], (int)messageBuf.size());
138 XS_FAIL("Unknown message");
145 inline TestClock (void)
150 inline void reset (void)
152 m_initTime = deGetMicroseconds();
155 inline int getMilliseconds (void)
157 return (int)((deGetMicroseconds() - m_initTime) / 1000);
167 TestContext (void) : startServer(false) {}
169 std::string serverPath;
170 std::string testerPath;
171 de::SocketAddress address;
174 // Passed from execserver.
175 std::string logFileName;
176 std::string caseList;
179 TestContext (const TestContext& other);
180 TestContext& operator= (const TestContext& other);
186 TestCase (TestContext& testCtx, const char* name) : m_testCtx(testCtx), m_name(name) {}
187 virtual ~TestCase (void) {}
189 const char* getName (void) const { return m_name.c_str(); }
191 virtual void runClient (de::Socket& socket) = DE_NULL;
192 virtual void runProgram (void) = DE_NULL;
195 TestContext& m_testCtx;
202 TestExecutor (TestContext& testCtx);
203 ~TestExecutor (void);
205 void runCases (const std::vector<TestCase*>& testCases);
206 bool runCase (TestCase* testCase);
209 TestContext& m_testCtx;
212 TestExecutor::TestExecutor (TestContext& testCtx)
217 TestExecutor::~TestExecutor (void)
221 void TestExecutor::runCases (const std::vector<TestCase*>& testCases)
224 int numCases = (int)testCases.size();
226 for (std::vector<TestCase*>::const_iterator i = testCases.begin(); i != testCases.end(); i++)
232 printf("\n %d/%d passed!\n", numPassed, numCases);
235 class FilePrinter : public de::Thread
243 void start (deFile* file)
245 DE_ASSERT(!m_curFile);
255 while (deFile_read(m_curFile, &buf[0], (deInt64)sizeof(buf), &numRead) == DE_FILERESULT_SUCCESS)
256 fwrite(&buf[0], 1, (size_t)numRead, stdout);
265 bool TestExecutor::runCase (TestCase* testCase)
267 printf("%s\n", testCase->getName());
269 bool success = false;
270 deProcess* serverProc = DE_NULL;
271 FilePrinter stdoutPrinter;
272 FilePrinter stderrPrinter;
276 if (m_testCtx.startServer)
278 string cmdLine = m_testCtx.serverPath + " --port=" + de::toString(m_testCtx.address.getPort());
279 serverProc = deProcess_create();
280 XS_CHECK(serverProc);
282 if (!deProcess_start(serverProc, cmdLine.c_str(), DE_NULL))
284 string errMsg = deProcess_getLastError(serverProc);
285 deProcess_destroy(serverProc);
286 XS_FAIL(errMsg.c_str());
289 deSleep(200); /* Give 200ms for server to start. */
290 XS_CHECK(deProcess_isRunning(serverProc));
292 // Start stdout/stderr printers.
293 stdoutPrinter.start(deProcess_getStdOut(serverProc));
294 stderrPrinter.start(deProcess_getStdErr(serverProc));
299 socket.connect(m_testCtx.address);
302 socket.setFlags(DE_SOCKET_CLOSE_ON_EXEC);
305 testCase->runClient(socket);
308 if (socket.isConnected())
312 if (serverProc && deProcess_isRunning(serverProc))
314 XS_CHECK(deProcess_terminate(serverProc));
316 XS_CHECK(deProcess_waitForFinish(serverProc));
318 stdoutPrinter.join();
319 stderrPrinter.join();
324 catch (const std::exception& e)
326 printf("FAIL: %s\n\n", e.what());
330 deProcess_destroy(serverProc);
335 class ConnectTest : public TestCase
338 ConnectTest (TestContext& testCtx)
339 : TestCase(testCtx, "connect")
343 void runClient (de::Socket& socket)
348 void runProgram (void) { /* nothing */ }
351 class HelloTest : public TestCase
354 HelloTest (TestContext& testCtx)
355 : TestCase(testCtx, "hello")
359 void runClient (de::Socket& socket)
361 xs::HelloMessage msg;
362 sendMessage(socket, (const xs::Message&)msg);
365 void runProgram (void) { /* nothing */ }
368 class ExecFailTest : public TestCase
371 ExecFailTest (TestContext& testCtx)
372 : TestCase(testCtx, "exec-fail")
376 void runClient (de::Socket& socket)
378 xs::ExecuteBinaryMessage execMsg;
379 execMsg.name = "foobar-notfound";
381 execMsg.caseList = "";
382 execMsg.workDir = "";
384 sendMessage(socket, execMsg);
386 const int timeout = 100; // 100ms.
391 if (clock.getMilliseconds() > timeout)
392 XS_FAIL("Didn't receive PROCESS_LAUNCH_FAILED");
394 ScopedMsgPtr msg(readMessage(socket));
396 if (msg->type == MESSAGETYPE_PROCESS_LAUNCH_FAILED)
398 else if (msg->type == MESSAGETYPE_KEEPALIVE)
401 XS_FAIL("Invalid message");
405 void runProgram (void) { /* nothing */ }
408 class SimpleExecTest : public TestCase
411 SimpleExecTest (TestContext& testCtx)
412 : TestCase(testCtx, "simple-exec")
416 void runClient (de::Socket& socket)
418 xs::ExecuteBinaryMessage execMsg;
419 execMsg.name = m_testCtx.testerPath;
420 execMsg.params = "--program=simple-exec";
421 execMsg.caseList = "";
422 execMsg.workDir = "";
424 sendMessage(socket, execMsg);
426 const int timeout = 5000; // 5s.
429 bool gotProcessStarted = false;
430 bool gotProcessFinished = false;
434 if (clock.getMilliseconds() > timeout)
437 ScopedMsgPtr msg(readMessage(socket));
439 if (msg->type == MESSAGETYPE_PROCESS_STARTED)
440 gotProcessStarted = true;
441 else if (msg->type == MESSAGETYPE_PROCESS_LAUNCH_FAILED)
442 XS_FAIL("Got PROCESS_LAUNCH_FAILED");
443 else if (gotProcessStarted && msg->type == MESSAGETYPE_PROCESS_FINISHED)
445 gotProcessFinished = true;
448 else if (msg->type == MESSAGETYPE_KEEPALIVE || msg->type == MESSAGETYPE_INFO)
451 XS_FAIL((string("Invalid message: ") + de::toString(msg->type)).c_str());
454 if (!gotProcessStarted)
455 XS_FAIL("Did't get PROCESS_STARTED message");
457 if (!gotProcessFinished)
458 XS_FAIL("Did't get PROCESS_FINISHED message");
461 void runProgram (void) { /* print nothing. */ }
464 class InfoTest : public TestCase
469 InfoTest (TestContext& testCtx)
470 : TestCase (testCtx, "info")
471 , infoStr ("Hello, World")
475 void runClient (de::Socket& socket)
477 xs::ExecuteBinaryMessage execMsg;
478 execMsg.name = m_testCtx.testerPath;
479 execMsg.params = "--program=info";
480 execMsg.caseList = "";
481 execMsg.workDir = "";
483 sendMessage(socket, execMsg);
485 const int timeout = 10000; // 10s.
488 bool gotProcessStarted = false;
489 bool gotProcessFinished = false;
490 std::string receivedInfo = "";
494 if (clock.getMilliseconds() > timeout)
497 ScopedMsgPtr msg(readMessage(socket));
499 if (msg->type == MESSAGETYPE_PROCESS_STARTED)
500 gotProcessStarted = true;
501 else if (msg->type == MESSAGETYPE_PROCESS_LAUNCH_FAILED)
502 XS_FAIL("Got PROCESS_LAUNCH_FAILED");
503 else if (gotProcessStarted && msg->type == MESSAGETYPE_INFO)
504 receivedInfo += static_cast<const InfoMessage*>(msg.get())->info;
505 else if (gotProcessStarted && msg->type == MESSAGETYPE_PROCESS_FINISHED)
507 gotProcessFinished = true;
510 else if (msg->type == MESSAGETYPE_KEEPALIVE)
513 XS_FAIL("Invalid message");
516 if (!gotProcessStarted)
517 XS_FAIL("Did't get PROCESS_STARTED message");
519 if (!gotProcessFinished)
520 XS_FAIL("Did't get PROCESS_FINISHED message");
522 if (receivedInfo != infoStr)
523 XS_FAIL("Info data doesn't match");
526 void runProgram (void) { printf("%s", infoStr.c_str()); }
529 class LogDataTest : public TestCase
532 LogDataTest (TestContext& testCtx)
533 : TestCase(testCtx, "logdata")
537 void runClient (de::Socket& socket)
539 xs::ExecuteBinaryMessage execMsg;
540 execMsg.name = m_testCtx.testerPath;
541 execMsg.params = "--program=logdata";
542 execMsg.caseList = "";
543 execMsg.workDir = "";
545 sendMessage(socket, execMsg);
547 const int timeout = 10000; // 10s.
550 bool gotProcessStarted = false;
551 bool gotProcessFinished = false;
552 std::string receivedData = "";
556 if (clock.getMilliseconds() > timeout)
559 ScopedMsgPtr msg(readMessage(socket));
561 if (msg->type == MESSAGETYPE_PROCESS_STARTED)
562 gotProcessStarted = true;
563 else if (msg->type == MESSAGETYPE_PROCESS_LAUNCH_FAILED)
564 XS_FAIL("Got PROCESS_LAUNCH_FAILED");
565 else if (gotProcessStarted && msg->type == MESSAGETYPE_PROCESS_LOG_DATA)
566 receivedData += static_cast<const ProcessLogDataMessage*>(msg.get())->logData;
567 else if (gotProcessStarted && msg->type == MESSAGETYPE_PROCESS_FINISHED)
569 gotProcessFinished = true;
572 else if (msg->type == MESSAGETYPE_KEEPALIVE)
574 else if (msg->type == MESSAGETYPE_INFO)
575 XS_FAIL(static_cast<const InfoMessage*>(msg.get())->info.c_str());
577 XS_FAIL("Invalid message");
580 if (!gotProcessStarted)
581 XS_FAIL("Did't get PROCESS_STARTED message");
583 if (!gotProcessFinished)
584 XS_FAIL("Did't get PROCESS_FINISHED message");
586 const char* expected = "Foo\nBar\n";
587 if (receivedData != expected)
589 printf(" received: '%s'\n expected: '%s'\n", receivedData.c_str(), expected);
590 XS_FAIL("Log data doesn't match");
594 void runProgram (void)
596 deFile* file = deFile_create(m_testCtx.logFileName.c_str(), DE_FILEMODE_OPEN|DE_FILEMODE_CREATE|DE_FILEMODE_TRUNCATE|DE_FILEMODE_WRITE);
599 const char line0[] = "Foo\n";
600 const char line1[] = "Bar\n";
601 deInt64 numWritten = 0;
604 XS_CHECK(deFile_write(file, line0, sizeof(line0)-1, &numWritten) == DE_FILERESULT_SUCCESS);
605 XS_CHECK(numWritten == sizeof(line0)-1);
607 // Sleep for 0.5s and write line 2.
609 XS_CHECK(deFile_write(file, line1, sizeof(line1)-1, &numWritten) == DE_FILERESULT_SUCCESS);
610 XS_CHECK(numWritten == sizeof(line1)-1);
612 deFile_destroy(file);
616 class BigLogDataTest : public TestCase
621 DATA_SIZE = 100*1024*1024
624 BigLogDataTest (TestContext& testCtx)
625 : TestCase(testCtx, "biglogdata")
629 void runClient (de::Socket& socket)
631 xs::ExecuteBinaryMessage execMsg;
632 execMsg.name = m_testCtx.testerPath;
633 execMsg.params = "--program=biglogdata";
634 execMsg.caseList = "";
635 execMsg.workDir = "";
637 sendMessage(socket, execMsg);
639 const int timeout = 30000; // 30s.
642 bool gotProcessStarted = false;
643 bool gotProcessFinished = false;
644 int receivedBytes = 0;
648 if (clock.getMilliseconds() > timeout)
651 ScopedMsgPtr msg(readMessage(socket));
653 if (msg->type == MESSAGETYPE_PROCESS_STARTED)
654 gotProcessStarted = true;
655 else if (msg->type == MESSAGETYPE_PROCESS_LAUNCH_FAILED)
656 XS_FAIL("Got PROCESS_LAUNCH_FAILED");
657 else if (gotProcessStarted && msg->type == MESSAGETYPE_PROCESS_LOG_DATA)
658 receivedBytes += (int)static_cast<const ProcessLogDataMessage*>(msg.get())->logData.length();
659 else if (gotProcessStarted && msg->type == MESSAGETYPE_PROCESS_FINISHED)
661 gotProcessFinished = true;
664 else if (msg->type == MESSAGETYPE_KEEPALIVE)
666 // Reply with keepalive.
667 sendMessage(socket, KeepAliveMessage());
670 else if (msg->type == MESSAGETYPE_INFO)
671 printf("%s", static_cast<const InfoMessage*>(msg.get())->info.c_str());
673 XS_FAIL("Invalid message");
676 if (!gotProcessStarted)
677 XS_FAIL("Did't get PROCESS_STARTED message");
679 if (!gotProcessFinished)
680 XS_FAIL("Did't get PROCESS_FINISHED message");
682 if (receivedBytes != DATA_SIZE)
684 printf(" received: %d bytes\n expected: %d bytes\n", receivedBytes, DATA_SIZE);
685 XS_FAIL("Log data size doesn't match");
688 int timeMs = clock.getMilliseconds();
689 printf(" Streamed %d bytes in %d ms: %.2f MiB/s\n", DATA_SIZE, timeMs, ((float)DATA_SIZE / (float)(1024*1024)) / ((float)timeMs / 1000.0f));
692 void runProgram (void)
694 deFile* file = deFile_create(m_testCtx.logFileName.c_str(), DE_FILEMODE_OPEN|DE_FILEMODE_CREATE|DE_FILEMODE_TRUNCATE|DE_FILEMODE_WRITE);
697 deUint8 tmpBuf[1024*16];
700 deMemset(&tmpBuf, 'a', sizeof(tmpBuf));
702 while (numWritten < DATA_SIZE)
704 deInt64 numWrittenInBatch = 0;
705 XS_CHECK(deFile_write(file, &tmpBuf[0], de::min((int)sizeof(tmpBuf), DATA_SIZE-numWritten), &numWrittenInBatch) == DE_FILERESULT_SUCCESS);
706 numWritten += (int)numWrittenInBatch;
709 deFile_destroy(file);
713 class KeepAliveTest : public TestCase
716 KeepAliveTest (TestContext& testCtx)
717 : TestCase(testCtx, "keepalive")
721 void runClient (de::Socket& socket)
724 const int sendInterval = 5000;
725 const int minReceiveInterval = 10000;
726 const int testTime = 30000;
727 const int sleepTime = 200;
728 const int expectedTimeout = 40000;
730 int lastSendTime = 0;
731 int lastReceiveTime = 0;
734 DE_ASSERT(sendInterval < minReceiveInterval);
736 curTime = clock.getMilliseconds();
738 while (curTime < testTime)
740 bool tryGetKeepalive = false;
742 if (curTime-lastSendTime > sendInterval)
744 printf(" %d ms: sending keepalive\n", curTime);
745 sendMessage(socket, KeepAliveMessage());
746 curTime = clock.getMilliseconds();
747 lastSendTime = curTime;
748 tryGetKeepalive = true;
753 // Try to acquire keepalive.
754 printf(" %d ms: waiting for keepalive\n", curTime);
755 ScopedMsgPtr msg(readMessage(socket));
756 int recvTime = clock.getMilliseconds();
758 if (msg->type != MESSAGETYPE_KEEPALIVE)
759 XS_FAIL("Got invalid message");
761 printf(" %d ms: got keepalive\n", curTime);
763 if (recvTime-lastReceiveTime > minReceiveInterval)
764 XS_FAIL("Server doesn't send keepalives");
766 lastReceiveTime = recvTime;
770 curTime = clock.getMilliseconds();
773 // Verify that server actually kills the connection upon timeout.
774 sendMessage(socket, KeepAliveMessage());
775 printf(" waiting %d ms for keepalive timeout...\n", expectedTimeout);
776 bool isClosed = false;
782 curTime = clock.getMilliseconds();
784 while (curTime < expectedTimeout)
786 // Try to get keepalive message.
787 ScopedMsgPtr msg(readMessage(socket));
788 if (msg->type != MESSAGETYPE_KEEPALIVE)
789 XS_FAIL("Got invalid message");
791 curTime = clock.getMilliseconds();
792 printf(" %d ms: got keepalive\n", curTime);
795 catch (const SocketError& e)
797 if (e.getResult() == DE_SOCKETRESULT_CONNECTION_CLOSED)
799 printf(" %d ms: server closed connection", clock.getMilliseconds());
809 XS_FAIL("Server didn't close connection");
812 void runProgram (void) { /* nothing */ }
815 void printHelp (const char* binName)
817 printf("%s:\n", binName);
818 printf(" --client=[name] Run test [name]\n");
819 printf(" --program=[name] Run program for test [name]\n");
820 printf(" --host=[host] Connect to host [host]\n");
821 printf(" --port=[name] Use port [port]\n");
822 printf(" --tester-cmd=[cmd] Launch tester with [cmd]\n");
823 printf(" --server-cmd=[cmd] Launch server with [cmd]\n");
824 printf(" --start-server Start server for test execution\n");
827 struct CompareCaseName
831 CompareCaseName (const string& name_) : name(name_) {}
833 bool operator() (const TestCase* testCase) const
835 return name == testCase->getName();
839 void runExecServerTests (int argc, const char* const* argv)
841 // Construct test context.
844 testCtx.serverPath = "execserver";
845 testCtx.testerPath = argv[0];
846 testCtx.startServer = false;
847 testCtx.address.setHost("127.0.0.1");
848 testCtx.address.setPort(50016);
850 std::string runClient = "";
851 std::string runProgram = "";
853 // Parse command line.
854 for (int argNdx = 1; argNdx < argc; argNdx++)
856 const char* arg = argv[argNdx];
858 if (deStringBeginsWith(arg, "--client="))
860 else if (deStringBeginsWith(arg, "--program="))
862 else if (deStringBeginsWith(arg, "--port="))
863 testCtx.address.setPort(atoi(arg+7));
864 else if (deStringBeginsWith(arg, "--host="))
865 testCtx.address.setHost(arg+7);
866 else if (deStringBeginsWith(arg, "--server-cmd="))
867 testCtx.serverPath = arg+13;
868 else if (deStringBeginsWith(arg, "--tester-cmd="))
869 testCtx.testerPath = arg+13;
870 else if (deStringBeginsWith(arg, "--deqp-log-filename="))
871 testCtx.logFileName = arg+20;
872 else if (deStringBeginsWith(arg, "--deqp-caselist="))
873 testCtx.caseList = arg+16;
874 else if (deStringEqual(arg, "--deqp-stdin-caselist"))
876 // \todo [pyry] This is rather brute-force solution...
878 while (fread(&c, 1, 1, stdin) == 1 && c != 0)
879 testCtx.caseList += c;
881 else if (deStringEqual(arg, "--start-server"))
882 testCtx.startServer = true;
891 std::vector<TestCase*> testCases;
892 testCases.push_back(new ConnectTest(testCtx));
893 testCases.push_back(new HelloTest(testCtx));
894 testCases.push_back(new ExecFailTest(testCtx));
895 testCases.push_back(new SimpleExecTest(testCtx));
896 testCases.push_back(new InfoTest(testCtx));
897 testCases.push_back(new LogDataTest(testCtx));
898 testCases.push_back(new KeepAliveTest(testCtx));
899 testCases.push_back(new BigLogDataTest(testCtx));
903 if (!runClient.empty())
906 vector<TestCase*>::iterator casePos = std::find_if(testCases.begin(), testCases.end(), CompareCaseName(runClient));
907 XS_CHECK(casePos != testCases.end());
908 TestExecutor executor(testCtx);
909 executor.runCase(*casePos);
911 else if (!runProgram.empty())
914 vector<TestCase*>::iterator casePos = std::find_if(testCases.begin(), testCases.end(), CompareCaseName(runProgram));
915 XS_CHECK(casePos != testCases.end());
916 (*casePos)->runProgram();
917 fflush(stdout); // Make sure handles are flushed.
923 TestExecutor executor(testCtx);
924 executor.runCases(testCases);
927 catch (const std::exception& e)
929 printf("ERROR: %s\n", e.what());
933 for (std::vector<TestCase*>::const_iterator i = testCases.begin(); i != testCases.end(); i++)
940 void testProcFile (void)
943 if (deFileExists("test.txt"))
944 deDeleteFile("test.txt");
945 deFile* file = deFile_create("test.txt", DE_FILEMODE_CREATE|DE_FILEMODE_WRITE);
946 const char test[] = "Hello";
947 XS_CHECK(deFile_write(file, test, sizeof(test), DE_NULL) == DE_FILERESULT_SUCCESS);
948 deFile_destroy(file);
951 char buf[10] = { 0 };
952 file = deFile_create("test.txt", DE_FILEMODE_OPEN|DE_FILEMODE_READ);
953 XS_CHECK(deFile_read(file, buf, sizeof(test), DE_NULL) == DE_FILERESULT_SUCCESS);
954 printf("buf: %s\n", buf);
955 deFile_destroy(file);
958 deProcess* proc = deProcess_create("ls -lah /Users/pyry", DE_NULL);
959 deFile* out = deProcess_getStdOut(proc);
963 while (deFile_read(out, buf, sizeof(buf)-1, &numRead) == DE_FILERESULT_SUCCESS)
968 deProcess_destroy(proc);
973 void testBlockingFile (const char* filename)
976 int dataSize = 1024*1024;
977 deUint8* data = (deUint8*)deCalloc(dataSize);
980 deRandom_init(&rnd, 0);
982 if (deFileExists(filename))
983 DE_VERIFY(deDeleteFile(filename));
985 /* Fill in with random data. */
986 DE_ASSERT(dataSize % sizeof(int) == 0);
987 for (int ndx = 0; ndx < (int)(dataSize/sizeof(int)); ndx++)
988 ((deUint32*)data)[ndx] = deRandom_getUint32(&rnd);
990 /* Write with random-sized blocks. */
991 file = deFile_create(filename, DE_FILEMODE_CREATE|DE_FILEMODE_WRITE);
995 while (curPos < dataSize)
997 int blockSize = 1 + deRandom_getUint32(&rnd) % (dataSize-curPos);
998 deInt64 numWritten = 0;
999 deFileResult result = deFile_write(file, &data[curPos], blockSize, &numWritten);
1001 DE_VERIFY(result == DE_FILERESULT_SUCCESS);
1002 DE_VERIFY(numWritten == blockSize);
1004 curPos += blockSize;
1007 deFile_destroy(file);
1009 /* Read and verify file. */
1010 file = deFile_create(filename, DE_FILEMODE_OPEN|DE_FILEMODE_READ);
1012 while (curPos < dataSize)
1014 deUint8 block[1024];
1015 int numToRead = 1 + deRandom_getUint32(&rnd) % deMin(dataSize-curPos, DE_LENGTH_OF_ARRAY(block));
1016 deInt64 numRead = 0;
1017 deFileResult result = deFile_read(file, block, numToRead, &numRead);
1019 DE_VERIFY(result == DE_FILERESULT_SUCCESS);
1020 DE_VERIFY((int)numRead == numToRead);
1021 DE_VERIFY(deMemCmp(block, &data[curPos], numToRead) == 0);
1023 curPos += numToRead;
1025 deFile_destroy(file);
1029 int main (int argc, const char* const* argv)
1031 xs::runExecServerTests(argc, argv);