1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Execution Server
3 * ---------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief Test Driver.
22 *//*--------------------------------------------------------------------*/
23
24 #include "xsTestDriver.hpp"
25 #include "deClock.h"
26
27 #include <string>
28 #include <vector>
29 #include <cstdio>
30
31 using std::string;
32 using std::vector;
33
34 #if 0
35 # define DBG_PRINT(X) printf X
36 #else
37 # define DBG_PRINT(X)
38 #endif
39
40 namespace xs
41 {
42
TestDriver(xs::TestProcess * testProcess)43 TestDriver::TestDriver (xs::TestProcess* testProcess)
44 : m_state (STATE_NOT_STARTED)
45 , m_lastExitCode (0)
46 , m_process (testProcess)
47 , m_lastProcessDataTime (0)
48 , m_dataMsgTmpBuf (SEND_RECV_TMP_BUFFER_SIZE)
49 {
50 }
51
~TestDriver(void)52 TestDriver::~TestDriver (void)
53 {
54 reset();
55 }
56
reset(void)57 void TestDriver::reset (void)
58 {
59 m_process->cleanup();
60
61 m_state = STATE_NOT_STARTED;
62 }
63
startProcess(const char * name,const char * params,const char * workingDir,const char * caseList)64 void TestDriver::startProcess (const char* name, const char* params, const char* workingDir, const char* caseList)
65 {
66 try
67 {
68 m_process->start(name, params, workingDir, caseList);
69 m_state = STATE_PROCESS_STARTED;
70 }
71 catch (const TestProcessException& e)
72 {
73 printf("Failed to launch test process: %s\n", e.what());
74 m_state = STATE_PROCESS_LAUNCH_FAILED;
75 m_lastLaunchFailure = e.what();
76 }
77 }
78
stopProcess(void)79 void TestDriver::stopProcess (void)
80 {
81 m_process->terminate();
82 }
83
poll(ByteBuffer & messageBuffer)84 bool TestDriver::poll (ByteBuffer& messageBuffer)
85 {
86 switch (m_state)
87 {
88 case STATE_NOT_STARTED:
89 return false; // Nothing to report.
90
91 case STATE_PROCESS_LAUNCH_FAILED:
92 DBG_PRINT((" STATE_PROCESS_LAUNCH_FAILED\n"));
93 if (writeMessage(messageBuffer, ProcessLaunchFailedMessage(m_lastLaunchFailure.c_str())))
94 {
95 m_state = STATE_NOT_STARTED;
96 m_lastLaunchFailure = "";
97 return true;
98 }
99 else
100 return false;
101
102 case STATE_PROCESS_STARTED:
103 DBG_PRINT((" STATE_PROCESS_STARTED\n"));
104 if (writeMessage(messageBuffer, ProcessStartedMessage()))
105 {
106 m_state = STATE_PROCESS_RUNNING;
107 return true;
108 }
109 else
110 return false;
111
112 case STATE_PROCESS_RUNNING:
113 {
114 DBG_PRINT((" STATE_PROCESS_RUNNING\n"));
115 bool gotProcessData = false;
116
117 // Poll log file and info buffer.
118 gotProcessData = pollLogFile(messageBuffer) || gotProcessData;
119 gotProcessData = pollInfo(messageBuffer) || gotProcessData;
120
121 if (gotProcessData)
122 return true; // Got IO.
123
124 if (!m_process->isRunning())
125 {
126 // Process died.
127 m_state = STATE_READING_DATA;
128 m_lastExitCode = m_process->getExitCode();
129 m_lastProcessDataTime = deGetMicroseconds();
130
131 return true; // Got state change.
132 }
133
134 return false; // Nothing to report.
135 }
136
137 case STATE_READING_DATA:
138 {
139 DBG_PRINT((" STATE_READING_DATA\n"));
140 bool gotProcessData = false;
141
142 // Poll log file and info buffer.
143 gotProcessData = pollLogFile(messageBuffer) || gotProcessData;
144 gotProcessData = pollInfo(messageBuffer) || gotProcessData;
145
146 if (gotProcessData)
147 {
148 // Got data.
149 m_lastProcessDataTime = deGetMicroseconds();
150 return true;
151 }
152 else if (deGetMicroseconds() - m_lastProcessDataTime > READ_DATA_TIMEOUT*1000)
153 {
154 // Read timeout occurred.
155 m_state = STATE_PROCESS_FINISHED;
156 return true; // State change.
157 }
158 else
159 return false; // Still waiting for data.
160 }
161
162 case STATE_PROCESS_FINISHED:
163 DBG_PRINT((" STATE_PROCESS_FINISHED\n"));
164 if (writeMessage(messageBuffer, ProcessFinishedMessage(m_lastExitCode)))
165 {
166 // Signal TestProcess to clean up any remaining resources.
167 m_process->cleanup();
168
169 m_state = STATE_NOT_STARTED;
170 m_lastExitCode = 0;
171 return true;
172 }
173 else
174 return false;
175
176 default:
177 DE_ASSERT(DE_FALSE);
178 return false;
179 }
180 }
181
pollLogFile(ByteBuffer & messageBuffer)182 bool TestDriver::pollLogFile (ByteBuffer& messageBuffer)
183 {
184 return pollBuffer(messageBuffer, MESSAGETYPE_PROCESS_LOG_DATA);
185 }
186
pollInfo(ByteBuffer & messageBuffer)187 bool TestDriver::pollInfo (ByteBuffer& messageBuffer)
188 {
189 return pollBuffer(messageBuffer, MESSAGETYPE_INFO);
190 }
191
pollBuffer(ByteBuffer & messageBuffer,MessageType msgType)192 bool TestDriver::pollBuffer (ByteBuffer& messageBuffer, MessageType msgType)
193 {
194 const int minBytesAvailable = MESSAGE_HEADER_SIZE + MIN_MSG_PAYLOAD_SIZE;
195
196 if (messageBuffer.getNumFree() < minBytesAvailable)
197 return false; // Not enough space in message buffer.
198
199 const int maxMsgSize = de::min((int)m_dataMsgTmpBuf.size(), messageBuffer.getNumFree());
200 int numRead = 0;
201 int msgSize = MESSAGE_HEADER_SIZE+1; // One byte is reserved for terminating 0.
202
203 // Fill in data \note Last byte is reserved for 0.
204 numRead = msgType == MESSAGETYPE_PROCESS_LOG_DATA
205 ? m_process->readTestLog(&m_dataMsgTmpBuf[MESSAGE_HEADER_SIZE], maxMsgSize-MESSAGE_HEADER_SIZE-1)
206 : m_process->readInfoLog(&m_dataMsgTmpBuf[MESSAGE_HEADER_SIZE], maxMsgSize-MESSAGE_HEADER_SIZE-1);
207
208 if (numRead <= 0)
209 return false; // Didn't get any data.
210
211 msgSize += numRead;
212
213 // Terminate with 0.
214 m_dataMsgTmpBuf[msgSize-1] = 0;
215
216 // Write header.
217 Message::writeHeader(msgType, msgSize, &m_dataMsgTmpBuf[0], MESSAGE_HEADER_SIZE);
218
219 // Write to messagebuffer.
220 messageBuffer.pushFront(&m_dataMsgTmpBuf[0], msgSize);
221
222 DBG_PRINT((" wrote %d bytes of %s data\n", msgSize, msgType == MESSAGETYPE_INFO ? "info" : "log"));
223
224 return true;
225 }
226
writeMessage(ByteBuffer & messageBuffer,const Message & message)227 bool TestDriver::writeMessage (ByteBuffer& messageBuffer, const Message& message)
228 {
229 vector<deUint8> buf;
230 message.write(buf);
231
232 if (messageBuffer.getNumFree() < (int)buf.size())
233 return false;
234
235 messageBuffer.pushFront(&buf[0], (int)buf.size());
236 return true;
237 }
238
239 } // xs
240