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