1 //
2 // Copyright 2014 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
7 // angle_test_instantiate.h: Adds support for filtering parameterized
8 // tests by platform, so we skip unsupported configs.
9
10 #ifndef ANGLE_TEST_INSTANTIATE_H_
11 #define ANGLE_TEST_INSTANTIATE_H_
12
13 #include <gtest/gtest.h>
14
15 #include "common/platform.h"
16
17 namespace angle
18 {
19 struct SystemInfo;
20 struct PlatformParameters;
21
22 // Operating systems
23 bool IsAndroid();
24 bool IsLinux();
25 bool IsOSX();
26 bool IsOzone();
27 bool IsWindows();
28 bool IsWindows7();
29 bool IsFuchsia();
30
31 // Android devices
32 bool IsNexus5X();
33 bool IsNexus6P();
34 bool IsNexus9();
35 bool IsPixelXL();
36 bool IsPixel2();
37 bool IsPixel2XL();
38 bool IsNVIDIAShield();
39
40 // GPU vendors.
41 bool IsIntel();
42 bool IsAMD();
43 bool IsNVIDIA();
44 bool IsARM();
45 bool IsARM64();
46
47 // GPU devices.
48 bool IsSwiftshaderDevice();
49
IsASan()50 inline bool IsASan()
51 {
52 #if defined(ANGLE_WITH_ASAN)
53 return true;
54 #else
55 return false;
56 #endif // defined(ANGLE_WITH_ASAN)
57 }
58
59 bool IsPlatformAvailable(const PlatformParameters ¶m);
60
61 // This functions is used to filter which tests should be registered,
62 // T must be or inherit from angle::PlatformParameters.
63 template <typename T>
FilterTestParams(const T * params,size_t numParams)64 std::vector<T> FilterTestParams(const T *params, size_t numParams)
65 {
66 std::vector<T> filtered;
67
68 for (size_t i = 0; i < numParams; i++)
69 {
70 if (IsPlatformAvailable(params[i]))
71 {
72 filtered.push_back(params[i]);
73 }
74 }
75
76 return filtered;
77 }
78
79 template <typename T>
FilterTestParams(const std::vector<T> & params)80 std::vector<T> FilterTestParams(const std::vector<T> ¶ms)
81 {
82 return FilterTestParams(params.data(), params.size());
83 }
84
85 // Used to generate valid test names out of testing::PrintToStringParamName used in combined tests.
86 struct CombinedPrintToStringParamName
87 {
88 template <class ParamType>
operatorCombinedPrintToStringParamName89 std::string operator()(const testing::TestParamInfo<ParamType> &info) const
90 {
91 std::string name = testing::PrintToStringParamName()(info);
92 std::string sanitized;
93 for (const char c : name)
94 {
95 if (c == ',')
96 {
97 sanitized += '_';
98 }
99 else if (isalnum(c) || c == '_')
100 {
101 sanitized += c;
102 }
103 }
104 return sanitized;
105 }
106 };
107
108 #define ANGLE_INSTANTIATE_TEST_PLATFORMS(testName, ...) \
109 testing::ValuesIn(::angle::FilterTestParams(testName##__VA_ARGS__##params, \
110 ArraySize(testName##__VA_ARGS__##params)))
111
112 // Instantiate the test once for each extra argument. The types of all the
113 // arguments must match, and getRenderer must be implemented for that type.
114 #define ANGLE_INSTANTIATE_TEST(testName, first, ...) \
115 const decltype(first) testName##params[] = {first, ##__VA_ARGS__}; \
116 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
117 testing::PrintToStringParamName())
118
119 #define ANGLE_INSTANTIATE_TEST_ARRAY(testName, valuesin) \
120 INSTANTIATE_TEST_SUITE_P(, testName, testing::ValuesIn(::angle::FilterTestParams(valuesin)), \
121 testing::PrintToStringParamName())
122
123 #define ANGLE_ALL_TEST_PLATFORMS_ES1 \
124 ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES(), ES1_VULKAN(), ES1_VULKAN_SWIFTSHADER()
125
126 #define ANGLE_ALL_TEST_PLATFORMS_ES2 \
127 ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(), ES2_VULKAN_SWIFTSHADER(), \
128 ES2_METAL()
129
130 #define ANGLE_ALL_TEST_PLATFORMS_ES3 \
131 ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER()
132
133 #define ANGLE_ALL_TEST_PLATFORMS_ES31 \
134 ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()
135
136 #define ANGLE_ALL_TEST_PLATFORMS_NULL ES2_NULL(), ES3_NULL(), ES31_NULL()
137
138 // Instantiate the test once for each GLES1 platform
139 #define ANGLE_INSTANTIATE_TEST_ES1(testName) \
140 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES1}; \
141 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
142 testing::PrintToStringParamName())
143
144 // Instantiate the test once for each GLES2 platform
145 #define ANGLE_INSTANTIATE_TEST_ES2(testName) \
146 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2}; \
147 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
148 testing::PrintToStringParamName())
149
150 // Instantiate the test once for each GLES3 platform
151 #define ANGLE_INSTANTIATE_TEST_ES3(testName) \
152 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3}; \
153 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
154 testing::PrintToStringParamName())
155
156 #define ANGLE_INSTANTIATE_TEST_ES3_AND(testName, extra) \
157 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, extra}; \
158 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
159 testing::PrintToStringParamName())
160
161 // Instantiate the test once for each GLES31 platform
162 #define ANGLE_INSTANTIATE_TEST_ES31(testName) \
163 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES31}; \
164 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
165 testing::PrintToStringParamName())
166
167 #define ANGLE_INSTANTIATE_TEST_ES31_AND(testName, extra) \
168 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES31, extra}; \
169 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
170 testing::PrintToStringParamName())
171
172 // Multiple ES Version macros
173 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(testName) \
174 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
175 ANGLE_ALL_TEST_PLATFORMS_ES3}; \
176 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
177 testing::PrintToStringParamName())
178
179 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(testName, extra) \
180 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
181 ANGLE_ALL_TEST_PLATFORMS_ES3, extra}; \
182 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
183 testing::PrintToStringParamName())
184
185 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(testName) \
186 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
187 ANGLE_ALL_TEST_PLATFORMS_ES3, \
188 ANGLE_ALL_TEST_PLATFORMS_ES31}; \
189 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
190 testing::PrintToStringParamName())
191
192 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL(testName) \
193 const PlatformParameters testName##params[] = { \
194 ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3, ANGLE_ALL_TEST_PLATFORMS_ES31, \
195 ANGLE_ALL_TEST_PLATFORMS_NULL}; \
196 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
197 testing::PrintToStringParamName())
198
199 #define ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(testName) \
200 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, \
201 ANGLE_ALL_TEST_PLATFORMS_ES31}; \
202 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
203 testing::PrintToStringParamName())
204
205 // Instantiate the test for a combination of N parameters and the
206 // enumeration of platforms in the extra args, similar to
207 // ANGLE_INSTANTIATE_TEST. The macros are defined only for the Ns
208 // currently in use, and can be expanded as necessary.
209 #define ANGLE_INSTANTIATE_TEST_COMBINE_1(testName, print, combine1, first, ...) \
210 const decltype(first) testName##params[] = {first, ##__VA_ARGS__}; \
211 INSTANTIATE_TEST_SUITE_P( \
212 , testName, testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), combine1), print)
213 #define ANGLE_INSTANTIATE_TEST_COMBINE_4(testName, print, combine1, combine2, combine3, combine4, \
214 first, ...) \
215 const decltype(first) testName##params[] = {first, ##__VA_ARGS__}; \
216 INSTANTIATE_TEST_SUITE_P(, testName, \
217 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
218 combine1, combine2, combine3, combine4), \
219 print)
220 #define ANGLE_INSTANTIATE_TEST_COMBINE_5(testName, print, combine1, combine2, combine3, combine4, \
221 combine5, first, ...) \
222 const decltype(first) testName##params[] = {first, ##__VA_ARGS__}; \
223 INSTANTIATE_TEST_SUITE_P(, testName, \
224 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
225 combine1, combine2, combine3, combine4, combine5), \
226 print)
227
228 // Checks if a config is expected to be supported by checking a system-based white list.
229 bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters ¶m);
230
231 // Determines if a config is supported by trying to initialize it. Does
232 // not require SystemInfo.
233 bool IsConfigSupported(const PlatformParameters ¶m);
234
235 // Returns shared test system information. Can be used globally in the
236 // tests.
237 SystemInfo *GetTestSystemInfo();
238
239 // Returns a list of all enabled test platform names. For use in
240 // configuration enumeration.
241 std::vector<std::string> GetAvailableTestPlatformNames();
242
243 // Active config (e.g. ES2_Vulkan).
244 void SetSelectedConfig(const char *selectedConfig);
245 bool IsConfigSelected();
246
247 // Use a separate isolated process per test config. This works around
248 // driver flakiness when using multiple APIs/windows/etc in the same
249 // process.
250 extern bool gSeparateProcessPerConfig;
251
252 // For use with ANGLE_INSTANTIATE_TEST_ARRAY
253 template <typename ParamsT>
254 using ModifierFunc = std::function<ParamsT(const ParamsT &)>;
255
256 template <typename ParamsT>
CombineWithFuncs(const std::vector<ParamsT> & in,const std::vector<ModifierFunc<ParamsT>> & modifiers)257 std::vector<ParamsT> CombineWithFuncs(const std::vector<ParamsT> &in,
258 const std::vector<ModifierFunc<ParamsT>> &modifiers)
259 {
260 std::vector<ParamsT> out;
261 for (const ParamsT ¶msIn : in)
262 {
263 for (ModifierFunc<ParamsT> modifier : modifiers)
264 {
265 out.push_back(modifier(paramsIn));
266 }
267 }
268 return out;
269 }
270
271 template <typename ParamT, typename RangeT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,RangeT begin,RangeT end,ParamT combine (const ParamT &,ModifierT))272 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
273 RangeT begin,
274 RangeT end,
275 ParamT combine(const ParamT &, ModifierT))
276 {
277 std::vector<ParamT> out;
278 for (const ParamT ¶msIn : in)
279 {
280 for (auto iter = begin; iter != end; ++iter)
281 {
282 out.push_back(combine(paramsIn, *iter));
283 }
284 }
285 return out;
286 }
287
288 template <typename ParamT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,const std::initializer_list<ModifierT> & modifiers,ParamT combine (const ParamT &,ModifierT))289 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
290 const std::initializer_list<ModifierT> &modifiers,
291 ParamT combine(const ParamT &, ModifierT))
292 {
293 return CombineWithValues(in, modifiers.begin(), modifiers.end(), combine);
294 }
295
296 template <typename ParamT, typename ModifiersT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,const ModifiersT & modifiers,ParamT combine (const ParamT &,ModifierT))297 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
298 const ModifiersT &modifiers,
299 ParamT combine(const ParamT &, ModifierT))
300 {
301 return CombineWithValues(in, std::begin(modifiers), std::end(modifiers), combine);
302 }
303 } // namespace angle
304
305 #define ANGLE_SKIP_TEST_IF(COND) \
306 do \
307 { \
308 if (COND) \
309 { \
310 std::cout << "Test skipped: " #COND "." << std::endl; \
311 return; \
312 } \
313 } while (0)
314
315 #endif // ANGLE_TEST_INSTANTIATE_H_
316