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