• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #ifndef skiatest_Test_DEFINED
8 #define skiatest_Test_DEFINED
9 
10 #include "include/core/SkString.h"
11 #include "include/core/SkTypes.h"
12 #include "src/core/SkTraceEvent.h"
13 #include "tools/Registry.h"
14 #include "tools/gpu/GrContextFactory.h"
15 
16 namespace skgpu { class Context; }
17 
18 namespace skiatest {
19 
20 SkString GetTmpDir();
21 
22 struct Failure {
FailureFailure23     Failure(const char* f, int l, const char* c, const SkString& m)
24         : fileName(f), lineNo(l), condition(c), message(m) {}
25     const char* fileName;
26     int lineNo;
27     const char* condition;
28     SkString message;
29     SkString toString() const;
30 };
31 
32 class Reporter : SkNoncopyable {
33 public:
~Reporter()34     virtual ~Reporter() {}
35     virtual void bumpTestCount();
36     virtual void reportFailed(const skiatest::Failure&) = 0;
37     virtual bool allowExtendedTest() const;
38     virtual bool verbose() const;
stats()39     virtual void* stats() const { return nullptr; }
40 
41     void reportFailedWithContext(const skiatest::Failure&);
42 
push(const SkString & message)43     void push(const SkString& message) {
44         fContextStack.push_back(message);
45     }
pop()46     void pop() {
47         fContextStack.pop_back();
48     }
49 
50 private:
51     SkTArray<SkString> fContextStack;
52 };
53 
54 #define REPORT_FAILURE(reporter, cond, message) \
55     reporter->reportFailedWithContext(skiatest::Failure(__FILE__, __LINE__, cond, message))
56 
57 class ReporterContext : SkNoncopyable {
58 public:
ReporterContext(Reporter * reporter,const SkString & message)59     ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
60         fReporter->push(message);
61     }
~ReporterContext()62     ~ReporterContext() {
63         fReporter->pop();
64     }
65 
66 private:
67     Reporter* fReporter;
68 };
69 
70 typedef void (*TestProc)(skiatest::Reporter*, const GrContextOptions&);
71 typedef void (*ContextOptionsProc)(GrContextOptions*);
72 
73 struct Test {
74     Test(const char* name,
75          bool needsGpu,
76          bool needsGraphite,
77          TestProc proc,
78          ContextOptionsProc optionsProc = nullptr)
fNameTest79             : fName(name)
80             , fNeedsGpu(needsGpu)
81             , fNeedsGraphite(needsGraphite)
82             , fProc(proc)
83             , fContextOptionsProc(optionsProc) {}
84     const char* fName;
85     bool fNeedsGpu;
86     bool fNeedsGraphite;
87     TestProc fProc;
88     ContextOptionsProc fContextOptionsProc;
89 
modifyGrContextOptionsTest90     void modifyGrContextOptions(GrContextOptions* options) {
91         if (fContextOptionsProc) {
92             (*fContextOptionsProc)(options);
93         }
94     }
95 
runTest96     void run(skiatest::Reporter* r, const GrContextOptions& options) const {
97         TRACE_EVENT1("test", TRACE_FUNC, "name", this->fName/*these are static*/);
98         this->fProc(r, options);
99     }
100 };
101 
102 typedef sk_tools::Registry<Test> TestRegistry;
103 
104 /*
105     Use the following macros to make use of the skiatest classes, e.g.
106 
107     #include "tests/Test.h"
108 
109     DEF_TEST(TestName, reporter) {
110         ...
111         REPORTER_ASSERT(reporter, x == 15);
112         ...
113         REPORTER_ASSERT(reporter, x == 15, "x should be 15");
114         ...
115         if (x != 15) {
116             ERRORF(reporter, "x should be 15, but is %d", x);
117             return;
118         }
119         ...
120     }
121 */
122 
123 using GrContextFactoryContextType = sk_gpu_test::GrContextFactory::ContextType;
124 
125 typedef void GrContextTestFn(Reporter*, const sk_gpu_test::ContextInfo&);
126 typedef bool GrContextTypeFilterFn(GrContextFactoryContextType);
127 
128 extern bool IsGLContextType(GrContextFactoryContextType);
129 extern bool IsVulkanContextType(GrContextFactoryContextType);
130 extern bool IsMetalContextType(GrContextFactoryContextType);
131 extern bool IsDawnContextType(GrContextFactoryContextType);
132 extern bool IsDirect3DContextType(GrContextFactoryContextType);
133 extern bool IsRenderingGLContextType(GrContextFactoryContextType);
134 extern bool IsMockContextType(GrContextFactoryContextType);
135 void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*,
136                             const GrContextOptions&);
137 
138 namespace graphite {
139 
140 typedef void GraphiteTestFn(Reporter*, skgpu::Context*);
141 
142 void RunWithGraphiteTestContexts(GraphiteTestFn*, Reporter*);
143 
144 } // namespace graphite
145 
146 /** Timer provides wall-clock duration since its creation. */
147 class Timer {
148 public:
149     /** Starts the timer. */
150     Timer();
151 
152     /** Nanoseconds since creation. */
153     double elapsedNs() const;
154 
155     /** Milliseconds since creation. */
156     double elapsedMs() const;
157 
158     /** Milliseconds since creation as an integer.
159         Behavior is undefined for durations longer than SK_MSecMax.
160     */
161     SkMSec elapsedMsInt() const;
162 private:
163     double fStartNanos;
164 };
165 
166 }  // namespace skiatest
167 
reporter_string()168 static inline SkString reporter_string() { return {}; }
169 /// Prevent security warnings when using a non-literal string i.e. not a format string.
reporter_string(const char * s)170 static inline SkString reporter_string(const char* s) { return SkString(s); }
171 template<typename... Args>
reporter_string(const char * fmt,Args...args)172 static inline SkString reporter_string(const char* fmt, Args... args)  {
173     return SkStringPrintf(fmt, std::forward<Args>(args)...);
174 }
175 
176 #define REPORTER_ASSERT(r, cond, ...)                               \
177     do {                                                            \
178         if (!(cond)) {                                              \
179             REPORT_FAILURE(r, #cond, reporter_string(__VA_ARGS__)); \
180         }                                                           \
181     } while (0)
182 
183 #define ERRORF(r, ...)                                       \
184     do {                                                     \
185         REPORT_FAILURE(r, "", reporter_string(__VA_ARGS__)); \
186     } while (0)
187 
188 #define INFOF(REPORTER, ...)         \
189     do {                             \
190         if ((REPORTER)->verbose()) { \
191             SkDebugf(__VA_ARGS__);   \
192         }                            \
193     } while (0)
194 
195 #define DEF_TEST(name, reporter)                                                            \
196     static void test_##name(skiatest::Reporter*, const GrContextOptions&);                  \
197     skiatest::TestRegistry name##TestRegistry(                                              \
198             skiatest::Test(#name, /*gpu*/ false, /*graphite*/ false, test_##name));         \
199     void test_##name(skiatest::Reporter* reporter, const GrContextOptions&)
200 
201 #define DEF_TEST_DISABLED(name, reporter) \
202     static void test_##name(skiatest::Reporter*, const GrContextOptions&);                  \
203     skiatest::TestRegistry name##TestRegistry(                                              \
204             skiatest::Test(#name, /*gpu*/ false, /*graphite*/ false, test_##name));         \
205     void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) {               \
206             /* SkDebugf("Disabled:"#name "\n"); */                                          \
207     }                                                                                       \
208     void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
209 
210 #ifdef SK_BUILD_FOR_UNIX
211     #define UNIX_ONLY_TEST DEF_TEST
212 #else
213     #define UNIX_ONLY_TEST DEF_TEST_DISABLED
214 #endif
215 
216 #define DEF_GRAPHITE_TEST(name, reporter)                                                   \
217     static void test_##name(skiatest::Reporter*);                                           \
218     static void test_graphite_##name(skiatest::Reporter* reporter,                          \
219                                      const GrContextOptions& /*unused*/) {                  \
220         test_##name(reporter);                                                              \
221     }                                                                                       \
222     skiatest::TestRegistry name##TestRegistry(                                              \
223             skiatest::Test(#name, /*gpu*/ false, /*graphite*/ true, test_graphite_##name)); \
224     void test_##name(skiatest::Reporter* reporter)
225 
226 #define DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, reporter, graphite_context)                    \
227     static void test_##name(skiatest::Reporter*, skgpu::Context*);                          \
228     static void test_graphite_contexts_##name(skiatest::Reporter* _reporter,                \
229                                               const GrContextOptions& /*unused*/) {         \
230         skiatest::graphite::RunWithGraphiteTestContexts(test_##name, _reporter);            \
231     }                                                                                       \
232     skiatest::TestRegistry name##TestRegistry(                                              \
233             skiatest::Test(#name, /*gpu*/ false, /*graphite*/ true,                         \
234                            test_graphite_contexts_##name));                                 \
235     void test_##name(skiatest::Reporter* reporter, skgpu::Context* graphite_context)
236 
237 #define DEF_GPUTEST(name, reporter, options)                                             \
238     static void test_##name(skiatest::Reporter*, const GrContextOptions&);               \
239     skiatest::TestRegistry name##TestRegistry(                                           \
240             skiatest::Test(#name, /*gpu*/ true, /*graphite*/ false, test_##name));       \
241     void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
242 
243 #define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter)  \
244     static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo&);              \
245     static void test_gpu_contexts_##name(skiatest::Reporter* reporter,                          \
246                                          const GrContextOptions& options) {                     \
247         skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options);       \
248     }                                                                                           \
249     skiatest::TestRegistry name##TestRegistry(                                                  \
250             skiatest::Test(#name, /*gpu*/ true, /*graphite*/ false, test_gpu_contexts_##name, options_filter));             \
251     void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info)
252 
253 #define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info)                          \
254         DEF_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr)
255 
256 #define DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info)                    \
257         DEF_GPUTEST_FOR_CONTEXTS(name, sk_gpu_test::GrContextFactory::IsRenderingContext,   \
258                                  reporter, context_info, nullptr)
259 #define DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(name, reporter, context_info)                       \
260         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsGLContextType,                          \
261                                  reporter, context_info, nullptr)
262 #define DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(name, reporter, context_info)                 \
263         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsRenderingGLContextType,                 \
264                                  reporter, context_info, nullptr)
265 #define DEF_GPUTEST_FOR_MOCK_CONTEXT(name, reporter, context_info)                          \
266         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMockContextType,                        \
267                                  reporter, context_info, nullptr)
268 #define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info)                        \
269         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType,                      \
270                                  reporter, context_info, nullptr)
271 #define DEF_GPUTEST_FOR_METAL_CONTEXT(name, reporter, context_info)                         \
272         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMetalContextType,                       \
273                                  reporter, context_info, nullptr)
274 #define DEF_GPUTEST_FOR_D3D_CONTEXT(name, reporter, context_info)                           \
275     DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsDirect3DContextType,                        \
276                              reporter, context_info, nullptr)
277 #define DEF_GPUTEST_FOR_DAWN_CONTEXT(name, reporter, context_info)                          \
278     DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsDawnContextType,                            \
279                              reporter, context_info, nullptr)
280 
281 #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER)                          \
282     do {                                                                   \
283         SkNullWStream testStream;                                          \
284         auto testDoc = SkPDF::MakeDocument(&testStream);                   \
285         if (!testDoc) {                                                    \
286             INFOF(REPORTER, "PDF disabled; %s test skipped.", #TEST_NAME); \
287             return;                                                        \
288         }                                                                  \
289     } while (false)
290 
291 #endif
292