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