Home | History | Annotate | Download | only in tests
      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 "../tools/Registry.h"
     11 #include "SkClipOpPriv.h"
     12 #include "SkString.h"
     13 #include "SkTraceEvent.h"
     14 #include "SkTypes.h"
     15 
     16 #if SK_SUPPORT_GPU
     17 #include "GrContextFactory.h"
     18 #else
     19 namespace sk_gpu_test {
     20 class GrContextFactory;
     21 class ContextInfo;
     22 class GLTestContext;
     23 }  // namespace sk_gpu_test
     24 class GrContext;
     25 struct GrContextOptions;
     26 #endif
     27 
     28 namespace skiatest {
     29 
     30 SkString GetTmpDir();
     31 
     32 struct Failure {
     33     Failure(const char* f, int l, const char* c, const SkString& m)
     34         : fileName(f), lineNo(l), condition(c), message(m) {}
     35     const char* fileName;
     36     int lineNo;
     37     const char* condition;
     38     SkString message;
     39     SkString toString() const;
     40 };
     41 
     42 class Reporter : SkNoncopyable {
     43 public:
     44     virtual ~Reporter() {}
     45     virtual void bumpTestCount();
     46     virtual void reportFailed(const skiatest::Failure&) = 0;
     47     virtual bool allowExtendedTest() const;
     48     virtual bool verbose() const;
     49     virtual void* stats() const { return nullptr; }
     50 
     51     void reportFailedWithContext(const skiatest::Failure& f) {
     52         SkString fullMessage = f.message;
     53         if (!fContextStack.empty()) {
     54             fullMessage.append(" [");
     55             for (int i = 0; i < fContextStack.count(); ++i) {
     56                 if (i > 0) {
     57                     fullMessage.append(", ");
     58                 }
     59                 fullMessage.append(fContextStack[i]);
     60             }
     61             fullMessage.append("]");
     62         }
     63         this->reportFailed(skiatest::Failure(f.fileName, f.lineNo, f.condition, fullMessage));
     64     }
     65     void push(const SkString& message) {
     66         fContextStack.push_back(message);
     67     }
     68     void pop() {
     69         fContextStack.pop_back();
     70     }
     71 
     72 private:
     73     SkTArray<SkString> fContextStack;
     74 };
     75 
     76 #define REPORT_FAILURE(reporter, cond, message) \
     77     reporter->reportFailedWithContext(skiatest::Failure(__FILE__, __LINE__, cond, message))
     78 
     79 class ReporterContext : SkNoncopyable {
     80 public:
     81     ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
     82         fReporter->push(message);
     83     }
     84     ~ReporterContext() {
     85         fReporter->pop();
     86     }
     87 
     88 private:
     89     Reporter* fReporter;
     90 };
     91 
     92 typedef void (*TestProc)(skiatest::Reporter*, const GrContextOptions&);
     93 typedef void (*ContextOptionsProc)(GrContextOptions*);
     94 
     95 struct Test {
     96     Test(const char* n, bool g, TestProc p, ContextOptionsProc optionsProc = nullptr)
     97         : name(n), needsGpu(g), proc(p), fContextOptionsProc(optionsProc) {}
     98     const char* name;
     99     bool needsGpu;
    100     TestProc proc;
    101     ContextOptionsProc fContextOptionsProc;
    102 
    103     void modifyGrContextOptions(GrContextOptions* options) {
    104         if (fContextOptionsProc) {
    105             (*fContextOptionsProc)(options);
    106         }
    107     }
    108 
    109     void run(skiatest::Reporter* r, const GrContextOptions& options) const {
    110         TRACE_EVENT1("test", TRACE_FUNC, "name", this->name/*these are static*/);
    111         this->proc(r, options);
    112     }
    113 };
    114 
    115 typedef sk_tools::Registry<Test> TestRegistry;
    116 
    117 /*
    118     Use the following macros to make use of the skiatest classes, e.g.
    119 
    120     #include "Test.h"
    121 
    122     DEF_TEST(TestName, reporter) {
    123         ...
    124         REPORTER_ASSERT(reporter, x == 15);
    125         ...
    126         REPORTER_ASSERT(reporter, x == 15, "x should be 15");
    127         ...
    128         if (x != 15) {
    129             ERRORF(reporter, "x should be 15, but is %d", x);
    130             return;
    131         }
    132         ...
    133     }
    134 */
    135 
    136 #if SK_SUPPORT_GPU
    137 using GrContextFactoryContextType = sk_gpu_test::GrContextFactory::ContextType;
    138 #else
    139 using GrContextFactoryContextType = int;
    140 #endif
    141 
    142 typedef void GrContextTestFn(Reporter*, const sk_gpu_test::ContextInfo&);
    143 typedef bool GrContextTypeFilterFn(GrContextFactoryContextType);
    144 
    145 extern bool IsGLContextType(GrContextFactoryContextType);
    146 extern bool IsVulkanContextType(GrContextFactoryContextType);
    147 extern bool IsRenderingGLContextType(GrContextFactoryContextType);
    148 extern bool IsNullGLContextType(GrContextFactoryContextType);
    149 void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*,
    150                             const GrContextOptions&);
    151 
    152 /** Timer provides wall-clock duration since its creation. */
    153 class Timer {
    154 public:
    155     /** Starts the timer. */
    156     Timer();
    157 
    158     /** Nanoseconds since creation. */
    159     double elapsedNs() const;
    160 
    161     /** Milliseconds since creation. */
    162     double elapsedMs() const;
    163 
    164     /** Milliseconds since creation as an integer.
    165         Behavior is undefined for durations longer than SK_MSecMax.
    166     */
    167     SkMSec elapsedMsInt() const;
    168 private:
    169     double fStartNanos;
    170 };
    171 
    172 }  // namespace skiatest
    173 
    174 #define REPORTER_ASSERT(r, cond, ...)                              \
    175     do {                                                           \
    176         if (!(cond)) {                                             \
    177             REPORT_FAILURE(r, #cond, SkStringPrintf(__VA_ARGS__)); \
    178         }                                                          \
    179     } while (0)
    180 
    181 #define ERRORF(r, ...)                                      \
    182     do {                                                    \
    183         REPORT_FAILURE(r, "", SkStringPrintf(__VA_ARGS__)); \
    184     } while (0)
    185 
    186 #define INFOF(REPORTER, ...)         \
    187     do {                             \
    188         if ((REPORTER)->verbose()) { \
    189             SkDebugf(__VA_ARGS__);   \
    190         }                            \
    191     } while (0)
    192 
    193 #define DEF_TEST(name, reporter)                                                          \
    194     static void test_##name(skiatest::Reporter*, const GrContextOptions&);                \
    195     skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
    196     void test_##name(skiatest::Reporter* reporter, const GrContextOptions&)
    197 
    198 #define DEF_GPUTEST(name, reporter, options)                                             \
    199     static void test_##name(skiatest::Reporter*, const GrContextOptions&);               \
    200     skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, true, test_##name)); \
    201     void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
    202 
    203 #define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter)  \
    204     static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo& context_info); \
    205     static void test_gpu_contexts_##name(skiatest::Reporter* reporter,                          \
    206                                          const GrContextOptions& options) {                     \
    207         skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options);       \
    208     }                                                                                           \
    209     skiatest::TestRegistry name##TestRegistry(                                                  \
    210             skiatest::Test(#name, true, test_gpu_contexts_##name, options_filter));             \
    211     void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info)
    212 
    213 #define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info)                          \
    214         DEF_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr)
    215 
    216 #define DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info)                    \
    217         DEF_GPUTEST_FOR_CONTEXTS(name, sk_gpu_test::GrContextFactory::IsRenderingContext,   \
    218                                  reporter, context_info, nullptr)
    219 #define DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(name, reporter, context_info)                       \
    220         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsGLContextType,                          \
    221                                  reporter, context_info, nullptr)
    222 #define DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(name, reporter, context_info)                 \
    223         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsRenderingGLContextType,                 \
    224                                  reporter, context_info, nullptr)
    225 #define DEF_GPUTEST_FOR_NULLGL_CONTEXT(name, reporter, context_info)                        \
    226         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsNullGLContextType,                      \
    227                                  reporter, context_info, nullptr)
    228 #define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info)                        \
    229         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType,                      \
    230                                  reporter, context_info, nullptr)
    231 
    232 #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER)                          \
    233     do {                                                                   \
    234         SkDynamicMemoryWStream testStream;                                 \
    235         sk_sp<SkDocument> testDoc(SkDocument::MakePDF(&testStream));       \
    236         if (!testDoc) {                                                    \
    237             INFOF(REPORTER, "PDF disabled; %s test skipped.", #TEST_NAME); \
    238             return;                                                        \
    239         }                                                                  \
    240     } while (false)
    241 
    242 #endif
    243