Flutter Engine
The Flutter Engine
Test.h
Go to the documentation of this file.
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
16#include "tests/TestType.h"
17#include "tools/Registry.h"
18
19#if defined(SK_GANESH) || defined(SK_GRAPHITE)
20namespace skgpu { enum class ContextType; }
21#endif
22
23#if defined(SK_GANESH)
24#include "tools/gpu/GrContextFactory.h" // IWYU pragma: export (because it is used by a macro)
25#else
26namespace sk_gpu_test { class ContextInfo; }
27#endif
28
29#include <atomic>
30#include <cstdint>
31#include <string>
32
33struct GrContextOptions;
34
35namespace skgpu::graphite {
36class Context;
37struct ContextOptions;
38}
39
40namespace skiatest {
41namespace graphite {
42class GraphiteTestContext;
43struct TestOptions;
44}
45
47
48struct Failure {
49 Failure(const char* f, int l, const char* c, const SkString& m)
50 : fileName(f), lineNo(l), condition(c), message(m) {}
51 const char* fileName;
52 int lineNo;
53 const char* condition;
55 SkString toString() const;
56};
57
59public:
60 virtual ~Reporter() {}
61 virtual void bumpTestCount();
62 virtual void reportFailed(const skiatest::Failure&) = 0;
63 virtual bool allowExtendedTest() const;
64 virtual bool verbose() const;
65 virtual void* stats() const { return nullptr; }
66
68
69 /**
70 * Show additional context (e.g. subtest name) on failure assertions.
71 */
72 void push(const SkString& message) {
73 fContextStack.push_back(message);
74 }
75 void push(const std::string& message) {
76 fContextStack.push_back(SkString(message));
77 }
78
79 /**
80 * Remove additional context from failure assertions.
81 */
82 void pop() {
83 fContextStack.pop_back();
84 }
85
86private:
88};
89
90#define REPORT_FAILURE(reporter, cond, message) \
91 reporter->reportFailedWithContext(skiatest::Failure(__FILE__, __LINE__, cond, message))
92
93/**
94 * Use this stack-allocated object to push and then automatically pop the context
95 * (e.g. subtest name) for a test.
96 */
98public:
100 fReporter->push(message);
101 }
102 ReporterContext(Reporter* reporter, const std::string& message) : fReporter(reporter) {
103 fReporter->push(message);
104 }
106 fReporter->pop();
107 }
108
109private:
110 Reporter* fReporter;
111};
112
113using CPUTestProc = void (*)(Reporter*);
114using GaneshTestProc = void (*)(Reporter*, const GrContextOptions&);
118
119struct Test {
120 static Test MakeCPU(const char* name, CPUTestProc proc) {
122 proc, nullptr, nullptr, nullptr, nullptr};
123 }
124
125 static Test MakeCPUSerial(const char* name, CPUTestProc proc) {
127 proc, nullptr, nullptr, nullptr, nullptr};
128 }
129
130 static Test MakeGanesh(const char* name,
131 CtsEnforcement ctsEnforcement,
132 GaneshTestProc proc,
133 GaneshContextOptionsProc optionsProc = nullptr) {
134 return Test{name, TestType::kGanesh, ctsEnforcement,
135 nullptr, proc, nullptr, optionsProc, nullptr};
136 }
137
138 static Test MakeGraphite(const char* name,
139 CtsEnforcement ctsEnforcement,
140 GraphiteTestProc proc,
141 GraphiteContextOptionsProc optionsProc = nullptr) {
142 return Test{name, TestType::kGraphite, ctsEnforcement,
143 nullptr, nullptr, proc, nullptr, optionsProc};
144 }
145
146 const char* fName;
154
157 (*fGaneshContextOptionsProc)(options);
158 }
159 }
160
163 (*fGraphiteContextOptionsProc)(options);
164 }
165 }
166
167 void cpu(skiatest::Reporter* r) const {
168 SkASSERT(this->fTestType == TestType::kCPU ||
169 this->fTestType == TestType::kCPUSerial);
170 TRACE_EVENT1("test_cpu", TRACE_FUNC, "name", this->fName/*these are static*/);
171 this->fCPUProc(r);
172 }
173
175 SkASSERT(this->fTestType == TestType::kGanesh);
176 TRACE_EVENT1("test_ganesh", TRACE_FUNC, "name", this->fName/*these are static*/);
177 this->fGaneshProc(r, options);
178 }
179
181 SkASSERT(this->fTestType == TestType::kGraphite);
182 TRACE_EVENT1("test_graphite", TRACE_FUNC, "name", this->fName/*these are static*/);
183 this->fGraphiteProc(r, options);
184 }
185
186private:
187 Test(const char* name,
188 TestType testType,
189 CtsEnforcement ctsEnforcement,
190 CPUTestProc cpuProc,
191 GaneshTestProc ganeshProc,
192 GraphiteTestProc graphiteProc,
193 GaneshContextOptionsProc ganeshOptionsProc,
194 GraphiteContextOptionsProc graphiteOptionsProc)
195 : fName(name)
196 , fTestType(testType)
197 , fCTSEnforcement(ctsEnforcement)
198 , fCPUProc(cpuProc)
199 , fGaneshProc(ganeshProc)
200 , fGraphiteProc(graphiteProc)
201 , fGaneshContextOptionsProc(ganeshOptionsProc)
202 , fGraphiteContextOptionsProc(graphiteOptionsProc) {}
203};
204
206
207#if defined(SK_GANESH)
209#else
210using GpuContextType = nullptr_t;
211#endif
212
215
216// We want to run the same test against potentially multiple Ganesh backends. Test runners should
217// implement this function by calling the testFn with a fresh ContextInfo if that backend matches
218// the provided filter. If filter is nullptr, then all compiled-in Ganesh backends should be used.
219// The reporter and opts arguments are piped in from Test::run.
222
223// These context filters should be implemented by test runners and return true if the backend was
224// compiled in (i.e. is supported) and matches the criteria indicated by the name of the filter.
231
232namespace graphite {
233
237
239 ContextTypeFilterFn* filter,
240 Reporter*,
241 const TestOptions&);
242
243} // namespace graphite
244
245/** Timer provides wall-clock duration since its creation. */
246class Timer {
247public:
248 /** Starts the timer. */
249 Timer();
250
251 /** Nanoseconds since creation. */
252 double elapsedNs() const;
253
254 /** Milliseconds since creation. */
255 double elapsedMs() const;
256
257 /** Milliseconds since creation as an integer.
258 Behavior is undefined for durations longer than SK_MSecMax.
259 */
260 SkMSec elapsedMsInt() const;
261private:
262 double fStartNanos;
263};
264
265} // namespace skiatest
266
267/*
268 Use the following macros to make use of the skiatest classes, e.g.
269
270 #include "tests/Test.h"
271
272 DEF_TEST(TestName, reporter) {
273 ...
274 REPORTER_ASSERT(reporter, x == 15);
275 ...
276 REPORTER_ASSERT(reporter, x == 15, "x should be 15");
277 ...
278 if (x != 15) {
279 ERRORF(reporter, "x should be 15, but is %d", x);
280 return;
281 }
282 ...
283 }
284*/
285
286#define REPORTER_ASSERT(r, cond, ...) \
287 do { \
288 if (!(cond)) { \
289 REPORT_FAILURE(r, #cond, SkStringPrintf(__VA_ARGS__)); \
290 } \
291 } while (0)
292
293#define ERRORF(r, ...) \
294 do { \
295 REPORT_FAILURE(r, "", SkStringPrintf(__VA_ARGS__)); \
296 } while (0)
297
298#define INFOF(REPORTER, ...) \
299 do { \
300 if ((REPORTER)->verbose()) { \
301 SkDebugf(__VA_ARGS__); \
302 } \
303 } while (0)
304
305using skiatest::Test;
306
307#define DEF_CONDITIONAL_TEST(name, reporter, condition) \
308 static void test_##name(skiatest::Reporter*); \
309 skiatest::TestRegistry name##TestRegistry(Test::MakeCPU(#name, test_##name), condition); \
310 void test_##name(skiatest::Reporter* reporter)
311
312#define DEF_TEST(name, reporter) DEF_CONDITIONAL_TEST(name, reporter, true)
313
314#define DEF_TEST_DISABLED(name, reporter) DEF_CONDITIONAL_TEST(name, reporter, false)
315
316#ifdef SK_BUILD_FOR_UNIX
317 #define UNIX_ONLY_TEST DEF_TEST
318#else
319 #define UNIX_ONLY_TEST DEF_TEST_DISABLED
320#endif
321
322#define DEF_SERIAL_TEST(name, reporter) \
323 static void test_##name(skiatest::Reporter*); \
324 skiatest::TestRegistry name##TestRegistry(Test::MakeCPUSerial(#name, test_##name)); \
325 void test_##name(skiatest::Reporter* reporter)
326
327#define DEF_GRAPHITE_TEST(name, reporter, ctsEnforcement) \
328 static void test_##name(skiatest::Reporter*); \
329 static void test_graphite_##name(skiatest::Reporter* reporter, \
330 const skiatest::graphite::TestOptions&) { \
331 test_##name(reporter); \
332 } \
333 skiatest::TestRegistry name##TestRegistry(Test::MakeGraphite(#name, ctsEnforcement, \
334 test_graphite_##name)); \
335 void test_##name(skiatest::Reporter* reporter)
336
337#define DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS( \
338 name, context_filter, reporter, graphite_ctx, test_ctx, opt_filter, cond, ctsEnforcement) \
339 static void test_##name(skiatest::Reporter*, skgpu::graphite::Context*, \
340 skiatest::graphite::GraphiteTestContext*); \
341 static void test_graphite_contexts_##name(skiatest::Reporter* _reporter, \
342 const skiatest::graphite::TestOptions& options) { \
343 skiatest::graphite::RunWithGraphiteTestContexts(test_##name, context_filter, \
344 _reporter, options); \
345 } \
346 skiatest::TestRegistry name##TestRegistry( \
347 Test::MakeGraphite(#name, ctsEnforcement, test_graphite_contexts_##name, opt_filter), \
348 cond); \
349 void test_##name(skiatest::Reporter* reporter, skgpu::graphite::Context* graphite_ctx, \
350 skiatest::graphite::GraphiteTestContext* test_ctx)
351
352#define DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(name, reporter, graphite_ctx, \
353 test_ctx, cond, ctsEnforcement) \
354 DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(name, nullptr, reporter, graphite_ctx, test_ctx, \
355 nullptr, cond, ctsEnforcement)
356
357#define DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS( \
358 name, reporter, graphite_context, test_context, cond, ctsEnforcement) \
359 DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(name, \
360 skgpu::IsRenderingContext, \
361 reporter, \
362 graphite_context, \
363 test_context, \
364 nullptr, \
365 cond, \
366 ctsEnforcement)
367
368#define DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, context_filter, reporter, graphite_ctx, \
369 test_ctx, ctsEnforcement) \
370 DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(name, context_filter, reporter, graphite_ctx, \
371 test_ctx, nullptr, true, ctsEnforcement)
372
373#define DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(name, reporter, graphite_ctx, ctsEnforcement) \
374 DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(name, reporter, graphite_ctx, \
375 /*anonymous test_ctx*/, true, ctsEnforcement)
376
377#define DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(name, reporter, graphite_context, ctsEnforcement) \
378 DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS( \
379 name, reporter, graphite_context, /*anonymous test_ctx*/, true, ctsEnforcement)
380
381#define DEF_GRAPHITE_TEST_FOR_VULKAN_CONTEXT(name, reporter, graphite_context, ctsEnforcement) \
382 DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, skiatest::IsVulkanContextType, reporter, \
383 graphite_context, /*anonymous test_ctx*/, ctsEnforcement)
384
385#define DEF_GRAPHITE_TEST_FOR_METAL_CONTEXT(name, reporter, graphite_context, test_context) \
386 DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, skiatest::IsMetalContextType, reporter, graphite_context, \
387 test_context, CtsEnforcement::kNever)
388
389#define DEF_GRAPHITE_TEST_FOR_DAWN_CONTEXT(name, reporter, graphite_context, test_context) \
390 DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, skiatest::IsDawnContextType, reporter, graphite_context, \
391 test_context, CtsEnforcement::kNever)
392
393#define DEF_GANESH_TEST(name, reporter, options, ctsEnforcement) \
394 static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
395 skiatest::TestRegistry name##TestRegistry( \
396 Test::MakeGanesh(#name, ctsEnforcement, test_##name, nullptr)); \
397 void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
398
399#define DEF_CONDITIONAL_GANESH_TEST_FOR_CONTEXTS( \
400 name, context_filter, reporter, context_info, options_filter, condition, ctsEnforcement) \
401 static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo&); \
402 static void test_gpu_contexts_##name(skiatest::Reporter* reporter, \
403 const GrContextOptions& options) { \
404 skiatest::RunWithGaneshTestContexts(test_##name, context_filter, reporter, options); \
405 } \
406 skiatest::TestRegistry name##TestRegistry( \
407 Test::MakeGanesh(#name, ctsEnforcement, test_gpu_contexts_##name, options_filter), \
408 condition); \
409 void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info)
410
411#define DEF_CONDITIONAL_GANESH_TEST_FOR_ALL_CONTEXTS( \
412 name, reporter, context_info, condition, ctsEnforcement) \
413 DEF_CONDITIONAL_GANESH_TEST_FOR_CONTEXTS( \
414 name, nullptr, reporter, context_info, nullptr, condition, ctsEnforcement)
415
416#define DEF_CONDITIONAL_GANESH_TEST_FOR_RENDERING_CONTEXTS( \
417 name, reporter, context_info, condition, ctsEnforcement) \
418 DEF_CONDITIONAL_GANESH_TEST_FOR_CONTEXTS(name, \
419 skgpu::IsRenderingContext, \
420 reporter, \
421 context_info, \
422 nullptr, \
423 condition, \
424 ctsEnforcement)
425
426#define DEF_GANESH_TEST_FOR_CONTEXTS( \
427 name, context_filter, reporter, context_info, options_filter, ctsEnforcement) \
428 DEF_CONDITIONAL_GANESH_TEST_FOR_CONTEXTS( \
429 name, context_filter, reporter, context_info, options_filter, true, ctsEnforcement)
430
431#define DEF_GANESH_TEST_FOR_ALL_CONTEXTS(name, reporter, context_info, ctsEnforcement) \
432 DEF_GANESH_TEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr, ctsEnforcement)
433
434#define DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, ctsEnforcement) \
435 DEF_GANESH_TEST_FOR_CONTEXTS( \
436 name, skgpu::IsRenderingContext, reporter, context_info, nullptr, ctsEnforcement)
437
438#define DEF_GANESH_TEST_FOR_ALL_GL_CONTEXTS(name, reporter, context_info, ctsEnforcement) \
439 DEF_GANESH_TEST_FOR_CONTEXTS( \
440 name, skiatest::IsGLContextType, reporter, context_info, nullptr, ctsEnforcement)
441
442#define DEF_GANESH_TEST_FOR_GL_CONTEXT(name, reporter, context_info, ctsEnforcement) \
443 DEF_GANESH_TEST_FOR_CONTEXTS(name, \
444 &skiatest::IsGLContextType, \
445 reporter, \
446 context_info, \
447 nullptr, \
448 ctsEnforcement)
449
450#define DEF_GANESH_TEST_FOR_MOCK_CONTEXT(name, reporter, context_info) \
451 DEF_GANESH_TEST_FOR_CONTEXTS(name, \
452 &skiatest::IsMockContextType, \
453 reporter, \
454 context_info, \
455 nullptr, \
456 CtsEnforcement::kNever)
457
458#define DEF_GANESH_TEST_FOR_VULKAN_CONTEXT(name, reporter, context_info, ctsEnforcement) \
459 DEF_GANESH_TEST_FOR_CONTEXTS( \
460 name, &skiatest::IsVulkanContextType, reporter, context_info, nullptr, ctsEnforcement)
461
462#define DEF_GANESH_TEST_FOR_METAL_CONTEXT(name, reporter, context_info) \
463 DEF_GANESH_TEST_FOR_CONTEXTS(name, \
464 &skiatest::IsMetalContextType, \
465 reporter, \
466 context_info, \
467 nullptr, \
468 CtsEnforcement::kNever)
469#define DEF_GANESH_TEST_FOR_D3D_CONTEXT(name, reporter, context_info) \
470 DEF_GANESH_TEST_FOR_CONTEXTS(name, \
471 &skiatest::IsDirect3DContextType, \
472 reporter, \
473 context_info, \
474 nullptr, \
475 CtsEnforcement::kNever)
476
477#define DEF_GANESH_TEST_FOR_DAWN_CONTEXT(name, reporter, context_info) \
478 DEF_GANESH_TEST_FOR_CONTEXTS(name, \
479 &skiatest::IsDawnContextType, \
480 reporter, \
481 context_info, \
482 nullptr, \
483 CtsEnforcement::kNever)
484
485#define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER) \
486 do { \
487 SkNullWStream testStream; \
488 auto testDoc = SkPDF::MakeDocument(&testStream); \
489 if (!testDoc) { \
490 INFOF(REPORTER, "PDF disabled; %s test skipped.", #TEST_NAME); \
491 return; \
492 } \
493 } while (false)
494
495#endif
const char * options
reporter
Definition: FontMgrTest.cpp:39
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
uint32_t SkMSec
Definition: SkTypes.h:184
ReporterContext(Reporter *reporter, const SkString &message)
Definition: Test.h:99
ReporterContext(Reporter *reporter, const std::string &message)
Definition: Test.h:102
void push(const SkString &message)
Definition: Test.h:72
void reportFailedWithContext(const skiatest::Failure &)
Definition: Test.cpp:26
virtual void bumpTestCount()
Definition: Test.cpp:19
virtual ~Reporter()
Definition: Test.h:60
virtual void reportFailed(const skiatest::Failure &)=0
virtual bool verbose() const
Definition: Test.cpp:23
void push(const std::string &message)
Definition: Test.h:75
virtual bool allowExtendedTest() const
Definition: Test.cpp:21
virtual void * stats() const
Definition: Test.h:65
void pop()
Definition: Test.h:82
SkMSec elapsedMsInt() const
Definition: Test.cpp:82
double elapsedNs() const
Definition: Test.cpp:76
double elapsedMs() const
Definition: Test.cpp:80
Win32Message message
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
Definition: GpuTools.h:21
ContextType
Definition: ContextType.h:19
void(Reporter *, skgpu::graphite::Context *, skiatest::graphite::GraphiteTestContext *) GraphiteTestFn
Definition: Test.h:236
void RunWithGraphiteTestContexts(GraphiteTestFn *, ContextTypeFilterFn *filter, Reporter *, const TestOptions &)
nullptr_t GpuContextType
Definition: Test.h:210
void(*)(Reporter *, const graphite::TestOptions &) GraphiteTestProc
Definition: Test.h:116
void(*)(Reporter *, const GrContextOptions &) GaneshTestProc
Definition: Test.h:114
void RunWithGaneshTestContexts(GrContextTestFn *testFn, ContextTypeFilterFn *filter, Reporter *reporter, const GrContextOptions &options)
bool IsMetalContextType(skgpu::ContextType type)
void(*)(skgpu::graphite::ContextOptions *) GraphiteContextOptionsProc
Definition: Test.h:117
void(*)(GrContextOptions *) GaneshContextOptionsProc
Definition: Test.h:115
bool IsGLContextType(skgpu::ContextType type)
SkString GetTmpDir()
Definition: Test.cpp:53
bool ContextTypeFilterFn(GpuContextType)
Definition: Test.h:214
bool IsMockContextType(skgpu::ContextType type)
bool IsDirect3DContextType(skgpu::ContextType type)
void(*)(Reporter *) CPUTestProc
Definition: Test.h:113
void GrContextTestFn(Reporter *, const sk_gpu_test::ContextInfo &)
Definition: Test.h:213
bool IsDawnContextType(skgpu::ContextType type)
bool IsVulkanContextType(skgpu::ContextType type)
const char * condition
Definition: Test.h:53
SkString message
Definition: Test.h:54
Failure(const char *f, int l, const char *c, const SkString &m)
Definition: Test.h:49
const char * fileName
Definition: Test.h:51
SkString toString() const
Definition: Test.cpp:41
GraphiteContextOptionsProc fGraphiteContextOptionsProc
Definition: Test.h:153
GraphiteTestProc fGraphiteProc
Definition: Test.h:151
GaneshContextOptionsProc fGaneshContextOptionsProc
Definition: Test.h:152
CtsEnforcement fCTSEnforcement
Definition: Test.h:148
static Test MakeCPU(const char *name, CPUTestProc proc)
Definition: Test.h:120
GaneshTestProc fGaneshProc
Definition: Test.h:150
CPUTestProc fCPUProc
Definition: Test.h:149
static Test MakeGraphite(const char *name, CtsEnforcement ctsEnforcement, GraphiteTestProc proc, GraphiteContextOptionsProc optionsProc=nullptr)
Definition: Test.h:138
void ganesh(skiatest::Reporter *r, const GrContextOptions &options) const
Definition: Test.h:174
TestType fTestType
Definition: Test.h:147
static Test MakeCPUSerial(const char *name, CPUTestProc proc)
Definition: Test.h:125
void modifyGrContextOptions(GrContextOptions *options)
Definition: Test.h:155
const char * fName
Definition: Test.h:146
void cpu(skiatest::Reporter *r) const
Definition: Test.h:167
void graphite(skiatest::Reporter *r, const graphite::TestOptions &options) const
Definition: Test.h:180
void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions *options)
Definition: Test.h:161
static Test MakeGanesh(const char *name, CtsEnforcement ctsEnforcement, GaneshTestProc proc, GaneshContextOptionsProc optionsProc=nullptr)
Definition: Test.h:130
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:141