1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief iOS App Wrapper.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuIOSApp.h"
25 #include "tcuIOSPlatform.hh"
27 #include "tcuCommandLine.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuResource.hpp"
31 #include "deThread.hpp"
32 #include "deMutex.hpp"
33 #include "xsExecutionServer.hpp"
34 #include "xsTestProcess.hpp"
35 #include "xsPosixFileReader.hpp"
36 #include "deFilePath.hpp"
42 #import <Foundation/NSObject.h>
43 #import <Foundation/NSString.h>
44 #import <Foundation/NSBundle.h>
45 #import <Foundation/NSPathUtilities.h>
57 STATE_NOT_RUNNING = 0,
64 TestThreadState (void);
65 ~TestThreadState (void);
67 void requestStart (const char* cmdLine);
68 void requestStop (void);
69 State getState (void);
71 void testExecFinished (void);
73 const char* getCommandLine (void) const { return m_cmdLine.c_str(); }
79 std::string m_cmdLine;
82 TestThreadState::TestThreadState (void)
83 : m_state(STATE_NOT_RUNNING)
87 TestThreadState::~TestThreadState (void)
91 void TestThreadState::requestStart (const char* cmdLine)
93 de::ScopedLock stateLock(m_lock);
95 TCU_CHECK(m_state == STATE_NOT_RUNNING);
98 m_state = STATE_RUNNING;
101 void TestThreadState::requestStop (void)
103 de::ScopedLock stateLock(m_lock);
105 if (m_state != STATE_NOT_RUNNING)
106 m_state = STATE_STOP_REQUESTED;
109 void TestThreadState::testExecFinished (void)
111 de::ScopedLock stateLock(m_lock);
112 m_state = STATE_NOT_RUNNING;
115 TestThreadState::State TestThreadState::getState (void)
117 de::ScopedLock stateLock(m_lock);
121 class LocalTestProcess : public xs::TestProcess
124 LocalTestProcess (TestThreadState& state, const char* logFileName);
125 ~LocalTestProcess (void);
127 void start (const char* name, const char* params, const char* workingDir, const char* caseList);
128 void terminate (void);
131 bool isRunning (void);
132 int getExitCode (void) const { return 0; /* not available */ }
134 int readInfoLog (deUint8* dst, int numBytes) { DE_UNREF(dst && numBytes); return 0; /* not supported */ }
135 int readTestLog (deUint8* dst, int numBytes);
137 const char* getLogFileName (void) const { return m_logFileName.c_str(); }
140 TestThreadState& m_state;
141 string m_logFileName;
142 xs::posix::FileReader m_logReader;
143 deUint64 m_processStartTime;
146 LocalTestProcess::LocalTestProcess (TestThreadState& state, const char* logFileName)
148 , m_logFileName (logFileName)
149 , m_logReader (xs::LOG_BUFFER_BLOCK_SIZE, xs::LOG_BUFFER_NUM_BLOCKS)
150 , m_processStartTime (0)
154 LocalTestProcess::~LocalTestProcess (void)
158 void LocalTestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList)
160 DE_UNREF(name && workingDir);
162 // Delete old log file.
163 if (deFileExists(m_logFileName.c_str()))
164 TCU_CHECK(deDeleteFile(m_logFileName.c_str()));
166 string cmdLine = string("deqp");
167 if (caseList && strlen(caseList) > 0)
168 cmdLine += string(" --deqp-caselist=") + caseList;
170 if (params && strlen(params) > 0)
171 cmdLine += string(" ") + params;
173 m_state.requestStart(cmdLine.c_str());
174 m_processStartTime = deGetMicroseconds();
177 void LocalTestProcess::terminate (void)
179 m_state.requestStop();
182 void LocalTestProcess::cleanup (void)
186 m_state.requestStop();
188 // Wait until stopped.
196 bool LocalTestProcess::isRunning (void)
198 return m_state.getState() != TestThreadState::STATE_NOT_RUNNING;
201 int LocalTestProcess::readTestLog (deUint8* dst, int numBytes)
203 if (!m_logReader.isRunning())
205 if (deGetMicroseconds() - m_processStartTime > xs::LOG_FILE_TIMEOUT*1000)
207 // Timeout, kill execution.
209 return 0; // \todo [2013-08-13 pyry] Throw exception?
212 if (!deFileExists(m_logFileName.c_str()))
216 m_logReader.start(m_logFileName.c_str());
219 DE_ASSERT(m_logReader.isRunning());
220 return m_logReader.read(dst, numBytes);
223 class ServerThread : public de::Thread
226 ServerThread (xs::TestProcess* testProcess, int port);
227 ~ServerThread (void);
233 xs::ExecutionServer m_server;
237 ServerThread::ServerThread (xs::TestProcess* testProcess, int port)
238 : m_server (testProcess, DE_SOCKETFAMILY_INET4, port, xs::ExecutionServer::RUNMODE_FOREVER)
239 , m_isRunning (false)
243 ServerThread::~ServerThread (void)
248 void ServerThread::run (void)
251 m_server.runServer();
254 void ServerThread::stop (void)
258 m_server.stopServer();
264 string getAppBundleDir (void)
266 NSString* dataPath = [[NSBundle mainBundle] bundlePath];
267 const char* utf8Str = [dataPath UTF8String];
269 return string(utf8Str);
272 string getAppDocumentsDir (void)
274 NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
275 NSString* docPath = [paths objectAtIndex:0];
276 const char* utf8Str = [docPath UTF8String];
278 return string(utf8Str);
286 tcuIOSApp_s (void* view);
292 void createTestApp (void);
293 void destroyTestApp (void);
295 TestThreadState m_state;
296 LocalTestProcess m_testProcess;
297 ServerThread m_server;
299 tcu::DirArchive m_archive;
300 tcu::ios::ScreenManager m_screenManager;
301 tcu::ios::Platform m_platform;
304 tcu::CommandLine* m_cmdLine;
308 tcuIOSApp_s::tcuIOSApp_s (void* view)
309 : m_testProcess (m_state, de::FilePath::join(getAppDocumentsDir(), "TestResults.qpa").getPath())
310 , m_server (&m_testProcess, 50016)
311 , m_archive (getAppBundleDir().c_str())
312 , m_screenManager ((tcuEAGLView*)view)
313 , m_platform (&m_screenManager)
315 , m_cmdLine (DE_NULL)
322 tcuIOSApp_s::~tcuIOSApp_s (void)
328 void tcuIOSApp::createTestApp (void)
330 DE_ASSERT(!m_app && !m_log && !m_cmdLine && !m_platform);
334 m_log = new tcu::TestLog(m_testProcess.getLogFileName());
335 m_cmdLine = new tcu::CommandLine(m_state.getCommandLine());
336 m_app = new tcu::App(m_platform, m_archive, *m_log, *m_cmdLine);
338 catch (const std::exception& e)
341 tcu::die("%s", e.what());
345 void tcuIOSApp::destroyTestApp (void)
355 void tcuIOSApp::iterate (void)
357 TestThreadState::State curState = m_state.getState();
359 if (curState == TestThreadState::STATE_RUNNING)
366 if (!m_app->iterate())
369 m_state.testExecFinished();
372 else if (curState == TestThreadState::STATE_STOP_REQUESTED)
375 m_state.testExecFinished();
377 // else wait until state has changed?
380 tcuIOSApp* tcuIOSApp_create (void* view)
384 return new tcuIOSApp(view);
386 catch (const std::exception& e)
388 tcu::die("FATAL ERROR: %s", e.what());
393 void tcuIOSApp_destroy (tcuIOSApp* app)
398 deBool tcuIOSApp_iterate (tcuIOSApp* app)
405 catch (const std::exception& e)
407 tcu::print("FATAL ERROR: %s\n", e.what());