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