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 &param);
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> &params)
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 &param);
273 
274 // Determines if a config is supported by trying to initialize it. Does
275 // not require SystemInfo.
276 bool IsConfigSupported(const PlatformParameters &param);
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 &paramsIn : 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 &paramsIn : 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 &param : 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