You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
5.0 KiB
214 lines
5.0 KiB
#ifndef _XSWIN32TESTPROCESS_HPP |
|
#define _XSWIN32TESTPROCESS_HPP |
|
/*------------------------------------------------------------------------- |
|
* drawElements Quality Program Execution Server |
|
* --------------------------------------------- |
|
* |
|
* Copyright 2014 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*//*! |
|
* \file |
|
* \brief TestProcess implementation for Win32. |
|
*//*--------------------------------------------------------------------*/ |
|
|
|
#include "xsDefs.hpp" |
|
#include "xsTestProcess.hpp" |
|
#include "deThread.hpp" |
|
|
|
#include <vector> |
|
#include <string> |
|
|
|
#if !defined(VC_EXTRALEAN) |
|
# define VC_EXTRALEAN 1 |
|
#endif |
|
#if !defined(WIN32_LEAN_AND_MEAN) |
|
# define WIN32_LEAN_AND_MEAN 1 |
|
#endif |
|
#if !defined(NOMINMAX) |
|
# define NOMINMAX 1 |
|
#endif |
|
#include <windows.h> |
|
|
|
namespace xs |
|
{ |
|
namespace win32 |
|
{ |
|
|
|
class Error : public std::runtime_error |
|
{ |
|
public: |
|
Error (DWORD error, const char* msg); |
|
|
|
private: |
|
DWORD m_error; |
|
}; |
|
|
|
class Event |
|
{ |
|
public: |
|
Event (bool manualReset, bool initialState); |
|
~Event (void); |
|
|
|
void setSignaled (void); |
|
void reset (void); |
|
|
|
HANDLE getHandle (void) const { return m_handle; } |
|
|
|
private: |
|
Event (const Event& other); |
|
Event& operator= (const Event& other); |
|
|
|
HANDLE m_handle; |
|
}; |
|
|
|
class CaseListWriter : public de::Thread |
|
{ |
|
public: |
|
CaseListWriter (void); |
|
~CaseListWriter (void); |
|
|
|
void start (const char* caseList, HANDLE dst); |
|
void stop (void); |
|
|
|
void run (void); |
|
|
|
private: |
|
std::vector<char> m_caseList; |
|
HANDLE m_dst; |
|
Event m_cancelEvent; |
|
}; |
|
|
|
class FileReader : public de::Thread |
|
{ |
|
public: |
|
FileReader (ThreadedByteBuffer* dst); |
|
~FileReader (void); |
|
|
|
void start (HANDLE file); |
|
void stop (void); |
|
|
|
void run (void); |
|
|
|
private: |
|
ThreadedByteBuffer* m_dstBuf; |
|
HANDLE m_handle; |
|
Event m_cancelEvent; |
|
}; |
|
|
|
class TestLogReader |
|
{ |
|
public: |
|
TestLogReader (void); |
|
~TestLogReader (void); |
|
|
|
void start (const char* filename); |
|
void stop (void); |
|
|
|
bool isRunning (void) const { return m_reader.isStarted(); } |
|
|
|
int read (deUint8* dst, int numBytes) { return m_logBuffer.tryRead(numBytes, dst); } |
|
|
|
private: |
|
ThreadedByteBuffer m_logBuffer; |
|
HANDLE m_logFile; |
|
|
|
FileReader m_reader; |
|
}; |
|
|
|
// \note deProcess uses anonymous pipes that don't have overlapped IO available. |
|
// For ExecServer purposes we need overlapped IO, and it makes the handles |
|
// incompatible with deFile. Thus separate Process implementation is used for now. |
|
class Process |
|
{ |
|
public: |
|
Process (void); |
|
~Process (void); |
|
|
|
void start (const char* commandLine, const char* workingDirectory); |
|
|
|
void waitForFinish (void); |
|
void terminate (void); |
|
void kill (void); |
|
|
|
bool isRunning (void); |
|
int getExitCode (void) const { return m_exitCode; } |
|
|
|
HANDLE getStdIn (void) const { return m_standardIn; } |
|
HANDLE getStdOut (void) const { return m_standardOut; } |
|
HANDLE getStdErr (void) const { return m_standardErr; } |
|
|
|
private: |
|
Process (const Process& other); |
|
Process& operator= (const Process& other); |
|
|
|
void stopProcess (bool kill); |
|
void cleanupHandles (void); |
|
|
|
enum State |
|
{ |
|
STATE_NOT_STARTED = 0, |
|
STATE_RUNNING, |
|
STATE_FINISHED, |
|
|
|
STATE_LAST |
|
}; |
|
|
|
State m_state; |
|
int m_exitCode; |
|
|
|
PROCESS_INFORMATION m_procInfo; |
|
HANDLE m_standardIn; |
|
HANDLE m_standardOut; |
|
HANDLE m_standardErr; |
|
}; |
|
|
|
} // win32 |
|
|
|
class Win32TestProcess : public TestProcess |
|
{ |
|
public: |
|
Win32TestProcess (void); |
|
virtual ~Win32TestProcess (void); |
|
|
|
virtual void start (const char* name, const char* params, const char* workingDir, const char* caseList); |
|
virtual void terminate (void); |
|
virtual void cleanup (void); |
|
|
|
virtual bool isRunning (void); |
|
virtual int getExitCode (void) const; |
|
|
|
virtual int readTestLog (deUint8* dst, int numBytes); |
|
virtual int readInfoLog (deUint8* dst, int numBytes) { return m_infoBuffer.tryRead(numBytes, dst); } |
|
|
|
private: |
|
Win32TestProcess (const Win32TestProcess& other); |
|
Win32TestProcess& operator= (const Win32TestProcess& other); |
|
|
|
win32::Process* m_process; |
|
deUint64 m_processStartTime; |
|
std::string m_logFileName; |
|
|
|
ThreadedByteBuffer m_infoBuffer; |
|
|
|
// Threads. |
|
win32::CaseListWriter m_caseListWriter; |
|
win32::FileReader m_stdOutReader; |
|
win32::FileReader m_stdErrReader; |
|
win32::TestLogReader m_testLogReader; |
|
}; |
|
|
|
} // xs |
|
|
|
#endif // _XSWIN32TESTPROCESS_HPP
|
|
|