1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief Command line parsing.
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuCommandLine.hpp"
25 #include "tcuPlatform.hpp"
26 #include "deFilePath.hpp"
27 #include "deStringUtil.hpp"
28 #include "deString.h"
29 #include "deInt32.h"
30 #include "deCommandLine.h"
31 #include "qpTestLog.h"
32 #include "qpDebugOut.h"
33
34 #include <string>
35 #include <vector>
36 #include <sstream>
37 #include <fstream>
38 #include <iostream>
39
40 using std::string;
41 using std::vector;
42
43 // OOM tests are enabled by default only on platforms that don't do memory overcommit (Win32)
44 #if (DE_OS == DE_OS_WIN32)
45 # define TEST_OOM_DEFAULT "enable"
46 #else
47 # define TEST_OOM_DEFAULT "disable"
48 #endif
49
50 namespace tcu
51 {
52
53 namespace opt
54 {
55
56 DE_DECLARE_COMMAND_LINE_OPT(CasePath, std::string);
57 DE_DECLARE_COMMAND_LINE_OPT(CaseList, std::string);
58 DE_DECLARE_COMMAND_LINE_OPT(CaseListFile, std::string);
59 DE_DECLARE_COMMAND_LINE_OPT(StdinCaseList, bool);
60 DE_DECLARE_COMMAND_LINE_OPT(LogFilename, std::string);
61 DE_DECLARE_COMMAND_LINE_OPT(RunMode, tcu::RunMode);
62 DE_DECLARE_COMMAND_LINE_OPT(WatchDog, bool);
63 DE_DECLARE_COMMAND_LINE_OPT(CrashHandler, bool);
64 DE_DECLARE_COMMAND_LINE_OPT(BaseSeed, int);
65 DE_DECLARE_COMMAND_LINE_OPT(TestIterationCount, int);
66 DE_DECLARE_COMMAND_LINE_OPT(Visibility, WindowVisibility);
67 DE_DECLARE_COMMAND_LINE_OPT(SurfaceWidth, int);
68 DE_DECLARE_COMMAND_LINE_OPT(SurfaceHeight, int);
69 DE_DECLARE_COMMAND_LINE_OPT(SurfaceType, tcu::SurfaceType);
70 DE_DECLARE_COMMAND_LINE_OPT(ScreenRotation, tcu::ScreenRotation);
71 DE_DECLARE_COMMAND_LINE_OPT(GLContextType, std::string);
72 DE_DECLARE_COMMAND_LINE_OPT(GLConfigID, int);
73 DE_DECLARE_COMMAND_LINE_OPT(GLConfigName, std::string);
74 DE_DECLARE_COMMAND_LINE_OPT(GLContextFlags, std::string);
75 DE_DECLARE_COMMAND_LINE_OPT(CLPlatformID, int);
76 DE_DECLARE_COMMAND_LINE_OPT(CLDeviceIDs, std::vector<int>);
77 DE_DECLARE_COMMAND_LINE_OPT(CLBuildOptions, std::string);
78 DE_DECLARE_COMMAND_LINE_OPT(EGLDisplayType, std::string);
79 DE_DECLARE_COMMAND_LINE_OPT(EGLWindowType, std::string);
80 DE_DECLARE_COMMAND_LINE_OPT(EGLPixmapType, std::string);
81 DE_DECLARE_COMMAND_LINE_OPT(LogImages, bool);
82 DE_DECLARE_COMMAND_LINE_OPT(TestOOM, bool);
83
parseIntList(const char * src,std::vector<int> * dst)84 static void parseIntList (const char* src, std::vector<int>* dst)
85 {
86 std::istringstream str (src);
87 std::string val;
88
89 while (std::getline(str, val, ','))
90 {
91 int intVal = 0;
92 de::cmdline::parseType(val.c_str(), &intVal);
93 dst->push_back(intVal);
94 }
95 }
96
registerOptions(de::cmdline::Parser & parser)97 void registerOptions (de::cmdline::Parser& parser)
98 {
99 using de::cmdline::Option;
100 using de::cmdline::NamedValue;
101
102 static const NamedValue<bool> s_enableNames[] =
103 {
104 { "enable", true },
105 { "disable", false }
106 };
107 static const NamedValue<tcu::RunMode> s_runModes[] =
108 {
109 { "execute", RUNMODE_EXECUTE },
110 { "xml-caselist", RUNMODE_DUMP_XML_CASELIST },
111 { "txt-caselist", RUNMODE_DUMP_TEXT_CASELIST }
112 };
113 static const NamedValue<WindowVisibility> s_visibilites[] =
114 {
115 { "windowed", WINDOWVISIBILITY_WINDOWED },
116 { "fullscreen", WINDOWVISIBILITY_FULLSCREEN },
117 { "hidden", WINDOWVISIBILITY_HIDDEN }
118 };
119 static const NamedValue<tcu::SurfaceType> s_surfaceTypes[] =
120 {
121 { "window", SURFACETYPE_WINDOW },
122 { "pixmap", SURFACETYPE_OFFSCREEN_NATIVE },
123 { "pbuffer", SURFACETYPE_OFFSCREEN_GENERIC },
124 { "fbo", SURFACETYPE_FBO }
125 };
126 static const NamedValue<tcu::ScreenRotation> s_screenRotations[] =
127 {
128 { "0", SCREENROTATION_0 },
129 { "90", SCREENROTATION_90 },
130 { "180", SCREENROTATION_180 },
131 { "270", SCREENROTATION_270 }
132 };
133
134 parser
135 << Option<CasePath> ("n", "deqp-case", "Test case(s) to run, supports wildcards (e.g. dEQP-GLES2.info.*)")
136 << Option<CaseList> (DE_NULL, "deqp-caselist", "Case list to run in trie format (e.g. {dEQP-GLES2{info{version,renderer}}})")
137 << Option<CaseListFile> (DE_NULL, "deqp-caselist-file", "Read case list (in trie format) from given file")
138 << Option<StdinCaseList> (DE_NULL, "deqp-stdin-caselist", "Read case list (in trie format) from stdin")
139 << Option<LogFilename> (DE_NULL, "deqp-log-filename", "Write test results to given file", "TestResults.qpa")
140 << Option<RunMode> (DE_NULL, "deqp-runmode", "Execute tests, or write list of test cases into a file",
141 s_runModes, "execute")
142 << Option<WatchDog> (DE_NULL, "deqp-watchdog", "Enable test watchdog", s_enableNames, "disable")
143 << Option<CrashHandler> (DE_NULL, "deqp-crashhandler", "Enable crash handling", s_enableNames, "disable")
144 << Option<BaseSeed> (DE_NULL, "deqp-base-seed", "Base seed for test cases that use randomization")
145 << Option<TestIterationCount> (DE_NULL, "deqp-test-iteration-count", "Iteration count for cases that support variable number of iterations")
146 << Option<Visibility> (DE_NULL, "deqp-visibility", "Default test window visibility", s_visibilites, "windowed")
147 << Option<SurfaceWidth> (DE_NULL, "deqp-surface-width", "Use given surface width if possible", "-1")
148 << Option<SurfaceHeight> (DE_NULL, "deqp-surface-height", "Use given surface height if possible", "-1")
149 << Option<SurfaceType> (DE_NULL, "deqp-surface-type", "Use given surface type", s_surfaceTypes, "window")
150 << Option<ScreenRotation> (DE_NULL, "deqp-screen-rotation", "Screen rotation for platforms that support it", s_screenRotations, "0")
151 << Option<GLContextType> (DE_NULL, "deqp-gl-context-type", "OpenGL context type for platforms that support multiple")
152 << Option<GLConfigID> (DE_NULL, "deqp-gl-config-id", "OpenGL (ES) render config ID (EGL config id on EGL platforms)", "-1")
153 << Option<GLConfigName> (DE_NULL, "deqp-gl-config-name", "Symbolic OpenGL (ES) render config name")
154 << Option<GLContextFlags> (DE_NULL, "deqp-gl-context-flags", "OpenGL context flags (comma-separated, supports debug and robust)")
155 << Option<CLPlatformID> (DE_NULL, "deqp-cl-platform-id", "Execute tests on given OpenCL platform (IDs start from 1)", "1")
156 << Option<CLDeviceIDs> (DE_NULL, "deqp-cl-device-ids", "Execute tests on given CL devices (comma-separated, IDs start from 1)", parseIntList)
157 << Option<CLBuildOptions> (DE_NULL, "deqp-cl-build-options", "Extra build options for OpenCL compiler")
158 << Option<EGLDisplayType> (DE_NULL, "deqp-egl-display-type", "EGL native display type")
159 << Option<EGLWindowType> (DE_NULL, "deqp-egl-window-type", "EGL native window type")
160 << Option<EGLPixmapType> (DE_NULL, "deqp-egl-pixmap-type", "EGL native pixmap type")
161 << Option<LogImages> (DE_NULL, "deqp-log-images", "Enable or disable logging of result images", s_enableNames, "enable")
162 << Option<TestOOM> (DE_NULL, "deqp-test-oom", "Run tests that exhaust memory on purpose", s_enableNames, TEST_OOM_DEFAULT);
163 }
164
registerLegacyOptions(de::cmdline::Parser & parser)165 void registerLegacyOptions (de::cmdline::Parser& parser)
166 {
167 using de::cmdline::Option;
168
169 parser
170 << Option<GLConfigID> (DE_NULL, "deqp-egl-config-id", "Legacy name for --deqp-gl-config-id", "-1")
171 << Option<GLConfigName> (DE_NULL, "deqp-egl-config-name", "Legacy name for --deqp-gl-config-name");
172 }
173
174 } // opt
175
176 // \todo [2014-02-13 pyry] This could be useful elsewhere as well.
177 class DebugOutStreambuf : public std::streambuf
178 {
179 public:
180 DebugOutStreambuf (void);
181 ~DebugOutStreambuf (void);
182
183 protected:
184 std::streamsize xsputn (const char* s, std::streamsize count);
185 int overflow (int ch = -1);
186
187 private:
188 void flushLine (void);
189
190 std::ostringstream m_curLine;
191 };
192
DebugOutStreambuf(void)193 DebugOutStreambuf::DebugOutStreambuf (void)
194 {
195 }
196
~DebugOutStreambuf(void)197 DebugOutStreambuf::~DebugOutStreambuf (void)
198 {
199 if (m_curLine.tellp() != std::streampos(0))
200 flushLine();
201 }
202
xsputn(const char * s,std::streamsize count)203 std::streamsize DebugOutStreambuf::xsputn (const char* s, std::streamsize count)
204 {
205 for (std::streamsize pos = 0; pos < count; pos++)
206 {
207 m_curLine.put(s[pos]);
208
209 if (s[pos] == '\n')
210 flushLine();
211 }
212
213 return count;
214 }
215
overflow(int ch)216 int DebugOutStreambuf::overflow (int ch)
217 {
218 if (ch == -1)
219 return -1;
220 else
221 {
222 DE_ASSERT((ch & 0xff) == ch);
223 const char chVal = (char)(deUint8)(ch & 0xff);
224 return xsputn(&chVal, 1) == 1 ? ch : -1;
225 }
226 }
227
flushLine(void)228 void DebugOutStreambuf::flushLine (void)
229 {
230 qpPrint(m_curLine.str().c_str());
231 m_curLine.str("");
232 }
233
234 class CaseTreeNode
235 {
236 public:
CaseTreeNode(const std::string & name)237 CaseTreeNode (const std::string& name) : m_name(name) {}
238 ~CaseTreeNode (void);
239
addChild(CaseTreeNode * child)240 void addChild (CaseTreeNode* child) { m_children.push_back(child); }
241
getName(void) const242 const std::string& getName (void) const { return m_name; }
getChildren(void) const243 const std::vector<CaseTreeNode*>& getChildren (void) const { return m_children; }
244
245 private:
246 CaseTreeNode (const CaseTreeNode&);
247 CaseTreeNode& operator= (const CaseTreeNode&);
248
249 std::string m_name;
250 std::vector<CaseTreeNode*> m_children;
251 };
252
~CaseTreeNode(void)253 CaseTreeNode::~CaseTreeNode (void)
254 {
255 for (vector<CaseTreeNode*>::const_iterator i = m_children.begin(); i != m_children.end(); ++i)
256 delete *i;
257 }
258
parseCaseTree(std::istream & in)259 static CaseTreeNode* parseCaseTree (std::istream& in)
260 {
261 vector<CaseTreeNode*> nodeStack;
262 string curName;
263
264 if (in.get() != '{')
265 throw std::invalid_argument("Malformed case tree");
266
267 nodeStack.reserve(1);
268 nodeStack.push_back(new CaseTreeNode(""));
269
270 try
271 {
272 for (;;)
273 {
274 const int curChr = in.get();
275
276 if (curChr == std::char_traits<char>::eof() || curChr == 0)
277 break;
278
279 if (nodeStack.empty())
280 throw std::invalid_argument("Trailing characters at end of case tree");
281
282 if (!curName.empty() && (curChr == '{' || curChr == ',' || curChr == '}'))
283 {
284 // Create child and push to stack.
285 nodeStack.reserve(nodeStack.size()+1);
286 nodeStack.push_back(new CaseTreeNode(curName));
287
288 curName.clear();
289 }
290
291 if (curChr == ',' || curChr == '}')
292 {
293 // Attach to parent
294 if (nodeStack.size() < 2)
295 throw std::invalid_argument("Malformed case tree");
296
297 (*(nodeStack.end()-2))->addChild(nodeStack.back());
298 nodeStack.pop_back();
299 }
300 else if (curChr != '{')
301 curName += (char)curChr;
302 }
303
304 if (nodeStack.size() != 1 || nodeStack[0]->getName() != "")
305 throw std::invalid_argument("Unterminated case tree");
306 }
307 catch (...)
308 {
309 // Nodes in stack are not attached to any parents and must be deleted individually.
310 for (vector<CaseTreeNode*>::const_iterator i = nodeStack.begin(); i != nodeStack.end(); ++i)
311 delete *i;
312
313 throw;
314 }
315
316 return nodeStack[0];
317 }
318
319 class CasePaths
320 {
321 public:
322 CasePaths (const string& pathList);
323 bool matches (const string& caseName, bool allowPrefix=false) const;
324
325 private:
326 const vector<string> m_casePatterns;
327 };
328
CasePaths(const string & pathList)329 CasePaths::CasePaths (const string& pathList)
330 : m_casePatterns(de::splitString(pathList, ','))
331 {
332 }
333
334 // Match a single path component against a pattern component that may contain *-wildcards.
matchWildcards(string::const_iterator patternStart,string::const_iterator patternEnd,string::const_iterator pathStart,string::const_iterator pathEnd,bool allowPrefix)335 static bool matchWildcards(string::const_iterator patternStart,
336 string::const_iterator patternEnd,
337 string::const_iterator pathStart,
338 string::const_iterator pathEnd,
339 bool allowPrefix)
340 {
341 string::const_iterator pattern = patternStart;
342 string::const_iterator path = pathStart;
343
344 while (pattern != patternEnd && path != pathEnd && *pattern == *path)
345 {
346 ++pattern;
347 ++path;
348 }
349
350 if (pattern == patternEnd)
351 return (path == pathEnd);
352 else if (*pattern == '*')
353 {
354 for (; path != pathEnd; ++path)
355 {
356 if (matchWildcards(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
357 return true;
358 }
359
360 if (matchWildcards(pattern + 1, patternEnd, pathEnd, pathEnd, allowPrefix))
361 return true;
362 }
363 else if (path == pathEnd && allowPrefix)
364 return true;
365
366 return false;
367 }
368
369 #if defined(TCU_HIERARCHICAL_CASEPATHS)
370 // Match a list of pattern components to a list of path components. A pattern
371 // component may contain *-wildcards. A pattern component "**" matches zero or
372 // more whole path components.
patternMatches(vector<string>::const_iterator patternStart,vector<string>::const_iterator patternEnd,vector<string>::const_iterator pathStart,vector<string>::const_iterator pathEnd,bool allowPrefix)373 static bool patternMatches(vector<string>::const_iterator patternStart,
374 vector<string>::const_iterator patternEnd,
375 vector<string>::const_iterator pathStart,
376 vector<string>::const_iterator pathEnd,
377 bool allowPrefix)
378 {
379 vector<string>::const_iterator pattern = patternStart;
380 vector<string>::const_iterator path = pathStart;
381
382 while (pattern != patternEnd && path != pathEnd && *pattern != "**" &&
383 (*pattern == *path || matchWildcards(pattern->begin(), pattern->end(),
384 path->begin(), path->end(), false)))
385 {
386 ++pattern;
387 ++path;
388 }
389
390 if (path == pathEnd && (allowPrefix || pattern == patternEnd))
391 return true;
392 else if (pattern != patternEnd && *pattern == "**")
393 {
394 for (; path != pathEnd; ++path)
395 if (patternMatches(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
396 return true;
397 if (patternMatches(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
398 return true;
399 }
400
401 return false;
402 }
403 #endif
404
matches(const string & caseName,bool allowPrefix) const405 bool CasePaths::matches (const string& caseName, bool allowPrefix) const
406 {
407 const vector<string> components = de::splitString(caseName, '.');
408
409 for (size_t ndx = 0; ndx < m_casePatterns.size(); ++ndx)
410 {
411 #if defined(TCU_HIERARCHICAL_CASEPATHS)
412 const vector<string> patternComponents = de::splitString(m_casePatterns[ndx], '.');
413
414 if (patternMatches(patternComponents.begin(), patternComponents.end(),
415 components.begin(), components.end(), allowPrefix))
416 return true;
417 #else
418 if (matchWildcards(m_casePatterns[ndx].begin(), m_casePatterns[ndx].end(),
419 caseName.begin(), caseName.end(), allowPrefix))
420 return true;
421 #endif
422 }
423
424 return false;
425 }
426
427 /*--------------------------------------------------------------------*//*!
428 * \brief Construct command line
429 * \note CommandLine is not fully initialized until parse() has been called.
430 *//*--------------------------------------------------------------------*/
CommandLine(void)431 CommandLine::CommandLine (void)
432 : m_logFlags (0)
433 , m_caseTree (DE_NULL)
434 {
435 }
436
437 /*--------------------------------------------------------------------*//*!
438 * \brief Construct command line from standard argc, argv pair.
439 *
440 * Calls parse() with given arguments
441 * \param argc Number of arguments
442 * \param argv Command line arguments
443 *//*--------------------------------------------------------------------*/
CommandLine(int argc,const char * const * argv)444 CommandLine::CommandLine (int argc, const char* const* argv)
445 : m_logFlags (0)
446 , m_caseTree (DE_NULL)
447 {
448 if (!parse(argc, argv))
449 throw Exception("Failed to parse command line");
450 }
451
452 /*--------------------------------------------------------------------*//*!
453 * \brief Construct command line from string.
454 *
455 * Calls parse() with given argument.
456 * \param cmdLine Full command line string.
457 *//*--------------------------------------------------------------------*/
CommandLine(const std::string & cmdLine)458 CommandLine::CommandLine (const std::string& cmdLine)
459 : m_logFlags (0)
460 , m_caseTree (DE_NULL)
461 {
462 if (!parse(cmdLine))
463 throw Exception("Failed to parse command line");
464 }
465
~CommandLine(void)466 CommandLine::~CommandLine (void)
467 {
468 delete m_caseTree;
469 }
470
clear(void)471 void CommandLine::clear (void)
472 {
473 m_cmdLine.clear();
474 m_logFlags = 0;
475
476 delete m_caseTree;
477 m_caseTree = DE_NULL;
478 }
479
480 /*--------------------------------------------------------------------*//*!
481 * \brief Parse command line from standard argc, argv pair.
482 * \note parse() must be called exactly once.
483 * \param argc Number of arguments
484 * \param argv Command line arguments
485 *//*--------------------------------------------------------------------*/
parse(int argc,const char * const * argv)486 bool CommandLine::parse (int argc, const char* const* argv)
487 {
488 DebugOutStreambuf sbuf;
489 std::ostream debugOut (&sbuf);
490 de::cmdline::Parser parser;
491
492 opt::registerOptions(parser);
493 opt::registerLegacyOptions(parser);
494
495 clear();
496
497 if (!parser.parse(argc-1, argv+1, &m_cmdLine, std::cerr))
498 {
499 debugOut << "\n" << de::FilePath(argv[0]).getBaseName() << " [options]\n\n";
500 parser.help(debugOut);
501
502 clear();
503 return false;
504 }
505
506 if (!m_cmdLine.getOption<opt::LogImages>())
507 m_logFlags |= QP_TEST_LOG_EXCLUDE_IMAGES;
508
509 if ((m_cmdLine.getOption<opt::CasePath>().empty()?0:1) +
510 (m_cmdLine.getOption<opt::CaseList>().empty()?0:1) +
511 (m_cmdLine.getOption<opt::CaseListFile>().empty()?0:1) +
512 (m_cmdLine.getOption<opt::StdinCaseList>()?1:0) > 1)
513 {
514 debugOut << "ERROR: multiple test case list options given!\n" << std::endl;
515 clear();
516 return false;
517 }
518
519 try
520 {
521 if (!m_cmdLine.getOption<opt::CaseList>().empty())
522 {
523 std::istringstream str(m_cmdLine.getOption<opt::CaseList>());
524
525 m_caseTree = parseCaseTree(str);
526 }
527 else if (!m_cmdLine.getOption<opt::CaseListFile>().empty())
528 {
529 std::ifstream in(m_cmdLine.getOption<opt::CaseListFile>().c_str(), std::ios_base::binary);
530
531 if (!in.is_open() || !in.good())
532 throw Exception("Failed to open case list file '" + m_cmdLine.getOption<opt::CaseListFile>() + "'");
533
534 m_caseTree = parseCaseTree(in);
535 }
536 else if (m_cmdLine.getOption<opt::StdinCaseList>())
537 {
538 m_caseTree = parseCaseTree(std::cin);
539 }
540 else if (!m_cmdLine.getOption<opt::CasePath>().empty())
541 m_casePaths = de::MovePtr<const CasePaths>(new CasePaths(m_cmdLine.getOption<opt::CasePath>()));
542 }
543 catch (const std::exception& e)
544 {
545 debugOut << "ERROR: Failed to parse test case list: " << e.what() << "\n";
546 clear();
547 return false;
548 }
549
550 return true;
551 }
552
553 /*--------------------------------------------------------------------*//*!
554 * \brief Parse command line from string.
555 * \note parse() must be called exactly once.
556 * \param cmdLine Full command line string.
557 *//*--------------------------------------------------------------------*/
parse(const std::string & cmdLine)558 bool CommandLine::parse (const std::string& cmdLine)
559 {
560 deCommandLine* parsedCmdLine = deCommandLine_parse(cmdLine.c_str());
561 if (!parsedCmdLine)
562 throw std::bad_alloc();
563
564 bool isOk = false;
565 try
566 {
567 isOk = parse(parsedCmdLine->numArgs, parsedCmdLine->args);
568 }
569 catch (...)
570 {
571 deCommandLine_destroy(parsedCmdLine);
572 throw;
573 }
574
575 deCommandLine_destroy(parsedCmdLine);
576 return isOk;
577 }
578
getLogFileName(void) const579 const char* CommandLine::getLogFileName (void) const { return m_cmdLine.getOption<opt::LogFilename>().c_str(); }
getLogFlags(void) const580 deUint32 CommandLine::getLogFlags (void) const { return m_logFlags; }
getRunMode(void) const581 RunMode CommandLine::getRunMode (void) const { return m_cmdLine.getOption<opt::RunMode>(); }
getVisibility(void) const582 WindowVisibility CommandLine::getVisibility (void) const { return m_cmdLine.getOption<opt::Visibility>(); }
isWatchDogEnabled(void) const583 bool CommandLine::isWatchDogEnabled (void) const { return m_cmdLine.getOption<opt::WatchDog>(); }
isCrashHandlingEnabled(void) const584 bool CommandLine::isCrashHandlingEnabled (void) const { return m_cmdLine.getOption<opt::CrashHandler>(); }
getBaseSeed(void) const585 int CommandLine::getBaseSeed (void) const { return m_cmdLine.getOption<opt::BaseSeed>(); }
getTestIterationCount(void) const586 int CommandLine::getTestIterationCount (void) const { return m_cmdLine.getOption<opt::TestIterationCount>(); }
getSurfaceWidth(void) const587 int CommandLine::getSurfaceWidth (void) const { return m_cmdLine.getOption<opt::SurfaceWidth>(); }
getSurfaceHeight(void) const588 int CommandLine::getSurfaceHeight (void) const { return m_cmdLine.getOption<opt::SurfaceHeight>(); }
getSurfaceType(void) const589 SurfaceType CommandLine::getSurfaceType (void) const { return m_cmdLine.getOption<opt::SurfaceType>(); }
getScreenRotation(void) const590 ScreenRotation CommandLine::getScreenRotation (void) const { return m_cmdLine.getOption<opt::ScreenRotation>(); }
getGLConfigId(void) const591 int CommandLine::getGLConfigId (void) const { return m_cmdLine.getOption<opt::GLConfigID>(); }
getCLPlatformId(void) const592 int CommandLine::getCLPlatformId (void) const { return m_cmdLine.getOption<opt::CLPlatformID>(); }
getCLDeviceIds(void) const593 const std::vector<int>& CommandLine::getCLDeviceIds (void) const { return m_cmdLine.getOption<opt::CLDeviceIDs>(); }
getEGLDisplayType(void) const594 const char* CommandLine::getEGLDisplayType (void) const { return m_cmdLine.getOption<opt::EGLDisplayType>().c_str(); }
getEGLWindowType(void) const595 const char* CommandLine::getEGLWindowType (void) const { return m_cmdLine.getOption<opt::EGLWindowType>().c_str(); }
getEGLPixmapType(void) const596 const char* CommandLine::getEGLPixmapType (void) const { return m_cmdLine.getOption<opt::EGLPixmapType>().c_str(); }
isOutOfMemoryTestEnabled(void) const597 bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption<opt::TestOOM>(); }
598
getGLContextType(void) const599 const char* CommandLine::getGLContextType (void) const
600 {
601 if (!m_cmdLine.getOption<opt::GLContextType>().empty())
602 return m_cmdLine.getOption<opt::GLContextType>().c_str();
603 else
604 return DE_NULL;
605 }
getGLConfigName(void) const606 const char* CommandLine::getGLConfigName (void) const
607 {
608 if (!m_cmdLine.getOption<opt::GLConfigName>().empty())
609 return m_cmdLine.getOption<opt::GLConfigName>().c_str();
610 else
611 return DE_NULL;
612 }
613
getGLContextFlags(void) const614 const char* CommandLine::getGLContextFlags (void) const
615 {
616 if (!m_cmdLine.getOption<opt::GLContextFlags>().empty())
617 return m_cmdLine.getOption<opt::GLContextFlags>().c_str();
618 else
619 return DE_NULL;
620 }
621
getCLBuildOptions(void) const622 const char* CommandLine::getCLBuildOptions (void) const
623 {
624 if (!m_cmdLine.getOption<opt::CLBuildOptions>().empty())
625 return m_cmdLine.getOption<opt::CLBuildOptions>().c_str();
626 else
627 return DE_NULL;
628 }
629
checkTestGroupName(const CaseTreeNode * node,const char * groupName)630 static bool checkTestGroupName (const CaseTreeNode* node, const char* groupName)
631 {
632 for (vector<CaseTreeNode*>::const_iterator childIter = node->getChildren().begin(); childIter != node->getChildren().end(); ++childIter)
633 {
634 const CaseTreeNode* const child = *childIter;
635
636 if (deStringBeginsWith(groupName, child->getName().c_str()))
637 {
638 const int prefixLen = (int)child->getName().length();
639
640 if (groupName[prefixLen] == 0)
641 return true;
642 else if (groupName[prefixLen] == '.')
643 return checkTestGroupName(child, groupName + prefixLen + 1);
644 }
645 }
646
647 return false;
648 }
649
checkTestCaseName(const CaseTreeNode * node,const char * caseName)650 static bool checkTestCaseName (const CaseTreeNode* node, const char* caseName)
651 {
652 for (vector<CaseTreeNode*>::const_iterator childIter = node->getChildren().begin(); childIter != node->getChildren().end(); ++childIter)
653 {
654 const CaseTreeNode* const child = *childIter;
655
656 if (deStringBeginsWith(caseName, child->getName().c_str()))
657 {
658 const int prefixLen = (int)child->getName().length();
659
660 if (caseName[prefixLen] == 0 && child->getChildren().empty())
661 return true;
662 else if (caseName[prefixLen] == '.')
663 return checkTestCaseName(child, caseName + prefixLen + 1);
664 }
665 }
666
667 return false;
668 }
669
checkTestGroupName(const char * groupName) const670 bool CommandLine::checkTestGroupName (const char* groupName) const
671 {
672 if (m_casePaths)
673 return m_casePaths->matches(groupName, true);
674 else if (m_caseTree)
675 return groupName[0] == 0 || tcu::checkTestGroupName(m_caseTree, groupName);
676 else
677 return true;
678 }
679
checkTestCaseName(const char * caseName) const680 bool CommandLine::checkTestCaseName (const char* caseName) const
681 {
682 if (m_casePaths)
683 return m_casePaths->matches(caseName, false);
684 else if (m_caseTree)
685 return tcu::checkTestCaseName(m_caseTree, caseName);
686 else
687 return true;
688 }
689
690 } // tcu
691