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 namespace dit
43 {
44 
45 namespace
46 {
47 
48 using std::string;
49 using std::vector;
50 using tcu::TestLog;
51 
52 struct MatchCase
53 {
54 	enum Expected { NO_MATCH, MATCH_GROUP, MATCH_CASE, EXPECTED_LAST };
55 
56 	const char*	path;
57 	Expected	expected;
58 };
59 
getMatchCaseExpectedDesc(MatchCase::Expected expected)60 const 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 
71 class CaseListParserCase : public tcu::TestCase
72 {
73 public:
CaseListParserCase(tcu::TestContext & testCtx,const char * name,const char * caseList,const MatchCase * subCases,int numSubCases)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 
iterate(void)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 
131 private:
132 	const char* const			m_caseList;
133 	const MatchCase* const		m_subCases;
134 	const int					m_numSubCases;
135 };
136 
137 class NegativeCaseListCase : public tcu::TestCase
138 {
139 public:
NegativeCaseListCase(tcu::TestContext & testCtx,const char * name,const char * caseList)140 	NegativeCaseListCase (tcu::TestContext& testCtx, const char* name, const char* caseList)
141 		: tcu::TestCase	(testCtx, name, "")
142 		, m_caseList	(caseList)
143 	{
144 	}
145 
iterate(void)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 
170 private:
171 	const char* const	m_caseList;
172 };
173 
174 class TrieParserTests : public tcu::TestCaseGroup
175 {
176 public:
TrieParserTests(tcu::TestContext & testCtx)177 	TrieParserTests (tcu::TestContext& testCtx)
178 		: tcu::TestCaseGroup(testCtx, "trie", "Test case trie parser tests")
179 	{
180 	}
181 
init(void)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 
327 class ListParserTests : public tcu::TestCaseGroup
328 {
329 public:
ListParserTests(tcu::TestContext & testCtx)330 	ListParserTests (tcu::TestContext& testCtx)
331 		: tcu::TestCaseGroup(testCtx, "list", "Test case list parser tests")
332 	{
333 	}
334 
init(void)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 
545 class CaseListParserTests : public tcu::TestCaseGroup
546 {
547 public:
CaseListParserTests(tcu::TestContext & testCtx)548 	CaseListParserTests (tcu::TestContext& testCtx)
549 		: tcu::TestCaseGroup(testCtx, "case_list_parser", "Test case list parser tests")
550 	{
551 	}
552 
init(void)553 	void init (void)
554 	{
555 		addChild(new TrieParserTests(m_testCtx));
556 		addChild(new ListParserTests(m_testCtx));
557 	}
558 };
559 
ulpDiff(float a,float b)560 inline 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 
567 template<int Size>
ulpDiff(const tcu::Vector<float,Size> & a,const tcu::Vector<float,Size> & b)568 inline 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 
576 class ConstantInterpolationTest : public tcu::TestCase
577 {
578 public:
ConstantInterpolationTest(tcu::TestContext & testCtx)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 
init(void)659 	void init (void)
660 	{
661 		m_caseIter = m_cases.begin();
662 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "All iterations passed");
663 	}
664 
iterate(void)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 
674 protected:
675 	struct SubCase
676 	{
677 		tcu::IVec3	rtSize;	// (width, height, samples)
678 		tcu::Vec4	vtx[3];
679 		tcu::Vec4	varying;
680 	};
681 
runCase(const SubCase & subCase)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 
869 class CommonFrameworkTests : public tcu::TestCaseGroup
870 {
871 public:
CommonFrameworkTests(tcu::TestContext & testCtx)872 	CommonFrameworkTests (tcu::TestContext& testCtx)
873 		: tcu::TestCaseGroup(testCtx, "common", "Tests for the common utility framework")
874 	{
875 	}
876 
init(void)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 
886 class ReferenceRendererTests : public tcu::TestCaseGroup
887 {
888 public:
ReferenceRendererTests(tcu::TestContext & testCtx)889 	ReferenceRendererTests (tcu::TestContext& testCtx)
890 		: tcu::TestCaseGroup(testCtx, "reference_renderer", "Reference renderer tests")
891 	{
892 	}
893 
init(void)894 	void init (void)
895 	{
896 		addChild(new ConstantInterpolationTest(m_testCtx));
897 	}
898 };
899 
900 } // anonymous
901 
FrameworkTests(tcu::TestContext & testCtx)902 FrameworkTests::FrameworkTests (tcu::TestContext& testCtx)
903 	: tcu::TestCaseGroup(testCtx, "framework", "Miscellaneous framework tests")
904 {
905 }
906 
~FrameworkTests(void)907 FrameworkTests::~FrameworkTests (void)
908 {
909 }
910 
init(void)911 void 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