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