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