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 IsIOS();
27 bool IsOzone();
28 bool IsWindows();
29 bool IsWindows7();
30 bool IsFuchsia();
31
32 // CPU architectures
33 bool IsARM64();
34
35 // Android devices
36 bool IsNexus5X();
37 bool IsNexus9();
38 bool IsPixelXL();
39 bool IsPixel2();
40 bool IsPixel2XL();
41 bool IsPixel4();
42 bool IsPixel4XL();
43 bool IsNVIDIAShield();
44
45 // GPU vendors.
46 bool IsIntel();
47 bool IsAMD();
48 bool IsApple();
49 bool IsARM();
50 bool IsNVIDIA();
51 bool IsQualcomm();
52
53 // GPU devices.
54 bool IsSwiftshaderDevice();
55 bool IsIntelUHD630Mobile();
56 bool IsIntelHD630Mobile();
57
58 bool Is64Bit();
59
60 bool IsPlatformAvailable(const PlatformParameters ¶m);
61
62 // This functions is used to filter which tests should be registered,
63 // T must be or inherit from angle::PlatformParameters.
64 template <typename T>
FilterTestParams(const T * params,size_t numParams)65 std::vector<T> FilterTestParams(const T *params, size_t numParams)
66 {
67 std::vector<T> filtered;
68
69 for (size_t i = 0; i < numParams; i++)
70 {
71 if (IsPlatformAvailable(params[i]))
72 {
73 filtered.push_back(params[i]);
74 }
75 }
76
77 return filtered;
78 }
79
80 template <typename T>
FilterTestParams(const std::vector<T> & params)81 std::vector<T> FilterTestParams(const std::vector<T> ¶ms)
82 {
83 return FilterTestParams(params.data(), params.size());
84 }
85
86 // Used to generate valid test names out of testing::PrintToStringParamName used in combined tests.
87 struct CombinedPrintToStringParamName
88 {
89 template <class ParamType>
operatorCombinedPrintToStringParamName90 std::string operator()(const testing::TestParamInfo<ParamType> &info) const
91 {
92 std::string name = testing::PrintToStringParamName()(info);
93 std::string sanitized;
94 for (const char c : name)
95 {
96 if (c == ',')
97 {
98 sanitized += '_';
99 }
100 else if (isalnum(c) || c == '_')
101 {
102 sanitized += c;
103 }
104 }
105 return sanitized;
106 }
107 };
108
109 #define ANGLE_INSTANTIATE_TEST_PLATFORMS(testName, ...) \
110 testing::ValuesIn(::angle::FilterTestParams(testName##__VA_ARGS__##params, \
111 ArraySize(testName##__VA_ARGS__##params)))
112
113 // Instantiate the test once for each extra argument. The types of all the
114 // arguments must match, and getRenderer must be implemented for that type.
115 #define ANGLE_INSTANTIATE_TEST(testName, first, ...) \
116 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
117 ##__VA_ARGS__}; \
118 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
119 testing::PrintToStringParamName())
120
121 #define ANGLE_INSTANTIATE_TEST_ARRAY(testName, valuesin) \
122 INSTANTIATE_TEST_SUITE_P(, testName, testing::ValuesIn(::angle::FilterTestParams(valuesin)), \
123 testing::PrintToStringParamName())
124
125 #define ANGLE_ALL_TEST_PLATFORMS_ES1 \
126 ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES(), ES1_VULKAN(), ES1_VULKAN_SWIFTSHADER(), \
127 ES1_VULKAN().enable(Feature::AsyncCommandQueue), \
128 ES1_VULKAN_SWIFTSHADER().enable(Feature::AsyncCommandQueue)
129
130 #define ANGLE_ALL_TEST_PLATFORMS_ES2 \
131 ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(), ES2_VULKAN_SWIFTSHADER(), \
132 ES2_METAL(), ES2_VULKAN().enable(Feature::AsyncCommandQueue), \
133 ES2_VULKAN_SWIFTSHADER().enable(Feature::AsyncCommandQueue)
134
135 #define ANGLE_ALL_TEST_PLATFORMS_ES3 \
136 ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER(), \
137 ES3_METAL(), ES3_VULKAN().enable(Feature::AsyncCommandQueue), \
138 ES3_VULKAN_SWIFTSHADER().enable(Feature::AsyncCommandQueue)
139
140 #define ANGLE_ALL_TEST_PLATFORMS_ES31 \
141 ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER(), \
142 ES31_VULKAN().enable(Feature::AsyncCommandQueue), \
143 ES31_VULKAN_SWIFTSHADER().enable(Feature::AsyncCommandQueue)
144
145 #define ANGLE_ALL_TEST_PLATFORMS_ES32 \
146 ES32_VULKAN(), ES32_VULKAN().enable(Feature::AsyncCommandQueue)
147
148 #define ANGLE_ALL_TEST_PLATFORMS_NULL ES2_NULL(), ES3_NULL(), ES31_NULL()
149
150 // Instantiate the test once for each GLES1 platform
151 #define ANGLE_INSTANTIATE_TEST_ES1(testName) \
152 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES1}; \
153 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
154 testing::PrintToStringParamName())
155
156 // Instantiate the test once for each GLES2 platform
157 #define ANGLE_INSTANTIATE_TEST_ES2(testName) \
158 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2}; \
159 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
160 testing::PrintToStringParamName())
161
162 #define ANGLE_INSTANTIATE_TEST_ES2_AND(testName, ...) \
163 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, __VA_ARGS__}; \
164 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
165 testing::PrintToStringParamName())
166
167 // Instantiate the test once for each GLES3 platform
168 #define ANGLE_INSTANTIATE_TEST_ES3(testName) \
169 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3}; \
170 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
171 testing::PrintToStringParamName())
172
173 #define ANGLE_INSTANTIATE_TEST_ES3_AND(testName, ...) \
174 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, __VA_ARGS__}; \
175 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
176 testing::PrintToStringParamName())
177
178 // Instantiate the test once for each GLES31 platform
179 #define ANGLE_INSTANTIATE_TEST_ES31(testName) \
180 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES31}; \
181 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
182 testing::PrintToStringParamName())
183
184 #define ANGLE_INSTANTIATE_TEST_ES31_AND(testName, ...) \
185 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES31, __VA_ARGS__}; \
186 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
187 testing::PrintToStringParamName())
188
189 // Instantiate the test once for each GLES32 platform
190 #define ANGLE_INSTANTIATE_TEST_ES32(testName) \
191 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES32}; \
192 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
193 testing::PrintToStringParamName())
194
195 #define ANGLE_INSTANTIATE_TEST_ES32_AND(testName, ...) \
196 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES32, __VA_ARGS__}; \
197 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
198 testing::PrintToStringParamName())
199
200 // Multiple ES Version macros
201 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(testName) \
202 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
203 ANGLE_ALL_TEST_PLATFORMS_ES3}; \
204 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
205 testing::PrintToStringParamName())
206
207 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(testName, ...) \
208 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
209 ANGLE_ALL_TEST_PLATFORMS_ES3, __VA_ARGS__}; \
210 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
211 testing::PrintToStringParamName())
212
213 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(testName) \
214 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
215 ANGLE_ALL_TEST_PLATFORMS_ES3, \
216 ANGLE_ALL_TEST_PLATFORMS_ES31}; \
217 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
218 testing::PrintToStringParamName())
219
220 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL(testName) \
221 const PlatformParameters testName##params[] = { \
222 ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3, ANGLE_ALL_TEST_PLATFORMS_ES31, \
223 ANGLE_ALL_TEST_PLATFORMS_NULL}; \
224 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
225 testing::PrintToStringParamName())
226
227 #define ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(testName) \
228 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, \
229 ANGLE_ALL_TEST_PLATFORMS_ES31}; \
230 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
231 testing::PrintToStringParamName())
232
233 #define ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(testName, ...) \
234 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, \
235 ANGLE_ALL_TEST_PLATFORMS_ES31, __VA_ARGS__}; \
236 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
237 testing::PrintToStringParamName())
238
239 // Instantiate the test for a combination of N parameters and the
240 // enumeration of platforms in the extra args, similar to
241 // ANGLE_INSTANTIATE_TEST. The macros are defined only for the Ns
242 // currently in use, and can be expanded as necessary.
243 #define ANGLE_INSTANTIATE_TEST_COMBINE_1(testName, print, combine1, first, ...) \
244 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
245 ##__VA_ARGS__}; \
246 INSTANTIATE_TEST_SUITE_P( \
247 , testName, testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), combine1), print)
248 #define ANGLE_INSTANTIATE_TEST_COMBINE_4(testName, print, combine1, combine2, combine3, combine4, \
249 first, ...) \
250 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
251 ##__VA_ARGS__}; \
252 INSTANTIATE_TEST_SUITE_P(, testName, \
253 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
254 combine1, combine2, combine3, combine4), \
255 print)
256 #define ANGLE_INSTANTIATE_TEST_COMBINE_5(testName, print, combine1, combine2, combine3, combine4, \
257 combine5, first, ...) \
258 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
259 ##__VA_ARGS__}; \
260 INSTANTIATE_TEST_SUITE_P(, testName, \
261 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
262 combine1, combine2, combine3, combine4, combine5), \
263 print)
264 #define ANGLE_INSTANTIATE_TEST_COMBINE_6(testName, print, combine1, combine2, combine3, combine4, \
265 combine5, combine6, first, ...) \
266 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
267 ##__VA_ARGS__}; \
268 INSTANTIATE_TEST_SUITE_P( \
269 , testName, \
270 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), combine1, combine2, combine3, \
271 combine4, combine5, combine6), \
272 print)
273
274 // Checks if a config is expected to be supported by checking a system-based allow list.
275 bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters ¶m);
276
277 // Determines if a config is supported by trying to initialize it. Does
278 // not require SystemInfo.
279 bool IsConfigSupported(const PlatformParameters ¶m);
280
281 // Returns shared test system information. Can be used globally in the
282 // tests.
283 SystemInfo *GetTestSystemInfo();
284
285 // Returns a list of all enabled test platform names. For use in
286 // configuration enumeration.
287 std::vector<std::string> GetAvailableTestPlatformNames();
288
289 // Active config (e.g. ES2_Vulkan).
290 void SetSelectedConfig(const char *selectedConfig);
291 bool IsConfigSelected();
292
293 // Check whether texture swizzle is natively supported on Metal device.
294 bool IsMetalTextureSwizzleAvailable();
295
296 // Check whether TEXTURE_3D target is supported for compressed formats on Metal device.
297 bool IsMetalCompressedTexture3DAvailable();
298
299 extern bool gEnableANGLEPerTestCaptureLabel;
300
301 // For use with ANGLE_INSTANTIATE_TEST_ARRAY
302 template <typename ParamsT>
303 using ModifierFunc = std::function<ParamsT(const ParamsT &)>;
304
305 template <typename ParamsT>
CombineWithFuncs(const std::vector<ParamsT> & in,const std::vector<ModifierFunc<ParamsT>> & modifiers)306 std::vector<ParamsT> CombineWithFuncs(const std::vector<ParamsT> &in,
307 const std::vector<ModifierFunc<ParamsT>> &modifiers)
308 {
309 std::vector<ParamsT> out;
310 for (const ParamsT ¶msIn : in)
311 {
312 for (ModifierFunc<ParamsT> modifier : modifiers)
313 {
314 out.push_back(modifier(paramsIn));
315 }
316 }
317 return out;
318 }
319
320 template <typename ParamT, typename RangeT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,RangeT begin,RangeT end,ParamT combine (const ParamT &,ModifierT))321 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
322 RangeT begin,
323 RangeT end,
324 ParamT combine(const ParamT &, ModifierT))
325 {
326 std::vector<ParamT> out;
327 for (const ParamT ¶msIn : in)
328 {
329 for (auto iter = begin; iter != end; ++iter)
330 {
331 out.push_back(combine(paramsIn, *iter));
332 }
333 }
334 return out;
335 }
336
337 template <typename ParamT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,const std::initializer_list<ModifierT> & modifiers,ParamT combine (const ParamT &,ModifierT))338 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
339 const std::initializer_list<ModifierT> &modifiers,
340 ParamT combine(const ParamT &, ModifierT))
341 {
342 return CombineWithValues(in, modifiers.begin(), modifiers.end(), combine);
343 }
344
345 template <typename ParamT, typename ModifiersT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,const ModifiersT & modifiers,ParamT combine (const ParamT &,ModifierT))346 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
347 const ModifiersT &modifiers,
348 ParamT combine(const ParamT &, ModifierT))
349 {
350 return CombineWithValues(in, std::begin(modifiers), std::end(modifiers), combine);
351 }
352
353 template <typename ParamT, typename FilterFunc>
FilterWithFunc(const std::vector<ParamT> & in,FilterFunc filter)354 std::vector<ParamT> FilterWithFunc(const std::vector<ParamT> &in, FilterFunc filter)
355 {
356 std::vector<ParamT> out;
357 for (const ParamT ¶m : in)
358 {
359 if (filter(param))
360 {
361 out.push_back(param);
362 }
363 }
364 return out;
365 }
366 } // namespace angle
367
368 #define ANGLE_SKIP_TEST_IF(COND) \
369 do \
370 { \
371 if (COND) \
372 { \
373 GTEST_SKIP() << "Test skipped: " #COND "."; \
374 return; \
375 } \
376 } while (0)
377
378 #endif // ANGLE_TEST_INSTANTIATE_H_
379