blob: cf3bca0e93db36791dd32e842627f1f45e152723 [file] [log] [blame]
Jarkko Poyry3c827362014-09-02 11:48:52 +03001/*-------------------------------------------------------------------------
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
31using std::string;
32using std::vector;
33
34#if 0
35# define DBG_PRINT(X) printf X
36#else
37# define DBG_PRINT(X)
38#endif
39
40namespace xs
41{
42
43TestDriver::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
52TestDriver::~TestDriver (void)
53{
54 reset();
55}
56
57void TestDriver::reset (void)
58{
59 m_process->cleanup();
60
61 m_state = STATE_NOT_STARTED;
62}
63
64void 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
79void TestDriver::stopProcess (void)
80{
81 m_process->terminate();
82}
83
84bool 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
182bool TestDriver::pollLogFile (ByteBuffer& messageBuffer)
183{
184 return pollBuffer(messageBuffer, MESSAGETYPE_PROCESS_LOG_DATA);
185}
186
187bool TestDriver::pollInfo (ByteBuffer& messageBuffer)
188{
189 return pollBuffer(messageBuffer, MESSAGETYPE_INFO);
190}
191
192bool 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
227bool 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