Merge vk-gl-cts/vulkan-cts-1.0.2 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / execserver / xsTestDriver.cpp
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