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 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 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 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 193 DebugOutStreambuf::DebugOutStreambuf (void) 194 { 195 } 196 197 DebugOutStreambuf::~DebugOutStreambuf (void) 198 { 199 if (m_curLine.tellp() != std::streampos(0)) 200 flushLine(); 201 } 202 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 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 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: 237 CaseTreeNode (const std::string& name) : m_name(name) {} 238 ~CaseTreeNode (void); 239 240 void addChild (CaseTreeNode* child) { m_children.push_back(child); } 241 242 const std::string& getName (void) const { return m_name; } 243 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 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 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 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. 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. 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 405 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 *//*--------------------------------------------------------------------*/ 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 *//*--------------------------------------------------------------------*/ 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 *//*--------------------------------------------------------------------*/ 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 466 CommandLine::~CommandLine (void) 467 { 468 delete m_caseTree; 469 } 470 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 *//*--------------------------------------------------------------------*/ 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 *//*--------------------------------------------------------------------*/ 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 579 const char* CommandLine::getLogFileName (void) const { return m_cmdLine.getOption<opt::LogFilename>().c_str(); } 580 deUint32 CommandLine::getLogFlags (void) const { return m_logFlags; } 581 RunMode CommandLine::getRunMode (void) const { return m_cmdLine.getOption<opt::RunMode>(); } 582 WindowVisibility CommandLine::getVisibility (void) const { return m_cmdLine.getOption<opt::Visibility>(); } 583 bool CommandLine::isWatchDogEnabled (void) const { return m_cmdLine.getOption<opt::WatchDog>(); } 584 bool CommandLine::isCrashHandlingEnabled (void) const { return m_cmdLine.getOption<opt::CrashHandler>(); } 585 int CommandLine::getBaseSeed (void) const { return m_cmdLine.getOption<opt::BaseSeed>(); } 586 int CommandLine::getTestIterationCount (void) const { return m_cmdLine.getOption<opt::TestIterationCount>(); } 587 int CommandLine::getSurfaceWidth (void) const { return m_cmdLine.getOption<opt::SurfaceWidth>(); } 588 int CommandLine::getSurfaceHeight (void) const { return m_cmdLine.getOption<opt::SurfaceHeight>(); } 589 SurfaceType CommandLine::getSurfaceType (void) const { return m_cmdLine.getOption<opt::SurfaceType>(); } 590 ScreenRotation CommandLine::getScreenRotation (void) const { return m_cmdLine.getOption<opt::ScreenRotation>(); } 591 int CommandLine::getGLConfigId (void) const { return m_cmdLine.getOption<opt::GLConfigID>(); } 592 int CommandLine::getCLPlatformId (void) const { return m_cmdLine.getOption<opt::CLPlatformID>(); } 593 const std::vector<int>& CommandLine::getCLDeviceIds (void) const { return m_cmdLine.getOption<opt::CLDeviceIDs>(); } 594 const char* CommandLine::getEGLDisplayType (void) const { return m_cmdLine.getOption<opt::EGLDisplayType>().c_str(); } 595 const char* CommandLine::getEGLWindowType (void) const { return m_cmdLine.getOption<opt::EGLWindowType>().c_str(); } 596 const char* CommandLine::getEGLPixmapType (void) const { return m_cmdLine.getOption<opt::EGLPixmapType>().c_str(); } 597 bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption<opt::TestOOM>(); } 598 599 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 } 606 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 614 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 622 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 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 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 670 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 680 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