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