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