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 Base class for a test case.
22 *//*--------------------------------------------------------------------*/
23
24#include "tcuTestCase.hpp"
25#include "tcuPlatform.hpp"
26#include "tcuCommandLine.hpp"
27
28#include "deString.h"
29
30namespace tcu
31{
32
33using namespace std;
34
35// TestNode.
36
37inline bool isValidCaseName (const char* name)
38{
39	for (const char* p = name; *p != '\0'; p++)
40	{
41		if (!isValidTestCaseNameChar(*p))
42			return false;
43	}
44	return true;
45}
46
47TestNode::TestNode (TestContext& testCtx, TestNodeType nodeType, const char* name)
48	: m_testCtx		(testCtx)
49	, m_name		(name)
50	, m_nodeType	(nodeType)
51{
52	DE_ASSERT(isValidCaseName(name));
53}
54
55TestNode::TestNode (TestContext& testCtx, TestNodeType nodeType, const char* name, const vector<TestNode*>& children)
56	: m_testCtx		(testCtx)
57	, m_name		(name)
58	, m_nodeType	(nodeType)
59{
60	DE_ASSERT(isValidCaseName(name));
61	for (int i = 0; i < (int)children.size(); i++)
62		addChild(children[i]);
63}
64
65TestNode::~TestNode (void)
66{
67	TestNode::deinit();
68}
69
70void TestNode::getChildren (vector<TestNode*>& res) const
71{
72	res.clear();
73	for (int i = 0; i < (int)m_children.size(); i++)
74		res.push_back(m_children[i]);
75}
76
77void TestNode::addRootChild (const std::string& groupName, const CaseListFilter* caseListFilter, TestCaseGroup* (*createTestGroup)(tcu::TestContext& testCtx, const std::string& name))
78{
79	// Skip tests not in case list
80	if (caseListFilter && !caseListFilter->checkTestGroupName((m_name + "." + groupName).c_str()))
81		return;
82
83	return addChild(createTestGroup(m_testCtx, groupName));
84}
85
86void TestNode::addChild (TestNode* node)
87{
88	// Child names must be unique!
89	// \todo [petri] O(n^2) algorithm, but shouldn't really matter..
90#if defined(DE_DEBUG)
91	for (int i = 0; i < (int)m_children.size(); i++)
92	{
93		if (deStringEqual(node->getName(), m_children[i]->getName()))
94			throw tcu::InternalError(std::string("Test case with non-unique name '") + node->getName() + "' added to group '" + getName() + "'.");
95	}
96#endif
97
98	// children only in group nodes
99	DE_ASSERT(getTestNodeTypeClass(m_nodeType) == NODECLASS_GROUP);
100
101	// children must have the same class
102	if (!m_children.empty())
103		DE_ASSERT(getTestNodeTypeClass(m_children.front()->getNodeType()) == getTestNodeTypeClass(node->getNodeType()));
104
105	m_children.push_back(node);
106}
107
108void TestNode::init (void)
109{
110}
111
112void TestNode::deinit (void)
113{
114	for (int i = 0; i < (int)m_children.size(); i++)
115		delete m_children[i];
116	m_children.clear();
117}
118
119// TestCaseGroup
120
121TestCaseGroup::TestCaseGroup (TestContext& testCtx, const char* name)
122	: TestNode(testCtx, NODETYPE_GROUP, name)
123{
124}
125
126TestCaseGroup::TestCaseGroup (TestContext& testCtx, const char* name, const vector<TestNode*>& children)
127	: TestNode(testCtx, NODETYPE_GROUP, name, children)
128{
129}
130
131// Deprecated constructor with an ignored description argument. These shouldn't really be used
132// in new code but are retained to avoid changing every test group construction at once.
133TestCaseGroup::TestCaseGroup (TestContext& testCtx, const char* name, const char* description)
134	: TestCaseGroup(testCtx, name)
135{
136	DE_UNREF(description);
137}
138
139TestCaseGroup::TestCaseGroup (TestContext& testCtx, const char* name, const char* description, const vector<TestNode*>& children)
140	: TestCaseGroup(testCtx, name, children)
141{
142	DE_UNREF(description);
143}
144
145TestCaseGroup::~TestCaseGroup (void)
146{
147}
148
149TestCase::IterateResult TestCaseGroup::iterate (void)
150{
151	DE_ASSERT(DE_FALSE); // should never be here!
152	throw InternalError("TestCaseGroup::iterate() called!", "", __FILE__, __LINE__);
153}
154
155// TestCase
156
157TestCase::TestCase (TestContext& testCtx, const char* name)
158	: TestNode(testCtx, NODETYPE_SELF_VALIDATE, name)
159{
160}
161
162TestCase::TestCase (TestContext& testCtx, TestNodeType nodeType, const char* name)
163	: TestNode(testCtx, nodeType, name)
164{
165	DE_ASSERT(isTestNodeTypeExecutable(nodeType));
166}
167
168// Deprecated constructor with an ignored description argument. These shouldn't really be used
169// in new code but are retained to avoid changing every test case construction at once.
170TestCase::TestCase (TestContext& testCtx, const char* name, const char* description)
171	: TestCase(testCtx, name)
172{
173	DE_UNREF(description);
174}
175
176TestCase::TestCase (TestContext& testCtx, TestNodeType nodeType, const char* name, const char* description)
177	: TestCase(testCtx, nodeType, name)
178{
179	DE_UNREF(description);
180}
181
182TestCase::~TestCase (void)
183{
184}
185
186} // tcu
187