• 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/main/gles2-master.txt"),
74     OPENGL_CTS_DIR("aosp_mustpass/main/gles3-master.txt"),
75     OPENGL_CTS_DIR("aosp_mustpass/main/gles31-master.txt"),
76     "/android/cts/main/egl-master.txt",
77     OPENGL_CTS_DIR("khronos_mustpass/main/gles2-khr-master.txt"),
78     OPENGL_CTS_DIR("khronos_mustpass/main/gles3-khr-master.txt"),
79     OPENGL_CTS_DIR("khronos_mustpass/main/gles31-khr-master.txt"),
80     OPENGL_CTS_DIR("khronos_mustpass/main/gles32-khr-master.txt"),
81     OPENGL_CTS_DIR("aosp_mustpass/main/gles3-rotate-landscape.txt"),
82     OPENGL_CTS_DIR("aosp_mustpass/main/gles3-rotate-reverse-portrait.txt"),
83     OPENGL_CTS_DIR("aosp_mustpass/main/gles3-rotate-reverse-landscape.txt"),
84     OPENGL_CTS_DIR("aosp_mustpass/main/gles31-rotate-landscape.txt"),
85     OPENGL_CTS_DIR("aosp_mustpass/main/gles31-rotate-reverse-portrait.txt"),
86     OPENGL_CTS_DIR("aosp_mustpass/main/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 constexpr char kNoRenderDocString[] = "--no-renderdoc";
122 constexpr char kdEQPFlagsPrefix[]   = "--deqp-";
123 
124 std::array<char, 500> gCaseStringBuffer;
125 
126 // For angle_deqp_gles3*_rotateN_tests, default gOptions.preRotation to N.
127 #if defined(ANGLE_DEQP_GLES3_ROTATE90_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE90_TESTS)
128 constexpr uint32_t kDefaultPreRotation = 90;
129 #elif defined(ANGLE_DEQP_GLES3_ROTATE180_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE180_TESTS)
130 constexpr uint32_t kDefaultPreRotation = 180;
131 #elif defined(ANGLE_DEQP_GLES3_ROTATE270_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE270_TESTS)
132 constexpr uint32_t kDefaultPreRotation = 270;
133 #else
134 constexpr uint32_t kDefaultPreRotation = 0;
135 #endif
136 
137 #if defined(ANGLE_TEST_ENABLE_RENDERDOC_CAPTURE)
138 constexpr bool kEnableRenderDocCapture = true;
139 #else
140 constexpr bool kEnableRenderDocCapture = false;
141 #endif
142 
143 const APIInfo *gInitAPI = nullptr;
144 dEQPOptions gOptions    = {
145     kDefaultPreRotation,      // preRotation
146     kEnableRenderDocCapture,  // enableRenderDocCapture
147 };
148 
149 constexpr const char gdEQPEGLConfigNameString[] = "--deqp-gl-config-name=";
150 constexpr const char gdEQPLogImagesString[]     = "--deqp-log-images=";
151 
152 // Default the config to RGBA8
153 const char *gEGLConfigName = "rgba8888d24s8";
154 
155 std::vector<const char *> gdEQPForwardFlags;
156 
157 // Returns the default API for a platform.
GetDefaultAPIName()158 const char *GetDefaultAPIName()
159 {
160 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX) || \
161     defined(ANGLE_PLATFORM_WINDOWS)
162     return "angle-vulkan";
163 #elif defined(ANGLE_PLATFORM_APPLE)
164     return "angle-gl";
165 #else
166 #    error Unknown platform.
167 #endif
168 }
169 
FindAPIInfo(const std::string & arg)170 const APIInfo *FindAPIInfo(const std::string &arg)
171 {
172     for (auto &displayAPI : kEGLDisplayAPIs)
173     {
174         if (arg == displayAPI.first)
175         {
176             return &displayAPI;
177         }
178     }
179     return nullptr;
180 }
181 
GetDefaultAPIInfo()182 const APIInfo *GetDefaultAPIInfo()
183 {
184     const APIInfo *defaultInfo = FindAPIInfo(GetDefaultAPIName());
185     ASSERT(defaultInfo);
186     return defaultInfo;
187 }
188 
GetTestStatLine(const std::string & key,const std::string & value)189 std::string GetTestStatLine(const std::string &key, const std::string &value)
190 {
191     return std::string(kInfoTag) + ": " + key + ": " + value + "\n";
192 }
193 
194 // During the CaseList initialization we cannot use the GTEST FAIL macro to quit the program because
195 // the initialization is called outside of tests the first time.
Die()196 void Die()
197 {
198     exit(EXIT_FAILURE);
199 }
200 
FindFileFromPath(const char * dirPath,const char * filePath)201 Optional<std::string> FindFileFromPath(const char *dirPath, const char *filePath)
202 {
203     std::stringstream strstr;
204     strstr << dirPath << filePath;
205     std::string path = strstr.str();
206 
207     constexpr size_t kMaxFoundPathLen = 1000;
208     char foundPath[kMaxFoundPathLen];
209     if (angle::FindTestDataPath(path.c_str(), foundPath, kMaxFoundPathLen))
210     {
211         return std::string(foundPath);
212     }
213 
214     return Optional<std::string>::Invalid();
215 }
216 
FindCaseListPath(size_t testModuleIndex)217 Optional<std::string> FindCaseListPath(size_t testModuleIndex)
218 {
219     return FindFileFromPath(kCTSRootPath, gCaseListFiles[testModuleIndex]);
220 }
221 
FindTestExpectationsPath(size_t testModuleIndex)222 Optional<std::string> FindTestExpectationsPath(size_t testModuleIndex)
223 {
224     return FindFileFromPath(kSupportPath, gTestExpectationsFiles[testModuleIndex]);
225 }
226 
227 class dEQPCaseList
228 {
229   public:
230     dEQPCaseList(size_t testModuleIndex);
231 
232     struct CaseInfo
233     {
CaseInfoangle::__anon142ce9e80111::dEQPCaseList::CaseInfo234         CaseInfo(const std::string &dEQPName, const std::string &gTestName, int expectation)
235             : mDEQPName(dEQPName), mGTestName(gTestName), mExpectation(expectation)
236         {}
237 
238         std::string mDEQPName;
239         std::string mGTestName;
240         int mExpectation;
241     };
242 
243     void initialize();
244 
getCaseInfo(size_t caseIndex) const245     const CaseInfo &getCaseInfo(size_t caseIndex) const
246     {
247         ASSERT(mInitialized);
248         ASSERT(caseIndex < mCaseInfoList.size());
249         return mCaseInfoList[caseIndex];
250     }
251 
numCases() const252     size_t numCases() const
253     {
254         ASSERT(mInitialized);
255         return mCaseInfoList.size();
256     }
257 
258   private:
259     std::vector<CaseInfo> mCaseInfoList;
260     size_t mTestModuleIndex;
261     bool mInitialized = false;
262 };
263 
dEQPCaseList(size_t testModuleIndex)264 dEQPCaseList::dEQPCaseList(size_t testModuleIndex) : mTestModuleIndex(testModuleIndex) {}
265 
initialize()266 void dEQPCaseList::initialize()
267 {
268     if (mInitialized)
269     {
270         return;
271     }
272 
273     mInitialized = true;
274 
275     Optional<std::string> caseListPath = FindCaseListPath(mTestModuleIndex);
276     if (!caseListPath.valid())
277     {
278         std::cerr << "Failed to find case list file." << std::endl;
279         Die();
280     }
281 
282     Optional<std::string> testExpectationsPath = FindTestExpectationsPath(mTestModuleIndex);
283     if (!testExpectationsPath.valid())
284     {
285         std::cerr << "Failed to find test expectations file." << std::endl;
286         Die();
287     }
288 
289     GPUTestConfig::API api = GetDefaultAPIInfo()->second;
290     // Set the API from the command line, or using the default platform API.
291     if (gInitAPI)
292     {
293         api = gInitAPI->second;
294     }
295 
296     GPUTestConfig testConfig = GPUTestConfig(api, gOptions.preRotation);
297 
298 #if !defined(ANGLE_PLATFORM_ANDROID)
299     // Note: These prints mess up parsing of test list when running on Android.
300     std::cout << "Using test config with:" << std::endl;
301     for (uint32_t condition : testConfig.getConditions())
302     {
303         const char *name = GetConditionName(condition);
304         if (name != nullptr)
305         {
306             std::cout << "  " << name << std::endl;
307         }
308     }
309 #endif
310 
311     TestSuite *testSuite = TestSuite::GetInstance();
312 
313     if (!testSuite->loadTestExpectationsFromFileWithConfig(testConfig,
314                                                            testExpectationsPath.value()))
315     {
316         Die();
317     }
318 
319     std::ifstream caseListStream(caseListPath.value());
320     if (caseListStream.fail())
321     {
322         std::cerr << "Failed to load the case list." << std::endl;
323         Die();
324     }
325 
326     while (!caseListStream.eof())
327     {
328         std::string inString;
329         std::getline(caseListStream, inString);
330 
331         std::string dEQPName = TrimString(inString, kWhitespaceASCII);
332         if (dEQPName.empty())
333             continue;
334         std::string gTestName = DrawElementsToGoogleTestName(dEQPName);
335         if (gTestName.empty())
336             continue;
337 
338         int expectation = testSuite->getTestExpectation(dEQPName);
339         mCaseInfoList.push_back(CaseInfo(dEQPName, gTestName, expectation));
340     }
341 
342     if (testSuite->logAnyUnusedTestExpectations())
343     {
344         Die();
345     }
346 }
347 
IsPassingResult(dEQPTestResult result)348 bool IsPassingResult(dEQPTestResult result)
349 {
350     // Check the global error flag for unexpected platform errors.
351     if (gGlobalError)
352     {
353         gGlobalError = false;
354         return false;
355     }
356 
357     switch (result)
358     {
359         case dEQPTestResult::Fail:
360         case dEQPTestResult::Exception:
361             return false;
362 
363         default:
364             return true;
365     }
366 }
367 
368 template <size_t TestModuleIndex>
369 class dEQPTest : public testing::TestWithParam<size_t>
370 {
371   public:
GetTestingRange()372     static testing::internal::ParamGenerator<size_t> GetTestingRange()
373     {
374         return testing::Range<size_t>(0, GetCaseList().numCases());
375     }
376 
GetCaseGTestName(size_t caseIndex)377     static std::string GetCaseGTestName(size_t caseIndex)
378     {
379         const auto &caseInfo = GetCaseList().getCaseInfo(caseIndex);
380         return caseInfo.mGTestName;
381     }
382 
GetCaseList()383     static const dEQPCaseList &GetCaseList()
384     {
385         static dEQPCaseList sCaseList(TestModuleIndex);
386         sCaseList.initialize();
387         return sCaseList;
388     }
389 
390     static void SetUpTestCase();
391     static void TearDownTestCase();
392 
393   protected:
runTest() const394     void runTest() const
395     {
396         if (sTestExceptionCount > 1)
397         {
398             std::cout << "Too many exceptions, skipping all remaining tests." << std::endl;
399             return;
400         }
401 
402         const auto &caseInfo = GetCaseList().getCaseInfo(GetParam());
403         std::cout << caseInfo.mDEQPName << std::endl;
404 
405         // Tests that crash exit the harness before collecting the result. To tally the number of
406         // crashed tests we track how many tests we "tried" to run.
407         sTestCount++;
408 
409         if (caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestSkip)
410         {
411             sSkippedTestCount++;
412             std::cout << "Test skipped.\n";
413             return;
414         }
415 
416         TestSuite *testSuite = TestSuite::GetInstance();
417         testSuite->maybeUpdateTestTimeout(caseInfo.mExpectation);
418 
419         gExpectError          = (caseInfo.mExpectation != GPUTestExpectationsParser::kGpuTestPass);
420         dEQPTestResult result = deqp_libtester_run(caseInfo.mDEQPName.c_str());
421 
422         bool testSucceeded = IsPassingResult(result);
423 
424         if (!testSucceeded && caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestFlaky)
425         {
426             result        = deqp_libtester_run(caseInfo.mDEQPName.c_str());
427             testSucceeded = IsPassingResult(result);
428         }
429 
430         countTestResult(result);
431 
432         if (caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestPass ||
433             caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestFlaky)
434         {
435             EXPECT_TRUE(testSucceeded);
436 
437             if (!testSucceeded)
438             {
439                 sUnexpectedFailed.push_back(caseInfo.mDEQPName);
440             }
441         }
442         else if (testSucceeded)
443         {
444             std::cout << "Test expected to fail but passed!" << std::endl;
445             sUnexpectedPasses.push_back(caseInfo.mDEQPName);
446         }
447     }
448 
countTestResult(dEQPTestResult result) const449     void countTestResult(dEQPTestResult result) const
450     {
451         switch (result)
452         {
453             case dEQPTestResult::Pass:
454                 sPassedTestCount++;
455                 break;
456             case dEQPTestResult::Fail:
457                 sFailedTestCount++;
458                 break;
459             case dEQPTestResult::NotSupported:
460                 sNotSupportedTestCount++;
461                 break;
462             case dEQPTestResult::Exception:
463                 sTestExceptionCount++;
464                 break;
465             default:
466                 std::cerr << "Unexpected test result code: " << static_cast<int>(result) << "\n";
467                 break;
468         }
469     }
470 
PrintTestStats()471     static void PrintTestStats()
472     {
473         uint32_t crashedCount =
474             sTestCount - (sPassedTestCount + sFailedTestCount + sNotSupportedTestCount +
475                           sTestExceptionCount + sSkippedTestCount);
476 
477         std::cout << GetTestStatLine("Total", std::to_string(sTestCount));
478         std::cout << GetTestStatLine("Passed", std::to_string(sPassedTestCount));
479         std::cout << GetTestStatLine("Failed", std::to_string(sFailedTestCount));
480         std::cout << GetTestStatLine("Skipped", std::to_string(sSkippedTestCount));
481         std::cout << GetTestStatLine("Not Supported", std::to_string(sNotSupportedTestCount));
482         std::cout << GetTestStatLine("Exception", std::to_string(sTestExceptionCount));
483         std::cout << GetTestStatLine("Crashed", std::to_string(crashedCount));
484 
485         if (!sUnexpectedPasses.empty())
486         {
487             std::cout << GetTestStatLine("Unexpected Passed Count",
488                                          std::to_string(sUnexpectedPasses.size()));
489             for (const std::string &testName : sUnexpectedPasses)
490             {
491                 std::cout << GetTestStatLine("Unexpected Passed Tests", testName);
492             }
493         }
494 
495         if (!sUnexpectedFailed.empty())
496         {
497             std::cout << GetTestStatLine("Unexpected Failed Count",
498                                          std::to_string(sUnexpectedFailed.size()));
499             for (const std::string &testName : sUnexpectedFailed)
500             {
501                 std::cout << GetTestStatLine("Unexpected Failed Tests", testName);
502             }
503         }
504     }
505 
506     static uint32_t sTestCount;
507     static uint32_t sPassedTestCount;
508     static uint32_t sFailedTestCount;
509     static uint32_t sTestExceptionCount;
510     static uint32_t sNotSupportedTestCount;
511     static uint32_t sSkippedTestCount;
512 
513     static std::vector<std::string> sUnexpectedFailed;
514     static std::vector<std::string> sUnexpectedPasses;
515 };
516 
517 template <size_t TestModuleIndex>
518 uint32_t dEQPTest<TestModuleIndex>::sTestCount = 0;
519 template <size_t TestModuleIndex>
520 uint32_t dEQPTest<TestModuleIndex>::sPassedTestCount = 0;
521 template <size_t TestModuleIndex>
522 uint32_t dEQPTest<TestModuleIndex>::sFailedTestCount = 0;
523 template <size_t TestModuleIndex>
524 uint32_t dEQPTest<TestModuleIndex>::sTestExceptionCount = 0;
525 template <size_t TestModuleIndex>
526 uint32_t dEQPTest<TestModuleIndex>::sNotSupportedTestCount = 0;
527 template <size_t TestModuleIndex>
528 uint32_t dEQPTest<TestModuleIndex>::sSkippedTestCount = 0;
529 template <size_t TestModuleIndex>
530 std::vector<std::string> dEQPTest<TestModuleIndex>::sUnexpectedFailed;
531 template <size_t TestModuleIndex>
532 std::vector<std::string> dEQPTest<TestModuleIndex>::sUnexpectedPasses;
533 
534 // static
535 template <size_t TestModuleIndex>
SetUpTestCase()536 void dEQPTest<TestModuleIndex>::SetUpTestCase()
537 {
538     sPassedTestCount       = 0;
539     sFailedTestCount       = 0;
540     sNotSupportedTestCount = 0;
541     sTestExceptionCount    = 0;
542     sTestCount             = 0;
543     sSkippedTestCount      = 0;
544     sUnexpectedPasses.clear();
545     sUnexpectedFailed.clear();
546 
547     std::vector<const char *> argv;
548 
549     // Reserve one argument for the binary name.
550     argv.push_back("");
551 
552     // Add init api.
553     const char *targetApi    = gInitAPI ? gInitAPI->first : GetDefaultAPIName();
554     std::string apiArgString = std::string(kdEQPEGLString) + targetApi;
555     argv.push_back(apiArgString.c_str());
556 
557     // Add config name
558     const char *targetConfigName = gEGLConfigName;
559     std::string configArgString  = std::string(gdEQPEGLConfigNameString) + targetConfigName;
560     argv.push_back(configArgString.c_str());
561 
562     // Hide SwiftShader window to prevent a race with Xvfb causing hangs on test bots
563     if (gInitAPI && gInitAPI->second == GPUTestConfig::kAPISwiftShader)
564     {
565         argv.push_back("--deqp-visibility=hidden");
566     }
567 
568     TestSuite *testSuite = TestSuite::GetInstance();
569 
570     std::stringstream logNameStream;
571     logNameStream << "TestResults";
572     if (testSuite->getBatchId() != -1)
573     {
574         logNameStream << "-Batch" << std::setfill('0') << std::setw(3) << testSuite->getBatchId();
575     }
576     logNameStream << ".qpa";
577 
578     std::stringstream logArgStream;
579     logArgStream << "--deqp-log-filename="
580                  << testSuite->reserveTestArtifactPath(logNameStream.str());
581 
582     std::string logNameString = logArgStream.str();
583     argv.push_back(logNameString.c_str());
584 
585     if (!gLogImages)
586     {
587         argv.push_back("--deqp-log-images=disable");
588     }
589 
590     // Flushing during multi-process execution punishes HDDs. http://anglebug.com/5157
591     if (testSuite->getBatchId() != -1)
592     {
593         argv.push_back("--deqp-log-flush=disable");
594     }
595 
596     // Add any additional flags specified from command line to be forwarded to dEQP.
597     argv.insert(argv.end(), gdEQPForwardFlags.begin(), gdEQPForwardFlags.end());
598 
599     // Init the platform.
600     if (!deqp_libtester_init_platform(static_cast<int>(argv.size()), argv.data(),
601                                       reinterpret_cast<void *>(&HandlePlatformError), gOptions))
602     {
603         std::cout << "Aborting test due to dEQP initialization error." << std::endl;
604         exit(1);
605     }
606 }
607 
608 // static
609 template <size_t TestModuleIndex>
TearDownTestCase()610 void dEQPTest<TestModuleIndex>::TearDownTestCase()
611 {
612     PrintTestStats();
613     deqp_libtester_shutdown_platform();
614 }
615 
616 #define ANGLE_INSTANTIATE_DEQP_TEST_CASE(API, N)                              \
617     class dEQP : public dEQPTest<N>                                           \
618     {};                                                                       \
619     TEST_P(dEQP, API) { runTest(); }                                          \
620                                                                               \
621     INSTANTIATE_TEST_SUITE_P(, dEQP, dEQP::GetTestingRange(),                 \
622                              [](const testing::TestParamInfo<size_t> &info) { \
623                                  return dEQP::GetCaseGTestName(info.param);   \
624                              })
625 
626 #ifdef ANGLE_DEQP_GLES2_TESTS
627 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES2, 0);
628 #endif
629 
630 #ifdef ANGLE_DEQP_GLES3_TESTS
631 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3, 1);
632 #endif
633 
634 #ifdef ANGLE_DEQP_GLES31_TESTS
635 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31, 2);
636 #endif
637 
638 #ifdef ANGLE_DEQP_EGL_TESTS
639 ANGLE_INSTANTIATE_DEQP_TEST_CASE(EGL, 3);
640 #endif
641 
642 #ifdef ANGLE_DEQP_KHR_GLES2_TESTS
643 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES2, 4);
644 #endif
645 
646 #ifdef ANGLE_DEQP_KHR_GLES3_TESTS
647 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES3, 5);
648 #endif
649 
650 #ifdef ANGLE_DEQP_KHR_GLES31_TESTS
651 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES31, 6);
652 #endif
653 
654 #ifdef ANGLE_DEQP_KHR_GLES32_TESTS
655 ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES32, 7);
656 #endif
657 
658 #ifdef ANGLE_DEQP_GLES3_ROTATE90_TESTS
659 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE90, 8);
660 #endif
661 
662 #ifdef ANGLE_DEQP_GLES3_ROTATE180_TESTS
663 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE180, 9);
664 #endif
665 
666 #ifdef ANGLE_DEQP_GLES3_ROTATE270_TESTS
667 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE270, 10);
668 #endif
669 
670 #ifdef ANGLE_DEQP_GLES31_ROTATE90_TESTS
671 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE90, 11);
672 #endif
673 
674 #ifdef ANGLE_DEQP_GLES31_ROTATE180_TESTS
675 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE180, 12);
676 #endif
677 
678 #ifdef ANGLE_DEQP_GLES31_ROTATE270_TESTS
679 ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE270, 13);
680 #endif
681 
HandleDisplayType(const char * displayTypeString)682 void HandleDisplayType(const char *displayTypeString)
683 {
684     std::stringstream argStream;
685 
686     if (gInitAPI)
687     {
688         std::cout << "Cannot specify two EGL displays!" << std::endl;
689         exit(1);
690     }
691 
692     if (strncmp(displayTypeString, "angle-", strlen("angle-")) != 0)
693     {
694         argStream << "angle-";
695     }
696 
697     argStream << displayTypeString;
698     std::string arg = argStream.str();
699 
700     gInitAPI = FindAPIInfo(arg);
701 
702     if (!gInitAPI)
703     {
704         std::cout << "Unknown ANGLE back-end API: " << displayTypeString << std::endl;
705         exit(1);
706     }
707 }
708 
HandlePreRotation(const char * preRotationString)709 void HandlePreRotation(const char *preRotationString)
710 {
711     std::istringstream argStream(preRotationString);
712 
713     uint32_t preRotation = 0;
714     argStream >> preRotation;
715 
716     if (!argStream ||
717         (preRotation != 0 && preRotation != 90 && preRotation != 180 && preRotation != 270))
718     {
719         std::cout << "Invalid PreRotation '" << preRotationString
720                   << "'; must be either 0, 90, 180 or 270" << std::endl;
721         exit(1);
722     }
723 
724     gOptions.preRotation = preRotation;
725 }
726 
HandleEGLConfigName(const char * configNameString)727 void HandleEGLConfigName(const char *configNameString)
728 {
729     gEGLConfigName = configNameString;
730 }
731 
732 // The --deqp-case flag takes a case expression that is parsed into a --gtest_filter. It converts
733 // the "dEQP" style names (functional.thing.*) into "GoogleTest" style names (functional_thing_*).
734 // Currently it does not handle multiple tests and multiple filters in different arguments.
HandleCaseName(const char * caseString,int * argc,int argIndex,char ** argv)735 void HandleCaseName(const char *caseString, int *argc, int argIndex, char **argv)
736 {
737     std::string googleTestName = DrawElementsToGoogleTestName(caseString);
738     gCaseStringBuffer.fill(0);
739     int bytesWritten = snprintf(gCaseStringBuffer.data(), gCaseStringBuffer.size() - 1,
740                                 "--gtest_filter=*%s", googleTestName.c_str());
741     if (bytesWritten <= 0 || static_cast<size_t>(bytesWritten) >= gCaseStringBuffer.size() - 1)
742     {
743         std::cout << "Error parsing test case string: " << caseString;
744         exit(1);
745     }
746 
747     argv[argIndex] = gCaseStringBuffer.data();
748 }
749 
HandleLogImages(const char * logImagesString)750 void HandleLogImages(const char *logImagesString)
751 {
752     if (strcmp(logImagesString, "enable") == 0)
753     {
754         gLogImages = true;
755     }
756     else if (strcmp(logImagesString, "disable") == 0)
757     {
758         gLogImages = false;
759     }
760     else
761     {
762         std::cout << "Error parsing log images setting. Use enable/disable.";
763         exit(1);
764     }
765 }
766 }  // anonymous namespace
767 
768 // Called from main() to process command-line arguments.
InitTestHarness(int * argc,char ** argv)769 void InitTestHarness(int *argc, char **argv)
770 {
771     int argIndex = 0;
772     while (argIndex < *argc)
773     {
774         if (strncmp(argv[argIndex], kdEQPEGLString, strlen(kdEQPEGLString)) == 0)
775         {
776             HandleDisplayType(argv[argIndex] + strlen(kdEQPEGLString));
777         }
778         else if (strncmp(argv[argIndex], kANGLEEGLString, strlen(kANGLEEGLString)) == 0)
779         {
780             HandleDisplayType(argv[argIndex] + strlen(kANGLEEGLString));
781         }
782         else if (strncmp(argv[argIndex], kANGLEPreRotation, strlen(kANGLEPreRotation)) == 0)
783         {
784             HandlePreRotation(argv[argIndex] + strlen(kANGLEPreRotation));
785         }
786         else if (strncmp(argv[argIndex], gdEQPEGLConfigNameString,
787                          strlen(gdEQPEGLConfigNameString)) == 0)
788         {
789             HandleEGLConfigName(argv[argIndex] + strlen(gdEQPEGLConfigNameString));
790         }
791         else if (strncmp(argv[argIndex], kdEQPCaseString, strlen(kdEQPCaseString)) == 0)
792         {
793             HandleCaseName(argv[argIndex] + strlen(kdEQPCaseString), argc, argIndex, argv);
794         }
795         else if (strncmp(argv[argIndex], kVerboseString, strlen(kVerboseString)) == 0 ||
796                  strcmp(argv[argIndex], "-v") == 0)
797         {
798             gVerbose = true;
799         }
800         else if (strncmp(argv[argIndex], gdEQPLogImagesString, strlen(gdEQPLogImagesString)) == 0)
801         {
802             HandleLogImages(argv[argIndex] + strlen(gdEQPLogImagesString));
803         }
804         else if (strncmp(argv[argIndex], kRenderDocString, strlen(kRenderDocString)) == 0)
805         {
806             gOptions.enableRenderDocCapture = true;
807         }
808         else if (strncmp(argv[argIndex], kNoRenderDocString, strlen(kNoRenderDocString)) == 0)
809         {
810             gOptions.enableRenderDocCapture = false;
811         }
812         else if (strncmp(argv[argIndex], kdEQPFlagsPrefix, strlen(kdEQPFlagsPrefix)) == 0)
813         {
814             gdEQPForwardFlags.push_back(argv[argIndex]);
815         }
816         argIndex++;
817     }
818 
819     GPUTestConfig::API api = GetDefaultAPIInfo()->second;
820     if (gInitAPI)
821     {
822         api = gInitAPI->second;
823     }
824     if (gOptions.preRotation != 0 && api != GPUTestConfig::kAPIVulkan &&
825         api != GPUTestConfig::kAPISwiftShader)
826     {
827         std::cout << "PreRotation is only supported on Vulkan" << std::endl;
828         exit(1);
829     }
830 }
831 }  // namespace angle
832