1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Execution Server
3 * ---------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief TestProcess implementation for Unix-like systems.
22 *//*--------------------------------------------------------------------*/
24 #include "xsPosixTestProcess.hpp"
25 #include "deFilePath.hpp"
40 CaseListWriter::CaseListWriter (void)
46 CaseListWriter::~CaseListWriter (void)
50 void CaseListWriter::start (const char* caseList, deFile* dst)
52 DE_ASSERT(!isStarted());
56 int caseListSize = (int)strlen(caseList)+1;
57 m_caseList.resize(caseListSize);
58 std::copy(caseList, caseList+caseListSize, m_caseList.begin());
60 // Set to non-blocking mode.
61 if (!deFile_setFlags(m_file, DE_FILE_NONBLOCKING))
62 XS_FAIL("Failed to set non-blocking mode");
67 void CaseListWriter::run (void)
71 while (m_run && pos < (deInt64)m_caseList.size())
73 deInt64 numWritten = 0;
74 deFileResult result = deFile_write(m_file, &m_caseList[0] + pos, m_caseList.size()-pos, &numWritten);
76 if (result == DE_FILERESULT_SUCCESS)
78 else if (result == DE_FILERESULT_WOULD_BLOCK)
85 void CaseListWriter::stop (void)
88 return; // Nothing to do.
98 PipeReader::PipeReader (ThreadedByteBuffer* dst)
104 PipeReader::~PipeReader (void)
108 void PipeReader::start (deFile* file)
110 DE_ASSERT(!isStarted());
112 // Set to non-blocking mode.
113 if (!deFile_setFlags(file, DE_FILE_NONBLOCKING))
114 XS_FAIL("Failed to set non-blocking mode");
121 void PipeReader::run (void)
123 std::vector<deUint8> tmpBuf (FILEREADER_TMP_BUFFER_SIZE);
126 while (!m_buf->isCanceled())
128 deFileResult result = deFile_read(m_file, &tmpBuf[0], (deInt64)tmpBuf.size(), &numRead);
130 if (result == DE_FILERESULT_SUCCESS)
135 m_buf->write((int)numRead, &tmpBuf[0]);
138 catch (const ThreadedByteBuffer::CanceledException&)
144 else if (result == DE_FILERESULT_END_OF_FILE ||
145 result == DE_FILERESULT_WOULD_BLOCK)
147 // Wait for more data.
148 deSleep(FILEREADER_IDLE_SLEEP);
155 void PipeReader::stop (void)
158 return; // Nothing to do.
160 // Buffer must be in canceled state or otherwise stopping reader might block.
161 DE_ASSERT(m_buf->isCanceled());
171 PosixTestProcess::PosixTestProcess (void)
172 : m_process (DE_NULL)
173 , m_processStartTime (0)
174 , m_infoBuffer (INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS)
175 , m_stdOutReader (&m_infoBuffer)
176 , m_stdErrReader (&m_infoBuffer)
177 , m_logReader (LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS)
181 PosixTestProcess::~PosixTestProcess (void)
186 void PosixTestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList)
188 bool hasCaseList = strlen(caseList) > 0;
190 XS_CHECK(!m_process);
192 de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa");
193 m_logFileName = logFilePath.getPath();
195 // Remove old file if such exists.
196 if (deFileExists(m_logFileName.c_str()))
198 if (!deDeleteFile(m_logFileName.c_str()) || deFileExists(m_logFileName.c_str()))
199 throw TestProcessException(string("Failed to remove '") + m_logFileName + "'");
202 // Construct command line.
203 string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).getPath();
204 cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();
207 cmdLine += " --deqp-stdin-caselist";
209 if (strlen(params) > 0)
210 cmdLine += string(" ") + params;
212 DE_ASSERT(!m_process);
213 m_process = new de::Process();
217 m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL);
219 catch (const de::ProcessError& e)
223 throw TestProcessException(e.what());
226 m_processStartTime = deGetMicroseconds();
228 // Create stdout & stderr readers.
229 if (m_process->getStdOut())
230 m_stdOutReader.start(m_process->getStdOut());
232 if (m_process->getStdErr())
233 m_stdErrReader.start(m_process->getStdErr());
235 // Start case list writer.
238 deFile* dst = m_process->getStdIn();
240 m_caseListWriter.start(caseList, dst);
244 throw TestProcessException("Failed to write case list");
249 void PosixTestProcess::terminate (void)
257 catch (const std::exception& e)
259 printf("PosixTestProcess::terminate(): Failed to kill process: %s\n", e.what());
264 void PosixTestProcess::cleanup (void)
266 m_caseListWriter.stop();
269 // \note Info buffer must be canceled before stopping pipe readers.
270 m_infoBuffer.cancel();
272 m_stdErrReader.stop();
273 m_stdOutReader.stop();
275 // Reset info buffer.
276 m_infoBuffer.clear();
282 if (m_process->isRunning())
285 m_process->waitForFinish();
288 catch (const de::ProcessError& e)
290 printf("PosixTestProcess::stop(): Failed to kill process: %s\n", e.what());
298 bool PosixTestProcess::isRunning (void)
301 return m_process->isRunning();
306 int PosixTestProcess::getExitCode (void) const
309 return m_process->getExitCode();
314 int PosixTestProcess::readTestLog (deUint8* dst, int numBytes)
316 if (!m_logReader.isRunning())
318 if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT*1000)
320 // Timeout, kill process.
322 return 0; // \todo [2013-08-13 pyry] Throw exception?
325 if (!deFileExists(m_logFileName.c_str()))
329 m_logReader.start(m_logFileName.c_str());
332 DE_ASSERT(m_logReader.isRunning());
333 return m_logReader.read(dst, numBytes);