1#ifndef _XSWIN32TESTPROCESS_HPP 2#define _XSWIN32TESTPROCESS_HPP 3/*------------------------------------------------------------------------- 4 * drawElements Quality Program Execution Server 5 * --------------------------------------------- 6 * 7 * Copyright 2014 The Android Open Source Project 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief TestProcess implementation for Win32. 24 *//*--------------------------------------------------------------------*/ 25 26#include "xsDefs.hpp" 27#include "xsTestProcess.hpp" 28#include "deThread.hpp" 29 30#include <vector> 31#include <string> 32 33#if !defined(VC_EXTRALEAN) 34# define VC_EXTRALEAN 1 35#endif 36#if !defined(WIN32_LEAN_AND_MEAN) 37# define WIN32_LEAN_AND_MEAN 1 38#endif 39#if !defined(NOMINMAX) 40# define NOMINMAX 1 41#endif 42#include <windows.h> 43 44namespace xs 45{ 46namespace win32 47{ 48 49class Error : public std::runtime_error 50{ 51public: 52 Error (DWORD error, const char* msg); 53 54private: 55 DWORD m_error; 56}; 57 58class Event 59{ 60public: 61 Event (bool manualReset, bool initialState); 62 ~Event (void); 63 64 void setSignaled (void); 65 void reset (void); 66 67 HANDLE getHandle (void) const { return m_handle; } 68 69private: 70 Event (const Event& other); 71 Event& operator= (const Event& other); 72 73 HANDLE m_handle; 74}; 75 76class CaseListWriter : public de::Thread 77{ 78public: 79 CaseListWriter (void); 80 ~CaseListWriter (void); 81 82 void start (const char* caseList, HANDLE dst); 83 void stop (void); 84 85 void run (void); 86 87private: 88 std::vector<char> m_caseList; 89 HANDLE m_dst; 90 Event m_cancelEvent; 91}; 92 93class FileReader : public de::Thread 94{ 95public: 96 FileReader (ThreadedByteBuffer* dst); 97 ~FileReader (void); 98 99 void start (HANDLE file); 100 void stop (void); 101 102 void run (void); 103 104private: 105 ThreadedByteBuffer* m_dstBuf; 106 HANDLE m_handle; 107 Event m_cancelEvent; 108}; 109 110class TestLogReader 111{ 112public: 113 TestLogReader (void); 114 ~TestLogReader (void); 115 116 void start (const char* filename); 117 void stop (void); 118 119 bool isRunning (void) const { return m_reader.isStarted(); } 120 121 int read (deUint8* dst, int numBytes) { return m_logBuffer.tryRead(numBytes, dst); } 122 123private: 124 ThreadedByteBuffer m_logBuffer; 125 HANDLE m_logFile; 126 127 FileReader m_reader; 128}; 129 130// \note deProcess uses anonymous pipes that don't have overlapped IO available. 131// For ExecServer purposes we need overlapped IO, and it makes the handles 132// incompatible with deFile. Thus separate Process implementation is used for now. 133class Process 134{ 135public: 136 Process (void); 137 ~Process (void); 138 139 void start (const char* commandLine, const char* workingDirectory); 140 141 void waitForFinish (void); 142 void terminate (void); 143 void kill (void); 144 145 bool isRunning (void); 146 int getExitCode (void) const { return m_exitCode; } 147 148 HANDLE getStdIn (void) const { return m_standardIn; } 149 HANDLE getStdOut (void) const { return m_standardOut; } 150 HANDLE getStdErr (void) const { return m_standardErr; } 151 152private: 153 Process (const Process& other); 154 Process& operator= (const Process& other); 155 156 void stopProcess (bool kill); 157 void cleanupHandles (void); 158 159 enum State 160 { 161 STATE_NOT_STARTED = 0, 162 STATE_RUNNING, 163 STATE_FINISHED, 164 165 STATE_LAST 166 }; 167 168 State m_state; 169 int m_exitCode; 170 171 PROCESS_INFORMATION m_procInfo; 172 HANDLE m_standardIn; 173 HANDLE m_standardOut; 174 HANDLE m_standardErr; 175}; 176 177} // win32 178 179class Win32TestProcess : public TestProcess 180{ 181public: 182 Win32TestProcess (void); 183 virtual ~Win32TestProcess (void); 184 185 virtual void start (const char* name, const char* params, const char* workingDir, const char* caseList); 186 virtual void terminate (void); 187 virtual void cleanup (void); 188 189 virtual bool isRunning (void); 190 virtual int getExitCode (void) const; 191 192 virtual int readTestLog (deUint8* dst, int numBytes); 193 virtual int readInfoLog (deUint8* dst, int numBytes) { return m_infoBuffer.tryRead(numBytes, dst); } 194 195private: 196 Win32TestProcess (const Win32TestProcess& other); 197 Win32TestProcess& operator= (const Win32TestProcess& other); 198 199 win32::Process* m_process; 200 deUint64 m_processStartTime; 201 std::string m_logFileName; 202 203 ThreadedByteBuffer m_infoBuffer; 204 205 // Threads. 206 win32::CaseListWriter m_caseListWriter; 207 win32::FileReader m_stdOutReader; 208 win32::FileReader m_stdErrReader; 209 win32::TestLogReader m_testLogReader; 210}; 211 212} // xs 213 214#endif // _XSWIN32TESTPROCESS_HPP 215