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 #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 
     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:
     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 
     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:
    145 	NegativeCaseListCase (tcu::TestContext& testCtx, const char* name, const char* caseList)
    146 		: tcu::TestCase	(testCtx, name, "")
    147 		, m_caseList	(caseList)
    148 	{
    149 	}
    150 
    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:
    191 	TrieParserTests (tcu::TestContext& testCtx)
    192 		: tcu::TestCaseGroup(testCtx, "trie", "Test case trie parser tests")
    193 	{
    194 	}
    195 
    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:
    344 	ListParserTests (tcu::TestContext& testCtx)
    345 		: tcu::TestCaseGroup(testCtx, "list", "Test case list parser tests")
    346 	{
    347 	}
    348 
    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:
    562 	CaseListParserTests (tcu::TestContext& testCtx)
    563 		: tcu::TestCaseGroup(testCtx, "case_list_parser", "Test case list parser tests")
    564 	{
    565 	}
    566 
    567 	void init (void)
    568 	{
    569 		addChild(new TrieParserTests(m_testCtx));
    570 		addChild(new ListParserTests(m_testCtx));
    571 	}
    572 };
    573 
    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>
    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:
    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 
    673 	void init (void)
    674 	{
    675 		m_caseIter = m_cases.begin();
    676 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "All iterations passed");
    677 	}
    678 
    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 
    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:
    886 	CommonFrameworkTests (tcu::TestContext& testCtx)
    887 		: tcu::TestCaseGroup(testCtx, "common", "Tests for the common utility framework")
    888 	{
    889 	}
    890 
    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:
    903 	ReferenceRendererTests (tcu::TestContext& testCtx)
    904 		: tcu::TestCaseGroup(testCtx, "reference_renderer", "Reference renderer tests")
    905 	{
    906 	}
    907 
    908 	void init (void)
    909 	{
    910 		addChild(new ConstantInterpolationTest(m_testCtx));
    911 	}
    912 };
    913 
    914 } // anonymous
    915 
    916 FrameworkTests::FrameworkTests (tcu::TestContext& testCtx)
    917 	: tcu::TestCaseGroup(testCtx, "framework", "Miscellaneous framework tests")
    918 {
    919 }
    920 
    921 FrameworkTests::~FrameworkTests (void)
    922 {
    923 }
    924 
    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