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/SkClipOpPriv.h" 13 #include "src/core/SkTraceEvent.h" 14 #include "tools/Registry.h" 15 #include "tools/gpu/GrContextFactory.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 "tests/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 IsRenderingGLOrMetalContextType(GrContextFactoryContextType); 123 extern bool IsMockContextType(GrContextFactoryContextType); 124 void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*, 125 const GrContextOptions&); 126 127 /** Timer provides wall-clock duration since its creation. */ 128 class Timer { 129 public: 130 /** Starts the timer. */ 131 Timer(); 132 133 /** Nanoseconds since creation. */ 134 double elapsedNs() const; 135 136 /** Milliseconds since creation. */ 137 double elapsedMs() const; 138 139 /** Milliseconds since creation as an integer. 140 Behavior is undefined for durations longer than SK_MSecMax. 141 */ 142 SkMSec elapsedMsInt() const; 143 private: 144 double fStartNanos; 145 }; 146 147 } // namespace skiatest 148 149 #define REPORTER_ASSERT(r, cond, ...) \ 150 do { \ 151 if (!(cond)) { \ 152 REPORT_FAILURE(r, #cond, SkStringPrintf(__VA_ARGS__)); \ 153 } \ 154 } while (0) 155 156 #define ERRORF(r, ...) \ 157 do { \ 158 REPORT_FAILURE(r, "", SkStringPrintf(__VA_ARGS__)); \ 159 } while (0) 160 161 #define INFOF(REPORTER, ...) \ 162 do { \ 163 if ((REPORTER)->verbose()) { \ 164 SkDebugf(__VA_ARGS__); \ 165 } \ 166 } while (0) 167 168 #define DEF_TEST(name, reporter) \ 169 static void test_##name(skiatest::Reporter*, const GrContextOptions&); \ 170 skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \ 171 void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) 172 173 #define DEF_GPUTEST(name, reporter, options) \ 174 static void test_##name(skiatest::Reporter*, const GrContextOptions&); \ 175 skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, true, test_##name)); \ 176 void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options) 177 178 #define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter) \ 179 static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo& context_info); \ 180 static void test_gpu_contexts_##name(skiatest::Reporter* reporter, \ 181 const GrContextOptions& options) { \ 182 skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options); \ 183 } \ 184 skiatest::TestRegistry name##TestRegistry( \ 185 skiatest::Test(#name, true, test_gpu_contexts_##name, options_filter)); \ 186 void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info) 187 188 #define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info) \ 189 DEF_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr) 190 191 #define DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info) \ 192 DEF_GPUTEST_FOR_CONTEXTS(name, sk_gpu_test::GrContextFactory::IsRenderingContext, \ 193 reporter, context_info, nullptr) 194 #define DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(name, reporter, context_info) \ 195 DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsGLContextType, \ 196 reporter, context_info, nullptr) 197 #define DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(name, reporter, context_info) \ 198 DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsRenderingGLContextType, \ 199 reporter, context_info, nullptr) 200 #define DEF_GPUTEST_FOR_MOCK_CONTEXT(name, reporter, context_info) \ 201 DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMockContextType, \ 202 reporter, context_info, nullptr) 203 #define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info) \ 204 DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType, \ 205 reporter, context_info, nullptr) 206 #define DEF_GPUTEST_FOR_METAL_CONTEXT(name, reporter, context_info) \ 207 DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMetalContextType, \ 208 reporter, context_info, nullptr) 209 210 #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER) \ 211 do { \ 212 SkNullWStream testStream; \ 213 auto testDoc = SkPDF::MakeDocument(&testStream); \ 214 if (!testDoc) { \ 215 INFOF(REPORTER, "PDF disabled; %s test skipped.", #TEST_NAME); \ 216 return; \ 217 } \ 218 } while (false) 219 220 #endif 221