1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program Execution Server 3e5c31af7Sopenharmony_ci * --------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief TestProcess implementation for Win32. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "xsWin32TestProcess.hpp" 25e5c31af7Sopenharmony_ci#include "deFilePath.hpp" 26e5c31af7Sopenharmony_ci#include "deString.h" 27e5c31af7Sopenharmony_ci#include "deMemory.h" 28e5c31af7Sopenharmony_ci#include "deClock.h" 29e5c31af7Sopenharmony_ci#include "deFile.h" 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_ci#include <sstream> 32e5c31af7Sopenharmony_ci#include <string.h> 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_ciusing std::string; 35e5c31af7Sopenharmony_ciusing std::vector; 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_cinamespace xs 38e5c31af7Sopenharmony_ci{ 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_cienum 41e5c31af7Sopenharmony_ci{ 42e5c31af7Sopenharmony_ci MAX_OLD_LOGFILE_DELETE_ATTEMPTS = 20, //!< How many times execserver tries to delete old log file 43e5c31af7Sopenharmony_ci LOGFILE_DELETE_SLEEP_MS = 50 //!< Sleep time (in ms) between log file delete attempts 44e5c31af7Sopenharmony_ci}; 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_cinamespace win32 47e5c31af7Sopenharmony_ci{ 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_ci// Error 50e5c31af7Sopenharmony_ci 51e5c31af7Sopenharmony_cistatic std::string formatErrMsg (DWORD error, const char* msg) 52e5c31af7Sopenharmony_ci{ 53e5c31af7Sopenharmony_ci std::ostringstream str; 54e5c31af7Sopenharmony_ci LPSTR msgBuf; 55e5c31af7Sopenharmony_ci 56e5c31af7Sopenharmony_ci#if defined(UNICODE) 57e5c31af7Sopenharmony_ci# error Unicode not supported. 58e5c31af7Sopenharmony_ci#endif 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_ci if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 61e5c31af7Sopenharmony_ci NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0) 62e5c31af7Sopenharmony_ci str << msg << ", error " << error << ": " << msgBuf; 63e5c31af7Sopenharmony_ci else 64e5c31af7Sopenharmony_ci str << msg << ", error " << error; 65e5c31af7Sopenharmony_ci 66e5c31af7Sopenharmony_ci return str.str(); 67e5c31af7Sopenharmony_ci} 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ciError::Error (DWORD error, const char* msg) 70e5c31af7Sopenharmony_ci : std::runtime_error(formatErrMsg(error, msg)) 71e5c31af7Sopenharmony_ci , m_error (error) 72e5c31af7Sopenharmony_ci{ 73e5c31af7Sopenharmony_ci} 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ci// Event 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ciEvent::Event (bool manualReset, bool initialState) 78e5c31af7Sopenharmony_ci : m_handle(0) 79e5c31af7Sopenharmony_ci{ 80e5c31af7Sopenharmony_ci m_handle = CreateEvent(NULL, manualReset ? TRUE : FALSE, initialState ? TRUE : FALSE, NULL); 81e5c31af7Sopenharmony_ci if (!m_handle) 82e5c31af7Sopenharmony_ci throw Error(GetLastError(), "CreateEvent() failed"); 83e5c31af7Sopenharmony_ci} 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ciEvent::~Event (void) 86e5c31af7Sopenharmony_ci{ 87e5c31af7Sopenharmony_ci CloseHandle(m_handle); 88e5c31af7Sopenharmony_ci} 89e5c31af7Sopenharmony_ci 90e5c31af7Sopenharmony_civoid Event::setSignaled (void) 91e5c31af7Sopenharmony_ci{ 92e5c31af7Sopenharmony_ci if (!SetEvent(m_handle)) 93e5c31af7Sopenharmony_ci throw Error(GetLastError(), "SetEvent() failed"); 94e5c31af7Sopenharmony_ci} 95e5c31af7Sopenharmony_ci 96e5c31af7Sopenharmony_civoid Event::reset (void) 97e5c31af7Sopenharmony_ci{ 98e5c31af7Sopenharmony_ci if (!ResetEvent(m_handle)) 99e5c31af7Sopenharmony_ci throw Error(GetLastError(), "ResetEvent() failed"); 100e5c31af7Sopenharmony_ci} 101e5c31af7Sopenharmony_ci 102e5c31af7Sopenharmony_ci// CaseListWriter 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ciCaseListWriter::CaseListWriter (void) 105e5c31af7Sopenharmony_ci : m_dst (INVALID_HANDLE_VALUE) 106e5c31af7Sopenharmony_ci , m_cancelEvent (true, false) 107e5c31af7Sopenharmony_ci{ 108e5c31af7Sopenharmony_ci} 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ciCaseListWriter::~CaseListWriter (void) 111e5c31af7Sopenharmony_ci{ 112e5c31af7Sopenharmony_ci} 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_civoid CaseListWriter::start (const char* caseList, HANDLE dst) 115e5c31af7Sopenharmony_ci{ 116e5c31af7Sopenharmony_ci DE_ASSERT(!isStarted()); 117e5c31af7Sopenharmony_ci 118e5c31af7Sopenharmony_ci m_dst = dst; 119e5c31af7Sopenharmony_ci 120e5c31af7Sopenharmony_ci int caseListSize = (int)strlen(caseList)+1; 121e5c31af7Sopenharmony_ci m_caseList.resize(caseListSize); 122e5c31af7Sopenharmony_ci std::copy(caseList, caseList+caseListSize, m_caseList.begin()); 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci de::Thread::start(); 125e5c31af7Sopenharmony_ci} 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_civoid CaseListWriter::run (void) 128e5c31af7Sopenharmony_ci{ 129e5c31af7Sopenharmony_ci try 130e5c31af7Sopenharmony_ci { 131e5c31af7Sopenharmony_ci Event ioEvent (true, false); // Manual reset, non-signaled state. 132e5c31af7Sopenharmony_ci HANDLE waitHandles[] = { ioEvent.getHandle(), m_cancelEvent.getHandle() }; 133e5c31af7Sopenharmony_ci OVERLAPPED overlapped; 134e5c31af7Sopenharmony_ci int curPos = 0; 135e5c31af7Sopenharmony_ci 136e5c31af7Sopenharmony_ci deMemset(&overlapped, 0, sizeof(overlapped)); 137e5c31af7Sopenharmony_ci overlapped.hEvent = ioEvent.getHandle(); 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci while (curPos < (int)m_caseList.size()) 140e5c31af7Sopenharmony_ci { 141e5c31af7Sopenharmony_ci const int maxWriteSize = 4096; 142e5c31af7Sopenharmony_ci const int numToWrite = de::min(maxWriteSize, (int)m_caseList.size() - curPos); 143e5c31af7Sopenharmony_ci DWORD waitRes = 0; 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci if (!WriteFile(m_dst, &m_caseList[curPos], (DWORD)numToWrite, NULL, &overlapped)) 146e5c31af7Sopenharmony_ci { 147e5c31af7Sopenharmony_ci DWORD err = GetLastError(); 148e5c31af7Sopenharmony_ci if (err != ERROR_IO_PENDING) 149e5c31af7Sopenharmony_ci throw Error(err, "WriteFile() failed"); 150e5c31af7Sopenharmony_ci } 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE); 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci if (waitRes == WAIT_OBJECT_0) 155e5c31af7Sopenharmony_ci { 156e5c31af7Sopenharmony_ci DWORD numBytesWritten = 0; 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci // \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be). 159e5c31af7Sopenharmony_ci if (!GetOverlappedResult(m_dst, &overlapped, &numBytesWritten, FALSE)) 160e5c31af7Sopenharmony_ci throw Error(GetLastError(), "GetOverlappedResult() failed"); 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci if (numBytesWritten == 0) 163e5c31af7Sopenharmony_ci throw Error(GetLastError(), "Writing to pipe failed (pipe closed?)"); 164e5c31af7Sopenharmony_ci 165e5c31af7Sopenharmony_ci curPos += (int)numBytesWritten; 166e5c31af7Sopenharmony_ci } 167e5c31af7Sopenharmony_ci else if (waitRes == WAIT_OBJECT_0 + 1) 168e5c31af7Sopenharmony_ci { 169e5c31af7Sopenharmony_ci // Cancel. 170e5c31af7Sopenharmony_ci if (!CancelIo(m_dst)) 171e5c31af7Sopenharmony_ci throw Error(GetLastError(), "CancelIo() failed"); 172e5c31af7Sopenharmony_ci break; 173e5c31af7Sopenharmony_ci } 174e5c31af7Sopenharmony_ci else 175e5c31af7Sopenharmony_ci throw Error(GetLastError(), "WaitForMultipleObjects() failed"); 176e5c31af7Sopenharmony_ci } 177e5c31af7Sopenharmony_ci } 178e5c31af7Sopenharmony_ci catch (const std::exception& e) 179e5c31af7Sopenharmony_ci { 180e5c31af7Sopenharmony_ci // \todo [2013-08-13 pyry] What to do about this? 181e5c31af7Sopenharmony_ci printf("win32::CaseListWriter::run(): %s\n", e.what()); 182e5c31af7Sopenharmony_ci } 183e5c31af7Sopenharmony_ci} 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_civoid CaseListWriter::stop (void) 186e5c31af7Sopenharmony_ci{ 187e5c31af7Sopenharmony_ci if (!isStarted()) 188e5c31af7Sopenharmony_ci return; // Nothing to do. 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_ci m_cancelEvent.setSignaled(); 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci // Join thread. 193e5c31af7Sopenharmony_ci join(); 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci m_cancelEvent.reset(); 196e5c31af7Sopenharmony_ci 197e5c31af7Sopenharmony_ci m_dst = INVALID_HANDLE_VALUE; 198e5c31af7Sopenharmony_ci} 199e5c31af7Sopenharmony_ci 200e5c31af7Sopenharmony_ci// FileReader 201e5c31af7Sopenharmony_ci 202e5c31af7Sopenharmony_ciFileReader::FileReader (ThreadedByteBuffer* dst) 203e5c31af7Sopenharmony_ci : m_dstBuf (dst) 204e5c31af7Sopenharmony_ci , m_handle (INVALID_HANDLE_VALUE) 205e5c31af7Sopenharmony_ci , m_cancelEvent (false, false) 206e5c31af7Sopenharmony_ci{ 207e5c31af7Sopenharmony_ci} 208e5c31af7Sopenharmony_ci 209e5c31af7Sopenharmony_ciFileReader::~FileReader (void) 210e5c31af7Sopenharmony_ci{ 211e5c31af7Sopenharmony_ci} 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_civoid FileReader::start (HANDLE file) 214e5c31af7Sopenharmony_ci{ 215e5c31af7Sopenharmony_ci DE_ASSERT(!isStarted()); 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_ci m_handle = file; 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci de::Thread::start(); 220e5c31af7Sopenharmony_ci} 221e5c31af7Sopenharmony_ci 222e5c31af7Sopenharmony_civoid FileReader::run (void) 223e5c31af7Sopenharmony_ci{ 224e5c31af7Sopenharmony_ci try 225e5c31af7Sopenharmony_ci { 226e5c31af7Sopenharmony_ci Event ioEvent (true, false); // Manual reset, not signaled state. 227e5c31af7Sopenharmony_ci HANDLE waitHandles[] = { ioEvent.getHandle(), m_cancelEvent.getHandle() }; 228e5c31af7Sopenharmony_ci OVERLAPPED overlapped; 229e5c31af7Sopenharmony_ci std::vector<deUint8> tmpBuf (FILEREADER_TMP_BUFFER_SIZE); 230e5c31af7Sopenharmony_ci deUint64 offset = 0; // Overlapped IO requires manual offset keeping. 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci deMemset(&overlapped, 0, sizeof(overlapped)); 233e5c31af7Sopenharmony_ci overlapped.hEvent = ioEvent.getHandle(); 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci for (;;) 236e5c31af7Sopenharmony_ci { 237e5c31af7Sopenharmony_ci DWORD numBytesRead = 0; 238e5c31af7Sopenharmony_ci DWORD waitRes; 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci overlapped.Offset = (DWORD)(offset & 0xffffffffu); 241e5c31af7Sopenharmony_ci overlapped.OffsetHigh = (DWORD)(offset >> 32); 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci if (!ReadFile(m_handle, &tmpBuf[0], (DWORD)tmpBuf.size(), NULL, &overlapped)) 244e5c31af7Sopenharmony_ci { 245e5c31af7Sopenharmony_ci DWORD err = GetLastError(); 246e5c31af7Sopenharmony_ci 247e5c31af7Sopenharmony_ci if (err == ERROR_BROKEN_PIPE) 248e5c31af7Sopenharmony_ci break; 249e5c31af7Sopenharmony_ci else if (err == ERROR_HANDLE_EOF) 250e5c31af7Sopenharmony_ci { 251e5c31af7Sopenharmony_ci if (m_dstBuf->isCanceled()) 252e5c31af7Sopenharmony_ci break; 253e5c31af7Sopenharmony_ci 254e5c31af7Sopenharmony_ci deSleep(FILEREADER_IDLE_SLEEP); 255e5c31af7Sopenharmony_ci 256e5c31af7Sopenharmony_ci if (m_dstBuf->isCanceled()) 257e5c31af7Sopenharmony_ci break; 258e5c31af7Sopenharmony_ci else 259e5c31af7Sopenharmony_ci continue; 260e5c31af7Sopenharmony_ci } 261e5c31af7Sopenharmony_ci else if (err != ERROR_IO_PENDING) 262e5c31af7Sopenharmony_ci throw Error(err, "ReadFile() failed"); 263e5c31af7Sopenharmony_ci } 264e5c31af7Sopenharmony_ci 265e5c31af7Sopenharmony_ci waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE); 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_ci if (waitRes == WAIT_OBJECT_0) 268e5c31af7Sopenharmony_ci { 269e5c31af7Sopenharmony_ci // \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be). 270e5c31af7Sopenharmony_ci if (!GetOverlappedResult(m_handle, &overlapped, &numBytesRead, FALSE)) 271e5c31af7Sopenharmony_ci { 272e5c31af7Sopenharmony_ci DWORD err = GetLastError(); 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci if (err == ERROR_HANDLE_EOF) 275e5c31af7Sopenharmony_ci { 276e5c31af7Sopenharmony_ci // End of file - for now. 277e5c31af7Sopenharmony_ci // \note Should check for end of buffer here, or otherwise may end up in infinite loop. 278e5c31af7Sopenharmony_ci if (m_dstBuf->isCanceled()) 279e5c31af7Sopenharmony_ci break; 280e5c31af7Sopenharmony_ci 281e5c31af7Sopenharmony_ci deSleep(FILEREADER_IDLE_SLEEP); 282e5c31af7Sopenharmony_ci 283e5c31af7Sopenharmony_ci if (m_dstBuf->isCanceled()) 284e5c31af7Sopenharmony_ci break; 285e5c31af7Sopenharmony_ci else 286e5c31af7Sopenharmony_ci continue; 287e5c31af7Sopenharmony_ci } 288e5c31af7Sopenharmony_ci else if (err == ERROR_BROKEN_PIPE) 289e5c31af7Sopenharmony_ci break; 290e5c31af7Sopenharmony_ci else 291e5c31af7Sopenharmony_ci throw Error(err, "GetOverlappedResult() failed"); 292e5c31af7Sopenharmony_ci } 293e5c31af7Sopenharmony_ci 294e5c31af7Sopenharmony_ci if (numBytesRead == 0) 295e5c31af7Sopenharmony_ci throw Error(GetLastError(), "Reading from file failed"); 296e5c31af7Sopenharmony_ci else 297e5c31af7Sopenharmony_ci offset += (deUint64)numBytesRead; 298e5c31af7Sopenharmony_ci } 299e5c31af7Sopenharmony_ci else if (waitRes == WAIT_OBJECT_0 + 1) 300e5c31af7Sopenharmony_ci { 301e5c31af7Sopenharmony_ci // Cancel. 302e5c31af7Sopenharmony_ci if (!CancelIo(m_handle)) 303e5c31af7Sopenharmony_ci throw Error(GetLastError(), "CancelIo() failed"); 304e5c31af7Sopenharmony_ci break; 305e5c31af7Sopenharmony_ci } 306e5c31af7Sopenharmony_ci else 307e5c31af7Sopenharmony_ci throw Error(GetLastError(), "WaitForMultipleObjects() failed"); 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci try 310e5c31af7Sopenharmony_ci { 311e5c31af7Sopenharmony_ci m_dstBuf->write((int)numBytesRead, &tmpBuf[0]); 312e5c31af7Sopenharmony_ci m_dstBuf->flush(); 313e5c31af7Sopenharmony_ci } 314e5c31af7Sopenharmony_ci catch (const ThreadedByteBuffer::CanceledException&) 315e5c31af7Sopenharmony_ci { 316e5c31af7Sopenharmony_ci // Canceled. 317e5c31af7Sopenharmony_ci break; 318e5c31af7Sopenharmony_ci } 319e5c31af7Sopenharmony_ci } 320e5c31af7Sopenharmony_ci } 321e5c31af7Sopenharmony_ci catch (const std::exception& e) 322e5c31af7Sopenharmony_ci { 323e5c31af7Sopenharmony_ci // \todo [2013-08-13 pyry] What to do? 324e5c31af7Sopenharmony_ci printf("win32::FileReader::run(): %s\n", e.what()); 325e5c31af7Sopenharmony_ci } 326e5c31af7Sopenharmony_ci} 327e5c31af7Sopenharmony_ci 328e5c31af7Sopenharmony_civoid FileReader::stop (void) 329e5c31af7Sopenharmony_ci{ 330e5c31af7Sopenharmony_ci if (!isStarted()) 331e5c31af7Sopenharmony_ci return; // Nothing to do. 332e5c31af7Sopenharmony_ci 333e5c31af7Sopenharmony_ci m_cancelEvent.setSignaled(); 334e5c31af7Sopenharmony_ci 335e5c31af7Sopenharmony_ci // Join thread. 336e5c31af7Sopenharmony_ci join(); 337e5c31af7Sopenharmony_ci 338e5c31af7Sopenharmony_ci m_cancelEvent.reset(); 339e5c31af7Sopenharmony_ci 340e5c31af7Sopenharmony_ci m_handle = INVALID_HANDLE_VALUE; 341e5c31af7Sopenharmony_ci} 342e5c31af7Sopenharmony_ci 343e5c31af7Sopenharmony_ci// TestLogReader 344e5c31af7Sopenharmony_ci 345e5c31af7Sopenharmony_ciTestLogReader::TestLogReader (void) 346e5c31af7Sopenharmony_ci : m_logBuffer (LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS) 347e5c31af7Sopenharmony_ci , m_logFile (INVALID_HANDLE_VALUE) 348e5c31af7Sopenharmony_ci , m_reader (&m_logBuffer) 349e5c31af7Sopenharmony_ci{ 350e5c31af7Sopenharmony_ci} 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ciTestLogReader::~TestLogReader (void) 353e5c31af7Sopenharmony_ci{ 354e5c31af7Sopenharmony_ci if (m_logFile != INVALID_HANDLE_VALUE) 355e5c31af7Sopenharmony_ci CloseHandle(m_logFile); 356e5c31af7Sopenharmony_ci} 357e5c31af7Sopenharmony_ci 358e5c31af7Sopenharmony_civoid TestLogReader::start (const char* filename) 359e5c31af7Sopenharmony_ci{ 360e5c31af7Sopenharmony_ci DE_ASSERT(m_logFile == INVALID_HANDLE_VALUE && !m_reader.isStarted()); 361e5c31af7Sopenharmony_ci 362e5c31af7Sopenharmony_ci m_logFile = CreateFile(filename, 363e5c31af7Sopenharmony_ci GENERIC_READ, 364e5c31af7Sopenharmony_ci FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, 365e5c31af7Sopenharmony_ci DE_NULL, 366e5c31af7Sopenharmony_ci OPEN_EXISTING, 367e5c31af7Sopenharmony_ci FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 368e5c31af7Sopenharmony_ci DE_NULL); 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci if (m_logFile == INVALID_HANDLE_VALUE) 371e5c31af7Sopenharmony_ci throw Error(GetLastError(), "Failed to open log file"); 372e5c31af7Sopenharmony_ci 373e5c31af7Sopenharmony_ci m_reader.start(m_logFile); 374e5c31af7Sopenharmony_ci} 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_civoid TestLogReader::stop (void) 377e5c31af7Sopenharmony_ci{ 378e5c31af7Sopenharmony_ci if (!m_reader.isStarted()) 379e5c31af7Sopenharmony_ci return; // Nothing to do. 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci m_logBuffer.cancel(); 382e5c31af7Sopenharmony_ci m_reader.stop(); 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ci CloseHandle(m_logFile); 385e5c31af7Sopenharmony_ci m_logFile = INVALID_HANDLE_VALUE; 386e5c31af7Sopenharmony_ci 387e5c31af7Sopenharmony_ci m_logBuffer.clear(); 388e5c31af7Sopenharmony_ci} 389e5c31af7Sopenharmony_ci 390e5c31af7Sopenharmony_ci// Process 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ciProcess::Process (void) 393e5c31af7Sopenharmony_ci : m_state (STATE_NOT_STARTED) 394e5c31af7Sopenharmony_ci , m_exitCode (0) 395e5c31af7Sopenharmony_ci , m_standardIn (INVALID_HANDLE_VALUE) 396e5c31af7Sopenharmony_ci , m_standardOut (INVALID_HANDLE_VALUE) 397e5c31af7Sopenharmony_ci , m_standardErr (INVALID_HANDLE_VALUE) 398e5c31af7Sopenharmony_ci{ 399e5c31af7Sopenharmony_ci deMemset(&m_procInfo, 0, sizeof(m_procInfo)); 400e5c31af7Sopenharmony_ci} 401e5c31af7Sopenharmony_ci 402e5c31af7Sopenharmony_ciProcess::~Process (void) 403e5c31af7Sopenharmony_ci{ 404e5c31af7Sopenharmony_ci try 405e5c31af7Sopenharmony_ci { 406e5c31af7Sopenharmony_ci if (isRunning()) 407e5c31af7Sopenharmony_ci { 408e5c31af7Sopenharmony_ci kill(); 409e5c31af7Sopenharmony_ci waitForFinish(); 410e5c31af7Sopenharmony_ci } 411e5c31af7Sopenharmony_ci } 412e5c31af7Sopenharmony_ci catch (...) 413e5c31af7Sopenharmony_ci { 414e5c31af7Sopenharmony_ci } 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci cleanupHandles(); 417e5c31af7Sopenharmony_ci} 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_civoid Process::cleanupHandles (void) 420e5c31af7Sopenharmony_ci{ 421e5c31af7Sopenharmony_ci DE_ASSERT(!isRunning()); 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci if (m_standardErr != INVALID_HANDLE_VALUE) 424e5c31af7Sopenharmony_ci CloseHandle(m_standardErr); 425e5c31af7Sopenharmony_ci 426e5c31af7Sopenharmony_ci if (m_standardOut != INVALID_HANDLE_VALUE) 427e5c31af7Sopenharmony_ci CloseHandle(m_standardOut); 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci if (m_standardIn != INVALID_HANDLE_VALUE) 430e5c31af7Sopenharmony_ci CloseHandle(m_standardIn); 431e5c31af7Sopenharmony_ci 432e5c31af7Sopenharmony_ci if (m_procInfo.hProcess) 433e5c31af7Sopenharmony_ci CloseHandle(m_procInfo.hProcess); 434e5c31af7Sopenharmony_ci 435e5c31af7Sopenharmony_ci if (m_procInfo.hThread) 436e5c31af7Sopenharmony_ci CloseHandle(m_procInfo.hThread); 437e5c31af7Sopenharmony_ci 438e5c31af7Sopenharmony_ci m_standardErr = INVALID_HANDLE_VALUE; 439e5c31af7Sopenharmony_ci m_standardOut = INVALID_HANDLE_VALUE; 440e5c31af7Sopenharmony_ci m_standardIn = INVALID_HANDLE_VALUE; 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ci deMemset(&m_procInfo, 0, sizeof(m_procInfo)); 443e5c31af7Sopenharmony_ci} 444e5c31af7Sopenharmony_ci 445e5c31af7Sopenharmony_ci__declspec(thread) static int t_pipeNdx = 0; 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_cistatic void createPipeWithOverlappedIO (HANDLE* readHandleOut, HANDLE* writeHandleOut, deUint32 readMode, deUint32 writeMode, SECURITY_ATTRIBUTES* securityAttr) 448e5c31af7Sopenharmony_ci{ 449e5c31af7Sopenharmony_ci const int defaultBufSize = 4096; 450e5c31af7Sopenharmony_ci char pipeName[128]; 451e5c31af7Sopenharmony_ci HANDLE readHandle; 452e5c31af7Sopenharmony_ci HANDLE writeHandle; 453e5c31af7Sopenharmony_ci 454e5c31af7Sopenharmony_ci DE_ASSERT(((readMode | writeMode) & ~FILE_FLAG_OVERLAPPED) == 0); 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci deSprintf(pipeName, sizeof(pipeName), "\\\\.\\Pipe\\dEQP-ExecServer-%08x-%08x-%08x", 457e5c31af7Sopenharmony_ci GetCurrentProcessId(), 458e5c31af7Sopenharmony_ci GetCurrentThreadId(), 459e5c31af7Sopenharmony_ci t_pipeNdx++); 460e5c31af7Sopenharmony_ci 461e5c31af7Sopenharmony_ci readHandle = CreateNamedPipe(pipeName, /* Pipe name. */ 462e5c31af7Sopenharmony_ci PIPE_ACCESS_INBOUND|readMode, /* Open mode. */ 463e5c31af7Sopenharmony_ci PIPE_TYPE_BYTE|PIPE_WAIT, /* Pipe flags. */ 464e5c31af7Sopenharmony_ci 1, /* Max number of instances. */ 465e5c31af7Sopenharmony_ci defaultBufSize, /* Output buffer size. */ 466e5c31af7Sopenharmony_ci defaultBufSize, /* Input buffer size. */ 467e5c31af7Sopenharmony_ci 0, /* Use default timeout. */ 468e5c31af7Sopenharmony_ci securityAttr); 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci if (readHandle == INVALID_HANDLE_VALUE) 471e5c31af7Sopenharmony_ci throw Error(GetLastError(), "CreateNamedPipe() failed"); 472e5c31af7Sopenharmony_ci 473e5c31af7Sopenharmony_ci writeHandle = CreateFile(pipeName, 474e5c31af7Sopenharmony_ci GENERIC_WRITE, /* Access mode. */ 475e5c31af7Sopenharmony_ci 0, /* No sharing. */ 476e5c31af7Sopenharmony_ci securityAttr, 477e5c31af7Sopenharmony_ci OPEN_EXISTING, /* Assume existing object. */ 478e5c31af7Sopenharmony_ci FILE_ATTRIBUTE_NORMAL|writeMode, /* Open mode / flags. */ 479e5c31af7Sopenharmony_ci DE_NULL /* Template file. */); 480e5c31af7Sopenharmony_ci 481e5c31af7Sopenharmony_ci if (writeHandle == INVALID_HANDLE_VALUE) 482e5c31af7Sopenharmony_ci { 483e5c31af7Sopenharmony_ci DWORD openErr = GetLastError(); 484e5c31af7Sopenharmony_ci CloseHandle(readHandle); 485e5c31af7Sopenharmony_ci throw Error(openErr, "Failed to open created pipe, CreateFile() failed"); 486e5c31af7Sopenharmony_ci } 487e5c31af7Sopenharmony_ci 488e5c31af7Sopenharmony_ci *readHandleOut = readHandle; 489e5c31af7Sopenharmony_ci *writeHandleOut = writeHandle; 490e5c31af7Sopenharmony_ci} 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_civoid Process::start (const char* commandLine, const char* workingDirectory) 493e5c31af7Sopenharmony_ci{ 494e5c31af7Sopenharmony_ci // Pipes. 495e5c31af7Sopenharmony_ci HANDLE stdInRead = INVALID_HANDLE_VALUE; 496e5c31af7Sopenharmony_ci HANDLE stdInWrite = INVALID_HANDLE_VALUE; 497e5c31af7Sopenharmony_ci HANDLE stdOutRead = INVALID_HANDLE_VALUE; 498e5c31af7Sopenharmony_ci HANDLE stdOutWrite = INVALID_HANDLE_VALUE; 499e5c31af7Sopenharmony_ci HANDLE stdErrRead = INVALID_HANDLE_VALUE; 500e5c31af7Sopenharmony_ci HANDLE stdErrWrite = INVALID_HANDLE_VALUE; 501e5c31af7Sopenharmony_ci 502e5c31af7Sopenharmony_ci if (m_state == STATE_RUNNING) 503e5c31af7Sopenharmony_ci throw std::runtime_error("Process already running"); 504e5c31af7Sopenharmony_ci else if (m_state == STATE_FINISHED) 505e5c31af7Sopenharmony_ci { 506e5c31af7Sopenharmony_ci // Process finished, clean up old cruft. 507e5c31af7Sopenharmony_ci cleanupHandles(); 508e5c31af7Sopenharmony_ci m_state = STATE_NOT_STARTED; 509e5c31af7Sopenharmony_ci } 510e5c31af7Sopenharmony_ci 511e5c31af7Sopenharmony_ci // Create pipes 512e5c31af7Sopenharmony_ci try 513e5c31af7Sopenharmony_ci { 514e5c31af7Sopenharmony_ci SECURITY_ATTRIBUTES securityAttr; 515e5c31af7Sopenharmony_ci STARTUPINFO startInfo; 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ci deMemset(&startInfo, 0, sizeof(startInfo)); 518e5c31af7Sopenharmony_ci deMemset(&securityAttr, 0, sizeof(securityAttr)); 519e5c31af7Sopenharmony_ci 520e5c31af7Sopenharmony_ci // Security attributes for inheriting handle. 521e5c31af7Sopenharmony_ci securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 522e5c31af7Sopenharmony_ci securityAttr.bInheritHandle = TRUE; 523e5c31af7Sopenharmony_ci securityAttr.lpSecurityDescriptor = DE_NULL; 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci createPipeWithOverlappedIO(&stdInRead, &stdInWrite, 0, FILE_FLAG_OVERLAPPED, &securityAttr); 526e5c31af7Sopenharmony_ci createPipeWithOverlappedIO(&stdOutRead, &stdOutWrite, FILE_FLAG_OVERLAPPED, 0, &securityAttr); 527e5c31af7Sopenharmony_ci createPipeWithOverlappedIO(&stdErrRead, &stdErrWrite, FILE_FLAG_OVERLAPPED, 0, &securityAttr); 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci if (!SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0) || 530e5c31af7Sopenharmony_ci !SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0) || 531e5c31af7Sopenharmony_ci !SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0)) 532e5c31af7Sopenharmony_ci throw Error(GetLastError(), "SetHandleInformation() failed"); 533e5c31af7Sopenharmony_ci 534e5c31af7Sopenharmony_ci // Startup info for process. 535e5c31af7Sopenharmony_ci startInfo.cb = sizeof(startInfo); 536e5c31af7Sopenharmony_ci startInfo.hStdError = stdErrWrite; 537e5c31af7Sopenharmony_ci startInfo.hStdOutput = stdOutWrite; 538e5c31af7Sopenharmony_ci startInfo.hStdInput = stdInRead; 539e5c31af7Sopenharmony_ci startInfo.dwFlags |= STARTF_USESTDHANDLES; 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL, workingDirectory, &startInfo, &m_procInfo)) 542e5c31af7Sopenharmony_ci throw Error(GetLastError(), "CreateProcess() failed"); 543e5c31af7Sopenharmony_ci } 544e5c31af7Sopenharmony_ci catch (...) 545e5c31af7Sopenharmony_ci { 546e5c31af7Sopenharmony_ci if (stdInRead != INVALID_HANDLE_VALUE) CloseHandle(stdInRead); 547e5c31af7Sopenharmony_ci if (stdInWrite != INVALID_HANDLE_VALUE) CloseHandle(stdInWrite); 548e5c31af7Sopenharmony_ci if (stdOutRead != INVALID_HANDLE_VALUE) CloseHandle(stdOutRead); 549e5c31af7Sopenharmony_ci if (stdOutWrite != INVALID_HANDLE_VALUE) CloseHandle(stdOutWrite); 550e5c31af7Sopenharmony_ci if (stdErrRead != INVALID_HANDLE_VALUE) CloseHandle(stdErrRead); 551e5c31af7Sopenharmony_ci if (stdErrWrite != INVALID_HANDLE_VALUE) CloseHandle(stdErrWrite); 552e5c31af7Sopenharmony_ci throw; 553e5c31af7Sopenharmony_ci } 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci // Store handles to be kept. 556e5c31af7Sopenharmony_ci m_standardIn = stdInWrite; 557e5c31af7Sopenharmony_ci m_standardOut = stdOutRead; 558e5c31af7Sopenharmony_ci m_standardErr = stdErrRead; 559e5c31af7Sopenharmony_ci 560e5c31af7Sopenharmony_ci // Close other ends of handles. 561e5c31af7Sopenharmony_ci CloseHandle(stdErrWrite); 562e5c31af7Sopenharmony_ci CloseHandle(stdOutWrite); 563e5c31af7Sopenharmony_ci CloseHandle(stdInRead); 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci m_state = STATE_RUNNING; 566e5c31af7Sopenharmony_ci} 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_cibool Process::isRunning (void) 569e5c31af7Sopenharmony_ci{ 570e5c31af7Sopenharmony_ci if (m_state == STATE_RUNNING) 571e5c31af7Sopenharmony_ci { 572e5c31af7Sopenharmony_ci int exitCode; 573e5c31af7Sopenharmony_ci BOOL result = GetExitCodeProcess(m_procInfo.hProcess, (LPDWORD)&exitCode); 574e5c31af7Sopenharmony_ci 575e5c31af7Sopenharmony_ci if (result != TRUE) 576e5c31af7Sopenharmony_ci throw Error(GetLastError(), "GetExitCodeProcess() failed"); 577e5c31af7Sopenharmony_ci 578e5c31af7Sopenharmony_ci if (exitCode == STILL_ACTIVE) 579e5c31af7Sopenharmony_ci return true; 580e5c31af7Sopenharmony_ci else 581e5c31af7Sopenharmony_ci { 582e5c31af7Sopenharmony_ci // Done. 583e5c31af7Sopenharmony_ci m_exitCode = exitCode; 584e5c31af7Sopenharmony_ci m_state = STATE_FINISHED; 585e5c31af7Sopenharmony_ci return false; 586e5c31af7Sopenharmony_ci } 587e5c31af7Sopenharmony_ci } 588e5c31af7Sopenharmony_ci else 589e5c31af7Sopenharmony_ci return false; 590e5c31af7Sopenharmony_ci} 591e5c31af7Sopenharmony_ci 592e5c31af7Sopenharmony_civoid Process::waitForFinish (void) 593e5c31af7Sopenharmony_ci{ 594e5c31af7Sopenharmony_ci if (m_state == STATE_RUNNING) 595e5c31af7Sopenharmony_ci { 596e5c31af7Sopenharmony_ci if (WaitForSingleObject(m_procInfo.hProcess, INFINITE) != WAIT_OBJECT_0) 597e5c31af7Sopenharmony_ci throw Error(GetLastError(), "Waiting for process failed, WaitForSingleObject() failed"); 598e5c31af7Sopenharmony_ci 599e5c31af7Sopenharmony_ci if (isRunning()) 600e5c31af7Sopenharmony_ci throw std::runtime_error("Process is still alive"); 601e5c31af7Sopenharmony_ci } 602e5c31af7Sopenharmony_ci else 603e5c31af7Sopenharmony_ci throw std::runtime_error("Process is not running"); 604e5c31af7Sopenharmony_ci} 605e5c31af7Sopenharmony_ci 606e5c31af7Sopenharmony_civoid Process::stopProcess (bool kill) 607e5c31af7Sopenharmony_ci{ 608e5c31af7Sopenharmony_ci if (m_state == STATE_RUNNING) 609e5c31af7Sopenharmony_ci { 610e5c31af7Sopenharmony_ci if (!TerminateProcess(m_procInfo.hProcess, kill ? -1 : 0)) 611e5c31af7Sopenharmony_ci throw Error(GetLastError(), "TerminateProcess() failed"); 612e5c31af7Sopenharmony_ci } 613e5c31af7Sopenharmony_ci else 614e5c31af7Sopenharmony_ci throw std::runtime_error("Process is not running"); 615e5c31af7Sopenharmony_ci} 616e5c31af7Sopenharmony_ci 617e5c31af7Sopenharmony_civoid Process::terminate (void) 618e5c31af7Sopenharmony_ci{ 619e5c31af7Sopenharmony_ci stopProcess(false); 620e5c31af7Sopenharmony_ci} 621e5c31af7Sopenharmony_ci 622e5c31af7Sopenharmony_civoid Process::kill (void) 623e5c31af7Sopenharmony_ci{ 624e5c31af7Sopenharmony_ci stopProcess(true); 625e5c31af7Sopenharmony_ci} 626e5c31af7Sopenharmony_ci 627e5c31af7Sopenharmony_ci} // win32 628e5c31af7Sopenharmony_ci 629e5c31af7Sopenharmony_ciWin32TestProcess::Win32TestProcess (void) 630e5c31af7Sopenharmony_ci : m_process (DE_NULL) 631e5c31af7Sopenharmony_ci , m_processStartTime (0) 632e5c31af7Sopenharmony_ci , m_infoBuffer (INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS) 633e5c31af7Sopenharmony_ci , m_stdOutReader (&m_infoBuffer) 634e5c31af7Sopenharmony_ci , m_stdErrReader (&m_infoBuffer) 635e5c31af7Sopenharmony_ci{ 636e5c31af7Sopenharmony_ci} 637e5c31af7Sopenharmony_ci 638e5c31af7Sopenharmony_ciWin32TestProcess::~Win32TestProcess (void) 639e5c31af7Sopenharmony_ci{ 640e5c31af7Sopenharmony_ci delete m_process; 641e5c31af7Sopenharmony_ci} 642e5c31af7Sopenharmony_ci 643e5c31af7Sopenharmony_civoid Win32TestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList) 644e5c31af7Sopenharmony_ci{ 645e5c31af7Sopenharmony_ci bool hasCaseList = strlen(caseList) > 0; 646e5c31af7Sopenharmony_ci 647e5c31af7Sopenharmony_ci XS_CHECK(!m_process); 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa"); 650e5c31af7Sopenharmony_ci m_logFileName = logFilePath.getPath(); 651e5c31af7Sopenharmony_ci 652e5c31af7Sopenharmony_ci // Remove old file if such exists. 653e5c31af7Sopenharmony_ci // \note Sometimes on Windows the test process dies slowly and may not release handle to log file 654e5c31af7Sopenharmony_ci // until a bit later. 655e5c31af7Sopenharmony_ci // \todo [2013-07-15 pyry] This should be solved by improving deProcess and killing all child processes as well. 656e5c31af7Sopenharmony_ci { 657e5c31af7Sopenharmony_ci int tryNdx = 0; 658e5c31af7Sopenharmony_ci while (tryNdx < MAX_OLD_LOGFILE_DELETE_ATTEMPTS && deFileExists(m_logFileName.c_str())) 659e5c31af7Sopenharmony_ci { 660e5c31af7Sopenharmony_ci if (deDeleteFile(m_logFileName.c_str())) 661e5c31af7Sopenharmony_ci break; 662e5c31af7Sopenharmony_ci deSleep(LOGFILE_DELETE_SLEEP_MS); 663e5c31af7Sopenharmony_ci tryNdx += 1; 664e5c31af7Sopenharmony_ci } 665e5c31af7Sopenharmony_ci 666e5c31af7Sopenharmony_ci if (deFileExists(m_logFileName.c_str())) 667e5c31af7Sopenharmony_ci throw TestProcessException(string("Failed to remove '") + m_logFileName + "'"); 668e5c31af7Sopenharmony_ci } 669e5c31af7Sopenharmony_ci 670e5c31af7Sopenharmony_ci // Construct command line. 671e5c31af7Sopenharmony_ci string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).normalize().getPath(); 672e5c31af7Sopenharmony_ci cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName(); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci if (hasCaseList) 675e5c31af7Sopenharmony_ci cmdLine += " --deqp-stdin-caselist"; 676e5c31af7Sopenharmony_ci 677e5c31af7Sopenharmony_ci if (strlen(params) > 0) 678e5c31af7Sopenharmony_ci cmdLine += string(" ") + params; 679e5c31af7Sopenharmony_ci 680e5c31af7Sopenharmony_ci DE_ASSERT(!m_process); 681e5c31af7Sopenharmony_ci m_process = new win32::Process(); 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ci try 684e5c31af7Sopenharmony_ci { 685e5c31af7Sopenharmony_ci m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL); 686e5c31af7Sopenharmony_ci } 687e5c31af7Sopenharmony_ci catch (const std::exception& e) 688e5c31af7Sopenharmony_ci { 689e5c31af7Sopenharmony_ci delete m_process; 690e5c31af7Sopenharmony_ci m_process = DE_NULL; 691e5c31af7Sopenharmony_ci throw TestProcessException(e.what()); 692e5c31af7Sopenharmony_ci } 693e5c31af7Sopenharmony_ci 694e5c31af7Sopenharmony_ci m_processStartTime = deGetMicroseconds(); 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci // Create stdout & stderr readers. 697e5c31af7Sopenharmony_ci m_stdOutReader.start(m_process->getStdOut()); 698e5c31af7Sopenharmony_ci m_stdErrReader.start(m_process->getStdErr()); 699e5c31af7Sopenharmony_ci 700e5c31af7Sopenharmony_ci // Start case list writer. 701e5c31af7Sopenharmony_ci if (hasCaseList) 702e5c31af7Sopenharmony_ci m_caseListWriter.start(caseList, m_process->getStdIn()); 703e5c31af7Sopenharmony_ci} 704e5c31af7Sopenharmony_ci 705e5c31af7Sopenharmony_civoid Win32TestProcess::terminate (void) 706e5c31af7Sopenharmony_ci{ 707e5c31af7Sopenharmony_ci if (m_process) 708e5c31af7Sopenharmony_ci { 709e5c31af7Sopenharmony_ci try 710e5c31af7Sopenharmony_ci { 711e5c31af7Sopenharmony_ci m_process->kill(); 712e5c31af7Sopenharmony_ci } 713e5c31af7Sopenharmony_ci catch (const std::exception& e) 714e5c31af7Sopenharmony_ci { 715e5c31af7Sopenharmony_ci printf("Win32TestProcess::terminate(): Failed to kill process: %s\n", e.what()); 716e5c31af7Sopenharmony_ci } 717e5c31af7Sopenharmony_ci } 718e5c31af7Sopenharmony_ci} 719e5c31af7Sopenharmony_ci 720e5c31af7Sopenharmony_civoid Win32TestProcess::cleanup (void) 721e5c31af7Sopenharmony_ci{ 722e5c31af7Sopenharmony_ci m_caseListWriter.stop(); 723e5c31af7Sopenharmony_ci 724e5c31af7Sopenharmony_ci // \note Buffers must be canceled before stopping readers. 725e5c31af7Sopenharmony_ci m_infoBuffer.cancel(); 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci m_stdErrReader.stop(); 728e5c31af7Sopenharmony_ci m_stdOutReader.stop(); 729e5c31af7Sopenharmony_ci m_testLogReader.stop(); 730e5c31af7Sopenharmony_ci 731e5c31af7Sopenharmony_ci // Reset buffers. 732e5c31af7Sopenharmony_ci m_infoBuffer.clear(); 733e5c31af7Sopenharmony_ci 734e5c31af7Sopenharmony_ci if (m_process) 735e5c31af7Sopenharmony_ci { 736e5c31af7Sopenharmony_ci try 737e5c31af7Sopenharmony_ci { 738e5c31af7Sopenharmony_ci if (m_process->isRunning()) 739e5c31af7Sopenharmony_ci { 740e5c31af7Sopenharmony_ci m_process->kill(); 741e5c31af7Sopenharmony_ci m_process->waitForFinish(); 742e5c31af7Sopenharmony_ci } 743e5c31af7Sopenharmony_ci } 744e5c31af7Sopenharmony_ci catch (const std::exception& e) 745e5c31af7Sopenharmony_ci { 746e5c31af7Sopenharmony_ci printf("Win32TestProcess::cleanup(): Failed to kill process: %s\n", e.what()); 747e5c31af7Sopenharmony_ci } 748e5c31af7Sopenharmony_ci 749e5c31af7Sopenharmony_ci delete m_process; 750e5c31af7Sopenharmony_ci m_process = DE_NULL; 751e5c31af7Sopenharmony_ci } 752e5c31af7Sopenharmony_ci} 753e5c31af7Sopenharmony_ci 754e5c31af7Sopenharmony_ciint Win32TestProcess::readTestLog (deUint8* dst, int numBytes) 755e5c31af7Sopenharmony_ci{ 756e5c31af7Sopenharmony_ci if (!m_testLogReader.isRunning()) 757e5c31af7Sopenharmony_ci { 758e5c31af7Sopenharmony_ci if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT*1000) 759e5c31af7Sopenharmony_ci { 760e5c31af7Sopenharmony_ci // Timeout, kill process. 761e5c31af7Sopenharmony_ci terminate(); 762e5c31af7Sopenharmony_ci return 0; // \todo [2013-08-13 pyry] Throw exception? 763e5c31af7Sopenharmony_ci } 764e5c31af7Sopenharmony_ci 765e5c31af7Sopenharmony_ci if (!deFileExists(m_logFileName.c_str())) 766e5c31af7Sopenharmony_ci return 0; 767e5c31af7Sopenharmony_ci 768e5c31af7Sopenharmony_ci // Start reader. 769e5c31af7Sopenharmony_ci m_testLogReader.start(m_logFileName.c_str()); 770e5c31af7Sopenharmony_ci } 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ci DE_ASSERT(m_testLogReader.isRunning()); 773e5c31af7Sopenharmony_ci return m_testLogReader.read(dst, numBytes); 774e5c31af7Sopenharmony_ci} 775e5c31af7Sopenharmony_ci 776e5c31af7Sopenharmony_cibool Win32TestProcess::isRunning (void) 777e5c31af7Sopenharmony_ci{ 778e5c31af7Sopenharmony_ci if (m_process) 779e5c31af7Sopenharmony_ci return m_process->isRunning(); 780e5c31af7Sopenharmony_ci else 781e5c31af7Sopenharmony_ci return false; 782e5c31af7Sopenharmony_ci} 783e5c31af7Sopenharmony_ci 784e5c31af7Sopenharmony_ciint Win32TestProcess::getExitCode (void) const 785e5c31af7Sopenharmony_ci{ 786e5c31af7Sopenharmony_ci if (m_process) 787e5c31af7Sopenharmony_ci return m_process->getExitCode(); 788e5c31af7Sopenharmony_ci else 789e5c31af7Sopenharmony_ci return -1; 790e5c31af7Sopenharmony_ci} 791e5c31af7Sopenharmony_ci 792e5c31af7Sopenharmony_ci} // xs 793