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
getMatchCaseExpectedDesc(MatchCase::Expected expected)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:
CaseListParserCase(tcu::TestContext & testCtx,const char * name,const char * caseList,const MatchCase * subCases,int numSubCases)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
iterate(void)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:
NegativeCaseListCase(tcu::TestContext & testCtx,const char * name,const char * caseList)136 NegativeCaseListCase (tcu::TestContext& testCtx, const char* name, const char* caseList)
137 : tcu::TestCase (testCtx, name, "")
138 , m_caseList (caseList)
139 {
140 }
141
iterate(void)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:
TrieParserTests(tcu::TestContext & testCtx)173 TrieParserTests (tcu::TestContext& testCtx)
174 : tcu::TestCaseGroup(testCtx, "trie", "Test case trie parser tests")
175 {
176 }
177
init(void)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:
ListParserTests(tcu::TestContext & testCtx)326 ListParserTests (tcu::TestContext& testCtx)
327 : tcu::TestCaseGroup(testCtx, "list", "Test case list parser tests")
328 {
329 }
330
init(void)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:
CaseListParserTests(tcu::TestContext & testCtx)544 CaseListParserTests (tcu::TestContext& testCtx)
545 : tcu::TestCaseGroup(testCtx, "case_list_parser", "Test case list parser tests")
546 {
547 }
548
init(void)549 void init (void)
550 {
551 addChild(new TrieParserTests(m_testCtx));
552 addChild(new ListParserTests(m_testCtx));
553 }
554 };
555
ulpDiff(float a,float b)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>
ulpDiff(const tcu::Vector<float,Size> & a,const tcu::Vector<float,Size> & b)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:
ConstantInterpolationTest(tcu::TestContext & testCtx)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
init(void)655 void init (void)
656 {
657 m_caseIter = m_cases.begin();
658 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "All iterations passed");
659 }
660
iterate(void)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
runCase(const SubCase & subCase)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:
CommonFrameworkTests(tcu::TestContext & testCtx)868 CommonFrameworkTests (tcu::TestContext& testCtx)
869 : tcu::TestCaseGroup(testCtx, "common", "Tests for the common utility framework")
870 {
871 }
872
init(void)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:
ReferenceRendererTests(tcu::TestContext & testCtx)885 ReferenceRendererTests (tcu::TestContext& testCtx)
886 : tcu::TestCaseGroup(testCtx, "reference_renderer", "Reference renderer tests")
887 {
888 }
889
init(void)890 void init (void)
891 {
892 addChild(new ConstantInterpolationTest(m_testCtx));
893 }
894 };
895
896 } // anonymous
897
FrameworkTests(tcu::TestContext & testCtx)898 FrameworkTests::FrameworkTests (tcu::TestContext& testCtx)
899 : tcu::TestCaseGroup(testCtx, "framework", "Miscellaneous framework tests")
900 {
901 }
902
~FrameworkTests(void)903 FrameworkTests::~FrameworkTests (void)
904 {
905 }
906
init(void)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