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