{ "no", false }
};
- parser << Option<StartServer> ("s", "start-server", "Start local execserver")
- << Option<Host> ("c", "connect", "Connect to host", "127.0.0.1")
- << Option<Port> ("p", "port", "Select TCP port to use", "50016")
- << Option<CaseListDir> ("cd", "caselistdir", "Path to test case XML files", ".")
- << Option<TestSet> ("t", "testset", "Test set", parseCommaSeparatedList)
- << Option<ExcludeSet> ("e", "exclude", "Comma-separated list of exclude filters", parseCommaSeparatedList)
+ parser << Option<StartServer> ("s", "start-server", "Start local execserver", "")
+ << Option<Host> ("c", "connect", "Connect to host", "127.0.0.1")
+ << Option<Port> ("p", "port", "Select TCP port to use", "50016")
+ << Option<CaseListDir> ("cd", "caselistdir", "Path to test case XML files", ".")
+ << Option<TestSet> ("t", "testset", "Test set", parseCommaSeparatedList, "")
+ << Option<ExcludeSet> ("e", "exclude", "Comma-separated list of exclude filters", parseCommaSeparatedList, "")
<< Option<ContinueFile> (DE_NULL, "continue", "Continue execution by initializing results from existing test log")
- << Option<TestLogFile> ("o", "out", "Output test log filename")
- << Option<InfoLogFile> ("i", "info", "Output info log filename")
- << Option<Summary> (DE_NULL, "summary", "Print summary at the end", s_yesNo, "yes")
- << Option<BinaryName> ("b", "binaryname", "Test binary path, relative to working directory")
- << Option<WorkingDir> ("wd", "workdir", "Working directory for test execution")
- << Option<CmdLineArgs> (DE_NULL, "cmdline", "Additional command line arguments for test binary");
+ << Option<TestLogFile> ("o", "out", "Output test log filename", "")
+ << Option<InfoLogFile> ("i", "info", "Output info log filename", "")
+ << Option<Summary> (DE_NULL, "summary", "Print summary at the end", s_yesNo, "yes")
+ << Option<BinaryName> ("b", "binaryname", "Test binary path, relative to working directory", "")
+ << Option<WorkingDir> ("wd", "workdir", "Working directory for test execution", "")
+ << Option<CmdLineArgs> (DE_NULL, "cmdline", "Additional command line arguments for test binary", "");
}
} // opt
#include "tcuCommandLine.hpp"
#include "tcuPlatform.hpp"
+#include "tcuTestCase.hpp"
#include "deFilePath.hpp"
#include "deStringUtil.hpp"
#include "deString.h"
<< Option<StdinCaseList> (DE_NULL, "deqp-stdin-caselist", "Read case list (in trie format) from stdin")
<< Option<LogFilename> (DE_NULL, "deqp-log-filename", "Write test results to given file", "TestResults.qpa")
<< Option<RunMode> (DE_NULL, "deqp-runmode", "Execute tests, or write list of test cases into a file",
- s_runModes, "execute")
+ s_runModes, "execute")
<< Option<WatchDog> (DE_NULL, "deqp-watchdog", "Enable test watchdog", s_enableNames, "disable")
<< Option<CrashHandler> (DE_NULL, "deqp-crashhandler", "Enable crash handling", s_enableNames, "disable")
- << Option<BaseSeed> (DE_NULL, "deqp-base-seed", "Base seed for test cases that use randomization")
- << Option<TestIterationCount> (DE_NULL, "deqp-test-iteration-count", "Iteration count for cases that support variable number of iterations")
+ << Option<BaseSeed> (DE_NULL, "deqp-base-seed", "Base seed for test cases that use randomization", "0")
+ << Option<TestIterationCount> (DE_NULL, "deqp-test-iteration-count", "Iteration count for cases that support variable number of iterations", "0")
<< Option<Visibility> (DE_NULL, "deqp-visibility", "Default test window visibility", s_visibilites, "windowed")
- << Option<SurfaceWidth> (DE_NULL, "deqp-surface-width", "Use given surface width if possible", "-1")
- << Option<SurfaceHeight> (DE_NULL, "deqp-surface-height", "Use given surface height if possible", "-1")
+ << Option<SurfaceWidth> (DE_NULL, "deqp-surface-width", "Use given surface width if possible", "-1")
+ << Option<SurfaceHeight> (DE_NULL, "deqp-surface-height", "Use given surface height if possible", "-1")
<< Option<SurfaceType> (DE_NULL, "deqp-surface-type", "Use given surface type", s_surfaceTypes, "window")
<< Option<ScreenRotation> (DE_NULL, "deqp-screen-rotation", "Screen rotation for platforms that support it", s_screenRotations, "0")
<< Option<GLContextType> (DE_NULL, "deqp-gl-context-type", "OpenGL context type for platforms that support multiple")
- << Option<GLConfigID> (DE_NULL, "deqp-gl-config-id", "OpenGL (ES) render config ID (EGL config id on EGL platforms)", "-1")
+ << Option<GLConfigID> (DE_NULL, "deqp-gl-config-id", "OpenGL (ES) render config ID (EGL config id on EGL platforms)", "-1")
<< Option<GLConfigName> (DE_NULL, "deqp-gl-config-name", "Symbolic OpenGL (ES) render config name")
<< Option<GLContextFlags> (DE_NULL, "deqp-gl-context-flags", "OpenGL context flags (comma-separated, supports debug and robust)")
- << Option<CLPlatformID> (DE_NULL, "deqp-cl-platform-id", "Execute tests on given OpenCL platform (IDs start from 1)", "1")
- << Option<CLDeviceIDs> (DE_NULL, "deqp-cl-device-ids", "Execute tests on given CL devices (comma-separated, IDs start from 1)", parseIntList)
+ << Option<CLPlatformID> (DE_NULL, "deqp-cl-platform-id", "Execute tests on given OpenCL platform (IDs start from 1)", "1")
+ << Option<CLDeviceIDs> (DE_NULL, "deqp-cl-device-ids", "Execute tests on given CL devices (comma-separated, IDs start from 1)", parseIntList, "")
<< Option<CLBuildOptions> (DE_NULL, "deqp-cl-build-options", "Extra build options for OpenCL compiler")
<< Option<EGLDisplayType> (DE_NULL, "deqp-egl-display-type", "EGL native display type")
<< Option<EGLWindowType> (DE_NULL, "deqp-egl-window-type", "EGL native window type")
CaseTreeNode (const std::string& name) : m_name(name) {}
~CaseTreeNode (void);
- void addChild (CaseTreeNode* child) { m_children.push_back(child); }
+ const std::string& getName (void) const { return m_name; }
+ bool hasChildren (void) const { return !m_children.empty(); }
+
+ bool hasChild (const std::string& name) const;
+ const CaseTreeNode* getChild (const std::string& name) const;
+ CaseTreeNode* getChild (const std::string& name);
- const std::string& getName (void) const { return m_name; }
- const std::vector<CaseTreeNode*>& getChildren (void) const { return m_children; }
+ void addChild (CaseTreeNode* child) { m_children.push_back(child); }
private:
CaseTreeNode (const CaseTreeNode&);
CaseTreeNode& operator= (const CaseTreeNode&);
+ enum { NOT_FOUND = -1 };
+
+ // \todo [2014-10-30 pyry] Speed up with hash / sorting
+ int findChildNdx (const std::string& name) const;
+
std::string m_name;
std::vector<CaseTreeNode*> m_children;
};
delete *i;
}
-static CaseTreeNode* parseCaseTree (std::istream& in)
+int CaseTreeNode::findChildNdx (const std::string& name) const
+{
+ for (int ndx = 0; ndx < (int)m_children.size(); ++ndx)
+ {
+ if (m_children[ndx]->getName() == name)
+ return ndx;
+ }
+ return NOT_FOUND;
+}
+
+inline bool CaseTreeNode::hasChild (const std::string& name) const
+{
+ return findChildNdx(name) != NOT_FOUND;
+}
+
+inline const CaseTreeNode* CaseTreeNode::getChild (const std::string& name) const
+{
+ const int ndx = findChildNdx(name);
+ return ndx == NOT_FOUND ? DE_NULL : m_children[ndx];
+}
+
+inline CaseTreeNode* CaseTreeNode::getChild (const std::string& name)
+{
+ const int ndx = findChildNdx(name);
+ return ndx == NOT_FOUND ? DE_NULL : m_children[ndx];
+}
+
+static int getCurrentComponentLen (const char* path)
+{
+ int ndx = 0;
+ for (; path[ndx] != 0 && path[ndx] != '.'; ++ndx);
+ return ndx;
+}
+
+static const CaseTreeNode* findNode (const CaseTreeNode* root, const char* path)
+{
+ const CaseTreeNode* curNode = root;
+ const char* curPath = path;
+ int curLen = getCurrentComponentLen(curPath);
+
+ for (;;)
+ {
+ curNode = curNode->getChild(std::string(curPath, curPath+curLen));
+
+ if (!curNode)
+ break;
+
+ curPath += curLen;
+
+ if (curPath[0] == 0)
+ break;
+ else
+ {
+ DE_ASSERT(curPath[0] == '.');
+ curPath += 1;
+ curLen = getCurrentComponentLen(curPath);
+ }
+ }
+
+ return curNode;
+}
+
+static void parseCaseTrie (CaseTreeNode* root, std::istream& in)
{
vector<CaseTreeNode*> nodeStack;
string curName;
+ bool expectNode = true;
if (in.get() != '{')
- throw std::invalid_argument("Malformed case tree");
+ throw std::invalid_argument("Malformed case trie");
- nodeStack.reserve(1);
- nodeStack.push_back(new CaseTreeNode(""));
+ nodeStack.push_back(root);
- try
+ while (!nodeStack.empty())
{
- for (;;)
+ const int curChr = in.get();
+
+ if (curChr == std::char_traits<char>::eof() || curChr == 0)
+ throw std::invalid_argument("Unterminated case tree");
+
+ if (curChr == '{' || curChr == ',' || curChr == '}')
{
- const int curChr = in.get();
+ if (!curName.empty() && expectNode)
+ {
+ CaseTreeNode* const newChild = new CaseTreeNode(curName);
- if (curChr == std::char_traits<char>::eof() || curChr == 0)
- break;
+ try
+ {
+ nodeStack.back()->addChild(newChild);
+ }
+ catch (...)
+ {
+ delete newChild;
+ throw;
+ }
- if (nodeStack.empty())
- throw std::invalid_argument("Trailing characters at end of case tree");
+ if (curChr == '{')
+ nodeStack.push_back(newChild);
- if (!curName.empty() && (curChr == '{' || curChr == ',' || curChr == '}'))
+ curName.clear();
+ }
+ else if (curName.empty() == expectNode)
+ throw std::invalid_argument(expectNode ? "Empty node name" : "Missing node separator");
+
+ if (curChr == '}')
{
- // Create child and push to stack.
- nodeStack.reserve(nodeStack.size()+1);
- nodeStack.push_back(new CaseTreeNode(curName));
+ expectNode = false;
+ nodeStack.pop_back();
+ }
+ else
+ expectNode = true;
+ }
+ else if (isValidTestCaseNameChar((char)curChr))
+ curName += (char)curChr;
+ else
+ throw std::invalid_argument("Illegal character in node name");
+ }
+}
- curName.clear();
+static void parseCaseList (CaseTreeNode* root, std::istream& in)
+{
+ // \note Algorithm assumes that cases are sorted by groups, but will
+ // function fine, albeit more slowly, if that is not the case.
+ vector<CaseTreeNode*> nodeStack;
+ int stackPos = 0;
+ string curName;
+
+ nodeStack.resize(8, DE_NULL);
+
+ nodeStack[0] = root;
+
+ for (;;)
+ {
+ const int curChr = in.get();
+
+ if (curChr == std::char_traits<char>::eof() || curChr == 0 || curChr == '\n' || curChr == '\r')
+ {
+ if (curName.empty())
+ throw std::invalid_argument("Empty test case name");
+
+ if (nodeStack[stackPos]->hasChild(curName))
+ throw std::invalid_argument("Duplicate test case");
+
+ CaseTreeNode* const newChild = new CaseTreeNode(curName);
+
+ try
+ {
+ nodeStack[stackPos]->addChild(newChild);
}
+ catch (...)
+ {
+ delete newChild;
+ throw;
+ }
+
+ curName.clear();
+ stackPos = 0;
+
+ if (curChr == '\r' && in.peek() == '\n')
+ in.get();
- if (curChr == ',' || curChr == '}')
{
- // Attach to parent
- if (nodeStack.size() < 2)
- throw std::invalid_argument("Malformed case tree");
+ const int nextChr = in.peek();
- (*(nodeStack.end()-2))->addChild(nodeStack.back());
- nodeStack.pop_back();
+ if (nextChr == std::char_traits<char>::eof() || nextChr == 0)
+ break;
}
- else if (curChr != '{')
- curName += (char)curChr;
}
+ else if (curChr == '.')
+ {
+ if (curName.empty())
+ throw std::invalid_argument("Empty test group name");
- if (nodeStack.size() != 1 || nodeStack[0]->getName() != "")
- throw std::invalid_argument("Unterminated case tree");
+ if ((int)nodeStack.size() <= stackPos+1)
+ nodeStack.resize(nodeStack.size()*2, DE_NULL);
+
+ if (!nodeStack[stackPos+1] || nodeStack[stackPos+1]->getName() != curName)
+ {
+ CaseTreeNode* curGroup = nodeStack[stackPos]->getChild(curName);
+
+ if (!curGroup)
+ {
+ curGroup = new CaseTreeNode(curName);
+
+ try
+ {
+ nodeStack[stackPos]->addChild(curGroup);
+ }
+ catch (...)
+ {
+ delete curGroup;
+ throw;
+ }
+ }
+
+ nodeStack[stackPos+1] = curGroup;
+
+ if ((int)nodeStack.size() > stackPos+2)
+ nodeStack[stackPos+2] = DE_NULL; // Invalidate rest of entries
+ }
+
+ DE_ASSERT(nodeStack[stackPos+1]->getName() == curName);
+
+ curName.clear();
+ stackPos += 1;
+ }
+ else if (isValidTestCaseNameChar((char)curChr))
+ curName += (char)curChr;
+ else
+ throw std::invalid_argument("Illegal character in test case name");
}
- catch (...)
+}
+
+static CaseTreeNode* parseCaseList (std::istream& in)
+{
+ CaseTreeNode* const root = new CaseTreeNode("");
+ try
{
- // Nodes in stack are not attached to any parents and must be deleted individually.
- for (vector<CaseTreeNode*>::const_iterator i = nodeStack.begin(); i != nodeStack.end(); ++i)
- delete *i;
+ if (in.peek() == '{')
+ parseCaseTrie(root, in);
+ else
+ parseCaseList(root, in);
+
+ {
+ const int curChr = in.get();
+ if (curChr != std::char_traits<char>::eof() && curChr != 0)
+ throw std::invalid_argument("Trailing characters at end of case list");
+ }
+ return root;
+ }
+ catch (...)
+ {
+ delete root;
throw;
}
-
- return nodeStack[0];
}
class CasePaths
if (!m_cmdLine.getOption<opt::LogImages>())
m_logFlags |= QP_TEST_LOG_EXCLUDE_IMAGES;
- if ((m_cmdLine.getOption<opt::CasePath>().empty()?0:1) +
- (m_cmdLine.getOption<opt::CaseList>().empty()?0:1) +
- (m_cmdLine.getOption<opt::CaseListFile>().empty()?0:1) +
+ if ((m_cmdLine.hasOption<opt::CasePath>()?1:0) +
+ (m_cmdLine.hasOption<opt::CaseList>()?1:0) +
+ (m_cmdLine.hasOption<opt::CaseListFile>()?1:0) +
(m_cmdLine.getOption<opt::StdinCaseList>()?1:0) > 1)
{
debugOut << "ERROR: multiple test case list options given!\n" << std::endl;
try
{
- if (!m_cmdLine.getOption<opt::CaseList>().empty())
+ if (m_cmdLine.hasOption<opt::CaseList>())
{
std::istringstream str(m_cmdLine.getOption<opt::CaseList>());
- m_caseTree = parseCaseTree(str);
+ m_caseTree = parseCaseList(str);
}
- else if (!m_cmdLine.getOption<opt::CaseListFile>().empty())
+ else if (m_cmdLine.hasOption<opt::CaseListFile>())
{
std::ifstream in(m_cmdLine.getOption<opt::CaseListFile>().c_str(), std::ios_base::binary);
if (!in.is_open() || !in.good())
throw Exception("Failed to open case list file '" + m_cmdLine.getOption<opt::CaseListFile>() + "'");
- m_caseTree = parseCaseTree(in);
+ m_caseTree = parseCaseList(in);
}
else if (m_cmdLine.getOption<opt::StdinCaseList>())
{
- m_caseTree = parseCaseTree(std::cin);
+ m_caseTree = parseCaseList(std::cin);
}
- else if (!m_cmdLine.getOption<opt::CasePath>().empty())
+ else if (m_cmdLine.hasOption<opt::CasePath>())
m_casePaths = de::MovePtr<const CasePaths>(new CasePaths(m_cmdLine.getOption<opt::CasePath>()));
}
catch (const std::exception& e)
int CommandLine::getGLConfigId (void) const { return m_cmdLine.getOption<opt::GLConfigID>(); }
int CommandLine::getCLPlatformId (void) const { return m_cmdLine.getOption<opt::CLPlatformID>(); }
const std::vector<int>& CommandLine::getCLDeviceIds (void) const { return m_cmdLine.getOption<opt::CLDeviceIDs>(); }
-const char* CommandLine::getEGLDisplayType (void) const { return m_cmdLine.getOption<opt::EGLDisplayType>().c_str(); }
-const char* CommandLine::getEGLWindowType (void) const { return m_cmdLine.getOption<opt::EGLWindowType>().c_str(); }
-const char* CommandLine::getEGLPixmapType (void) const { return m_cmdLine.getOption<opt::EGLPixmapType>().c_str(); }
bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption<opt::TestOOM>(); }
const char* CommandLine::getGLContextType (void) const
{
- if (!m_cmdLine.getOption<opt::GLContextType>().empty())
+ if (m_cmdLine.hasOption<opt::GLContextType>())
return m_cmdLine.getOption<opt::GLContextType>().c_str();
else
return DE_NULL;
}
const char* CommandLine::getGLConfigName (void) const
{
- if (!m_cmdLine.getOption<opt::GLConfigName>().empty())
+ if (m_cmdLine.hasOption<opt::GLConfigName>())
return m_cmdLine.getOption<opt::GLConfigName>().c_str();
else
return DE_NULL;
const char* CommandLine::getGLContextFlags (void) const
{
- if (!m_cmdLine.getOption<opt::GLContextFlags>().empty())
+ if (m_cmdLine.hasOption<opt::GLContextFlags>())
return m_cmdLine.getOption<opt::GLContextFlags>().c_str();
else
return DE_NULL;
const char* CommandLine::getCLBuildOptions (void) const
{
- if (!m_cmdLine.getOption<opt::CLBuildOptions>().empty())
+ if (m_cmdLine.hasOption<opt::CLBuildOptions>())
return m_cmdLine.getOption<opt::CLBuildOptions>().c_str();
else
return DE_NULL;
}
-static bool checkTestGroupName (const CaseTreeNode* node, const char* groupName)
+const char* CommandLine::getEGLDisplayType (void) const
{
- for (vector<CaseTreeNode*>::const_iterator childIter = node->getChildren().begin(); childIter != node->getChildren().end(); ++childIter)
- {
- const CaseTreeNode* const child = *childIter;
-
- if (deStringBeginsWith(groupName, child->getName().c_str()))
- {
- const int prefixLen = (int)child->getName().length();
-
- if (groupName[prefixLen] == 0)
- return true;
- else if (groupName[prefixLen] == '.')
- return checkTestGroupName(child, groupName + prefixLen + 1);
- }
- }
-
- return false;
+ if (m_cmdLine.hasOption<opt::EGLDisplayType>())
+ return m_cmdLine.getOption<opt::EGLDisplayType>().c_str();
+ else
+ return DE_NULL;
}
-static bool checkTestCaseName (const CaseTreeNode* node, const char* caseName)
+const char* CommandLine::getEGLWindowType (void) const
{
- for (vector<CaseTreeNode*>::const_iterator childIter = node->getChildren().begin(); childIter != node->getChildren().end(); ++childIter)
- {
- const CaseTreeNode* const child = *childIter;
+ if (m_cmdLine.hasOption<opt::EGLWindowType>())
+ return m_cmdLine.getOption<opt::EGLWindowType>().c_str();
+ else
+ return DE_NULL;
+}
- if (deStringBeginsWith(caseName, child->getName().c_str()))
- {
- const int prefixLen = (int)child->getName().length();
+const char* CommandLine::getEGLPixmapType (void) const
+{
+ if (m_cmdLine.hasOption<opt::EGLPixmapType>())
+ return m_cmdLine.getOption<opt::EGLPixmapType>().c_str();
+ else
+ return DE_NULL;
+}
- if (caseName[prefixLen] == 0 && child->getChildren().empty())
- return true;
- else if (caseName[prefixLen] == '.')
- return checkTestCaseName(child, caseName + prefixLen + 1);
- }
- }
+static bool checkTestGroupName (const CaseTreeNode* root, const char* groupPath)
+{
+ const CaseTreeNode* node = findNode(root, groupPath);
+ return node && node->hasChildren();
+}
- return false;
+static bool checkTestCaseName (const CaseTreeNode* root, const char* casePath)
+{
+ const CaseTreeNode* node = findNode(root, casePath);
+ return node && !node->hasChildren();
}
bool CommandLine::checkTestGroupName (const char* groupName) const
// TestNode.
-inline bool isValidCaseNameChar (char c)
-{
- return de::inRange(c, 'a', 'z') ||
- de::inRange(c, 'A', 'Z') ||
- de::inRange(c, '0', '9') ||
- c == '_' || c == '-';
-}
-
inline bool isValidCaseName (const char* name)
{
for (const char* p = name; *p != '\0'; p++)
{
- if (!isValidCaseNameChar(*p))
+ if (!isValidTestCaseNameChar(*p))
return false;
}
return true;
type == NODETYPE_ACCURACY;
}
+inline bool isValidTestCaseNameChar (char c)
+{
+ return de::inRange(c, 'a', 'z') ||
+ de::inRange(c, 'A', 'Z') ||
+ de::inRange(c, '0', '9') ||
+ c == '_' || c == '-';
+}
+
/*--------------------------------------------------------------------*//*!
* \brief Test case hierarchy node
*
TypedFieldMap::~TypedFieldMap (void)
{
+ clear();
+}
+
+void TypedFieldMap::clear (void)
+{
for (Map::const_iterator iter = m_fields.begin(); iter != m_fields.end(); ++iter)
{
if (iter->second.value)
iter->second.destructor(iter->second.value);
}
+ m_fields.clear();
}
bool TypedFieldMap::contains (const std::type_info* key) const
// Set default values.
if (opt.defaultValue)
opt.dispatchParse(&opt, opt.defaultValue, &dst->m_options);
- else
- opt.getDefault(&dst->m_options);
+ else if (opt.setDefault)
+ opt.setDefault(&dst->m_options);
}
DE_ASSERT(!dst->m_options.get<Help>());
// Tests
-DE_DECLARE_COMMAND_LINE_OPT(TestStringOpt, std::string);
-DE_DECLARE_COMMAND_LINE_OPT(TestIntOpt, int);
-DE_DECLARE_COMMAND_LINE_OPT(TestBoolOpt, bool);
-DE_DECLARE_COMMAND_LINE_OPT(TestNamedOpt, deUint64);
+DE_DECLARE_COMMAND_LINE_OPT(TestStringOpt, std::string);
+DE_DECLARE_COMMAND_LINE_OPT(TestStringDefOpt, std::string);
+DE_DECLARE_COMMAND_LINE_OPT(TestIntOpt, int);
+DE_DECLARE_COMMAND_LINE_OPT(TestBoolOpt, bool);
+DE_DECLARE_COMMAND_LINE_OPT(TestNamedOpt, deUint64);
void selfTest (void)
{
{ "huge", ~0ull }
};
- parser << Option<TestStringOpt> ("s", "string", "String option")
- << Option<TestIntOpt> ("i", "int", "Int option")
- << Option<TestBoolOpt> ("b", "bool", "Test boolean flag")
- << Option<TestNamedOpt> ("n", "named", "Test named opt", DE_ARRAY_BEGIN(s_namedValues), DE_ARRAY_END(s_namedValues), "one");
+ parser << Option<TestStringOpt> ("s", "string", "String option")
+ << Option<TestStringDefOpt> ("x", "xyz", "String option w/ default value", "foo")
+ << Option<TestIntOpt> ("i", "int", "Int option")
+ << Option<TestBoolOpt> ("b", "bool", "Test boolean flag")
+ << Option<TestNamedOpt> ("n", "named", "Test named opt", DE_ARRAY_BEGIN(s_namedValues), DE_ARRAY_END(s_namedValues), "one");
{
std::ostringstream err;
DE_TEST_ASSERT(parseOk);
DE_TEST_ASSERT(err.str().empty());
- DE_TEST_ASSERT(cmdLine.getOption<TestStringOpt>() == "");
- DE_TEST_ASSERT(cmdLine.getOption<TestIntOpt>() == 0);
- DE_TEST_ASSERT(cmdLine.getOption<TestBoolOpt>() == false);
+ DE_TEST_ASSERT(!cmdLine.hasOption<TestStringOpt>());
+ DE_TEST_ASSERT(!cmdLine.hasOption<TestIntOpt>());
DE_TEST_ASSERT(cmdLine.getOption<TestNamedOpt>() == 1);
+ DE_TEST_ASSERT(cmdLine.getOption<TestBoolOpt>() == false);
+ DE_TEST_ASSERT(cmdLine.getOption<TestStringDefOpt>() == "foo");
}
// Basic parsing
DE_TEST_ASSERT(cmdLine.getOption<TestIntOpt>() == 9);
DE_TEST_ASSERT(cmdLine.getOption<TestBoolOpt>());
DE_TEST_ASSERT(cmdLine.getOption<TestNamedOpt>() == ~0ull);
+ DE_TEST_ASSERT(cmdLine.getOption<TestStringDefOpt>() == "foo");
}
// End of argument list (--)
DE_TEST_ASSERT(cmdLine.getOption<TestStringOpt>() == "foo");
DE_TEST_ASSERT(cmdLine.getOption<TestBoolOpt>());
- DE_TEST_ASSERT(cmdLine.getOption<TestIntOpt>() == 0); // Not specified
+ DE_TEST_ASSERT(!cmdLine.hasOption<TestIntOpt>());
DE_TEST_ASSERT(cmdLine.getArgs().size() == 2);
DE_TEST_ASSERT(cmdLine.getArgs()[0] == "--int=2");
DE_TEST_ASSERT(cmdLine.getOption<TestStringOpt>() == "--");
DE_TEST_ASSERT(cmdLine.getOption<TestBoolOpt>());
- DE_TEST_ASSERT(cmdLine.getOption<TestIntOpt>() == 0); // Not specified
+ DE_TEST_ASSERT(!cmdLine.hasOption<TestIntOpt>());
DE_TEST_ASSERT(cmdLine.getArgs().size() == 1);
DE_TEST_ASSERT(cmdLine.getArgs()[0] == "foo");
// Empty value --arg=
{
- const char* args[] = { "--string=", "-b" };
+ const char* args[] = { "--string=", "-b", "-x", "" };
CommandLine cmdLine;
std::ostringstream err;
bool parseOk = parser.parse(DE_LENGTH_OF_ARRAY(args), &args[0], &cmdLine, err);
DE_TEST_ASSERT(parseOk);
DE_TEST_ASSERT(err.str().empty());
DE_TEST_ASSERT(cmdLine.getOption<TestStringOpt>() == "");
+ DE_TEST_ASSERT(cmdLine.getOption<TestStringDefOpt>() == "");
DE_TEST_ASSERT(cmdLine.getOption<TestBoolOpt>());
}
}
const char* shortName;
const char* longName;
const char* description;
- const char* defaultValue; //!< Default value (parsed from string), or null if default should be T()
+ const char* defaultValue; //!< Default value (parsed from string), or null if should not be set
// \note Either parse or namedValues must be null.
ParseFunc parse; //!< Custom parsing function or null.
~TypedFieldMap (void);
bool empty (void) const { return m_fields.empty(); }
- void clear (void) { m_fields.clear(); }
+ void clear (void);
template<typename Name>
void set (typename TypedFieldTraits<Name>::ValueType* value);
struct OptInfo;
typedef void (*DispatchParseFunc) (const OptInfo* info, const char* src, TypedFieldMap* dst);
- typedef void (*GetDefaultFunc) (TypedFieldMap* dst);
+ typedef void (*SetDefaultFunc) (TypedFieldMap* dst);
struct OptInfo
{
size_t namedValueStride;
DispatchParseFunc dispatchParse;
- GetDefaultFunc getDefault;
+ SetDefaultFunc setDefault;
OptInfo (void)
: shortName (DE_NULL)
, namedValuesEnd (DE_NULL)
, namedValueStride (0)
, dispatchParse (DE_NULL)
- , getDefault (DE_NULL)
+ , setDefault (DE_NULL)
{}
};
}
template<typename OptType>
-void dispatchGetDefault (TypedFieldMap* dst)
+void dispatchSetDefault (TypedFieldMap* dst)
{
typename OptTraits<OptType>::ValueType* value = new typename OptTraits<OptType>::ValueType();
try
opt.namedValuesEnd = (const void*)option.namedValuesEnd;
opt.namedValueStride = sizeof(*option.namedValues);
opt.dispatchParse = dispatchParse<OptType>;
- opt.getDefault = dispatchGetDefault<OptType>;
+
+ if (opt.isFlag)
+ opt.setDefault = dispatchSetDefault<OptType>;
addOption(opt);
}
const vector<string>& getArgs (void) const { return m_args; }
template<typename Option>
+ bool hasOption (void) const { return m_options.contains<Option>(); }
+
+ template<typename Option>
const typename TypedFieldTraits<Option>::ValueType&
- getOption (void) const { return m_options.get<Option>(); }
+ getOption (void) const { return m_options.get<Option>(); }
private:
TypedFieldMap m_options;
template<typename Factory>
const Factory* selectFactory (const tcu::FactoryRegistry<Factory>& registry, const char* objectTypeName, const char* cmdLineArg)
{
- if (cmdLineArg[0] != 0)
+ if (cmdLineArg)
{
const Factory* factory = registry.getFactoryByName(cmdLineArg);
, m_caseWrapper (DE_NULL)
{
const eglu::NativeDisplayFactoryRegistry& dpyFactoryRegistry = testCtx.getPlatform().getEGLPlatform().getNativeDisplayFactoryRegistry();
- const std::string displayFactoryName = testCtx.getCommandLine().getEGLDisplayType();
- const std::string windowFactoryName = testCtx.getCommandLine().getEGLWindowType();
- const std::string pixmapFactoryName = testCtx.getCommandLine().getEGLPixmapType();
+ const char* const displayFactoryName = testCtx.getCommandLine().getEGLDisplayType();
+ const char* const windowFactoryName = testCtx.getCommandLine().getEGLWindowType();
+ const char* const pixmapFactoryName = testCtx.getCommandLine().getEGLPixmapType();
const eglu::NativeDisplayFactory* displayFactory = DE_NULL;
const eglu::NativeWindowFactory* windowFactory = DE_NULL;
throw tcu::NotSupportedError("Platform doesn't have EGL any native display factories", DE_NULL, __FILE__, __LINE__);
}
- if (displayFactoryName.empty())
+ if (!displayFactoryName)
displayFactory = dpyFactoryRegistry.getDefaultFactory();
else
{
- displayFactory = dpyFactoryRegistry.getFactoryByName(displayFactoryName.c_str());
+ displayFactory = dpyFactoryRegistry.getFactoryByName(displayFactoryName);
if (!displayFactory)
{
- tcu::print("ERROR: Unknown/unsupported EGL native display type '%s'\n", displayFactoryName.c_str());
+ tcu::print("ERROR: Unknown/unsupported EGL native display type '%s'\n", displayFactoryName);
tcu::print("Supported EGL native display types:\n");
for (int factoryNdx = 0; factoryNdx < (int)dpyFactoryRegistry.getFactoryCount(); factoryNdx++)
tcu::print(" %s: %s\n", name, desc);
}
- throw tcu::NotSupportedError(("Unknown EGL native display type '" + displayFactoryName + "'.").c_str(), DE_NULL, __FILE__, __LINE__);
+ throw tcu::NotSupportedError(("Unknown EGL native display type '" + std::string(displayFactoryName) + "'.").c_str(), DE_NULL, __FILE__, __LINE__);
}
}
if (!displayFactory->getNativeWindowRegistry().empty())
{
- windowFactory = windowFactoryName.empty() ? displayFactory->getNativeWindowRegistry().getDefaultFactory()
- : displayFactory->getNativeWindowRegistry().getFactoryByName(windowFactoryName.c_str());
+ windowFactory = windowFactoryName ? displayFactory->getNativeWindowRegistry().getFactoryByName(windowFactoryName)
+ : displayFactory->getNativeWindowRegistry().getDefaultFactory();
if (!windowFactory)
{
- DE_ASSERT(!windowFactoryName.empty());
- tcu::print("ERROR: Unknown/unsupported EGL native window type '%s'\n", windowFactoryName.c_str());
+ DE_ASSERT(windowFactoryName);
+ tcu::print("ERROR: Unknown/unsupported EGL native window type '%s'\n", windowFactoryName);
tcu::print("Supported EGL native window types for native display '%s':\n", displayFactory->getName());
for (int factoryNdx = 0; factoryNdx < (int)displayFactory->getNativeWindowRegistry().getFactoryCount(); factoryNdx++)
tcu::print(" %s: %s\n", name, desc);
}
- throw tcu::NotSupportedError(("Unknown EGL native window type '" + windowFactoryName + "'").c_str(), DE_NULL, __FILE__, __LINE__);
+ throw tcu::NotSupportedError(("Unknown EGL native window type '" + std::string(windowFactoryName) + "'").c_str(), DE_NULL, __FILE__, __LINE__);
}
}
else
if (!displayFactory->getNativePixmapRegistry().empty())
{
- pixmapFactory = pixmapFactoryName.empty() ? displayFactory->getNativePixmapRegistry().getDefaultFactory()
- : displayFactory->getNativePixmapRegistry().getFactoryByName(pixmapFactoryName.c_str());
+ pixmapFactory = pixmapFactoryName ? displayFactory->getNativePixmapRegistry().getFactoryByName(pixmapFactoryName)
+ : displayFactory->getNativePixmapRegistry().getDefaultFactory();
if (!pixmapFactory)
{
- DE_ASSERT(!pixmapFactoryName.empty());
- tcu::print("ERROR: Unknown/unsupported EGL native pixmap type '%s'\n", pixmapFactoryName.c_str());
+ DE_ASSERT(pixmapFactoryName);
+ tcu::print("ERROR: Unknown/unsupported EGL native pixmap type '%s'\n", pixmapFactoryName);
tcu::print("Supported EGL native pixmap types for native display '%s':\n", displayFactory->getName());
for (int factoryNdx = 0; factoryNdx < (int)displayFactory->getNativePixmapRegistry().getFactoryCount(); factoryNdx++)
tcu::print(" %s: %s\n", name, desc);
}
- throw tcu::NotSupportedError(("Unknown EGL native pixmap type '" + pixmapFactoryName + "'").c_str(), DE_NULL, __FILE__, __LINE__);
+ throw tcu::NotSupportedError(("Unknown EGL native pixmap type '" + std::string(pixmapFactoryName) + "'").c_str(), DE_NULL, __FILE__, __LINE__);
}
}
else
*//*--------------------------------------------------------------------*/
#include "ditFrameworkTests.hpp"
-
#include "tcuFloatFormat.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuCommandLine.hpp"
namespace dit
{
+namespace
+{
+
+using std::string;
+using std::vector;
+using tcu::TestLog;
+
+struct MatchCase
+{
+ enum Expected { NO_MATCH, MATCH_GROUP, MATCH_CASE, EXPECTED_LAST };
+
+ const char* path;
+ Expected expected;
+};
+
+const char* getMatchCaseExpectedDesc (MatchCase::Expected expected)
+{
+ static const char* descs[] =
+ {
+ "no match",
+ "group to match",
+ "case to match"
+ };
+ return de::getSizedArrayElement<MatchCase::EXPECTED_LAST>(descs, expected);
+}
+
+class CaseListParserCase : public tcu::TestCase
+{
+public:
+ CaseListParserCase (tcu::TestContext& testCtx, const char* name, const char* caseList, const MatchCase* subCases, int numSubCases)
+ : tcu::TestCase (testCtx, name, "")
+ , m_caseList (caseList)
+ , m_subCases (subCases)
+ , m_numSubCases (numSubCases)
+ {
+ }
+
+ IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+ tcu::CommandLine cmdLine;
+ int numPass = 0;
+
+ log << TestLog::Message << "Input:\n\"" << m_caseList << "\"" << TestLog::EndMessage;
+
+ {
+ const char* argv[] =
+ {
+ "deqp",
+ "--deqp-caselist",
+ m_caseList
+ };
+
+ if (!cmdLine.parse(DE_LENGTH_OF_ARRAY(argv), argv))
+ TCU_FAIL("Failed to parse case list");
+ }
+
+ for (int subCaseNdx = 0; subCaseNdx < m_numSubCases; subCaseNdx++)
+ {
+ const MatchCase& curCase = m_subCases[subCaseNdx];
+ bool matchGroup;
+ bool matchCase;
+
+ log << TestLog::Message << "Checking \"" << curCase.path << "\""
+ << ", expecting " << getMatchCaseExpectedDesc(curCase.expected)
+ << TestLog::EndMessage;
+
+ matchGroup = cmdLine.checkTestGroupName(curCase.path);
+ matchCase = cmdLine.checkTestCaseName(curCase.path);
+
+ if ((matchGroup == (curCase.expected == MatchCase::MATCH_GROUP)) &&
+ (matchCase == (curCase.expected == MatchCase::MATCH_CASE)))
+ {
+ log << TestLog::Message << " pass" << TestLog::EndMessage;
+ numPass += 1;
+ }
+ else
+ log << TestLog::Message << " FAIL!" << TestLog::EndMessage;
+ }
+
+ m_testCtx.setTestResult((numPass == m_numSubCases) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
+ (numPass == m_numSubCases) ? "All passed" : "Unexpected match result");
+
+ return STOP;
+ }
+
+private:
+ const char* const m_caseList;
+ const MatchCase* const m_subCases;
+ const int m_numSubCases;
+};
+
+class NegativeCaseListCase : public tcu::TestCase
+{
+public:
+ NegativeCaseListCase (tcu::TestContext& testCtx, const char* name, const char* caseList)
+ : tcu::TestCase (testCtx, name, "")
+ , m_caseList (caseList)
+ {
+ }
+
+ IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+ tcu::CommandLine cmdLine;
+
+ log << TestLog::Message << "Input:\n\"" << m_caseList << "\"" << TestLog::EndMessage;
+
+ {
+ const char* argv[] =
+ {
+ "deqp",
+ "--deqp-caselist",
+ m_caseList
+ };
+
+ if (cmdLine.parse(DE_LENGTH_OF_ARRAY(argv), argv))
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Parsing passed, should have failed");
+ else
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Parsing failed as expected");
+ }
+
+ return STOP;
+ }
+
+private:
+ const char* const m_caseList;
+};
+
+class TrieParserTests : public tcu::TestCaseGroup
+{
+public:
+ TrieParserTests (tcu::TestContext& testCtx)
+ : tcu::TestCaseGroup(testCtx, "trie", "Test case trie parser tests")
+ {
+ }
+
+ void init (void)
+ {
+ {
+ static const char* const caseList = "{test}";
+ static const MatchCase subCases[] =
+ {
+ { "test", MatchCase::MATCH_CASE },
+ { "test.cd", MatchCase::NO_MATCH },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "single_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "{a{b}}";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "simple_group_1", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "{a{b,c}}";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "simple_group_2", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "{a{b},c{d,e}}";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.c", MatchCase::NO_MATCH },
+ { "a.d", MatchCase::NO_MATCH },
+ { "a.e", MatchCase::NO_MATCH },
+ { "c", MatchCase::MATCH_GROUP },
+ { "c.b", MatchCase::NO_MATCH },
+ { "c.d", MatchCase::MATCH_CASE },
+ { "c.e", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "two_groups", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "{a,c{d,e}}";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_CASE },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::NO_MATCH },
+ { "a.d", MatchCase::NO_MATCH },
+ { "a.e", MatchCase::NO_MATCH },
+ { "c", MatchCase::MATCH_GROUP },
+ { "c.b", MatchCase::NO_MATCH },
+ { "c.d", MatchCase::MATCH_CASE },
+ { "c.e", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "case_group", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "{c{d,e},a}";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_CASE },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::NO_MATCH },
+ { "a.d", MatchCase::NO_MATCH },
+ { "a.e", MatchCase::NO_MATCH },
+ { "c", MatchCase::MATCH_GROUP },
+ { "c.b", MatchCase::NO_MATCH },
+ { "c.d", MatchCase::MATCH_CASE },
+ { "c.e", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "group_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+
+ // Negative tests
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_string", ""));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_root", "{}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_group", "{test{}}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name_1", "{{}}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name_2", "{{test}}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_1", "{"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_2", "{test"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_3", "{test,"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_4", "{test{a}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_5", "{a,b"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_1", "{test{"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_2", "{test{a"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_3", "{test{a,"));
+ addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_4", "{test{a,b"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_1", "{a,,b}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_2", "{,b}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_3", "{a,}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "no_separator", "{a{b}c}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "invalid_char_1", "{a.b}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "invalid_char_2", "{a[]}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "trailing_char_1", "{a}}"));
+ addChild(new NegativeCaseListCase(m_testCtx, "trailing_char_2", "{a}x"));
+ }
+};
+
+class ListParserTests : public tcu::TestCaseGroup
+{
+public:
+ ListParserTests (tcu::TestContext& testCtx)
+ : tcu::TestCaseGroup(testCtx, "list", "Test case list parser tests")
+ {
+ }
+
+ void init (void)
+ {
+ {
+ static const char* const caseList = "test";
+ static const MatchCase subCases[] =
+ {
+ { "test", MatchCase::MATCH_CASE },
+ { "test.cd", MatchCase::NO_MATCH },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "single_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "simple_group_1", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\na.c";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "simple_group_2", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\na.c";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "separator_ln", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\ra.c";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "separator_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\r\na.c";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "separator_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\na.c\n";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "end_ln", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\na.c\r";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "end_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\na.c\r\n";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.a", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "end_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b\nc.d\nc.e";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_CASE },
+ { "a.c", MatchCase::NO_MATCH },
+ { "a.d", MatchCase::NO_MATCH },
+ { "a.e", MatchCase::NO_MATCH },
+ { "c", MatchCase::MATCH_GROUP },
+ { "c.b", MatchCase::NO_MATCH },
+ { "c.d", MatchCase::MATCH_CASE },
+ { "c.e", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "two_groups", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a\nc.d\nc.e";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_CASE },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::NO_MATCH },
+ { "a.d", MatchCase::NO_MATCH },
+ { "a.e", MatchCase::NO_MATCH },
+ { "c", MatchCase::MATCH_GROUP },
+ { "c.b", MatchCase::NO_MATCH },
+ { "c.d", MatchCase::MATCH_CASE },
+ { "c.e", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "case_group", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "c.d\nc.e\na";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_CASE },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::NO_MATCH },
+ { "a.c", MatchCase::NO_MATCH },
+ { "a.d", MatchCase::NO_MATCH },
+ { "a.e", MatchCase::NO_MATCH },
+ { "c", MatchCase::MATCH_GROUP },
+ { "c.b", MatchCase::NO_MATCH },
+ { "c.d", MatchCase::MATCH_CASE },
+ { "c.e", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "group_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList = "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.x";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "b", MatchCase::NO_MATCH },
+ { "a.b", MatchCase::MATCH_GROUP },
+ { "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.x", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "long_name", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList =
+ "a.b.c.d.e\n"
+ "a.b.c.f\n"
+ "x.y.z\n"
+ "a.b.c.d.g\n"
+ "a.b.c.x\n";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "a.b", MatchCase::MATCH_GROUP },
+ { "a.b.c.d.e", MatchCase::MATCH_CASE },
+ { "a.b.c.d.g", MatchCase::MATCH_CASE },
+ { "x.y", MatchCase::MATCH_GROUP },
+ { "x.y.z", MatchCase::MATCH_CASE },
+ { "a.b.c.f", MatchCase::MATCH_CASE },
+ { "a.b.c.x", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "partial_prefix", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+ {
+ static const char* const caseList =
+ "a.a.c.d\n"
+ "a.b.c.d\n";
+ static const MatchCase subCases[] =
+ {
+ { "a", MatchCase::MATCH_GROUP },
+ { "a.a", MatchCase::MATCH_GROUP },
+ { "a.b.c.d", MatchCase::MATCH_CASE },
+ { "a.b.c.d", MatchCase::MATCH_CASE },
+ };
+ addChild(new CaseListParserCase(m_testCtx, "reparenting", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
+ }
+
+ // Negative tests
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_string", ""));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_line", "\n"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name", ".test"));
+ addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name", "test."));
+ }
+};
+
+class CaseListParserTests : public tcu::TestCaseGroup
+{
+public:
+ CaseListParserTests (tcu::TestContext& testCtx)
+ : tcu::TestCaseGroup(testCtx, "case_list_parser", "Test case list parser tests")
+ {
+ }
+
+ void init (void)
+ {
+ addChild(new TrieParserTests(m_testCtx));
+ addChild(new ListParserTests(m_testCtx));
+ }
+};
+
class CommonFrameworkTests : public tcu::TestCaseGroup
{
public:
{
addChild(new SelfCheckCase(m_testCtx, "float_format","tcu::FloatFormat_selfTest()",
tcu::FloatFormat_selfTest));
+ addChild(new CaseListParserTests(m_testCtx));
}
};
+} // anonymous
+
FrameworkTests::FrameworkTests (tcu::TestContext& testCtx)
: tcu::TestCaseGroup(testCtx, "framework", "Miscellaneous framework tests")
{