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