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