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