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 68 { 69 return m_handle; 70 } 71 72 private: 73 Event(const Event &other); 74 Event &operator=(const Event &other); 75 76 HANDLE m_handle; 77 }; 78 79 class CaseListWriter : public de::Thread 80 { 81 public: 82 CaseListWriter(void); 83 ~CaseListWriter(void); 84 85 void start(const char *caseList, HANDLE dst); 86 void stop(void); 87 88 void run(void); 89 90 private: 91 std::vector<char> m_caseList; 92 HANDLE m_dst; 93 Event m_cancelEvent; 94 }; 95 96 class FileReader : public de::Thread 97 { 98 public: 99 FileReader(ThreadedByteBuffer *dst); 100 ~FileReader(void); 101 102 void start(HANDLE file); 103 void stop(void); 104 105 void run(void); 106 107 private: 108 ThreadedByteBuffer *m_dstBuf; 109 HANDLE m_handle; 110 Event m_cancelEvent; 111 }; 112 113 class TestLogReader 114 { 115 public: 116 TestLogReader(void); 117 ~TestLogReader(void); 118 119 void start(const char *filename); 120 void stop(void); 121 isRunning(void) const122 bool isRunning(void) const 123 { 124 return m_reader.isStarted(); 125 } 126 read(uint8_t * dst,int numBytes)127 int read(uint8_t *dst, int numBytes) 128 { 129 return m_logBuffer.tryRead(numBytes, dst); 130 } 131 132 private: 133 ThreadedByteBuffer m_logBuffer; 134 HANDLE m_logFile; 135 136 FileReader m_reader; 137 }; 138 139 // \note deProcess uses anonymous pipes that don't have overlapped IO available. 140 // For ExecServer purposes we need overlapped IO, and it makes the handles 141 // incompatible with deFile. Thus separate Process implementation is used for now. 142 class Process 143 { 144 public: 145 Process(void); 146 ~Process(void); 147 148 void start(const char *commandLine, const char *workingDirectory); 149 150 void waitForFinish(void); 151 void terminate(void); 152 void kill(void); 153 154 bool isRunning(void); getExitCode(void) const155 int getExitCode(void) const 156 { 157 return m_exitCode; 158 } 159 getStdIn(void) const160 HANDLE getStdIn(void) const 161 { 162 return m_standardIn; 163 } getStdOut(void) const164 HANDLE getStdOut(void) const 165 { 166 return m_standardOut; 167 } getStdErr(void) const168 HANDLE getStdErr(void) const 169 { 170 return m_standardErr; 171 } 172 173 private: 174 Process(const Process &other); 175 Process &operator=(const Process &other); 176 177 void stopProcess(bool kill); 178 void cleanupHandles(void); 179 180 enum State 181 { 182 STATE_NOT_STARTED = 0, 183 STATE_RUNNING, 184 STATE_FINISHED, 185 186 STATE_LAST 187 }; 188 189 State m_state; 190 int m_exitCode; 191 192 PROCESS_INFORMATION m_procInfo; 193 HANDLE m_standardIn; 194 HANDLE m_standardOut; 195 HANDLE m_standardErr; 196 }; 197 198 } // namespace win32 199 200 class Win32TestProcess : public TestProcess 201 { 202 public: 203 Win32TestProcess(void); 204 virtual ~Win32TestProcess(void); 205 206 virtual void start(const char *name, const char *params, const char *workingDir, const char *caseList); 207 virtual void terminate(void); 208 virtual void cleanup(void); 209 210 virtual bool isRunning(void); 211 virtual int getExitCode(void) const; 212 213 virtual int readTestLog(uint8_t *dst, int numBytes); readInfoLog(uint8_t * dst,int numBytes)214 virtual int readInfoLog(uint8_t *dst, int numBytes) 215 { 216 return m_infoBuffer.tryRead(numBytes, dst); 217 } 218 219 private: 220 Win32TestProcess(const Win32TestProcess &other); 221 Win32TestProcess &operator=(const Win32TestProcess &other); 222 223 win32::Process *m_process; 224 uint64_t m_processStartTime; 225 std::string m_logFileName; 226 227 ThreadedByteBuffer m_infoBuffer; 228 229 // Threads. 230 win32::CaseListWriter m_caseListWriter; 231 win32::FileReader m_stdOutReader; 232 win32::FileReader m_stdErrReader; 233 win32::TestLogReader m_testLogReader; 234 }; 235 236 } // namespace xs 237 238 #endif // _XSWIN32TESTPROCESS_HPP 239