• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
FailureFailure31     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:
~Reporter()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;
stats()47     virtual void* stats() const { return nullptr; }
48 
reportFailedWithContext(const skiatest::Failure & f)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     }
push(const SkString & message)63     void push(const SkString& message) {
64         fContextStack.push_back(message);
65     }
pop()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:
ReporterContext(Reporter * reporter,const SkString & message)79     ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
80         fReporter->push(message);
81     }
~ReporterContext()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 {
TestTest93     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