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