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