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