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