Home | History | Annotate | Download | only in execserver
      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 
     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 
     52 TestDriver::~TestDriver (void)
     53 {
     54 	reset();
     55 }
     56 
     57 void TestDriver::reset (void)
     58 {
     59 	m_process->cleanup();
     60 
     61 	m_state = STATE_NOT_STARTED;
     62 }
     63 
     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 
     79 void TestDriver::stopProcess (void)
     80 {
     81 	m_process->terminate();
     82 }
     83 
     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 
    182 bool TestDriver::pollLogFile (ByteBuffer& messageBuffer)
    183 {
    184 	return pollBuffer(messageBuffer, MESSAGETYPE_PROCESS_LOG_DATA);
    185 }
    186 
    187 bool TestDriver::pollInfo (ByteBuffer& messageBuffer)
    188 {
    189 	return pollBuffer(messageBuffer, MESSAGETYPE_INFO);
    190 }
    191 
    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 
    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