1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program Tester Core
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 iOS App Wrapper.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "tcuIOSApp.h"
25e5c31af7Sopenharmony_ci#include "tcuIOSPlatform.hh"
26e5c31af7Sopenharmony_ci#include "tcuApp.hpp"
27e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
28e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
30e5c31af7Sopenharmony_ci#include "tcuResource.hpp"
31e5c31af7Sopenharmony_ci#include "deThread.hpp"
32e5c31af7Sopenharmony_ci#include "deMutex.hpp"
33e5c31af7Sopenharmony_ci#include "xsExecutionServer.hpp"
34e5c31af7Sopenharmony_ci#include "xsTestProcess.hpp"
35e5c31af7Sopenharmony_ci#include "xsPosixFileReader.hpp"
36e5c31af7Sopenharmony_ci#include "deFilePath.hpp"
37e5c31af7Sopenharmony_ci#include "deClock.h"
38e5c31af7Sopenharmony_ci#include "deMemory.h"
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_ci#include <string>
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci#import <Foundation/NSObject.h>
43e5c31af7Sopenharmony_ci#import <Foundation/NSString.h>
44e5c31af7Sopenharmony_ci#import <Foundation/NSBundle.h>
45e5c31af7Sopenharmony_ci#import <Foundation/NSPathUtilities.h>
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ciusing std::string;
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cinamespace
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_ciclass TestThreadState
53e5c31af7Sopenharmony_ci{
54e5c31af7Sopenharmony_cipublic:
55e5c31af7Sopenharmony_ci	enum State
56e5c31af7Sopenharmony_ci	{
57e5c31af7Sopenharmony_ci		STATE_NOT_RUNNING	= 0,
58e5c31af7Sopenharmony_ci		STATE_RUNNING,
59e5c31af7Sopenharmony_ci		STATE_STOP_REQUESTED,
60e5c31af7Sopenharmony_ci
61e5c31af7Sopenharmony_ci		STATE_LAST
62e5c31af7Sopenharmony_ci	};
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_ci							TestThreadState			(void);
65e5c31af7Sopenharmony_ci							~TestThreadState		(void);
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	void					requestStart			(const char* cmdLine);
68e5c31af7Sopenharmony_ci	void					requestStop				(void);
69e5c31af7Sopenharmony_ci	State					getState				(void);
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci	void					testExecFinished		(void);
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ci	const char*				getCommandLine			(void) const { return m_cmdLine.c_str(); }
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ciprivate:
76e5c31af7Sopenharmony_ci	de::Mutex				m_lock;
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci	State					m_state;
79e5c31af7Sopenharmony_ci	std::string				m_cmdLine;
80e5c31af7Sopenharmony_ci};
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ciTestThreadState::TestThreadState (void)
83e5c31af7Sopenharmony_ci	: m_state(STATE_NOT_RUNNING)
84e5c31af7Sopenharmony_ci{
85e5c31af7Sopenharmony_ci}
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ciTestThreadState::~TestThreadState (void)
88e5c31af7Sopenharmony_ci{
89e5c31af7Sopenharmony_ci}
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_civoid TestThreadState::requestStart (const char* cmdLine)
92e5c31af7Sopenharmony_ci{
93e5c31af7Sopenharmony_ci	de::ScopedLock stateLock(m_lock);
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci	TCU_CHECK(m_state == STATE_NOT_RUNNING);
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ci	m_cmdLine	= cmdLine;
98e5c31af7Sopenharmony_ci	m_state		= STATE_RUNNING;
99e5c31af7Sopenharmony_ci}
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_civoid TestThreadState::requestStop (void)
102e5c31af7Sopenharmony_ci{
103e5c31af7Sopenharmony_ci	de::ScopedLock stateLock(m_lock);
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_ci	if (m_state != STATE_NOT_RUNNING)
106e5c31af7Sopenharmony_ci		m_state = STATE_STOP_REQUESTED;
107e5c31af7Sopenharmony_ci}
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_civoid TestThreadState::testExecFinished (void)
110e5c31af7Sopenharmony_ci{
111e5c31af7Sopenharmony_ci	de::ScopedLock stateLock(m_lock);
112e5c31af7Sopenharmony_ci	m_state = STATE_NOT_RUNNING;
113e5c31af7Sopenharmony_ci}
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ciTestThreadState::State TestThreadState::getState (void)
116e5c31af7Sopenharmony_ci{
117e5c31af7Sopenharmony_ci	de::ScopedLock stateLock(m_lock);
118e5c31af7Sopenharmony_ci	return m_state;
119e5c31af7Sopenharmony_ci}
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ciclass LocalTestProcess : public xs::TestProcess
122e5c31af7Sopenharmony_ci{
123e5c31af7Sopenharmony_cipublic:
124e5c31af7Sopenharmony_ci							LocalTestProcess		(TestThreadState& state, const char* logFileName);
125e5c31af7Sopenharmony_ci							~LocalTestProcess		(void);
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	void					start					(const char* name, const char* params, const char* workingDir, const char* caseList);
128e5c31af7Sopenharmony_ci	void					terminate				(void);
129e5c31af7Sopenharmony_ci	void					cleanup					(void);
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	bool					isRunning				(void);
132e5c31af7Sopenharmony_ci	int						getExitCode				(void) const { return 0; /* not available */ }
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	int						readInfoLog				(deUint8* dst, int numBytes) { DE_UNREF(dst && numBytes); return 0; /* not supported */ }
135e5c31af7Sopenharmony_ci	int						readTestLog				(deUint8* dst, int numBytes);
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ci	const char*				getLogFileName			(void) const { return m_logFileName.c_str(); }
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_ciprivate:
140e5c31af7Sopenharmony_ci	TestThreadState&		m_state;
141e5c31af7Sopenharmony_ci	string					m_logFileName;
142e5c31af7Sopenharmony_ci	xs::posix::FileReader	m_logReader;
143e5c31af7Sopenharmony_ci	deUint64				m_processStartTime;
144e5c31af7Sopenharmony_ci};
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ciLocalTestProcess::LocalTestProcess (TestThreadState& state, const char* logFileName)
147e5c31af7Sopenharmony_ci	: m_state				(state)
148e5c31af7Sopenharmony_ci	, m_logFileName			(logFileName)
149e5c31af7Sopenharmony_ci	, m_logReader			(xs::LOG_BUFFER_BLOCK_SIZE, xs::LOG_BUFFER_NUM_BLOCKS)
150e5c31af7Sopenharmony_ci	, m_processStartTime	(0)
151e5c31af7Sopenharmony_ci{
152e5c31af7Sopenharmony_ci}
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_ciLocalTestProcess::~LocalTestProcess (void)
155e5c31af7Sopenharmony_ci{
156e5c31af7Sopenharmony_ci}
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_civoid LocalTestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList)
159e5c31af7Sopenharmony_ci{
160e5c31af7Sopenharmony_ci	DE_UNREF(name && workingDir);
161e5c31af7Sopenharmony_ci
162e5c31af7Sopenharmony_ci	// Delete old log file.
163e5c31af7Sopenharmony_ci	if (deFileExists(m_logFileName.c_str()))
164e5c31af7Sopenharmony_ci		TCU_CHECK(deDeleteFile(m_logFileName.c_str()));
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci	string cmdLine = string("deqp");
167e5c31af7Sopenharmony_ci	if (caseList && strlen(caseList) > 0)
168e5c31af7Sopenharmony_ci		cmdLine += string(" --deqp-caselist=") + caseList;
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ci	if (params && strlen(params) > 0)
171e5c31af7Sopenharmony_ci		cmdLine += string(" ") + params;
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_ci	m_state.requestStart(cmdLine.c_str());
174e5c31af7Sopenharmony_ci	m_processStartTime = deGetMicroseconds();
175e5c31af7Sopenharmony_ci}
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_civoid LocalTestProcess::terminate (void)
178e5c31af7Sopenharmony_ci{
179e5c31af7Sopenharmony_ci	m_state.requestStop();
180e5c31af7Sopenharmony_ci}
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_civoid LocalTestProcess::cleanup (void)
183e5c31af7Sopenharmony_ci{
184e5c31af7Sopenharmony_ci	if (isRunning())
185e5c31af7Sopenharmony_ci	{
186e5c31af7Sopenharmony_ci		m_state.requestStop();
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci		// Wait until stopped.
189e5c31af7Sopenharmony_ci		while (isRunning())
190e5c31af7Sopenharmony_ci			deSleep(50);
191e5c31af7Sopenharmony_ci	}
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_ci	m_logReader.stop();
194e5c31af7Sopenharmony_ci}
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_cibool LocalTestProcess::isRunning (void)
197e5c31af7Sopenharmony_ci{
198e5c31af7Sopenharmony_ci	return m_state.getState() != TestThreadState::STATE_NOT_RUNNING;
199e5c31af7Sopenharmony_ci}
200e5c31af7Sopenharmony_ci
201e5c31af7Sopenharmony_ciint LocalTestProcess::readTestLog (deUint8* dst, int numBytes)
202e5c31af7Sopenharmony_ci{
203e5c31af7Sopenharmony_ci	if (!m_logReader.isRunning())
204e5c31af7Sopenharmony_ci	{
205e5c31af7Sopenharmony_ci		if (deGetMicroseconds() - m_processStartTime > xs::LOG_FILE_TIMEOUT*1000)
206e5c31af7Sopenharmony_ci		{
207e5c31af7Sopenharmony_ci			// Timeout, kill execution.
208e5c31af7Sopenharmony_ci			terminate();
209e5c31af7Sopenharmony_ci			return 0; // \todo [2013-08-13 pyry] Throw exception?
210e5c31af7Sopenharmony_ci		}
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci		if (!deFileExists(m_logFileName.c_str()))
213e5c31af7Sopenharmony_ci			return 0;
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci		// Start reader.
216e5c31af7Sopenharmony_ci		m_logReader.start(m_logFileName.c_str());
217e5c31af7Sopenharmony_ci	}
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_ci	DE_ASSERT(m_logReader.isRunning());
220e5c31af7Sopenharmony_ci	return m_logReader.read(dst, numBytes);
221e5c31af7Sopenharmony_ci}
222e5c31af7Sopenharmony_ci
223e5c31af7Sopenharmony_ciclass ServerThread : public de::Thread
224e5c31af7Sopenharmony_ci{
225e5c31af7Sopenharmony_cipublic:
226e5c31af7Sopenharmony_ci						ServerThread		(xs::TestProcess* testProcess, int port);
227e5c31af7Sopenharmony_ci						~ServerThread		(void);
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_ci	void				run					(void);
230e5c31af7Sopenharmony_ci	void				stop				(void);
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ciprivate:
233e5c31af7Sopenharmony_ci	xs::ExecutionServer	m_server;
234e5c31af7Sopenharmony_ci	bool				m_isRunning;
235e5c31af7Sopenharmony_ci};
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ciServerThread::ServerThread (xs::TestProcess* testProcess, int port)
238e5c31af7Sopenharmony_ci	: m_server		(testProcess, DE_SOCKETFAMILY_INET4, port, xs::ExecutionServer::RUNMODE_FOREVER)
239e5c31af7Sopenharmony_ci	, m_isRunning	(false)
240e5c31af7Sopenharmony_ci{
241e5c31af7Sopenharmony_ci}
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ciServerThread::~ServerThread (void)
244e5c31af7Sopenharmony_ci{
245e5c31af7Sopenharmony_ci	stop();
246e5c31af7Sopenharmony_ci}
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_civoid ServerThread::run (void)
249e5c31af7Sopenharmony_ci{
250e5c31af7Sopenharmony_ci	m_isRunning = true;
251e5c31af7Sopenharmony_ci	m_server.runServer();
252e5c31af7Sopenharmony_ci}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_civoid ServerThread::stop (void)
255e5c31af7Sopenharmony_ci{
256e5c31af7Sopenharmony_ci	if (m_isRunning)
257e5c31af7Sopenharmony_ci	{
258e5c31af7Sopenharmony_ci		m_server.stopServer();
259e5c31af7Sopenharmony_ci		join();
260e5c31af7Sopenharmony_ci		m_isRunning = false;
261e5c31af7Sopenharmony_ci	}
262e5c31af7Sopenharmony_ci}
263e5c31af7Sopenharmony_ci
264e5c31af7Sopenharmony_cistring getAppBundleDir (void)
265e5c31af7Sopenharmony_ci{
266e5c31af7Sopenharmony_ci	NSString*	dataPath	= [[NSBundle mainBundle] bundlePath];
267e5c31af7Sopenharmony_ci	const char*	utf8Str		= [dataPath UTF8String];
268e5c31af7Sopenharmony_ci
269e5c31af7Sopenharmony_ci	return string(utf8Str);
270e5c31af7Sopenharmony_ci}
271e5c31af7Sopenharmony_ci
272e5c31af7Sopenharmony_cistring getAppDocumentsDir (void)
273e5c31af7Sopenharmony_ci{
274e5c31af7Sopenharmony_ci	NSArray*	paths		= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
275e5c31af7Sopenharmony_ci	NSString*	docPath		= [paths objectAtIndex:0];
276e5c31af7Sopenharmony_ci	const char*	utf8Str		= [docPath UTF8String];
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci	return string(utf8Str);
279e5c31af7Sopenharmony_ci}
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci} // anonymous
282e5c31af7Sopenharmony_ci
283e5c31af7Sopenharmony_cistruct tcuIOSApp_s
284e5c31af7Sopenharmony_ci{
285e5c31af7Sopenharmony_cipublic:
286e5c31af7Sopenharmony_ci							tcuIOSApp_s		(void* view);
287e5c31af7Sopenharmony_ci							~tcuIOSApp_s	(void);
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci	void					iterate			(void);
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ciprotected:
292e5c31af7Sopenharmony_ci	void					createTestApp	(void);
293e5c31af7Sopenharmony_ci	void					destroyTestApp	(void);
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci	TestThreadState			m_state;
296e5c31af7Sopenharmony_ci	LocalTestProcess		m_testProcess;
297e5c31af7Sopenharmony_ci	ServerThread			m_server;
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci	tcu::DirArchive			m_archive;
300e5c31af7Sopenharmony_ci	tcu::ios::ScreenManager	m_screenManager;
301e5c31af7Sopenharmony_ci	tcu::ios::Platform		m_platform;
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci	tcu::TestLog*			m_log;
304e5c31af7Sopenharmony_ci	tcu::CommandLine*		m_cmdLine;
305e5c31af7Sopenharmony_ci	tcu::App*				m_app;
306e5c31af7Sopenharmony_ci};
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_citcuIOSApp_s::tcuIOSApp_s (void* view)
309e5c31af7Sopenharmony_ci	: m_testProcess		(m_state, de::FilePath::join(getAppDocumentsDir(), "TestResults.qpa").getPath())
310e5c31af7Sopenharmony_ci	, m_server			(&m_testProcess, 50016)
311e5c31af7Sopenharmony_ci	, m_archive			(getAppBundleDir().c_str())
312e5c31af7Sopenharmony_ci	, m_screenManager	((tcuEAGLView*)view)
313e5c31af7Sopenharmony_ci	, m_platform		(&m_screenManager)
314e5c31af7Sopenharmony_ci	, m_log				(DE_NULL)
315e5c31af7Sopenharmony_ci	, m_cmdLine			(DE_NULL)
316e5c31af7Sopenharmony_ci	, m_app				(DE_NULL)
317e5c31af7Sopenharmony_ci{
318e5c31af7Sopenharmony_ci	// Start server.
319e5c31af7Sopenharmony_ci	m_server.start();
320e5c31af7Sopenharmony_ci}
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_citcuIOSApp_s::~tcuIOSApp_s (void)
323e5c31af7Sopenharmony_ci{
324e5c31af7Sopenharmony_ci	m_server.stop();
325e5c31af7Sopenharmony_ci	destroyTestApp();
326e5c31af7Sopenharmony_ci}
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_civoid tcuIOSApp::createTestApp (void)
329e5c31af7Sopenharmony_ci{
330e5c31af7Sopenharmony_ci	DE_ASSERT(!m_app && !m_log && !m_cmdLine && !m_platform);
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	try
333e5c31af7Sopenharmony_ci	{
334e5c31af7Sopenharmony_ci		m_log		= new tcu::TestLog(m_testProcess.getLogFileName());
335e5c31af7Sopenharmony_ci		m_cmdLine	= new tcu::CommandLine(m_state.getCommandLine());
336e5c31af7Sopenharmony_ci		m_app		= new tcu::App(m_platform, m_archive, *m_log, *m_cmdLine);
337e5c31af7Sopenharmony_ci	}
338e5c31af7Sopenharmony_ci	catch (const std::exception& e)
339e5c31af7Sopenharmony_ci	{
340e5c31af7Sopenharmony_ci		destroyTestApp();
341e5c31af7Sopenharmony_ci		tcu::die("%s", e.what());
342e5c31af7Sopenharmony_ci	}
343e5c31af7Sopenharmony_ci}
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_civoid tcuIOSApp::destroyTestApp (void)
346e5c31af7Sopenharmony_ci{
347e5c31af7Sopenharmony_ci	delete m_app;
348e5c31af7Sopenharmony_ci	delete m_cmdLine;
349e5c31af7Sopenharmony_ci	delete m_log;
350e5c31af7Sopenharmony_ci	m_app		= DE_NULL;
351e5c31af7Sopenharmony_ci	m_cmdLine	= DE_NULL;
352e5c31af7Sopenharmony_ci	m_log		= DE_NULL;
353e5c31af7Sopenharmony_ci}
354e5c31af7Sopenharmony_ci
355e5c31af7Sopenharmony_civoid tcuIOSApp::iterate (void)
356e5c31af7Sopenharmony_ci{
357e5c31af7Sopenharmony_ci	TestThreadState::State curState = m_state.getState();
358e5c31af7Sopenharmony_ci
359e5c31af7Sopenharmony_ci	if (curState == TestThreadState::STATE_RUNNING)
360e5c31af7Sopenharmony_ci	{
361e5c31af7Sopenharmony_ci		if (!m_app)
362e5c31af7Sopenharmony_ci			createTestApp();
363e5c31af7Sopenharmony_ci
364e5c31af7Sopenharmony_ci		TCU_CHECK(m_app);
365e5c31af7Sopenharmony_ci
366e5c31af7Sopenharmony_ci		if (!m_app->iterate())
367e5c31af7Sopenharmony_ci		{
368e5c31af7Sopenharmony_ci			destroyTestApp();
369e5c31af7Sopenharmony_ci			m_state.testExecFinished();
370e5c31af7Sopenharmony_ci		}
371e5c31af7Sopenharmony_ci	}
372e5c31af7Sopenharmony_ci	else if (curState == TestThreadState::STATE_STOP_REQUESTED)
373e5c31af7Sopenharmony_ci	{
374e5c31af7Sopenharmony_ci		destroyTestApp();
375e5c31af7Sopenharmony_ci		m_state.testExecFinished();
376e5c31af7Sopenharmony_ci	}
377e5c31af7Sopenharmony_ci	// else wait until state has changed?
378e5c31af7Sopenharmony_ci}
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_citcuIOSApp* tcuIOSApp_create (void* view)
381e5c31af7Sopenharmony_ci{
382e5c31af7Sopenharmony_ci	try
383e5c31af7Sopenharmony_ci	{
384e5c31af7Sopenharmony_ci		return new tcuIOSApp(view);
385e5c31af7Sopenharmony_ci	}
386e5c31af7Sopenharmony_ci	catch (const std::exception& e)
387e5c31af7Sopenharmony_ci	{
388e5c31af7Sopenharmony_ci		tcu::die("FATAL ERROR: %s", e.what());
389e5c31af7Sopenharmony_ci		return DE_NULL;
390e5c31af7Sopenharmony_ci	}
391e5c31af7Sopenharmony_ci}
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_civoid tcuIOSApp_destroy (tcuIOSApp* app)
394e5c31af7Sopenharmony_ci{
395e5c31af7Sopenharmony_ci	delete app;
396e5c31af7Sopenharmony_ci}
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_cideBool tcuIOSApp_iterate (tcuIOSApp* app)
399e5c31af7Sopenharmony_ci{
400e5c31af7Sopenharmony_ci	try
401e5c31af7Sopenharmony_ci	{
402e5c31af7Sopenharmony_ci		app->iterate();
403e5c31af7Sopenharmony_ci		return DE_TRUE;
404e5c31af7Sopenharmony_ci	}
405e5c31af7Sopenharmony_ci	catch (const std::exception& e)
406e5c31af7Sopenharmony_ci	{
407e5c31af7Sopenharmony_ci		tcu::print("FATAL ERROR: %s\n", e.what());
408e5c31af7Sopenharmony_ci		return DE_FALSE;
409e5c31af7Sopenharmony_ci	}
410e5c31af7Sopenharmony_ci}
411