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