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