Coverage Report

Created: 2024-05-20 07:14

/src/skia/tests/Test.h
Line
Count
Source (jump to first uncovered line)
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 "include/private/base/SkNoncopyable.h"
13
#include "include/private/base/SkTArray.h"
14
#include "src/core/SkTraceEvent.h"
15
#include "tests/CtsEnforcement.h"
16
#include "tests/TestType.h"
17
#include "tools/Registry.h"
18
19
#if defined(SK_GANESH) || defined(SK_GRAPHITE)
20
namespace 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
26
namespace sk_gpu_test { class ContextInfo; }
27
#endif
28
29
#include <atomic>
30
#include <cstdint>
31
#include <string>
32
33
struct GrContextOptions;
34
35
namespace skgpu::graphite {
36
class Context;
37
struct ContextOptions;
38
}
39
40
namespace skiatest {
41
namespace graphite {
42
class GraphiteTestContext;
43
struct TestOptions;
44
}
45
46
SkString GetTmpDir();
47
48
struct Failure {
49
    Failure(const char* f, int l, const char* c, const SkString& m)
50
0
        : fileName(f), lineNo(l), condition(c), message(m) {}
51
    const char* fileName;
52
    int lineNo;
53
    const char* condition;
54
    SkString message;
55
    SkString toString() const;
56
};
57
58
class Reporter : SkNoncopyable {
59
public:
60
0
    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
0
    virtual void* stats() const { return nullptr; }
66
67
    void reportFailedWithContext(const skiatest::Failure&);
68
69
    /**
70
     * Show additional context (e.g. subtest name) on failure assertions.
71
     */
72
0
    void push(const SkString& message) {
73
0
        fContextStack.push_back(message);
74
0
    }
75
0
    void push(const std::string& message) {
76
0
        fContextStack.push_back(SkString(message));
77
0
    }
78
79
    /**
80
     * Remove additional context from failure assertions.
81
     */
82
0
    void pop() {
83
0
        fContextStack.pop_back();
84
0
    }
85
86
private:
87
    skia_private::TArray<SkString> fContextStack;
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
 */
97
class ReporterContext : SkNoncopyable {
98
public:
99
0
    ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
100
0
        fReporter->push(message);
101
0
    }
102
0
    ReporterContext(Reporter* reporter, const std::string& message) : fReporter(reporter) {
103
0
        fReporter->push(message);
104
0
    }
105
0
    ~ReporterContext() {
106
0
        fReporter->pop();
107
0
    }
108
109
private:
110
    Reporter* fReporter;
111
};
112
113
using CPUTestProc                = void (*)(Reporter*);
114
using GaneshTestProc             = void (*)(Reporter*, const GrContextOptions&);
115
using GaneshContextOptionsProc   = void (*)(GrContextOptions*);
116
using GraphiteTestProc           = void (*)(Reporter*, const graphite::TestOptions&);
117
using GraphiteContextOptionsProc = void (*)(skgpu::graphite::ContextOptions*);
118
119
struct Test {
120
0
    static Test MakeCPU(const char* name, CPUTestProc proc) {
121
0
        return Test{name, TestType::kCPU, CtsEnforcement::kNever,
122
0
                    proc, nullptr, nullptr, nullptr, nullptr};
123
0
    }
124
125
0
    static Test MakeCPUSerial(const char* name, CPUTestProc proc) {
126
0
        return Test{name, TestType::kCPUSerial, CtsEnforcement::kNever,
127
0
                    proc, nullptr, nullptr, nullptr, nullptr};
128
0
    }
129
130
    static Test MakeGanesh(const char* name,
131
                           CtsEnforcement ctsEnforcement,
132
                           GaneshTestProc proc,
133
0
                           GaneshContextOptionsProc optionsProc = nullptr) {
134
0
        return Test{name, TestType::kGanesh, ctsEnforcement,
135
0
                    nullptr, proc, nullptr, optionsProc, nullptr};
136
0
    }
137
138
    static Test MakeGraphite(const char* name,
139
                             CtsEnforcement ctsEnforcement,
140
                             GraphiteTestProc proc,
141
0
                             GraphiteContextOptionsProc optionsProc = nullptr) {
142
0
        return Test{name, TestType::kGraphite, ctsEnforcement,
143
0
                    nullptr, nullptr, proc, nullptr, optionsProc};
144
0
    }
145
146
    const char* fName;
147
    TestType fTestType;
148
    CtsEnforcement fCTSEnforcement;
149
    CPUTestProc fCPUProc = nullptr;
150
    GaneshTestProc fGaneshProc = nullptr;
151
    GraphiteTestProc fGraphiteProc = nullptr;
152
    GaneshContextOptionsProc fGaneshContextOptionsProc = nullptr;
153
    GraphiteContextOptionsProc fGraphiteContextOptionsProc = nullptr;
154
155
0
    void modifyGrContextOptions(GrContextOptions* options) {
156
0
        if (fGaneshContextOptionsProc) {
157
0
            (*fGaneshContextOptionsProc)(options);
158
0
        }
159
0
    }
160
161
0
    void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions* options) {
162
0
        if (fGraphiteContextOptionsProc) {
163
0
            (*fGraphiteContextOptionsProc)(options);
164
0
        }
165
0
    }
166
167
0
    void cpu(skiatest::Reporter* r) const {
168
0
        SkASSERT(this->fTestType == TestType::kCPU ||
169
0
                 this->fTestType == TestType::kCPUSerial);
170
0
        TRACE_EVENT1("test_cpu", TRACE_FUNC, "name", this->fName/*these are static*/);
171
0
        this->fCPUProc(r);
172
0
    }
173
174
0
    void ganesh(skiatest::Reporter* r, const GrContextOptions& options) const {
175
0
        SkASSERT(this->fTestType == TestType::kGanesh);
176
0
        TRACE_EVENT1("test_ganesh", TRACE_FUNC, "name", this->fName/*these are static*/);
177
0
        this->fGaneshProc(r, options);
178
0
    }
179
180
0
    void graphite(skiatest::Reporter* r, const graphite::TestOptions& options) const {
181
0
        SkASSERT(this->fTestType == TestType::kGraphite);
182
0
        TRACE_EVENT1("test_graphite", TRACE_FUNC, "name", this->fName/*these are static*/);
183
0
        this->fGraphiteProc(r, options);
184
0
    }
185
186
private:
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
0
            , fGraphiteContextOptionsProc(graphiteOptionsProc) {}
203
};
204
205
using TestRegistry = sk_tools::Registry<Test>;
206
207
#if defined(SK_GANESH)
208
using GpuContextType = skgpu::ContextType;
209
#else
210
using GpuContextType = nullptr_t;
211
#endif
212
213
typedef void GrContextTestFn(Reporter*, const sk_gpu_test::ContextInfo&);
214
typedef bool ContextTypeFilterFn(GpuContextType);
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.
220
void RunWithGaneshTestContexts(GrContextTestFn* testFn, ContextTypeFilterFn* filter,
221
                               Reporter* reporter, const GrContextOptions& options);
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.
225
extern bool IsGLContextType(GpuContextType);
226
extern bool IsVulkanContextType(GpuContextType);
227
extern bool IsMetalContextType(GpuContextType);
228
extern bool IsDawnContextType(GpuContextType);
229
extern bool IsDirect3DContextType(GpuContextType);
230
extern bool IsMockContextType(GpuContextType);
231
232
namespace graphite {
233
234
using GraphiteTestFn = void(Reporter*,
235
                            skgpu::graphite::Context*,
236
                            skiatest::graphite::GraphiteTestContext*);
237
238
void RunWithGraphiteTestContexts(GraphiteTestFn*,
239
                                 ContextTypeFilterFn* filter,
240
                                 Reporter*,
241
                                 const TestOptions&);
242
243
} // namespace graphite
244
245
/** Timer provides wall-clock duration since its creation. */
246
class Timer {
247
public:
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;
261
private:
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
305
using 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