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 44 namespace xs 45 { 46 namespace win32 47 { 48 49 class Error : public std::runtime_error 50 { 51 public: 52 Error (DWORD error, const char* msg); 53 54 private: 55 DWORD m_error; 56 }; 57 58 class Event 59 { 60 public: 61 Event (bool manualReset, bool initialState); 62 ~Event (void); 63 64 void setSignaled (void); 65 void reset (void); 66 getHandle(void) const67 HANDLE getHandle (void) const { return m_handle; } 68 69 private: 70 Event (const Event& other); 71 Event& operator= (const Event& other); 72 73 HANDLE m_handle; 74 }; 75 76 class CaseListWriter : public de::Thread 77 { 78 public: 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 87 private: 88 std::vector<char> m_caseList; 89 HANDLE m_dst; 90 Event m_cancelEvent; 91 }; 92 93 class FileReader : public de::Thread 94 { 95 public: 96 FileReader (ThreadedByteBuffer* dst); 97 ~FileReader (void); 98 99 void start (HANDLE file); 100 void stop (void); 101 102 void run (void); 103 104 private: 105 ThreadedByteBuffer* m_dstBuf; 106 HANDLE m_handle; 107 Event m_cancelEvent; 108 }; 109 110 class TestLogReader 111 { 112 public: 113 TestLogReader (void); 114 ~TestLogReader (void); 115 116 void start (const char* filename); 117 void stop (void); 118 isRunning(void) const119 bool isRunning (void) const { return m_reader.isStarted(); } 120 read(deUint8 * dst,int numBytes)121 int read (deUint8* dst, int numBytes) { return m_logBuffer.tryRead(numBytes, dst); } 122 123 private: 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. 133 class Process 134 { 135 public: 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); getExitCode(void) const146 int getExitCode (void) const { return m_exitCode; } 147 getStdIn(void) const148 HANDLE getStdIn (void) const { return m_standardIn; } getStdOut(void) const149 HANDLE getStdOut (void) const { return m_standardOut; } getStdErr(void) const150 HANDLE getStdErr (void) const { return m_standardErr; } 151 152 private: 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 179 class Win32TestProcess : public TestProcess 180 { 181 public: 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); readInfoLog(deUint8 * dst,int numBytes)193 virtual int readInfoLog (deUint8* dst, int numBytes) { return m_infoBuffer.tryRead(numBytes, dst); } 194 195 private: 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