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 Command line parsing.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuCommandLine.hpp"
25 #include "tcuPlatform.hpp"
26 #include "tcuTestCase.hpp"
27 #include "tcuResource.hpp"
28 #include "deFilePath.hpp"
29 #include "deStringUtil.hpp"
32 #include "deCommandLine.h"
33 #include "qpTestLog.h"
34 #include "qpDebugOut.h"
45 // OOM tests are enabled by default only on platforms that don't do memory overcommit (Win32)
46 #if (DE_OS == DE_OS_WIN32)
47 # define TEST_OOM_DEFAULT "enable"
49 # define TEST_OOM_DEFAULT "disable"
58 DE_DECLARE_COMMAND_LINE_OPT(CasePath, std::string);
59 DE_DECLARE_COMMAND_LINE_OPT(CaseList, std::string);
60 DE_DECLARE_COMMAND_LINE_OPT(CaseListFile, std::string);
61 DE_DECLARE_COMMAND_LINE_OPT(CaseListResource, std::string);
62 DE_DECLARE_COMMAND_LINE_OPT(StdinCaseList, bool);
63 DE_DECLARE_COMMAND_LINE_OPT(LogFilename, std::string);
64 DE_DECLARE_COMMAND_LINE_OPT(RunMode, tcu::RunMode);
65 DE_DECLARE_COMMAND_LINE_OPT(ExportFilenamePattern, std::string);
66 DE_DECLARE_COMMAND_LINE_OPT(WatchDog, bool);
67 DE_DECLARE_COMMAND_LINE_OPT(CrashHandler, bool);
68 DE_DECLARE_COMMAND_LINE_OPT(BaseSeed, int);
69 DE_DECLARE_COMMAND_LINE_OPT(TestIterationCount, int);
70 DE_DECLARE_COMMAND_LINE_OPT(Visibility, WindowVisibility);
71 DE_DECLARE_COMMAND_LINE_OPT(SurfaceWidth, int);
72 DE_DECLARE_COMMAND_LINE_OPT(SurfaceHeight, int);
73 DE_DECLARE_COMMAND_LINE_OPT(SurfaceType, tcu::SurfaceType);
74 DE_DECLARE_COMMAND_LINE_OPT(ScreenRotation, tcu::ScreenRotation);
75 DE_DECLARE_COMMAND_LINE_OPT(GLContextType, std::string);
76 DE_DECLARE_COMMAND_LINE_OPT(GLConfigID, int);
77 DE_DECLARE_COMMAND_LINE_OPT(GLConfigName, std::string);
78 DE_DECLARE_COMMAND_LINE_OPT(GLContextFlags, std::string);
79 DE_DECLARE_COMMAND_LINE_OPT(CLPlatformID, int);
80 DE_DECLARE_COMMAND_LINE_OPT(CLDeviceIDs, std::vector<int>);
81 DE_DECLARE_COMMAND_LINE_OPT(CLBuildOptions, std::string);
82 DE_DECLARE_COMMAND_LINE_OPT(EGLDisplayType, std::string);
83 DE_DECLARE_COMMAND_LINE_OPT(EGLWindowType, std::string);
84 DE_DECLARE_COMMAND_LINE_OPT(EGLPixmapType, std::string);
85 DE_DECLARE_COMMAND_LINE_OPT(LogImages, bool);
86 DE_DECLARE_COMMAND_LINE_OPT(LogShaderSources, bool);
87 DE_DECLARE_COMMAND_LINE_OPT(TestOOM, bool);
88 DE_DECLARE_COMMAND_LINE_OPT(VKDeviceID, int);
89 DE_DECLARE_COMMAND_LINE_OPT(LogFlush, bool);
90 DE_DECLARE_COMMAND_LINE_OPT(Validation, bool);
92 static void parseIntList (const char* src, std::vector<int>* dst)
94 std::istringstream str (src);
97 while (std::getline(str, val, ','))
100 de::cmdline::parseType(val.c_str(), &intVal);
101 dst->push_back(intVal);
105 void registerOptions (de::cmdline::Parser& parser)
107 using de::cmdline::Option;
108 using de::cmdline::NamedValue;
110 static const NamedValue<bool> s_enableNames[] =
115 static const NamedValue<tcu::RunMode> s_runModes[] =
117 { "execute", RUNMODE_EXECUTE },
118 { "xml-caselist", RUNMODE_DUMP_XML_CASELIST },
119 { "txt-caselist", RUNMODE_DUMP_TEXT_CASELIST },
120 { "stdout-caselist",RUNMODE_DUMP_STDOUT_CASELIST}
122 static const NamedValue<WindowVisibility> s_visibilites[] =
124 { "windowed", WINDOWVISIBILITY_WINDOWED },
125 { "fullscreen", WINDOWVISIBILITY_FULLSCREEN },
126 { "hidden", WINDOWVISIBILITY_HIDDEN }
128 static const NamedValue<tcu::SurfaceType> s_surfaceTypes[] =
130 { "window", SURFACETYPE_WINDOW },
131 { "pixmap", SURFACETYPE_OFFSCREEN_NATIVE },
132 { "pbuffer", SURFACETYPE_OFFSCREEN_GENERIC },
133 { "fbo", SURFACETYPE_FBO }
135 static const NamedValue<tcu::ScreenRotation> s_screenRotations[] =
137 { "unspecified", SCREENROTATION_UNSPECIFIED },
138 { "0", SCREENROTATION_0 },
139 { "90", SCREENROTATION_90 },
140 { "180", SCREENROTATION_180 },
141 { "270", SCREENROTATION_270 }
145 << Option<CasePath> ("n", "deqp-case", "Test case(s) to run, supports wildcards (e.g. dEQP-GLES2.info.*)")
146 << Option<CaseList> (DE_NULL, "deqp-caselist", "Case list to run in trie format (e.g. {dEQP-GLES2{info{version,renderer}}})")
147 << Option<CaseListFile> (DE_NULL, "deqp-caselist-file", "Read case list (in trie format) from given file")
148 << Option<CaseListResource> (DE_NULL, "deqp-caselist-resource", "Read case list (in trie format) from given file located application's assets")
149 << Option<StdinCaseList> (DE_NULL, "deqp-stdin-caselist", "Read case list (in trie format) from stdin")
150 << Option<LogFilename> (DE_NULL, "deqp-log-filename", "Write test results to given file", "TestResults.qpa")
151 << Option<RunMode> (DE_NULL, "deqp-runmode", "Execute tests, or write list of test cases into a file",
152 s_runModes, "execute")
153 << Option<ExportFilenamePattern>(DE_NULL, "deqp-caselist-export-file", "Set the target file name pattern for caselist export", "${packageName}-cases.${typeExtension}")
154 << Option<WatchDog> (DE_NULL, "deqp-watchdog", "Enable test watchdog", s_enableNames, "disable")
155 << Option<CrashHandler> (DE_NULL, "deqp-crashhandler", "Enable crash handling", s_enableNames, "disable")
156 << Option<BaseSeed> (DE_NULL, "deqp-base-seed", "Base seed for test cases that use randomization", "0")
157 << Option<TestIterationCount> (DE_NULL, "deqp-test-iteration-count", "Iteration count for cases that support variable number of iterations", "0")
158 << Option<Visibility> (DE_NULL, "deqp-visibility", "Default test window visibility", s_visibilites, "windowed")
159 << Option<SurfaceWidth> (DE_NULL, "deqp-surface-width", "Use given surface width if possible", "-1")
160 << Option<SurfaceHeight> (DE_NULL, "deqp-surface-height", "Use given surface height if possible", "-1")
161 << Option<SurfaceType> (DE_NULL, "deqp-surface-type", "Use given surface type", s_surfaceTypes, "window")
162 << Option<ScreenRotation> (DE_NULL, "deqp-screen-rotation", "Screen rotation for platforms that support it", s_screenRotations, "0")
163 << Option<GLContextType> (DE_NULL, "deqp-gl-context-type", "OpenGL context type for platforms that support multiple")
164 << Option<GLConfigID> (DE_NULL, "deqp-gl-config-id", "OpenGL (ES) render config ID (EGL config id on EGL platforms)", "-1")
165 << Option<GLConfigName> (DE_NULL, "deqp-gl-config-name", "Symbolic OpenGL (ES) render config name")
166 << Option<GLContextFlags> (DE_NULL, "deqp-gl-context-flags", "OpenGL context flags (comma-separated, supports debug and robust)")
167 << Option<CLPlatformID> (DE_NULL, "deqp-cl-platform-id", "Execute tests on given OpenCL platform (IDs start from 1)", "1")
168 << Option<CLDeviceIDs> (DE_NULL, "deqp-cl-device-ids", "Execute tests on given CL devices (comma-separated, IDs start from 1)", parseIntList, "")
169 << Option<CLBuildOptions> (DE_NULL, "deqp-cl-build-options", "Extra build options for OpenCL compiler")
170 << Option<EGLDisplayType> (DE_NULL, "deqp-egl-display-type", "EGL native display type")
171 << Option<EGLWindowType> (DE_NULL, "deqp-egl-window-type", "EGL native window type")
172 << Option<EGLPixmapType> (DE_NULL, "deqp-egl-pixmap-type", "EGL native pixmap type")
173 << Option<VKDeviceID> (DE_NULL, "deqp-vk-device-id", "Vulkan device ID (IDs start from 1)", "1")
174 << Option<LogImages> (DE_NULL, "deqp-log-images", "Enable or disable logging of result images", s_enableNames, "enable")
175 << Option<LogShaderSources> (DE_NULL, "deqp-log-shader-sources", "Enable or disable logging of shader sources", s_enableNames, "enable")
176 << Option<TestOOM> (DE_NULL, "deqp-test-oom", "Run tests that exhaust memory on purpose", s_enableNames, TEST_OOM_DEFAULT)
177 << Option<LogFlush> (DE_NULL, "deqp-log-flush", "Enable or disable log file fflush", s_enableNames, "enable")
178 << Option<Validation> (DE_NULL, "deqp-validation", "Enable or disable test case validation", s_enableNames, "disable");
181 void registerLegacyOptions (de::cmdline::Parser& parser)
183 using de::cmdline::Option;
186 << Option<GLConfigID> (DE_NULL, "deqp-egl-config-id", "Legacy name for --deqp-gl-config-id", "-1")
187 << Option<GLConfigName> (DE_NULL, "deqp-egl-config-name", "Legacy name for --deqp-gl-config-name");
192 // \todo [2014-02-13 pyry] This could be useful elsewhere as well.
193 class DebugOutStreambuf : public std::streambuf
196 DebugOutStreambuf (void);
197 ~DebugOutStreambuf (void);
200 std::streamsize xsputn (const char* s, std::streamsize count);
201 int overflow (int ch = -1);
204 void flushLine (void);
206 std::ostringstream m_curLine;
209 DebugOutStreambuf::DebugOutStreambuf (void)
213 DebugOutStreambuf::~DebugOutStreambuf (void)
215 if (m_curLine.tellp() != std::streampos(0))
219 std::streamsize DebugOutStreambuf::xsputn (const char* s, std::streamsize count)
221 for (std::streamsize pos = 0; pos < count; pos++)
223 m_curLine.put(s[pos]);
232 int DebugOutStreambuf::overflow (int ch)
238 DE_ASSERT((ch & 0xff) == ch);
239 const char chVal = (char)(deUint8)(ch & 0xff);
240 return xsputn(&chVal, 1) == 1 ? ch : -1;
244 void DebugOutStreambuf::flushLine (void)
246 qpPrint(m_curLine.str().c_str());
253 CaseTreeNode (const std::string& name) : m_name(name) {}
254 ~CaseTreeNode (void);
256 const std::string& getName (void) const { return m_name; }
257 bool hasChildren (void) const { return !m_children.empty(); }
259 bool hasChild (const std::string& name) const;
260 const CaseTreeNode* getChild (const std::string& name) const;
261 CaseTreeNode* getChild (const std::string& name);
263 void addChild (CaseTreeNode* child) { m_children.push_back(child); }
266 CaseTreeNode (const CaseTreeNode&);
267 CaseTreeNode& operator= (const CaseTreeNode&);
269 enum { NOT_FOUND = -1 };
271 // \todo [2014-10-30 pyry] Speed up with hash / sorting
272 int findChildNdx (const std::string& name) const;
275 std::vector<CaseTreeNode*> m_children;
278 CaseTreeNode::~CaseTreeNode (void)
280 for (vector<CaseTreeNode*>::const_iterator i = m_children.begin(); i != m_children.end(); ++i)
284 int CaseTreeNode::findChildNdx (const std::string& name) const
286 for (int ndx = 0; ndx < (int)m_children.size(); ++ndx)
288 if (m_children[ndx]->getName() == name)
294 inline bool CaseTreeNode::hasChild (const std::string& name) const
296 return findChildNdx(name) != NOT_FOUND;
299 inline const CaseTreeNode* CaseTreeNode::getChild (const std::string& name) const
301 const int ndx = findChildNdx(name);
302 return ndx == NOT_FOUND ? DE_NULL : m_children[ndx];
305 inline CaseTreeNode* CaseTreeNode::getChild (const std::string& name)
307 const int ndx = findChildNdx(name);
308 return ndx == NOT_FOUND ? DE_NULL : m_children[ndx];
311 static int getCurrentComponentLen (const char* path)
314 for (; path[ndx] != 0 && path[ndx] != '.'; ++ndx);
318 static const CaseTreeNode* findNode (const CaseTreeNode* root, const char* path)
320 const CaseTreeNode* curNode = root;
321 const char* curPath = path;
322 int curLen = getCurrentComponentLen(curPath);
326 curNode = curNode->getChild(std::string(curPath, curPath+curLen));
337 DE_ASSERT(curPath[0] == '.');
339 curLen = getCurrentComponentLen(curPath);
346 static void parseCaseTrie (CaseTreeNode* root, std::istream& in)
348 vector<CaseTreeNode*> nodeStack;
350 bool expectNode = true;
353 throw std::invalid_argument("Malformed case trie");
355 nodeStack.push_back(root);
357 while (!nodeStack.empty())
359 const int curChr = in.get();
361 if (curChr == std::char_traits<char>::eof() || curChr == 0)
362 throw std::invalid_argument("Unterminated case tree");
364 if (curChr == '{' || curChr == ',' || curChr == '}')
366 if (!curName.empty() && expectNode)
368 CaseTreeNode* const newChild = new CaseTreeNode(curName);
372 nodeStack.back()->addChild(newChild);
381 nodeStack.push_back(newChild);
385 else if (curName.empty() == expectNode)
386 throw std::invalid_argument(expectNode ? "Empty node name" : "Missing node separator");
391 nodeStack.pop_back();
393 // consume trailing new line
394 if (nodeStack.empty())
396 if (in.peek() == '\r')
398 if (in.peek() == '\n')
405 else if (isValidTestCaseNameChar((char)curChr))
406 curName += (char)curChr;
408 throw std::invalid_argument("Illegal character in node name");
412 static void parseCaseList (CaseTreeNode* root, std::istream& in)
414 // \note Algorithm assumes that cases are sorted by groups, but will
415 // function fine, albeit more slowly, if that is not the case.
416 vector<CaseTreeNode*> nodeStack;
420 nodeStack.resize(8, DE_NULL);
426 const int curChr = in.get();
428 if (curChr == std::char_traits<char>::eof() || curChr == 0 || curChr == '\n' || curChr == '\r')
431 throw std::invalid_argument("Empty test case name");
433 if (nodeStack[stackPos]->hasChild(curName))
434 throw std::invalid_argument("Duplicate test case");
436 CaseTreeNode* const newChild = new CaseTreeNode(curName);
440 nodeStack[stackPos]->addChild(newChild);
451 if (curChr == '\r' && in.peek() == '\n')
455 const int nextChr = in.peek();
457 if (nextChr == std::char_traits<char>::eof() || nextChr == 0)
461 else if (curChr == '.')
464 throw std::invalid_argument("Empty test group name");
466 if ((int)nodeStack.size() <= stackPos+1)
467 nodeStack.resize(nodeStack.size()*2, DE_NULL);
469 if (!nodeStack[stackPos+1] || nodeStack[stackPos+1]->getName() != curName)
471 CaseTreeNode* curGroup = nodeStack[stackPos]->getChild(curName);
475 curGroup = new CaseTreeNode(curName);
479 nodeStack[stackPos]->addChild(curGroup);
488 nodeStack[stackPos+1] = curGroup;
490 if ((int)nodeStack.size() > stackPos+2)
491 nodeStack[stackPos+2] = DE_NULL; // Invalidate rest of entries
494 DE_ASSERT(nodeStack[stackPos+1]->getName() == curName);
499 else if (isValidTestCaseNameChar((char)curChr))
500 curName += (char)curChr;
502 throw std::invalid_argument("Illegal character in test case name");
506 static CaseTreeNode* parseCaseList (std::istream& in)
508 CaseTreeNode* const root = new CaseTreeNode("");
511 if (in.peek() == '{')
512 parseCaseTrie(root, in);
514 parseCaseList(root, in);
517 const int curChr = in.get();
518 if (curChr != std::char_traits<char>::eof() && curChr != 0)
519 throw std::invalid_argument("Trailing characters at end of case list");
534 CasePaths (const string& pathList);
535 bool matches (const string& caseName, bool allowPrefix=false) const;
538 const vector<string> m_casePatterns;
541 CasePaths::CasePaths (const string& pathList)
542 : m_casePatterns(de::splitString(pathList, ','))
546 // Match a single path component against a pattern component that may contain *-wildcards.
547 static bool matchWildcards(string::const_iterator patternStart,
548 string::const_iterator patternEnd,
549 string::const_iterator pathStart,
550 string::const_iterator pathEnd,
553 string::const_iterator pattern = patternStart;
554 string::const_iterator path = pathStart;
556 while (pattern != patternEnd && path != pathEnd && *pattern == *path)
562 if (pattern == patternEnd)
563 return (path == pathEnd);
564 else if (*pattern == '*')
566 for (; path != pathEnd; ++path)
568 if (matchWildcards(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
572 if (matchWildcards(pattern + 1, patternEnd, pathEnd, pathEnd, allowPrefix))
575 else if (path == pathEnd && allowPrefix)
581 #if defined(TCU_HIERARCHICAL_CASEPATHS)
582 // Match a list of pattern components to a list of path components. A pattern
583 // component may contain *-wildcards. A pattern component "**" matches zero or
584 // more whole path components.
585 static bool patternMatches(vector<string>::const_iterator patternStart,
586 vector<string>::const_iterator patternEnd,
587 vector<string>::const_iterator pathStart,
588 vector<string>::const_iterator pathEnd,
591 vector<string>::const_iterator pattern = patternStart;
592 vector<string>::const_iterator path = pathStart;
594 while (pattern != patternEnd && path != pathEnd && *pattern != "**" &&
595 (*pattern == *path || matchWildcards(pattern->begin(), pattern->end(),
596 path->begin(), path->end(), false)))
602 if (path == pathEnd && (allowPrefix || pattern == patternEnd))
604 else if (pattern != patternEnd && *pattern == "**")
606 for (; path != pathEnd; ++path)
607 if (patternMatches(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
609 if (patternMatches(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
617 bool CasePaths::matches (const string& caseName, bool allowPrefix) const
619 const vector<string> components = de::splitString(caseName, '.');
621 for (size_t ndx = 0; ndx < m_casePatterns.size(); ++ndx)
623 #if defined(TCU_HIERARCHICAL_CASEPATHS)
624 const vector<string> patternComponents = de::splitString(m_casePatterns[ndx], '.');
626 if (patternMatches(patternComponents.begin(), patternComponents.end(),
627 components.begin(), components.end(), allowPrefix))
630 if (matchWildcards(m_casePatterns[ndx].begin(), m_casePatterns[ndx].end(),
631 caseName.begin(), caseName.end(), allowPrefix))
639 /*--------------------------------------------------------------------*//*!
640 * \brief Construct command line
641 * \note CommandLine is not fully initialized until parse() has been called.
642 *//*--------------------------------------------------------------------*/
643 CommandLine::CommandLine (void)
648 /*--------------------------------------------------------------------*//*!
649 * \brief Construct command line from standard argc, argv pair.
651 * Calls parse() with given arguments
652 * \param archive application's assets
653 * \param argc Number of arguments
654 * \param argv Command line arguments
655 *//*--------------------------------------------------------------------*/
656 CommandLine::CommandLine (int argc, const char* const* argv)
659 if (!parse(argc, argv))
660 throw Exception("Failed to parse command line");
663 /*--------------------------------------------------------------------*//*!
664 * \brief Construct command line from string.
666 * Calls parse() with given argument.
667 * \param archive application's assets
668 * \param cmdLine Full command line string.
669 *//*--------------------------------------------------------------------*/
670 CommandLine::CommandLine (const std::string& cmdLine)
673 throw Exception("Failed to parse command line");
676 CommandLine::~CommandLine (void)
680 void CommandLine::clear (void)
686 const de::cmdline::CommandLine& CommandLine::getCommandLine (void) const
691 void CommandLine::registerExtendedOptions (de::cmdline::Parser& parser)
696 /*--------------------------------------------------------------------*//*!
697 * \brief Parse command line from standard argc, argv pair.
698 * \note parse() must be called exactly once.
699 * \param argc Number of arguments
700 * \param argv Command line arguments
701 *//*--------------------------------------------------------------------*/
702 bool CommandLine::parse (int argc, const char* const* argv)
704 DebugOutStreambuf sbuf;
705 std::ostream debugOut (&sbuf);
706 de::cmdline::Parser parser;
708 opt::registerOptions(parser);
709 opt::registerLegacyOptions(parser);
710 registerExtendedOptions(parser);
714 if (!parser.parse(argc-1, argv+1, &m_cmdLine, std::cerr))
716 debugOut << "\n" << de::FilePath(argv[0]).getBaseName() << " [options]\n\n";
717 parser.help(debugOut);
723 if (!m_cmdLine.getOption<opt::LogImages>())
724 m_logFlags |= QP_TEST_LOG_EXCLUDE_IMAGES;
726 if (!m_cmdLine.getOption<opt::LogShaderSources>())
727 m_logFlags |= QP_TEST_LOG_EXCLUDE_SHADER_SOURCES;
729 if (!m_cmdLine.getOption<opt::LogFlush>())
730 m_logFlags |= QP_TEST_LOG_NO_FLUSH;
732 if ((m_cmdLine.hasOption<opt::CasePath>()?1:0) +
733 (m_cmdLine.hasOption<opt::CaseList>()?1:0) +
734 (m_cmdLine.hasOption<opt::CaseListFile>()?1:0) +
735 (m_cmdLine.hasOption<opt::CaseListResource>()?1:0) +
736 (m_cmdLine.getOption<opt::StdinCaseList>()?1:0) > 1)
738 debugOut << "ERROR: multiple test case list options given!\n" << std::endl;
746 /*--------------------------------------------------------------------*//*!
747 * \brief Parse command line from string.
748 * \note parse() must be called exactly once.
749 * \param cmdLine Full command line string.
750 *//*--------------------------------------------------------------------*/
751 bool CommandLine::parse (const std::string& cmdLine)
753 deCommandLine* parsedCmdLine = deCommandLine_parse(cmdLine.c_str());
755 throw std::bad_alloc();
760 isOk = parse(parsedCmdLine->numArgs, parsedCmdLine->args);
764 deCommandLine_destroy(parsedCmdLine);
768 deCommandLine_destroy(parsedCmdLine);
772 const char* CommandLine::getLogFileName (void) const { return m_cmdLine.getOption<opt::LogFilename>().c_str(); }
773 deUint32 CommandLine::getLogFlags (void) const { return m_logFlags; }
774 RunMode CommandLine::getRunMode (void) const { return m_cmdLine.getOption<opt::RunMode>(); }
775 const char* CommandLine::getCaseListExportFile (void) const { return m_cmdLine.getOption<opt::ExportFilenamePattern>().c_str(); }
776 WindowVisibility CommandLine::getVisibility (void) const { return m_cmdLine.getOption<opt::Visibility>(); }
777 bool CommandLine::isWatchDogEnabled (void) const { return m_cmdLine.getOption<opt::WatchDog>(); }
778 bool CommandLine::isCrashHandlingEnabled (void) const { return m_cmdLine.getOption<opt::CrashHandler>(); }
779 int CommandLine::getBaseSeed (void) const { return m_cmdLine.getOption<opt::BaseSeed>(); }
780 int CommandLine::getTestIterationCount (void) const { return m_cmdLine.getOption<opt::TestIterationCount>(); }
781 int CommandLine::getSurfaceWidth (void) const { return m_cmdLine.getOption<opt::SurfaceWidth>(); }
782 int CommandLine::getSurfaceHeight (void) const { return m_cmdLine.getOption<opt::SurfaceHeight>(); }
783 SurfaceType CommandLine::getSurfaceType (void) const { return m_cmdLine.getOption<opt::SurfaceType>(); }
784 ScreenRotation CommandLine::getScreenRotation (void) const { return m_cmdLine.getOption<opt::ScreenRotation>(); }
785 int CommandLine::getGLConfigId (void) const { return m_cmdLine.getOption<opt::GLConfigID>(); }
786 int CommandLine::getCLPlatformId (void) const { return m_cmdLine.getOption<opt::CLPlatformID>(); }
787 const std::vector<int>& CommandLine::getCLDeviceIds (void) const { return m_cmdLine.getOption<opt::CLDeviceIDs>(); }
788 int CommandLine::getVKDeviceId (void) const { return m_cmdLine.getOption<opt::VKDeviceID>(); }
789 bool CommandLine::isValidationEnabled (void) const { return m_cmdLine.getOption<opt::Validation>(); }
790 bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption<opt::TestOOM>(); }
792 const char* CommandLine::getGLContextType (void) const
794 if (m_cmdLine.hasOption<opt::GLContextType>())
795 return m_cmdLine.getOption<opt::GLContextType>().c_str();
799 const char* CommandLine::getGLConfigName (void) const
801 if (m_cmdLine.hasOption<opt::GLConfigName>())
802 return m_cmdLine.getOption<opt::GLConfigName>().c_str();
807 const char* CommandLine::getGLContextFlags (void) const
809 if (m_cmdLine.hasOption<opt::GLContextFlags>())
810 return m_cmdLine.getOption<opt::GLContextFlags>().c_str();
815 const char* CommandLine::getCLBuildOptions (void) const
817 if (m_cmdLine.hasOption<opt::CLBuildOptions>())
818 return m_cmdLine.getOption<opt::CLBuildOptions>().c_str();
823 const char* CommandLine::getEGLDisplayType (void) const
825 if (m_cmdLine.hasOption<opt::EGLDisplayType>())
826 return m_cmdLine.getOption<opt::EGLDisplayType>().c_str();
831 const char* CommandLine::getEGLWindowType (void) const
833 if (m_cmdLine.hasOption<opt::EGLWindowType>())
834 return m_cmdLine.getOption<opt::EGLWindowType>().c_str();
839 const char* CommandLine::getEGLPixmapType (void) const
841 if (m_cmdLine.hasOption<opt::EGLPixmapType>())
842 return m_cmdLine.getOption<opt::EGLPixmapType>().c_str();
847 static bool checkTestGroupName (const CaseTreeNode* root, const char* groupPath)
849 const CaseTreeNode* node = findNode(root, groupPath);
850 return node && node->hasChildren();
853 static bool checkTestCaseName (const CaseTreeNode* root, const char* casePath)
855 const CaseTreeNode* node = findNode(root, casePath);
856 return node && !node->hasChildren();
859 de::MovePtr<CaseListFilter> CommandLine::createCaseListFilter (const tcu::Archive& archive) const
861 return de::MovePtr<CaseListFilter>(new CaseListFilter(m_cmdLine, archive));
864 bool CaseListFilter::checkTestGroupName (const char* groupName) const
867 return m_casePaths->matches(groupName, true);
869 return groupName[0] == 0 || tcu::checkTestGroupName(m_caseTree, groupName);
874 bool CaseListFilter::checkTestCaseName (const char* caseName) const
877 return m_casePaths->matches(caseName, false);
879 return tcu::checkTestCaseName(m_caseTree, caseName);
884 CaseListFilter::CaseListFilter (void)
885 : m_caseTree(DE_NULL)
889 CaseListFilter::CaseListFilter (const de::cmdline::CommandLine& cmdLine, const tcu::Archive& archive)
890 : m_caseTree(DE_NULL)
892 if (cmdLine.hasOption<opt::CaseList>())
894 std::istringstream str(cmdLine.getOption<opt::CaseList>());
896 m_caseTree = parseCaseList(str);
898 else if (cmdLine.hasOption<opt::CaseListFile>())
900 std::ifstream in(cmdLine.getOption<opt::CaseListFile>().c_str(), std::ios_base::binary);
902 if (!in.is_open() || !in.good())
903 throw Exception("Failed to open case list file '" + cmdLine.getOption<opt::CaseListFile>() + "'");
905 m_caseTree = parseCaseList(in);
907 else if (cmdLine.hasOption<opt::CaseListResource>())
909 // \todo [2016-11-14 pyry] We are cloning potentially large buffers here. Consider writing
910 // istream adaptor for tcu::Resource.
911 de::UniquePtr<Resource> caseListResource (archive.getResource(cmdLine.getOption<opt::CaseListResource>().c_str()));
912 const int bufferSize = caseListResource->getSize();
913 std::vector<char> buffer ((size_t)bufferSize);
916 throw Exception("Empty case list resource");
918 caseListResource->read(reinterpret_cast<deUint8*>(&buffer[0]), bufferSize);
921 std::istringstream in (std::string(&buffer[0], (size_t)bufferSize));
923 m_caseTree = parseCaseList(in);
926 else if (cmdLine.getOption<opt::StdinCaseList>())
928 m_caseTree = parseCaseList(std::cin);
930 else if (cmdLine.hasOption<opt::CasePath>())
931 m_casePaths = de::MovePtr<const CasePaths>(new CasePaths(cmdLine.getOption<opt::CasePath>()));
934 CaseListFilter::~CaseListFilter (void)