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