You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
5.9 KiB
240 lines
5.9 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program Execution Server
|
|
* ---------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Test Driver.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "xsTestDriver.hpp"
|
|
#include "deClock.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstdio>
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
#if 0
|
|
# define DBG_PRINT(X) printf X
|
|
#else
|
|
# define DBG_PRINT(X)
|
|
#endif
|
|
|
|
namespace xs
|
|
{
|
|
|
|
TestDriver::TestDriver (xs::TestProcess* testProcess)
|
|
: m_state (STATE_NOT_STARTED)
|
|
, m_lastExitCode (0)
|
|
, m_process (testProcess)
|
|
, m_lastProcessDataTime (0)
|
|
, m_dataMsgTmpBuf (SEND_RECV_TMP_BUFFER_SIZE)
|
|
{
|
|
}
|
|
|
|
TestDriver::~TestDriver (void)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void TestDriver::reset (void)
|
|
{
|
|
m_process->cleanup();
|
|
|
|
m_state = STATE_NOT_STARTED;
|
|
}
|
|
|
|
void TestDriver::startProcess (const char* name, const char* params, const char* workingDir, const char* caseList)
|
|
{
|
|
try
|
|
{
|
|
m_process->start(name, params, workingDir, caseList);
|
|
m_state = STATE_PROCESS_STARTED;
|
|
}
|
|
catch (const TestProcessException& e)
|
|
{
|
|
printf("Failed to launch test process: %s\n", e.what());
|
|
m_state = STATE_PROCESS_LAUNCH_FAILED;
|
|
m_lastLaunchFailure = e.what();
|
|
}
|
|
}
|
|
|
|
void TestDriver::stopProcess (void)
|
|
{
|
|
m_process->terminate();
|
|
}
|
|
|
|
bool TestDriver::poll (ByteBuffer& messageBuffer)
|
|
{
|
|
switch (m_state)
|
|
{
|
|
case STATE_NOT_STARTED:
|
|
return false; // Nothing to report.
|
|
|
|
case STATE_PROCESS_LAUNCH_FAILED:
|
|
DBG_PRINT((" STATE_PROCESS_LAUNCH_FAILED\n"));
|
|
if (writeMessage(messageBuffer, ProcessLaunchFailedMessage(m_lastLaunchFailure.c_str())))
|
|
{
|
|
m_state = STATE_NOT_STARTED;
|
|
m_lastLaunchFailure = "";
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
case STATE_PROCESS_STARTED:
|
|
DBG_PRINT((" STATE_PROCESS_STARTED\n"));
|
|
if (writeMessage(messageBuffer, ProcessStartedMessage()))
|
|
{
|
|
m_state = STATE_PROCESS_RUNNING;
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
case STATE_PROCESS_RUNNING:
|
|
{
|
|
DBG_PRINT((" STATE_PROCESS_RUNNING\n"));
|
|
bool gotProcessData = false;
|
|
|
|
// Poll log file and info buffer.
|
|
gotProcessData = pollLogFile(messageBuffer) || gotProcessData;
|
|
gotProcessData = pollInfo(messageBuffer) || gotProcessData;
|
|
|
|
if (gotProcessData)
|
|
return true; // Got IO.
|
|
|
|
if (!m_process->isRunning())
|
|
{
|
|
// Process died.
|
|
m_state = STATE_READING_DATA;
|
|
m_lastExitCode = m_process->getExitCode();
|
|
m_lastProcessDataTime = deGetMicroseconds();
|
|
|
|
return true; // Got state change.
|
|
}
|
|
|
|
return false; // Nothing to report.
|
|
}
|
|
|
|
case STATE_READING_DATA:
|
|
{
|
|
DBG_PRINT((" STATE_READING_DATA\n"));
|
|
bool gotProcessData = false;
|
|
|
|
// Poll log file and info buffer.
|
|
gotProcessData = pollLogFile(messageBuffer) || gotProcessData;
|
|
gotProcessData = pollInfo(messageBuffer) || gotProcessData;
|
|
|
|
if (gotProcessData)
|
|
{
|
|
// Got data.
|
|
m_lastProcessDataTime = deGetMicroseconds();
|
|
return true;
|
|
}
|
|
else if (deGetMicroseconds() - m_lastProcessDataTime > READ_DATA_TIMEOUT*1000)
|
|
{
|
|
// Read timeout occurred.
|
|
m_state = STATE_PROCESS_FINISHED;
|
|
return true; // State change.
|
|
}
|
|
else
|
|
return false; // Still waiting for data.
|
|
}
|
|
|
|
case STATE_PROCESS_FINISHED:
|
|
DBG_PRINT((" STATE_PROCESS_FINISHED\n"));
|
|
if (writeMessage(messageBuffer, ProcessFinishedMessage(m_lastExitCode)))
|
|
{
|
|
// Signal TestProcess to clean up any remaining resources.
|
|
m_process->cleanup();
|
|
|
|
m_state = STATE_NOT_STARTED;
|
|
m_lastExitCode = 0;
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool TestDriver::pollLogFile (ByteBuffer& messageBuffer)
|
|
{
|
|
return pollBuffer(messageBuffer, MESSAGETYPE_PROCESS_LOG_DATA);
|
|
}
|
|
|
|
bool TestDriver::pollInfo (ByteBuffer& messageBuffer)
|
|
{
|
|
return pollBuffer(messageBuffer, MESSAGETYPE_INFO);
|
|
}
|
|
|
|
bool TestDriver::pollBuffer (ByteBuffer& messageBuffer, MessageType msgType)
|
|
{
|
|
const int minBytesAvailable = MESSAGE_HEADER_SIZE + MIN_MSG_PAYLOAD_SIZE;
|
|
|
|
if (messageBuffer.getNumFree() < minBytesAvailable)
|
|
return false; // Not enough space in message buffer.
|
|
|
|
const int maxMsgSize = de::min((int)m_dataMsgTmpBuf.size(), messageBuffer.getNumFree());
|
|
int numRead = 0;
|
|
int msgSize = MESSAGE_HEADER_SIZE+1; // One byte is reserved for terminating 0.
|
|
|
|
// Fill in data \note Last byte is reserved for 0.
|
|
numRead = msgType == MESSAGETYPE_PROCESS_LOG_DATA
|
|
? m_process->readTestLog(&m_dataMsgTmpBuf[MESSAGE_HEADER_SIZE], maxMsgSize-MESSAGE_HEADER_SIZE-1)
|
|
: m_process->readInfoLog(&m_dataMsgTmpBuf[MESSAGE_HEADER_SIZE], maxMsgSize-MESSAGE_HEADER_SIZE-1);
|
|
|
|
if (numRead <= 0)
|
|
return false; // Didn't get any data.
|
|
|
|
msgSize += numRead;
|
|
|
|
// Terminate with 0.
|
|
m_dataMsgTmpBuf[msgSize-1] = 0;
|
|
|
|
// Write header.
|
|
Message::writeHeader(msgType, msgSize, &m_dataMsgTmpBuf[0], MESSAGE_HEADER_SIZE);
|
|
|
|
// Write to messagebuffer.
|
|
messageBuffer.pushFront(&m_dataMsgTmpBuf[0], msgSize);
|
|
|
|
DBG_PRINT((" wrote %d bytes of %s data\n", msgSize, msgType == MESSAGETYPE_INFO ? "info" : "log"));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TestDriver::writeMessage (ByteBuffer& messageBuffer, const Message& message)
|
|
{
|
|
vector<deUint8> buf;
|
|
message.write(buf);
|
|
|
|
if (messageBuffer.getNumFree() < (int)buf.size())
|
|
return false;
|
|
|
|
messageBuffer.pushFront(&buf[0], (int)buf.size());
|
|
return true;
|
|
}
|
|
|
|
} // xs
|