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 // deqp_libtester_main.cpp: Entry point for tester DLL.
7
8 #include <cstdio>
9 #include <iostream>
10
11 #include "angle_deqp_libtester.h"
12 #include "common/angleutils.h"
13 #include "common/system_utils.h"
14 #include "deMath.h"
15 #include "deUniquePtr.hpp"
16 #include "platform/PlatformMethods.h"
17 #include "tcuApp.hpp"
18 #include "tcuCommandLine.hpp"
19 #include "tcuDefs.hpp"
20 #include "tcuPlatform.hpp"
21 #include "tcuRandomOrderExecutor.h"
22 #include "tcuResource.hpp"
23 #include "tcuTestLog.hpp"
24
25 tcu::Platform *CreateANGLEPlatform(angle::LogErrorFunc logErrorFunc);
26
27 namespace
28 {
29
30 tcu::Platform *g_platform = nullptr;
31 tcu::CommandLine *g_cmdLine = nullptr;
32 tcu::DirArchive *g_archive = nullptr;
33 tcu::TestLog *g_log = nullptr;
34 tcu::TestContext *g_testCtx = nullptr;
35 tcu::TestPackageRoot *g_root = nullptr;
36 tcu::RandomOrderExecutor *g_executor = nullptr;
37
38 const char *kDataPaths[] = {
39 ".",
40 "../../sdcard/chromium_tests_root",
41 "../../sdcard/chromium_tests_root/third_party/angle/third_party/VK-GL-CTS/src",
42 "../../third_party/angle/third_party/VK-GL-CTS/src",
43 "../../third_party/VK-GL-CTS/src",
44 "third_party/VK-GL-CTS/src",
45 };
46
FindDataDir(std::string * dataDirOut)47 bool FindDataDir(std::string *dataDirOut)
48 {
49 for (const char *dataPath : kDataPaths)
50 {
51 std::stringstream dirStream;
52 dirStream << angle::GetExecutableDirectory() << "/" << dataPath << "/"
53 << ANGLE_DEQP_DATA_DIR;
54 std::string candidateDataDir = dirStream.str();
55
56 if (angle::IsDirectory(candidateDataDir.c_str()))
57 {
58 *dataDirOut = candidateDataDir;
59 return true;
60 }
61 }
62
63 return false;
64 }
65
GetLogFileName(std::string deqpDataDir)66 std::string GetLogFileName(std::string deqpDataDir)
67 {
68 #if (DE_OS == DE_OS_ANDROID)
69 // On Android executable dir is not writable, so use data dir instead
70 return deqpDataDir + "/" + g_cmdLine->getLogFileName();
71 #else
72 return g_cmdLine->getLogFileName();
73 #endif
74 }
75
76 } // anonymous namespace
77
deqp_libtester_init_platform(int argc,const char * argv[],void * logErrorFunc)78 ANGLE_LIBTESTER_EXPORT bool deqp_libtester_init_platform(int argc,
79 const char *argv[],
80 void *logErrorFunc)
81 {
82 try
83 {
84 #if (DE_OS != DE_OS_WIN32)
85 // Set stdout to line-buffered mode (will be fully buffered by default if stdout is pipe).
86 setvbuf(stdout, DE_NULL, _IOLBF, 4 * 1024);
87 #endif
88 g_platform = CreateANGLEPlatform(reinterpret_cast<angle::LogErrorFunc>(logErrorFunc));
89
90 if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN))
91 {
92 std::cout << "Failed to set floating point rounding mode." << std::endl;
93 return false;
94 }
95
96 std::string deqpDataDir;
97 if (!FindDataDir(&deqpDataDir))
98 {
99 std::cout << "Failed to find dEQP data directory." << std::endl;
100 return false;
101 }
102
103 g_cmdLine = new tcu::CommandLine(argc, argv);
104 g_archive = new tcu::DirArchive(deqpDataDir.c_str());
105 g_log = new tcu::TestLog(GetLogFileName(deqpDataDir).c_str(), g_cmdLine->getLogFlags());
106 g_testCtx = new tcu::TestContext(*g_platform, *g_archive, *g_log, *g_cmdLine, DE_NULL);
107 g_root = new tcu::TestPackageRoot(*g_testCtx, tcu::TestPackageRegistry::getSingleton());
108 g_executor = new tcu::RandomOrderExecutor(*g_root, *g_testCtx);
109 }
110 catch (const std::exception &e)
111 {
112 tcu::die("%s", e.what());
113 return false;
114 }
115
116 return true;
117 }
118
119 // Exported to the tester app.
deqp_libtester_main(int argc,const char * argv[])120 ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[])
121 {
122 if (!deqp_libtester_init_platform(argc, argv, nullptr))
123 {
124 tcu::die("Could not initialize the dEQP platform");
125 }
126
127 try
128 {
129 de::UniquePtr<tcu::App> app(new tcu::App(*g_platform, *g_archive, *g_log, *g_cmdLine));
130
131 // Main loop.
132 for (;;)
133 {
134 if (!app->iterate())
135 break;
136 }
137 }
138 catch (const std::exception &e)
139 {
140 deqp_libtester_shutdown_platform();
141 tcu::die("%s", e.what());
142 }
143
144 deqp_libtester_shutdown_platform();
145 return 0;
146 }
147
deqp_libtester_shutdown_platform()148 ANGLE_LIBTESTER_EXPORT void deqp_libtester_shutdown_platform()
149 {
150 delete g_executor;
151 g_executor = nullptr;
152 delete g_root;
153 g_root = nullptr;
154 delete g_testCtx;
155 g_testCtx = nullptr;
156 delete g_log;
157 g_log = nullptr;
158 delete g_archive;
159 g_archive = nullptr;
160 delete g_cmdLine;
161 g_cmdLine = nullptr;
162 delete g_platform;
163 g_platform = nullptr;
164 }
165
deqp_libtester_run(const char * caseName)166 ANGLE_LIBTESTER_EXPORT TestResult deqp_libtester_run(const char *caseName)
167 {
168 const char *emptyString = "";
169 if (g_platform == nullptr && !deqp_libtester_init_platform(1, &emptyString, nullptr))
170 {
171 tcu::die("Failed to initialize platform.");
172 }
173
174 try
175 {
176 // Poll platform events
177 const bool platformOk = g_platform->processEvents();
178
179 if (platformOk)
180 {
181 const tcu::TestStatus &result = g_executor->execute(caseName);
182 switch (result.getCode())
183 {
184 case QP_TEST_RESULT_PASS:
185 return TestResult::Pass;
186 case QP_TEST_RESULT_NOT_SUPPORTED:
187 std::cout << "Not supported! " << result.getDescription() << std::endl;
188 return TestResult::NotSupported;
189 case QP_TEST_RESULT_QUALITY_WARNING:
190 std::cout << "Quality warning! " << result.getDescription() << std::endl;
191 return TestResult::Pass;
192 case QP_TEST_RESULT_COMPATIBILITY_WARNING:
193 std::cout << "Compatiblity warning! " << result.getDescription() << std::endl;
194 return TestResult::Pass;
195 default:
196 return TestResult::Fail;
197 }
198 }
199 else
200 {
201 std::cout << "Aborted test!" << std::endl;
202 }
203 }
204 catch (const std::exception &e)
205 {
206 std::cout << "Exception running test: " << e.what() << std::endl;
207 return TestResult::Exception;
208 }
209
210 return TestResult::Fail;
211 }
212