• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // angle_deqp_gtest:
7 //   dEQP and GoogleTest integration logic. Calls through to the random
8 //   order executor.
9 
10 #include <stdint.h>
11 #include <array>
12 #include <fstream>
13 
14 #include <gtest/gtest.h>
15 
16 #include "angle_deqp_libtester.h"
17 #include "common/Optional.h"
18 #include "common/angleutils.h"
19 #include "common/debug.h"
20 #include "common/platform.h"
21 #include "common/string_utils.h"
22 #include "common/system_utils.h"
23 #include "platform/PlatformMethods.h"
24 #include "tests/test_utils/runner/TestSuite.h"
25 #include "util/OSWindow.h"
26 #include "util/test_utils.h"
27 
28 namespace angle
29 {
30 namespace
31 {
32 #if !defined(NDEBUG)
33 constexpr bool kIsDebug = true;
34 #else
35 constexpr bool kIsDebug                = false;
36 #endif  // !defined(NDEBUG)
37 
38 bool gGlobalError = false;
39 bool gExpectError = false;
40 bool gVerbose     = false;
41 
42 // Set this to true temporarily to enable image logging in release. Useful for diagnosing errors.
43 bool gLogImages = kIsDebug;
44 
45 constexpr char kInfoTag[] = "*RESULT";
46 
HandlePlatformError(PlatformMethods * platform,const char * errorMessage)47 void HandlePlatformError(PlatformMethods *platform, const char *errorMessage)
48 {
49     if (!gExpectError)
50     {
51         FAIL() << errorMessage;
52     }
53     gGlobalError = true;
54 }
55 
DrawElementsToGoogleTestName(const std::string & dEQPName)56 std::string DrawElementsToGoogleTestName(const std::string &dEQPName)
57 {
58     std::string gTestName = dEQPName.substr(dEQPName.find('.') + 1);
59     std::replace(gTestName.begin(), gTestName.end(), '.', '_');
60 
61     // Occurs in some luminance tests
62     gTestName.erase(std::remove(gTestName.begin(), gTestName.end(), '-'), gTestName.end());
63     return gTestName;
64 }
65 
66 // Relative to the ANGLE root folder.
67 constexpr char kCTSRootPath[] = "third_party/VK-GL-CTS/src/";
68 constexpr char kSupportPath[] = "src/tests/deqp_support/";
69 
70 #define OPENGL_CTS_DIR(PATH) "external/openglcts/data/mustpass/gles/" PATH
71 
72 const char *gCaseListFiles[] = {
73     OPENGL_CTS_DIR("aosp_mustpass/master/gles2-master.txt"),
74     OPENGL_CTS_DIR("aosp_mustpass/master/gles3-master.txt"),
75     OPENGL_CTS_DIR("aosp_mustpass/master/gles31-master.txt"),
76     "/android/cts/master/egl-master.txt",
77     OPENGL_CTS_DIR("khronos_mustpass/master/gles2-khr-master.txt"),
78     OPENGL_CTS_DIR("khronos_mustpass/master/gles3-khr-master.txt"),
79     OPENGL_CTS_DIR("khronos_mustpass/master/gles31-khr-master.txt"),
80     OPENGL_CTS_DIR("khronos_mustpass/master/gles32-khr-master.txt"),
81     OPENGL_CTS_DIR("aosp_mustpass/master/gles3-rotate-landscape.txt"),
82     OPENGL_CTS_DIR("aosp_mustpass/master/gles3-rotate-reverse-portrait.txt"),
83     OPENGL_CTS_DIR("aosp_mustpass/master/gles3-rotate-reverse-landscape.txt"),
84     OPENGL_CTS_DIR("aosp_mustpass/master/gles31-rotate-landscape.txt"),
85     OPENGL_CTS_DIR("aosp_mustpass/master/gles31-rotate-reverse-portrait.txt"),
86     OPENGL_CTS_DIR("aosp_mustpass/master/gles31-rotate-reverse-landscape.txt"),
87 };
88 
89 #undef OPENGL_CTS_DIR
90 
91 const char *gTestExpectationsFiles[] = {
92     "deqp_gles2_test_expectations.txt",         "deqp_gles3_test_expectations.txt",
93     "deqp_gles31_test_expectations.txt",        "deqp_egl_test_expectations.txt",
94     "deqp_khr_gles2_test_expectations.txt",     "deqp_khr_gles3_test_expectations.txt",
95     "deqp_khr_gles31_test_expectations.txt",    "deqp_khr_gles32_test_expectations.txt",
96     "deqp_gles3_rotate_test_expectations.txt",  "deqp_gles3_rotate_test_expectations.txt",
97     "deqp_gles3_rotate_test_expectations.txt",  "deqp_gles31_rotate_test_expectations.txt",
98     "deqp_gles31_rotate_test_expectations.txt", "deqp_gles31_rotate_test_expectations.txt",
99 };
100 
101 using APIInfo = std::pair<const char *, GPUTestConfig::API>;
102 
103 constexpr APIInfo kEGLDisplayAPIs[] = {
104     {"angle-d3d9", GPUTestConfig::kAPID3D9},
105     {"angle-d3d11", GPUTestConfig::kAPID3D11},
106     {"angle-d3d11-ref", GPUTestConfig::kAPID3D11},
107     {"angle-gl", GPUTestConfig::kAPIGLDesktop},
108     {"angle-gles", GPUTestConfig::kAPIGLES},
109     {"angle-metal", GPUTestConfig::kAPIMetal},
110     {"angle-null", GPUTestConfig::kAPIUnknown},
111     {"angle-swiftshader", GPUTestConfig::kAPISwiftShader},
112     {"angle-vulkan", GPUTestConfig::kAPIVulkan},
113 };
114 
115 constexpr char kdEQPEGLString[]    = "--deqp-egl-display-type=";
116 constexpr char kANGLEEGLString[]   = "--use-angle=";
117 constexpr char kANGLEPreRotation[] = "--emulated-pre-rotation=";
118 constexpr char kdEQPCaseString[]   = "--deqp-case=";
119 constexpr char kVerboseString[]    = "--verbose";
120 constexpr char kRenderDocString[]  = "--renderdoc";
121 
122 std::array<char, 500> gCaseStringBuffer;
123 
124 // For angle_deqp_gles3*_rotateN_tests, default gPreRotation to N.
125 #if defined(ANGLE_DEQP_GLES3_ROTATE90_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE90_TESTS)
126 constexpr uint32_t kDefaultPreRotation = 90;
127 #elif defined(ANGLE_DEQP_GLES3_ROTATE180_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE180_TESTS)
128 constexpr uint32_t kDefaultPreRotation = 180;
129 #elif defined(ANGLE_DEQP_GLES3_ROTATE270_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE270_TESTS)
130 constexpr uint32_t kDefaultPreRotation = 270;
131 #else
132 constexpr uint32_t kDefaultPreRotation = 0;
133 #endif
134 
135 const APIInfo *gInitAPI = nullptr;
136 uint32_t gPreRotation   = kDefaultPreRotation;
137 
138 bool gEnableRenderDocCapture = false;
139 
140 constexpr const char gdEQPEGLConfigNameString[] = "--deqp-gl-config-name=";
141 constexpr const char gdEQPLogImagesString[]     = "--deqp-log-images=";
142 
143 // Default the config to RGBA8
144 const char *gEGLConfigName = "rgba8888d24s8";
145 
146 // Returns the default API for a platform.
GetDefaultAPIName()147 const char *GetDefaultAPIName()
148 {
149 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX) || \
150     defined(ANGLE_PLATFORM_WINDOWS)
151     return "angle-vulkan";
152 #elif defined(ANGLE_PLATFORM_APPLE)
153     return "angle-gl";
154 #else
155 #    error Unknown platform.
156 #endif
157 }
158 
FindAPIInfo(const std::string & arg)159 const APIInfo *FindAPIInfo(const std::string &arg)
160 {
161     for (auto &displayAPI : kEGLDisplayAPIs)
162     {
163         if (arg == displayAPI.first)
164         {
165             return &displayAPI;
166         }
167     }
168     return nullptr;
169 }
170 
GetDefaultAPIInfo()171 const APIInfo *GetDefaultAPIInfo()
172 {
173     const APIInfo *defaultInfo = FindAPIInfo(GetDefaultAPIName());
174     ASSERT(defaultInfo);
175     return defaultInfo;
176 }
177 
GetTestStatLine(const std::string & key,const std::string & value)178 std::string GetTestStatLine(const std::string &key, const std::string &value)
179 {
180     return std::string(kInfoTag) + ": " + key + ": " + value + "\n";
181 }
182 
183 // During the CaseList initialization we cannot use the GTEST FAIL macro to quit the program because
184 // the initialization is called outside of tests the first time.
Die()185 void Die()
186 {
187     exit(EXIT_FAILURE);
188 }
189 
FindFileFromPath(const char * dirPath,const char * filePath)190 Optional<std::string> FindFileFromPath(const char *dirPath, const char *filePath)
191 {
192     std::stringstream strstr;
193     strstr << dirPath << filePath;
194     std::string path = strstr.str();
195 
196     constexpr size_t kMaxFoundPathLen = 1000;
197     char foundPath[kMaxFoundPathLen];
198     if (angle::FindTestDataPath(path.c_str(), foundPath, kMaxFoundPathLen))
199     {
200         return std::string(foundPath);
201     }
202 
203     return Optional<std::string>::Invalid();
204 }
205 
FindCaseListPath(size_t testModuleIndex)206 Optional<std::string> FindCaseListPath(size_t testModuleIndex)
207 {
208     return FindFileFromPath(kCTSRootPath, gCaseListFiles[testModuleIndex]);
209 }
210 
FindTestExpectationsPath(size_t testModuleIndex)211 Optional<std::string> FindTestExpectationsPath(size_t testModuleIndex)
212 {
213     return FindFileFromPath(kSupportPath, gTestExpectationsFiles[testModuleIndex]);
214 }
215 
216 class dEQPCaseList
217 {
218   public:
219     dEQPCaseList(size_t testModuleIndex);
220 
221     struct CaseInfo
222     {
CaseInfoangle::__anon95caab630111::dEQPCaseList::CaseInfo223         CaseInfo(const std::string &dEQPName, const std::string &gTestName, int expectation)
224             : mDEQPName(dEQPName), mGTestName(gTestName), mExpectation(expectation)
225         {}
226 
227         std::string mDEQPName;
228         std::string mGTestName;
229         int mExpectation;
230     };
231 
232     void initialize();
233 
getCaseInfo(size_t caseIndex) const234     const CaseInfo &getCaseInfo(size_t caseIndex) const
235     {
236         ASSERT(mInitialized);
237         ASSERT(caseIndex < mCaseInfoList.size());
238         return mCaseInfoList[caseIndex];
239     }
240 
numCases() const241     size_t numCases() const
242     {
243         ASSERT(mInitialized);
244         return mCaseInfoList.size();
245     }
246 
247   private:
248     std::vector<CaseInfo> mCaseInfoList;
249     size_t mTestModuleIndex;
250     bool mInitialized = false;
251 };
252 
dEQPCaseList(size_t testModuleIndex)253 dEQPCaseList::dEQPCaseList(size_t testModuleIndex) : mTestModuleIndex(testModuleIndex) {}
254 
initialize()255 void dEQPCaseList::initialize()
256 {
257     if (mInitialized)
258     {
259         return;
260     }
261 
262     mInitialized = true;
263 
264     Optional<std::string> caseListPath = FindCaseListPath(mTestModuleIndex);
265     if (!caseListPath.valid())
266     {
267         std::cerr << "Failed to find case list file." << std::endl;
268         Die();
269     }
270 
271     Optional<std::string> testExpectationsPath = FindTestExpectationsPath(mTestModuleIndex);
272     if (!testExpectationsPath.valid())
273     {
274         std::cerr << "Failed to find test expectations file." << std::endl;
275         Die();
276     }
277 
278     GPUTestConfig::API api = GetDefaultAPIInfo()->second;
279     // Set the API from the command line, or using the default platform API.
280     if (gInitAPI)
281     {
282         api = gInitAPI->second;
283     }
284 
285     GPUTestConfig testConfig = GPUTestConfig(api, gPreRotation);
286 
287 #if !defined(ANGLE_PLATFORM_ANDROID)
288     // Note: These prints mess up parsing of test list when running on Android.
289     std::cout << "Using test config with:" << std::endl;
290     for (uint32_t condition : testConfig.getConditions())
291     {
292         const char *name = GetConditionName(condition);
293         if (name != nullptr)
294         {
295             std::cout << "  " << name << std::endl;
296         }
297     }
298 #endif
299 
300     TestSuite *testSuite = TestSuite::GetInstance();
301 
302     if (!testSuite->loadTestExpectationsFromFileWithConfig(testConfig,
303                                                            testExpectationsPath.value()))
304     {
305         Die();
306     }
307 
308     std::ifstream caseListStream(caseListPath.value());
309     if (caseListStream.fail())
310     {
311         std::cerr << "Failed to load the case list." << std::endl;
312         Die();
313     }
314 
315     while (!caseListStream.eof())
316     {
317         std::string inString;
318         std::getline(caseListStream, inString);
319 
320         std::string dEQPName = TrimString(inString, kWhitespaceASCII);
321         if (dEQPName.empty())
322             continue;
323         std::string gTestName = DrawElementsToGoogleTestName(dEQPName);
324         if (gTestName.empty())
325             continue;
326 
327         int expectation = testSuite->getTestExpectation(dEQPName);
328         mCaseInfoList.push_back(CaseInfo(dEQPName, gTestName, expectation));
329     }
330 
331     if (testSuite->logAnyUnusedTestExpectations())
332     {
333         Die();
334     }
335 }
336 
337 template <size_t TestModuleIndex>
338 class dEQPTest : public testing::TestWithParam<size_t>
339 {
340   public:
GetTestingRange()341     static testing::internal::ParamGenerator<size_t> GetTestingRange()
342     {
343         return testing::Range<size_t>(0, GetCaseList().numCases());
344     }
345 
GetCaseGTestName(size_t caseIndex)346     static std::string GetCaseGTestName(size_t caseIndex)
347     {
348         const auto &caseInfo = GetCaseList().getCaseInfo(caseIndex);
349         return caseInfo.mGTestName;
350     }
351 
GetCaseList()352     static const dEQPCaseList &GetCaseList()
353     {
354         static dEQPCaseList sCaseList(TestModuleIndex);
355         sCaseList.initialize();
356         return sCaseList;
357     }
358 
359     static void SetUpTestCase();
360     static void TearDownTestCase();
361 
362   protected:
runTest() const363     void runTest() const
364     {
365         if (sTestExceptionCount > 1)
366         {
367             std::cout << "Too many exceptions, skipping all remaining tests." << std::endl;
368             return;
369         }
370 
371         const auto &caseInfo = GetCaseList().getCaseInfo(GetParam());
372         std::cout << caseInfo.mDEQPName << std::endl;
373 
374         // Tests that crash exit the harness before collecting the result. To tally the number of
375         // crashed tests we track how many tests we "tried" to run.
376         sTestCount++;
377 
378         if (caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestSkip ||
379             caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestTimeout)
380         {
381             sSkippedTestCount++;
382             std::cout << "Test skipped.\n";
383             return;
384         }
385 
386         gExpectError          = (caseInfo.mExpectation != GPUTestExpectationsParser::kGpuTestPass);
387         dEQPTestResult result = deqp_libtester_run(caseInfo.mDEQPName.c_str());
388 
389         bool testSucceeded = countTestResultAndReturnSuccess(result);
390 
391         // Check the global error flag for unexpected platform errors.
392         if (gGlobalError)
393         {
394             testSucceeded = false;
395             gGlobalError  = false;
396         }
397 
398         if (caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestPass)
399         {
400             EXPECT_TRUE(testSucceeded);
401 
402             if (!testSucceeded)
403             {
404                 sUnexpectedFailed.push_back(caseInfo.mDEQPName);
405             }
406         }
407         else if (testSucceeded)
408         {
409             std::cout << "Test expected to fail but passed!" << std::endl;
410             sUnexpectedPasses.push_back(caseInfo.mDEQPName);
411         }
412     }
413 
countTestResultAndReturnSuccess(dEQPTestResult result) const414     bool countTestResultAndReturnSuccess(dEQPTestResult result) const
415     {
416         switch (result)
417         {
418             case dEQPTestResult::Pass:
419                 sPassedTestCount++;
420                 return true;
421             case dEQPTestResult::Fail:
422                 sFailedTestCount++;
423                 return false;
424             case dEQPTestResult::NotSupported:
425                 sNotSupportedTestCount++;
426                 return true;
427             case dEQPTestResult::Exception:
428                 sTestExceptionCount++;
429                 return false;
430             default:
431                 std::cerr << "Unexpected test result code: " << static_cast<int>(result) << "\n";
432                 return false;
433         }
434     }
435 
PrintTestStats()436     static void PrintTestStats()
437     {
438         uint32_t crashedCount =
439             sTestCount - (sPassedTestCount + sFailedTestCount + sNotSupportedTestCount +
440                           sTestExceptionCount + sSkippedTestCount);
441 
442         std::cout << GetTestStatLine("Total", std::to_string(sTestCount));
443         std::cout << GetTestStatLine("Passed", std::to_string(sPassedTestCount));
444         std::cout << GetTestStatLine("Failed", std::to_string(sFailedTestCount));
445         std::cout << GetTestStatLine("Skipped", std::to_string(sSkippedTestCount));
446         std::cout << GetTestStatLine("Not Supported", std::to_string(sNotSupportedTestCount));
447         std::cout << GetTestStatLine("Exception", std::to_string(sTestExceptionCount));
448         std::cout << GetTestStatLine("Crashed", std::to_string(crashedCount));
449 
450         if (!sUnexpectedPasses.empty())
451         {
452             std::cout << GetTestStatLine("Unexpected Passed Count",
453                                          std::to_string(sUnexpectedPasses.size()));
454             for (const std::string &testName : sUnexpectedPasses)
455             {
456                 std::cout << GetTestStatLine("Unexpected Passed Tests", testName);
457             }
458         }
459 
460         if (!sUnexpectedFailed.empty())
461         {
462             std::cout << GetTestStatLine("Unexpected Failed Count",
463                                          std::to_string(sUnexpectedFailed.size()));
464             for (const std::string &testName : sUnexpectedFailed)
465             {
466                 std::cout << GetTestStatLine("Unexpected Failed Tests", testName);
467             }
468         }
469     }
470 
471     static uint32_t sTestCount;
472     static uint32_t sPassedTestCount;
473     static uint32_t sFailedTestCount;
474     static uint32_t sTestExceptionCount;
475     static uint32_t sNotSupportedTestCount;
476     static uint32_t sSkippedTestCount;
477 
478     static std::vector<std::string> sUnexpectedFailed;
479     static std::vector<std::string> sUnexpectedPasses;
480 };
481 
482 template <size_t TestModuleIndex>
483 uint32_t dEQPTest<TestModuleIndex>::sTestCount = 0;
484 template <size_t TestModuleIndex>
485 uint32_t dEQPTest<TestModuleIndex>::sPassedTestCount = 0;
486 template <size_t TestModuleIndex>
487 uint32_t dEQPTest<TestModuleIndex>::sFailedTestCount = 0;
488 template <size_t TestModuleIndex>
489 uint32_t dEQPTest<TestModuleIndex>::sTestExceptionCount = 0;
490 template <size_t TestModuleIndex>
491 uint32_t dEQPTest<TestModuleIndex>::sNotSupportedTestCount = 0;
492 template <size_t TestModuleIndex>
493 uint32_t dEQPTest<TestModuleIndex>::sSkippedTestCount = 0;
494 template <size_t TestModuleIndex>
495 std::vector<std::string> dEQPTest<TestModuleIndex>::sUnexpectedFailed;
496 template <size_t TestModuleIndex>
497 std::vector<std::string> dEQPTest<TestModuleIndex>::sUnexpectedPasses;
498 
499 // static
500 template <size_t TestModuleIndex>
SetUpTestCase()501 void dEQPTest<TestModuleIndex>::SetUpTestCase()
502 {
503     sPassedTestCount       = 0;
504     sFailedTestCount       = 0;
505     sNotSupportedTestCount = 0;
506     sTestExceptionCount    = 0;
507     sTestCount             = 0;
508     sSkippedTestCount      = 0;
509     sUnexpectedPasses.clear();
510     sUnexpectedFailed.clear();
511 
512     std::vector<const char *> argv;
513 
514     // Reserve one argument for the binary name.
515     argv.push_back("");
516 
517     // Add init api.
518     const char *targetApi    = gInitAPI ? gInitAPI->first : GetDefaultAPIName();
519     std::string apiArgString = std::string(kdEQPEGLString) + targetApi;
520     argv.push_back(apiArgString.c_str());
521 
522     // Add config name
523     const char *targetConfigName = gEGLConfigName;
524     std::string configArgString  = std::string(gdEQPEGLConfigNameString) + targetConfigName;
525     argv.push_back(configArgString.c_str());
526 
527     // Hide SwiftShader window to prevent a race with Xvfb causing hangs on test bots
528     if (gInitAPI && gInitAPI->second == GPUTestConfig::kAPISwiftShader)
529     {
530         argv.push_back("--deqp-visibility=hidden");
531     }
532 
533     TestSuite *testSuite = TestSuite::GetInstance();
534 
535     std::stringstream logNameStream;
536     logNameStream << "TestResults";
537     if (testSuite->getBatchId() != -1)
538     {
539         logNameStream << "-Batch" << std::setfill('0') << std::setw(3) << testSuite->getBatchId();
540     }
541     logNameStream << ".qpa";
542 
543     std::stringstream logArgStream;
544     logArgStream << "--deqp-log-filename=" << testSuite->addTestArtifact(logNameStream.str());
545 
546     std::string logNameString = logArgStream.str();
547     argv.push_back(logNameString.c_str());
548 
549     if (!gLogImages)
550     {
551         argv.push_back("--deqp-log-images=disable");
552     }
553 
554     // Flushing during multi-process execution punishes HDDs. http://anglebug.com/5157
555     if (testSuite->getBatchId() != -1)
556     {
557         argv.push_back("--deqp-log-flush=disable");
558     }
559 
560     // Init the platform.
561     if (!deqp_libtester_init_platform(static_cast<int>(argv.size()), argv.data(),
562                                       reinterpret_cast<void *>(&HandlePlatformError), gPreRotation,
563                                       gEnableRenderDocCapture))
564     {
565         std::cout << "Aborting test due to dEQP initialization error." << std::endl;
566         exit(1);
567     }
568 }
569 
570 // static
571 template <size_t TestModuleIndex>
TearDownTestCase()572 void dEQPTest<TestModuleIndex>::TearDownTestCase()
573 {
574     PrintTestStats();
575     deqp_libtester_shutdown_platform();
576 }
577 
578 #define ANGLE_INSTANTIATE_DEQP_TEST_CASE(API, N)                              \
579     class dEQP : public dEQPTest<N>                                           \
580     {};                                                                       \
581     TEST_P(dEQP, API) { runTest(); }                                          \
582                                                                               \
583     INSTANTIATE_TEST_SUITE_P(, dEQP, dEQP::GetTestingRange(),                 \
584                              [](const testing::TestParamInfo<size_t> &info) { \
585                                  return dEQP::GetCaseGTestName(info.param);   \
586                              })
587 
588 #ifdef ANGLE_DEQP_GLES2_TESTS
589 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES2, 0);
590 #endif
591 
592 #ifdef ANGLE_DEQP_GLES3_TESTS
593 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3, 1);
594 #endif
595 
596 #ifdef ANGLE_DEQP_GLES31_TESTS
597 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31, 2);
598 #endif
599 
600 #ifdef ANGLE_DEQP_EGL_TESTS
601 ANGLE_INSTANTIATE_DEQP_TEST_CASE(EGL, 3);
602 #endif
603 
604 #ifdef ANGLE_DEQP_KHR_GLES2_TESTS
605 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES2, 4);
606 #endif
607 
608 #ifdef ANGLE_DEQP_KHR_GLES3_TESTS
609 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES3, 5);
610 #endif
611 
612 #ifdef ANGLE_DEQP_KHR_GLES31_TESTS
613 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES31, 6);
614 #endif
615 
616 #ifdef ANGLE_DEQP_KHR_GLES32_TESTS
617 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES32, 7);
618 #endif
619 
620 #ifdef ANGLE_DEQP_GLES3_ROTATE90_TESTS
621 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE90, 8);
622 #endif
623 
624 #ifdef ANGLE_DEQP_GLES3_ROTATE180_TESTS
625 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE180, 9);
626 #endif
627 
628 #ifdef ANGLE_DEQP_GLES3_ROTATE270_TESTS
629 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE270, 10);
630 #endif
631 
632 #ifdef ANGLE_DEQP_GLES31_ROTATE90_TESTS
633 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE90, 11);
634 #endif
635 
636 #ifdef ANGLE_DEQP_GLES31_ROTATE180_TESTS
637 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE180, 12);
638 #endif
639 
640 #ifdef ANGLE_DEQP_GLES31_ROTATE270_TESTS
641 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE270, 13);
642 #endif
643 
HandleDisplayType(const char * displayTypeString)644 void HandleDisplayType(const char *displayTypeString)
645 {
646     std::stringstream argStream;
647 
648     if (gInitAPI)
649     {
650         std::cout << "Cannot specify two EGL displays!" << std::endl;
651         exit(1);
652     }
653 
654     if (strncmp(displayTypeString, "angle-", strlen("angle-")) != 0)
655     {
656         argStream << "angle-";
657     }
658 
659     argStream << displayTypeString;
660     std::string arg = argStream.str();
661 
662     gInitAPI = FindAPIInfo(arg);
663 
664     if (!gInitAPI)
665     {
666         std::cout << "Unknown ANGLE back-end API: " << displayTypeString << std::endl;
667         exit(1);
668     }
669 }
670 
HandlePreRotation(const char * preRotationString)671 void HandlePreRotation(const char *preRotationString)
672 {
673     std::istringstream argStream(preRotationString);
674 
675     uint32_t preRotation = 0;
676     argStream >> preRotation;
677 
678     if (!argStream ||
679         (preRotation != 0 && preRotation != 90 && preRotation != 180 && preRotation != 270))
680     {
681         std::cout << "Invalid PreRotation '" << preRotationString
682                   << "'; must be either 0, 90, 180 or 270" << std::endl;
683         exit(1);
684     }
685 
686     gPreRotation = preRotation;
687 }
688 
HandleEGLConfigName(const char * configNameString)689 void HandleEGLConfigName(const char *configNameString)
690 {
691     gEGLConfigName = configNameString;
692 }
693 
694 // The --deqp-case flag takes a case expression that is parsed into a --gtest_filter. It converts
695 // the "dEQP" style names (functional.thing.*) into "GoogleTest" style names (functional_thing_*).
696 // Currently it does not handle multiple tests and multiple filters in different arguments.
HandleCaseName(const char * caseString,int * argc,int argIndex,char ** argv)697 void HandleCaseName(const char *caseString, int *argc, int argIndex, char **argv)
698 {
699     std::string googleTestName = DrawElementsToGoogleTestName(caseString);
700     gCaseStringBuffer.fill(0);
701     int bytesWritten = snprintf(gCaseStringBuffer.data(), gCaseStringBuffer.size() - 1,
702                                 "--gtest_filter=*%s", googleTestName.c_str());
703     if (bytesWritten <= 0 || static_cast<size_t>(bytesWritten) >= gCaseStringBuffer.size() - 1)
704     {
705         std::cout << "Error parsing test case string: " << caseString;
706         exit(1);
707     }
708 
709     argv[argIndex] = gCaseStringBuffer.data();
710 }
711 
HandleLogImages(const char * logImagesString)712 void HandleLogImages(const char *logImagesString)
713 {
714     if (strcmp(logImagesString, "enable") == 0)
715     {
716         gLogImages = true;
717     }
718     else if (strcmp(logImagesString, "disable") == 0)
719     {
720         gLogImages = false;
721     }
722     else
723     {
724         std::cout << "Error parsing log images setting. Use enable/disable.";
725         exit(1);
726     }
727 }
728 }  // anonymous namespace
729 
730 // Called from main() to process command-line arguments.
InitTestHarness(int * argc,char ** argv)731 void InitTestHarness(int *argc, char **argv)
732 {
733     int argIndex = 0;
734     while (argIndex < *argc)
735     {
736         if (strncmp(argv[argIndex], kdEQPEGLString, strlen(kdEQPEGLString)) == 0)
737         {
738             HandleDisplayType(argv[argIndex] + strlen(kdEQPEGLString));
739         }
740         else if (strncmp(argv[argIndex], kANGLEEGLString, strlen(kANGLEEGLString)) == 0)
741         {
742             HandleDisplayType(argv[argIndex] + strlen(kANGLEEGLString));
743         }
744         else if (strncmp(argv[argIndex], kANGLEPreRotation, strlen(kANGLEPreRotation)) == 0)
745         {
746             HandlePreRotation(argv[argIndex] + strlen(kANGLEPreRotation));
747         }
748         else if (strncmp(argv[argIndex], gdEQPEGLConfigNameString,
749                          strlen(gdEQPEGLConfigNameString)) == 0)
750         {
751             HandleEGLConfigName(argv[argIndex] + strlen(gdEQPEGLConfigNameString));
752         }
753         else if (strncmp(argv[argIndex], kdEQPCaseString, strlen(kdEQPCaseString)) == 0)
754         {
755             HandleCaseName(argv[argIndex] + strlen(kdEQPCaseString), argc, argIndex, argv);
756         }
757         else if (strncmp(argv[argIndex], kVerboseString, strlen(kVerboseString)) == 0 ||
758                  strcmp(argv[argIndex], "-v") == 0)
759         {
760             gVerbose = true;
761         }
762         else if (strncmp(argv[argIndex], gdEQPLogImagesString, strlen(gdEQPLogImagesString)) == 0)
763         {
764             HandleLogImages(argv[argIndex] + strlen(gdEQPLogImagesString));
765         }
766         else if (strncmp(argv[argIndex], kRenderDocString, strlen(kRenderDocString)) == 0)
767         {
768             gEnableRenderDocCapture = true;
769         }
770         argIndex++;
771     }
772 
773     GPUTestConfig::API api = GetDefaultAPIInfo()->second;
774     if (gInitAPI)
775     {
776         api = gInitAPI->second;
777     }
778     if (gPreRotation != 0 && api != GPUTestConfig::kAPIVulkan &&
779         api != GPUTestConfig::kAPISwiftShader)
780     {
781         std::cout << "PreRotation is only supported on Vulkan" << std::endl;
782         exit(1);
783     }
784 }
785 }  // namespace angle
786