xref: /aosp_15_r20/external/deqp/execserver/xsTestDriver.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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(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<uint8_t> 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 } // namespace xs
240