• 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 "../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 {
FailureFailure33     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:
~Reporter()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;
stats()49     virtual void* stats() const { return nullptr; }
50 
reportFailedWithContext(const skiatest::Failure & f)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     }
push(const SkString & message)65     void push(const SkString& message) {
66         fContextStack.push_back(message);
67     }
pop()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:
ReporterContext(Reporter * reporter,const SkString & message)81     ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
82         fReporter->push(message);
83     }
~ReporterContext()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)
nameTest97         : name(n), needsGpu(g), proc(p), fContextOptionsProc(optionsProc) {}
98     const char* name;
99     bool needsGpu;
100     TestProc proc;
101     ContextOptionsProc fContextOptionsProc;
102 
modifyGrContextOptionsTest103     void modifyGrContextOptions(GrContextOptions* options) {
104         if (fContextOptionsProc) {
105             (*fContextOptionsProc)(options);
106         }
107     }
108 
runTest109     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