1 /*-------------------------------------------------------------------------
2  * drawElements Internal Test Module
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 Miscellaneous framework tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "ditFrameworkTests.hpp"
25 #include "tcuFloatFormat.hpp"
26 #include "tcuEither.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuCommandLine.hpp"
29 
30 #include "rrRenderer.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 #include "tcuFloat.hpp"
34 
35 #include "deRandom.hpp"
36 #include "deArrayUtil.hpp"
37 
38 namespace dit
39 {
40 
41 namespace
42 {
43 
44 using std::string;
45 using std::vector;
46 using tcu::TestLog;
47 
48 struct MatchCase
49 {
50 	enum Expected { NO_MATCH, MATCH_GROUP, MATCH_CASE, EXPECTED_LAST };
51 
52 	const char*	path;
53 	Expected	expected;
54 };
55 
getMatchCaseExpectedDesc(MatchCase::Expected expected)56 const char* getMatchCaseExpectedDesc (MatchCase::Expected expected)
57 {
58 	static const char* descs[] =
59 	{
60 		"no match",
61 		"group to match",
62 		"case to match"
63 	};
64 	return de::getSizedArrayElement<MatchCase::EXPECTED_LAST>(descs, expected);
65 }
66 
67 class CaseListParserCase : public tcu::TestCase
68 {
69 public:
CaseListParserCase(tcu::TestContext & testCtx,const char * name,const char * caseList,const MatchCase * subCases,int numSubCases)70 	CaseListParserCase (tcu::TestContext& testCtx, const char* name, const char* caseList, const MatchCase* subCases, int numSubCases)
71 		: tcu::TestCase	(testCtx, name, "")
72 		, m_caseList	(caseList)
73 		, m_subCases	(subCases)
74 		, m_numSubCases	(numSubCases)
75 	{
76 	}
77 
iterate(void)78 	IterateResult iterate (void)
79 	{
80 		TestLog&			log		= m_testCtx.getLog();
81 		tcu::CommandLine	cmdLine;
82 		int					numPass	= 0;
83 
84 		log << TestLog::Message << "Input:\n\"" << m_caseList << "\"" << TestLog::EndMessage;
85 
86 		{
87 			const char* argv[] =
88 			{
89 				"deqp",
90 				"--deqp-caselist",
91 				m_caseList
92 			};
93 
94 			if (!cmdLine.parse(DE_LENGTH_OF_ARRAY(argv), argv))
95 				TCU_FAIL("Failed to parse case list");
96 		}
97 
98 		for (int subCaseNdx = 0; subCaseNdx < m_numSubCases; subCaseNdx++)
99 		{
100 			const MatchCase&	curCase		= m_subCases[subCaseNdx];
101 			bool				matchGroup;
102 			bool				matchCase;
103 
104 			log << TestLog::Message << "Checking \"" << curCase.path << "\""
105 									<< ", expecting " << getMatchCaseExpectedDesc(curCase.expected)
106 				<< TestLog::EndMessage;
107 
108 			matchGroup	= cmdLine.checkTestGroupName(curCase.path);
109 			matchCase	= cmdLine.checkTestCaseName(curCase.path);
110 
111 			if ((matchGroup	== (curCase.expected == MatchCase::MATCH_GROUP)) &&
112 				(matchCase	== (curCase.expected == MatchCase::MATCH_CASE)))
113 			{
114 				log << TestLog::Message << "   pass" << TestLog::EndMessage;
115 				numPass += 1;
116 			}
117 			else
118 				log << TestLog::Message << "   FAIL!" << TestLog::EndMessage;
119 		}
120 
121 		m_testCtx.setTestResult((numPass == m_numSubCases) ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
122 								(numPass == m_numSubCases) ? "All passed"			: "Unexpected match result");
123 
124 		return STOP;
125 	}
126 
127 private:
128 	const char* const			m_caseList;
129 	const MatchCase* const		m_subCases;
130 	const int					m_numSubCases;
131 };
132 
133 class NegativeCaseListCase : public tcu::TestCase
134 {
135 public:
NegativeCaseListCase(tcu::TestContext & testCtx,const char * name,const char * caseList)136 	NegativeCaseListCase (tcu::TestContext& testCtx, const char* name, const char* caseList)
137 		: tcu::TestCase	(testCtx, name, "")
138 		, m_caseList	(caseList)
139 	{
140 	}
141 
iterate(void)142 	IterateResult iterate (void)
143 	{
144 		TestLog&			log		= m_testCtx.getLog();
145 		tcu::CommandLine	cmdLine;
146 
147 		log << TestLog::Message << "Input:\n\"" << m_caseList << "\"" << TestLog::EndMessage;
148 
149 		{
150 			const char* argv[] =
151 			{
152 				"deqp",
153 				"--deqp-caselist",
154 				m_caseList
155 			};
156 
157 			if (cmdLine.parse(DE_LENGTH_OF_ARRAY(argv), argv))
158 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Parsing passed, should have failed");
159 			else
160 				m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Parsing failed as expected");
161 		}
162 
163 		return STOP;
164 	}
165 
166 private:
167 	const char* const	m_caseList;
168 };
169 
170 class TrieParserTests : public tcu::TestCaseGroup
171 {
172 public:
TrieParserTests(tcu::TestContext & testCtx)173 	TrieParserTests (tcu::TestContext& testCtx)
174 		: tcu::TestCaseGroup(testCtx, "trie", "Test case trie parser tests")
175 	{
176 	}
177 
init(void)178 	void init (void)
179 	{
180 		{
181 			static const char* const	caseList	= "{test}";
182 			static const MatchCase		subCases[]	=
183 			{
184 				{ "test",		MatchCase::MATCH_CASE	},
185 				{ "test.cd",	MatchCase::NO_MATCH		},
186 			};
187 			addChild(new CaseListParserCase(m_testCtx, "single_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
188 		}
189 		{
190 			static const char* const	caseList	= "{a{b}}";
191 			static const MatchCase		subCases[]	=
192 			{
193 				{ "a",		MatchCase::MATCH_GROUP	},
194 				{ "b",		MatchCase::NO_MATCH		},
195 				{ "a.b",	MatchCase::MATCH_CASE	},
196 				{ "a.a",	MatchCase::NO_MATCH		},
197 			};
198 			addChild(new CaseListParserCase(m_testCtx, "simple_group_1", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
199 		}
200 		{
201 			static const char* const	caseList	= "{a{b,c}}";
202 			static const MatchCase		subCases[]	=
203 			{
204 				{ "a",		MatchCase::MATCH_GROUP	},
205 				{ "b",		MatchCase::NO_MATCH		},
206 				{ "a.b",	MatchCase::MATCH_CASE	},
207 				{ "a.a",	MatchCase::NO_MATCH		},
208 				{ "a.c",	MatchCase::MATCH_CASE	},
209 			};
210 			addChild(new CaseListParserCase(m_testCtx, "simple_group_2", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
211 		}
212 		{
213 			static const char* const	caseList	= "{a{b},c{d,e}}";
214 			static const MatchCase		subCases[]	=
215 			{
216 				{ "a",		MatchCase::MATCH_GROUP	},
217 				{ "b",		MatchCase::NO_MATCH		},
218 				{ "a.b",	MatchCase::MATCH_CASE	},
219 				{ "a.c",	MatchCase::NO_MATCH		},
220 				{ "a.d",	MatchCase::NO_MATCH		},
221 				{ "a.e",	MatchCase::NO_MATCH		},
222 				{ "c",		MatchCase::MATCH_GROUP	},
223 				{ "c.b",	MatchCase::NO_MATCH		},
224 				{ "c.d",	MatchCase::MATCH_CASE	},
225 				{ "c.e",	MatchCase::MATCH_CASE	},
226 			};
227 			addChild(new CaseListParserCase(m_testCtx, "two_groups", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
228 		}
229 		{
230 			static const char* const	caseList	= "{a,c{d,e}}";
231 			static const MatchCase		subCases[]	=
232 			{
233 				{ "a",		MatchCase::MATCH_CASE	},
234 				{ "b",		MatchCase::NO_MATCH		},
235 				{ "a.b",	MatchCase::NO_MATCH		},
236 				{ "a.c",	MatchCase::NO_MATCH		},
237 				{ "a.d",	MatchCase::NO_MATCH		},
238 				{ "a.e",	MatchCase::NO_MATCH		},
239 				{ "c",		MatchCase::MATCH_GROUP	},
240 				{ "c.b",	MatchCase::NO_MATCH		},
241 				{ "c.d",	MatchCase::MATCH_CASE	},
242 				{ "c.e",	MatchCase::MATCH_CASE	},
243 			};
244 			addChild(new CaseListParserCase(m_testCtx, "case_group", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
245 		}
246 		{
247 			static const char* const	caseList	= "{c{d,e},a}";
248 			static const MatchCase		subCases[]	=
249 			{
250 				{ "a",		MatchCase::MATCH_CASE	},
251 				{ "b",		MatchCase::NO_MATCH		},
252 				{ "a.b",	MatchCase::NO_MATCH		},
253 				{ "a.c",	MatchCase::NO_MATCH		},
254 				{ "a.d",	MatchCase::NO_MATCH		},
255 				{ "a.e",	MatchCase::NO_MATCH		},
256 				{ "c",		MatchCase::MATCH_GROUP	},
257 				{ "c.b",	MatchCase::NO_MATCH		},
258 				{ "c.d",	MatchCase::MATCH_CASE	},
259 				{ "c.e",	MatchCase::MATCH_CASE	},
260 			};
261 			addChild(new CaseListParserCase(m_testCtx, "group_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
262 		}
263 		{
264 			static const char* const	caseList	= "{test}\r";
265 			static const MatchCase		subCases[]	=
266 			{
267 				{ "test",		MatchCase::MATCH_CASE	},
268 				{ "test.cd",	MatchCase::NO_MATCH		},
269 			};
270 			addChild(new CaseListParserCase(m_testCtx, "trailing_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
271 		}
272 		{
273 			static const char* const	caseList	= "{test}\n";
274 			static const MatchCase		subCases[]	=
275 			{
276 				{ "test",		MatchCase::MATCH_CASE	},
277 				{ "test.cd",	MatchCase::NO_MATCH		},
278 			};
279 			addChild(new CaseListParserCase(m_testCtx, "trailing_lf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
280 		}
281 		{
282 			static const char* const	caseList	= "{test}\r\n";
283 			static const MatchCase		subCases[]	=
284 			{
285 				{ "test",		MatchCase::MATCH_CASE	},
286 				{ "test.cd",	MatchCase::NO_MATCH		},
287 			};
288 			addChild(new CaseListParserCase(m_testCtx, "trailing_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
289 		}
290 
291 		// Negative tests
292 		addChild(new NegativeCaseListCase(m_testCtx, "empty_string",			""));
293 		addChild(new NegativeCaseListCase(m_testCtx, "empty_line",				"\n"));
294 		addChild(new NegativeCaseListCase(m_testCtx, "empty_root",				"{}"));
295 		addChild(new NegativeCaseListCase(m_testCtx, "empty_group",				"{test{}}"));
296 		addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name_1",		"{{}}"));
297 		addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name_2",		"{{test}}"));
298 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_1",		"{"));
299 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_2",		"{test"));
300 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_3",		"{test,"));
301 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_4",		"{test{a}"));
302 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_5",		"{a,b"));
303 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_1",	"{test{"));
304 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_2",	"{test{a"));
305 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_3",	"{test{a,"));
306 		addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_4",	"{test{a,b"));
307 		addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_1",		"{a,,b}"));
308 		addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_2",		"{,b}"));
309 		addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_3",		"{a,}"));
310 		addChild(new NegativeCaseListCase(m_testCtx, "no_separator",			"{a{b}c}"));
311 		addChild(new NegativeCaseListCase(m_testCtx, "invalid_char_1",			"{a.b}"));
312 		addChild(new NegativeCaseListCase(m_testCtx, "invalid_char_2",			"{a[]}"));
313 		addChild(new NegativeCaseListCase(m_testCtx, "trailing_char_1",			"{a}}"));
314 		addChild(new NegativeCaseListCase(m_testCtx, "trailing_char_2",			"{a}x"));
315 		addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_1",		"{\na}"));
316 		addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_2",		"{a\n,b}"));
317 		addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_3",		"{a,\nb}"));
318 		addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_4",		"{a{b\n}}"));
319 		addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_5",		"{a{b}\n}"));
320 	}
321 };
322 
323 class ListParserTests : public tcu::TestCaseGroup
324 {
325 public:
ListParserTests(tcu::TestContext & testCtx)326 	ListParserTests (tcu::TestContext& testCtx)
327 		: tcu::TestCaseGroup(testCtx, "list", "Test case list parser tests")
328 	{
329 	}
330 
init(void)331 	void init (void)
332 	{
333 		{
334 			static const char* const	caseList	= "test";
335 			static const MatchCase		subCases[]	=
336 			{
337 				{ "test",		MatchCase::MATCH_CASE	},
338 				{ "test.cd",	MatchCase::NO_MATCH		},
339 			};
340 			addChild(new CaseListParserCase(m_testCtx, "single_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
341 		}
342 		{
343 			static const char* const	caseList	= "a.b";
344 			static const MatchCase		subCases[]	=
345 			{
346 				{ "a",		MatchCase::MATCH_GROUP	},
347 				{ "b",		MatchCase::NO_MATCH		},
348 				{ "a.b",	MatchCase::MATCH_CASE	},
349 				{ "a.a",	MatchCase::NO_MATCH		},
350 			};
351 			addChild(new CaseListParserCase(m_testCtx, "simple_group_1", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
352 		}
353 		{
354 			static const char* const	caseList	= "a.b\na.c";
355 			static const MatchCase		subCases[]	=
356 			{
357 				{ "a",		MatchCase::MATCH_GROUP	},
358 				{ "b",		MatchCase::NO_MATCH		},
359 				{ "a.b",	MatchCase::MATCH_CASE	},
360 				{ "a.a",	MatchCase::NO_MATCH		},
361 				{ "a.c",	MatchCase::MATCH_CASE	},
362 			};
363 			addChild(new CaseListParserCase(m_testCtx, "simple_group_2", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
364 		}
365 		{
366 			static const char* const	caseList	= "a.b\na.c";
367 			static const MatchCase		subCases[]	=
368 			{
369 				{ "a",		MatchCase::MATCH_GROUP	},
370 				{ "b",		MatchCase::NO_MATCH		},
371 				{ "a.b",	MatchCase::MATCH_CASE	},
372 				{ "a.a",	MatchCase::NO_MATCH		},
373 				{ "a.c",	MatchCase::MATCH_CASE	},
374 			};
375 			addChild(new CaseListParserCase(m_testCtx, "separator_ln", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
376 		}
377 		{
378 			static const char* const	caseList	= "a.b\ra.c";
379 			static const MatchCase		subCases[]	=
380 			{
381 				{ "a",		MatchCase::MATCH_GROUP	},
382 				{ "b",		MatchCase::NO_MATCH		},
383 				{ "a.b",	MatchCase::MATCH_CASE	},
384 				{ "a.a",	MatchCase::NO_MATCH		},
385 				{ "a.c",	MatchCase::MATCH_CASE	},
386 			};
387 			addChild(new CaseListParserCase(m_testCtx, "separator_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
388 		}
389 		{
390 			static const char* const	caseList	= "a.b\r\na.c";
391 			static const MatchCase		subCases[]	=
392 			{
393 				{ "a",		MatchCase::MATCH_GROUP	},
394 				{ "b",		MatchCase::NO_MATCH		},
395 				{ "a.b",	MatchCase::MATCH_CASE	},
396 				{ "a.a",	MatchCase::NO_MATCH		},
397 				{ "a.c",	MatchCase::MATCH_CASE	},
398 			};
399 			addChild(new CaseListParserCase(m_testCtx, "separator_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
400 		}
401 		{
402 			static const char* const	caseList	= "a.b\na.c\n";
403 			static const MatchCase		subCases[]	=
404 			{
405 				{ "a",		MatchCase::MATCH_GROUP	},
406 				{ "b",		MatchCase::NO_MATCH		},
407 				{ "a.b",	MatchCase::MATCH_CASE	},
408 				{ "a.a",	MatchCase::NO_MATCH		},
409 				{ "a.c",	MatchCase::MATCH_CASE	},
410 			};
411 			addChild(new CaseListParserCase(m_testCtx, "end_ln", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
412 		}
413 		{
414 			static const char* const	caseList	= "a.b\na.c\r";
415 			static const MatchCase		subCases[]	=
416 			{
417 				{ "a",		MatchCase::MATCH_GROUP	},
418 				{ "b",		MatchCase::NO_MATCH		},
419 				{ "a.b",	MatchCase::MATCH_CASE	},
420 				{ "a.a",	MatchCase::NO_MATCH		},
421 				{ "a.c",	MatchCase::MATCH_CASE	},
422 			};
423 			addChild(new CaseListParserCase(m_testCtx, "end_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
424 		}
425 		{
426 			static const char* const	caseList	= "a.b\na.c\r\n";
427 			static const MatchCase		subCases[]	=
428 			{
429 				{ "a",		MatchCase::MATCH_GROUP	},
430 				{ "b",		MatchCase::NO_MATCH		},
431 				{ "a.b",	MatchCase::MATCH_CASE	},
432 				{ "a.a",	MatchCase::NO_MATCH		},
433 				{ "a.c",	MatchCase::MATCH_CASE	},
434 			};
435 			addChild(new CaseListParserCase(m_testCtx, "end_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
436 		}
437 		{
438 			static const char* const	caseList	= "a.b\nc.d\nc.e";
439 			static const MatchCase		subCases[]	=
440 			{
441 				{ "a",		MatchCase::MATCH_GROUP	},
442 				{ "b",		MatchCase::NO_MATCH		},
443 				{ "a.b",	MatchCase::MATCH_CASE	},
444 				{ "a.c",	MatchCase::NO_MATCH		},
445 				{ "a.d",	MatchCase::NO_MATCH		},
446 				{ "a.e",	MatchCase::NO_MATCH		},
447 				{ "c",		MatchCase::MATCH_GROUP	},
448 				{ "c.b",	MatchCase::NO_MATCH		},
449 				{ "c.d",	MatchCase::MATCH_CASE	},
450 				{ "c.e",	MatchCase::MATCH_CASE	},
451 			};
452 			addChild(new CaseListParserCase(m_testCtx, "two_groups", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
453 		}
454 		{
455 			static const char* const	caseList	= "a\nc.d\nc.e";
456 			static const MatchCase		subCases[]	=
457 			{
458 				{ "a",		MatchCase::MATCH_CASE	},
459 				{ "b",		MatchCase::NO_MATCH		},
460 				{ "a.b",	MatchCase::NO_MATCH		},
461 				{ "a.c",	MatchCase::NO_MATCH		},
462 				{ "a.d",	MatchCase::NO_MATCH		},
463 				{ "a.e",	MatchCase::NO_MATCH		},
464 				{ "c",		MatchCase::MATCH_GROUP	},
465 				{ "c.b",	MatchCase::NO_MATCH		},
466 				{ "c.d",	MatchCase::MATCH_CASE	},
467 				{ "c.e",	MatchCase::MATCH_CASE	},
468 			};
469 			addChild(new CaseListParserCase(m_testCtx, "case_group", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
470 		}
471 		{
472 			static const char* const	caseList	= "c.d\nc.e\na";
473 			static const MatchCase		subCases[]	=
474 			{
475 				{ "a",		MatchCase::MATCH_CASE	},
476 				{ "b",		MatchCase::NO_MATCH		},
477 				{ "a.b",	MatchCase::NO_MATCH		},
478 				{ "a.c",	MatchCase::NO_MATCH		},
479 				{ "a.d",	MatchCase::NO_MATCH		},
480 				{ "a.e",	MatchCase::NO_MATCH		},
481 				{ "c",		MatchCase::MATCH_GROUP	},
482 				{ "c.b",	MatchCase::NO_MATCH		},
483 				{ "c.d",	MatchCase::MATCH_CASE	},
484 				{ "c.e",	MatchCase::MATCH_CASE	},
485 			};
486 			addChild(new CaseListParserCase(m_testCtx, "group_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
487 		}
488 		{
489 			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";
490 			static const MatchCase		subCases[]	=
491 			{
492 				{ "a",												MatchCase::MATCH_GROUP	},
493 				{ "b",												MatchCase::NO_MATCH		},
494 				{ "a.b",											MatchCase::MATCH_GROUP	},
495 				{ "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	},
496 			};
497 			addChild(new CaseListParserCase(m_testCtx, "long_name", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
498 		}
499 		{
500 			static const char* const	caseList	=
501 				"a.b.c.d.e\n"
502 				"a.b.c.f\n"
503 				"x.y.z\n"
504 				"a.b.c.d.g\n"
505 				"a.b.c.x\n";
506 			static const MatchCase		subCases[]	=
507 			{
508 				{ "a",				MatchCase::MATCH_GROUP	},
509 				{ "a.b",			MatchCase::MATCH_GROUP	},
510 				{ "a.b.c.d.e",		MatchCase::MATCH_CASE	},
511 				{ "a.b.c.d.g",		MatchCase::MATCH_CASE	},
512 				{ "x.y",			MatchCase::MATCH_GROUP	},
513 				{ "x.y.z",			MatchCase::MATCH_CASE	},
514 				{ "a.b.c.f",		MatchCase::MATCH_CASE	},
515 				{ "a.b.c.x",		MatchCase::MATCH_CASE	},
516 			};
517 			addChild(new CaseListParserCase(m_testCtx, "partial_prefix", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
518 		}
519 		{
520 			static const char* const	caseList	=
521 				"a.a.c.d\n"
522 				"a.b.c.d\n";
523 			static const MatchCase		subCases[]	=
524 			{
525 				{ "a",				MatchCase::MATCH_GROUP	},
526 				{ "a.a",			MatchCase::MATCH_GROUP	},
527 				{ "a.b.c.d",		MatchCase::MATCH_CASE	},
528 				{ "a.b.c.d",		MatchCase::MATCH_CASE	},
529 			};
530 			addChild(new CaseListParserCase(m_testCtx, "reparenting", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases)));
531 		}
532 
533 		// Negative tests
534 		addChild(new NegativeCaseListCase(m_testCtx, "empty_string",			""));
535 		addChild(new NegativeCaseListCase(m_testCtx, "empty_line",				"\n"));
536 		addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name",		".test"));
537 		addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name",			"test."));
538 	}
539 };
540 
541 class CaseListParserTests : public tcu::TestCaseGroup
542 {
543 public:
CaseListParserTests(tcu::TestContext & testCtx)544 	CaseListParserTests (tcu::TestContext& testCtx)
545 		: tcu::TestCaseGroup(testCtx, "case_list_parser", "Test case list parser tests")
546 	{
547 	}
548 
init(void)549 	void init (void)
550 	{
551 		addChild(new TrieParserTests(m_testCtx));
552 		addChild(new ListParserTests(m_testCtx));
553 	}
554 };
555 
ulpDiff(float a,float b)556 inline deUint32 ulpDiff (float a, float b)
557 {
558 	const deUint32 ab = tcu::Float32(a).bits();
559 	const deUint32 bb = tcu::Float32(b).bits();
560 	return de::max(ab, bb) - de::min(ab, bb);
561 }
562 
563 template<int Size>
ulpDiff(const tcu::Vector<float,Size> & a,const tcu::Vector<float,Size> & b)564 inline tcu::Vector<deUint32, Size> ulpDiff (const tcu::Vector<float, Size>& a, const tcu::Vector<float,  Size>& b)
565 {
566 	tcu::Vector<deUint32, Size> res;
567 	for (int ndx = 0; ndx < Size; ndx++)
568 		res[ndx] = ulpDiff(a[ndx], b[ndx]);
569 	return res;
570 }
571 
572 class ConstantInterpolationTest : public tcu::TestCase
573 {
574 public:
ConstantInterpolationTest(tcu::TestContext & testCtx)575 	ConstantInterpolationTest (tcu::TestContext& testCtx)
576 		: tcu::TestCase(testCtx, "const_interpolation", "Constant value interpolation")
577 	{
578 		const int supportedMsaaLevels[] = {1, 2, 4, 8, 16};
579 
580 		for (int msaaNdx = 0; msaaNdx < DE_LENGTH_OF_ARRAY(supportedMsaaLevels); msaaNdx++)
581 		{
582 			const int numSamples = supportedMsaaLevels[msaaNdx];
583 			{
584 				SubCase c;
585 				c.rtSize	= tcu::IVec3(128, 128, numSamples);
586 				c.vtx[0]	= tcu::Vec4(-1.0f, -1.0f, 0.5f, 1.0f);
587 				c.vtx[1]	= tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f);
588 				c.vtx[2]	= tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f);
589 				c.varying	= tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f);
590 				m_cases.push_back(c);
591 			}
592 
593 			{
594 				SubCase c;
595 				c.rtSize	= tcu::IVec3(128, 128, numSamples);
596 				c.vtx[0]	= tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f);
597 				c.vtx[1]	= tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f);
598 				c.vtx[2]	= tcu::Vec4(+1.0f, +1.0f, 0.5f, 1.0f);
599 				c.varying	= tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f);
600 				m_cases.push_back(c);
601 			}
602 			{
603 				SubCase c;
604 				c.rtSize	= tcu::IVec3(129, 113, numSamples);
605 				c.vtx[0]	= tcu::Vec4(-1.0f, -1.0f, 0.5f, 1.0f);
606 				c.vtx[1]	= tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f);
607 				c.vtx[2]	= tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f);
608 				c.varying	= tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f);
609 				m_cases.push_back(c);
610 			}
611 			{
612 				SubCase c;
613 				c.rtSize	= tcu::IVec3(107, 131, numSamples);
614 				c.vtx[0]	= tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f);
615 				c.vtx[1]	= tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f);
616 				c.vtx[2]	= tcu::Vec4(+1.0f, +1.0f, 0.5f, 1.0f);
617 				c.varying	= tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f);
618 				m_cases.push_back(c);
619 			}
620 		}
621 
622 		{
623 			de::Random rnd(0x89423f);
624 			for (int ndx = 0; ndx < 25; ndx++)
625 			{
626 				const float	depth	= rnd.getFloat()*2.0f - 1.0f;
627 				SubCase		c;
628 
629 				c.rtSize.x() = rnd.getInt(16, 256);
630 				c.rtSize.y() = rnd.getInt(16, 256);
631 				c.rtSize.z() = rnd.choose<int>(DE_ARRAY_BEGIN(supportedMsaaLevels), DE_ARRAY_END(supportedMsaaLevels));
632 
633 				for (int vtxNdx = 0; vtxNdx < DE_LENGTH_OF_ARRAY(c.vtx); vtxNdx++)
634 				{
635 					c.vtx[vtxNdx].x() = rnd.getFloat()*2.0f - 1.0f;
636 					c.vtx[vtxNdx].y() = rnd.getFloat()*2.0f - 1.0f;
637 					c.vtx[vtxNdx].z() = depth;
638 					c.vtx[vtxNdx].w() = 1.0f;
639 				}
640 
641 				for (int compNdx = 0; compNdx < 4; compNdx++)
642 				{
643 					float v;
644 					do
645 					{
646 						v = tcu::Float32(rnd.getUint32()).asFloat();
647 					} while (deFloatIsInf(v) || deFloatIsNaN(v));
648 					c.varying[compNdx] = v;
649 				}
650 				m_cases.push_back(c);
651 			}
652 		}
653 	}
654 
init(void)655 	void init (void)
656 	{
657 		m_caseIter = m_cases.begin();
658 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "All iterations passed");
659 	}
660 
iterate(void)661 	IterateResult iterate (void)
662 	{
663 		{
664 			tcu::ScopedLogSection section(m_testCtx.getLog(), "SubCase", "");
665 			runCase(*m_caseIter);
666 		}
667 		return (++m_caseIter != m_cases.end()) ? CONTINUE : STOP;
668 	}
669 
670 protected:
671 	struct SubCase
672 	{
673 		tcu::IVec3	rtSize;	// (width, height, samples)
674 		tcu::Vec4	vtx[3];
675 		tcu::Vec4	varying;
676 	};
677 
runCase(const SubCase & subCase)678 	void runCase (const SubCase& subCase)
679 	{
680 		using namespace tcu;
681 
682 		const deUint32	maxColorUlpDiff	= 2;
683 		const deUint32	maxDepthUlpDiff	= 0;
684 
685 		const int		width			= subCase.rtSize.x();
686 		const int		height			= subCase.rtSize.y();
687 		const int		numSamples		= subCase.rtSize.z();
688 		const float		zn				= 0.0f;
689 		const float		zf				= 1.0f;
690 
691 		TextureLevel	interpolated	(TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT), numSamples, width, height);
692 		TextureLevel	depthStencil	(TextureFormat(TextureFormat::DS, TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV), numSamples, width, height);
693 
694 		m_testCtx.getLog() << TestLog::Message
695 						   << "RT size (w, h, #samples) = " << subCase.rtSize << "\n"
696 						   << "vtx[0] = " << subCase.vtx[0] << "\n"
697 						   << "vtx[1] = " << subCase.vtx[1] << "\n"
698 						   << "vtx[2] = " << subCase.vtx[2] << "\n"
699 						   << "color = " << subCase.varying
700 						   << TestLog::EndMessage;
701 
702 		clear			(interpolated.getAccess(), subCase.varying - Vec4(0.0f, 0.0f, 0.0f, 1.0f));
703 		clearDepth		(depthStencil.getAccess(), 0.0f);
704 		clearStencil	(depthStencil.getAccess(), 0);
705 
706 		{
707 			class VtxShader : public rr::VertexShader
708 			{
709 			public:
710 				VtxShader (void)
711 					: rr::VertexShader(2, 1)
712 				{
713 					m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
714 					m_inputs[1].type	= rr::GENERICVECTYPE_FLOAT;
715 					m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
716 				}
717 
718 				void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
719 				{
720 					for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
721 					{
722 						rr::readVertexAttrib(packets[packetNdx]->position, inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
723 						packets[packetNdx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
724 					}
725 				}
726 			} vtxShader;
727 
728 			class FragShader : public rr::FragmentShader
729 			{
730 			public:
731 				FragShader (void)
732 					: rr::FragmentShader(1, 1)
733 				{
734 					m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
735 					m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
736 				}
737 
738 				void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
739 				{
740 					for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
741 					{
742 						for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
743 						{
744 							const tcu::Vec4 interp = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
745 							rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, interp);
746 						}
747 					}
748 				}
749 			} fragShader;
750 
751 			const rr::Program						program			(&vtxShader, &fragShader);
752 
753 			const rr::MultisamplePixelBufferAccess	colorAccess		= rr::MultisamplePixelBufferAccess::fromMultisampleAccess(interpolated.getAccess());
754 			const rr::MultisamplePixelBufferAccess	dsAccess		= rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthStencil.getAccess());
755 			const rr::RenderTarget					renderTarget	(colorAccess, dsAccess, dsAccess);
756 			const rr::VertexAttrib					vertexAttribs[]	=
757 			{
758 				rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, 0, 0, subCase.vtx),
759 				rr::VertexAttrib(subCase.varying)
760 			};
761 			rr::ViewportState						viewport		(colorAccess);
762 			rr::RenderState							state			(viewport);
763 			const rr::DrawCommand					drawCmd			(state, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0));
764 			const rr::Renderer						renderer;
765 
766 			viewport.zn	= zn;
767 			viewport.zf	= zf;
768 
769 			state.fragOps.depthTestEnabled							= true;
770 			state.fragOps.depthFunc									= rr::TESTFUNC_ALWAYS;
771 			state.fragOps.stencilTestEnabled						= true;
772 			state.fragOps.stencilStates[rr::FACETYPE_BACK].func		= rr::TESTFUNC_ALWAYS;
773 			state.fragOps.stencilStates[rr::FACETYPE_BACK].dpPass	= rr::STENCILOP_INCR;
774 			state.fragOps.stencilStates[rr::FACETYPE_FRONT]			= state.fragOps.stencilStates[rr::FACETYPE_BACK];
775 
776 			renderer.draw(drawCmd);
777 		}
778 
779 		// Verify interpolated values
780 		{
781 			TextureLevel					resolvedColor			(interpolated.getFormat(), width, height); // For debugging
782 			TextureLevel					resolvedDepthStencil	(depthStencil.getFormat(), width, height); // For debugging
783 			TextureLevel					errorMask				(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height);
784 			const ConstPixelBufferAccess	interpAccess			= interpolated.getAccess();
785 			const ConstPixelBufferAccess	dsAccess				= depthStencil.getAccess();
786 			const PixelBufferAccess			errorAccess				= errorMask.getAccess();
787 			int								numCoveredSamples		= 0;
788 			int								numFailedColorSamples	= 0;
789 			int								numFailedDepthSamples	= 0;
790 			const bool						verifyDepth				= (subCase.vtx[0].z() == subCase.vtx[1].z()) &&
791 																	  (subCase.vtx[1].z() == subCase.vtx[2].z());
792 			const float						refDepth				= subCase.vtx[0].z()*(zf - zn)/2.0f + (zn + zf)/2.0f;
793 
794 			rr::resolveMultisampleColorBuffer(resolvedColor.getAccess(), rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(interpolated.getAccess()));
795 			rr::resolveMultisampleColorBuffer(resolvedDepthStencil.getAccess(), rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(depthStencil.getAccess()));
796 			clear(errorAccess, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
797 
798 			for (int y = 0; y < height; y++)
799 			{
800 				for (int x = 0; x < width; x++)
801 				{
802 					for (int sampleNdx = 0; sampleNdx < numSamples; sampleNdx++)
803 					{
804 						if (dsAccess.getPixStencil(sampleNdx, x, y) != 0)
805 						{
806 							const Vec4		color		= interpAccess.getPixel(sampleNdx, x, y);
807 							const UVec4		colorDiff	= ulpDiff(color, subCase.varying);
808 							const bool		colorOk		= boolAll(lessThanEqual(colorDiff, tcu::UVec4(maxColorUlpDiff)));
809 
810 							const float		depth		= dsAccess.getPixDepth(sampleNdx, x, y);
811 							const deUint32	depthDiff	= ulpDiff(depth, refDepth);
812 							const bool		depthOk		= verifyDepth && (depthDiff <= maxDepthUlpDiff);
813 
814 							const int		maxMsgs		= 10;
815 
816 							numCoveredSamples += 1;
817 
818 							if (!colorOk)
819 							{
820 								numFailedColorSamples += 1;
821 
822 								if (numFailedColorSamples <= maxMsgs)
823 									m_testCtx.getLog() << TestLog::Message
824 													   << "FAIL: " << tcu::IVec3(x, y, sampleNdx)
825 													   << " color ulp diff = " << colorDiff
826 													   << TestLog::EndMessage;
827 							}
828 
829 							if (!depthOk)
830 								numFailedDepthSamples += 1;
831 
832 							if (!colorOk || !depthOk)
833 								errorAccess.setPixel(errorAccess.getPixel(x, y) + Vec4(1.0f, -1.0f, 0.0f, 0.0f) / float(numSamples-1), x, y);
834 						}
835 					}
836 				}
837 			}
838 
839 			m_testCtx.getLog() << TestLog::Image("ResolvedColor", "Resolved colorbuffer", resolvedColor)
840 							   << TestLog::Image("ResolvedDepthStencil", "Resolved depth- & stencilbuffer", resolvedDepthStencil);
841 
842 			if (numFailedColorSamples != 0 || numFailedDepthSamples != 0)
843 			{
844 				m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask);
845 
846 				if (numFailedColorSamples != 0)
847 					m_testCtx.getLog() << TestLog::Message << "FAIL: Found " << numFailedColorSamples << " invalid color samples!" << TestLog::EndMessage;
848 
849 				if (numFailedDepthSamples != 0)
850 					m_testCtx.getLog() << TestLog::Message << "FAIL: Found " << numFailedDepthSamples << " invalid depth samples!" << TestLog::EndMessage;
851 
852 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
853 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid samples found");
854 			}
855 
856 			m_testCtx.getLog() << TestLog::Message << (numCoveredSamples-numFailedColorSamples) << " / " << numCoveredSamples << " color samples passed" << TestLog::EndMessage;
857 			m_testCtx.getLog() << TestLog::Message << (numCoveredSamples-numFailedDepthSamples) << " / " << numCoveredSamples << " depth samples passed" << TestLog::EndMessage;
858 		}
859 	}
860 
861 	vector<SubCase>					m_cases;
862 	vector<SubCase>::const_iterator	m_caseIter;
863 };
864 
865 class CommonFrameworkTests : public tcu::TestCaseGroup
866 {
867 public:
CommonFrameworkTests(tcu::TestContext & testCtx)868 	CommonFrameworkTests (tcu::TestContext& testCtx)
869 		: tcu::TestCaseGroup(testCtx, "common", "Tests for the common utility framework")
870 	{
871 	}
872 
init(void)873 	void init (void)
874 	{
875 		addChild(new SelfCheckCase(m_testCtx, "float_format","tcu::FloatFormat_selfTest()",
876 								   tcu::FloatFormat_selfTest));
877 		addChild(new SelfCheckCase(m_testCtx, "either","tcu::Either_selfTest()",
878 								   tcu::Either_selfTest));
879 	}
880 };
881 
882 class ReferenceRendererTests : public tcu::TestCaseGroup
883 {
884 public:
ReferenceRendererTests(tcu::TestContext & testCtx)885 	ReferenceRendererTests (tcu::TestContext& testCtx)
886 		: tcu::TestCaseGroup(testCtx, "reference_renderer", "Reference renderer tests")
887 	{
888 	}
889 
init(void)890 	void init (void)
891 	{
892 		addChild(new ConstantInterpolationTest(m_testCtx));
893 	}
894 };
895 
896 } // anonymous
897 
FrameworkTests(tcu::TestContext & testCtx)898 FrameworkTests::FrameworkTests (tcu::TestContext& testCtx)
899 	: tcu::TestCaseGroup(testCtx, "framework", "Miscellaneous framework tests")
900 {
901 }
902 
~FrameworkTests(void)903 FrameworkTests::~FrameworkTests (void)
904 {
905 }
906 
init(void)907 void FrameworkTests::init (void)
908 {
909 	addChild(new CommonFrameworkTests	(m_testCtx));
910 	addChild(new CaseListParserTests	(m_testCtx));
911 	addChild(new ReferenceRendererTests	(m_testCtx));
912 }
913 
914 }
915