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