• 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 "include/core/SkString.h"
11 #include "include/core/SkTypes.h"
12 #include "src/core/SkTraceEvent.h"
13 #include "tools/Registry.h"
14 #include "tools/gpu/GrContextFactory.h"
15 
16 namespace skgpu { class Context; }
17 
18 namespace skiatest {
19 
20 SkString GetTmpDir();
21 
22 struct Failure {
FailureFailure23     Failure(const char* f, int l, const char* c, const SkString& m)
24         : fileName(f), lineNo(l), condition(c), message(m) {}
25     const char* fileName;
26     int lineNo;
27     const char* condition;
28     SkString message;
29     SkString toString() const;
30 };
31 
32 class Reporter : SkNoncopyable {
33 public:
~Reporter()34     virtual ~Reporter() {}
35     virtual void bumpTestCount();
36     virtual void reportFailed(const skiatest::Failure&) = 0;
37     virtual bool allowExtendedTest() const;
38     virtual bool verbose() const;
stats()39     virtual void* stats() const { return nullptr; }
40 
41     void reportFailedWithContext(const skiatest::Failure&);
42 
push(const SkString & message)43     void push(const SkString& message) {
44         fContextStack.push_back(message);
45     }
pop()46     void pop() {
47         fContextStack.pop_back();
48     }
49 
50 private:
51     SkTArray<SkString> fContextStack;
52 };
53 
54 #define REPORT_FAILURE(reporter, cond, message) \
55     reporter->reportFailedWithContext(skiatest::Failure(__FILE__, __LINE__, cond, message))
56 
57 class ReporterContext : SkNoncopyable {
58 public:
ReporterContext(Reporter * reporter,const SkString & message)59     ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
60         fReporter->push(message);
61     }
~ReporterContext()62     ~ReporterContext() {
63         fReporter->pop();
64     }
65 
66 private:
67     Reporter* fReporter;
68 };
69 
70 typedef void (*TestProc)(skiatest::Reporter*, const GrContextOptions&);
71 typedef void (*ContextOptionsProc)(GrContextOptions*);
72 
73 struct Test {
74     Test(const char* name,
75          bool needsGpu,
76          bool needsGraphite,
77          TestProc proc,
78          ContextOptionsProc optionsProc = nullptr)
fNameTest79             : fName(name)
80             , fNeedsGpu(needsGpu)
81             , fNeedsGraphite(needsGraphite)
82             , fProc(proc)
83             , fContextOptionsProc(optionsProc) {}
84     const char* fName;
85     bool fNeedsGpu;
86     bool fNeedsGraphite;
87     TestProc fProc;
88     ContextOptionsProc fContextOptionsProc;
89 
modifyGrContextOptionsTest90     void modifyGrContextOptions(GrContextOptions* options) {
91         if (fContextOptionsProc) {
92             (*fContextOptionsProc)(options);
93         }
94     }
95 
runTest96     void run(skiatest::Reporter* r, const GrContextOptions& options) const {
97         TRACE_EVENT1("test", TRACE_FUNC, "name", this->fName/*these are static*/);
98         this->fProc(r, options);
99     }
100 };
101 
102 using TestRegistry = sk_tools::Registry<Test>;
103 
104 /*
105     Use the following macros to make use of the skiatest classes, e.g.
106 
107     #include "tests/Test.h"
108 
109     DEF_TEST(TestName, reporter) {
110         ...
111         REPORTER_ASSERT(reporter, x == 15);
112         ...
113         REPORTER_ASSERT(reporter, x == 15, "x should be 15");
114         ...
115         if (x != 15) {
116             ERRORF(reporter, "x should be 15, but is %d", x);
117             return;
118         }
119         ...
120     }
121 */
122 
123 using GrContextFactoryContextType = sk_gpu_test::GrContextFactory::ContextType;
124 
125 typedef void GrContextTestFn(Reporter*, const sk_gpu_test::ContextInfo&);
126 typedef bool GrContextTypeFilterFn(GrContextFactoryContextType);
127 
128 extern bool IsGLContextType(GrContextFactoryContextType);
129 extern bool IsVulkanContextType(GrContextFactoryContextType);
130 extern bool IsMetalContextType(GrContextFactoryContextType);
131 extern bool IsDawnContextType(GrContextFactoryContextType);
132 extern bool IsDirect3DContextType(GrContextFactoryContextType);
133 extern bool IsRenderingGLContextType(GrContextFactoryContextType);
134 extern bool IsMockContextType(GrContextFactoryContextType);
135 void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*,
136                             const GrContextOptions&);
137 
138 namespace graphite {
139 
140 typedef void GraphiteTestFn(Reporter*, skgpu::Context*);
141 
142 void RunWithGraphiteTestContexts(GraphiteTestFn*, Reporter*);
143 
144 } // namespace graphite
145 
146 /** Timer provides wall-clock duration since its creation. */
147 class Timer {
148 public:
149     /** Starts the timer. */
150     Timer();
151 
152     /** Nanoseconds since creation. */
153     double elapsedNs() const;
154 
155     /** Milliseconds since creation. */
156     double elapsedMs() const;
157 
158     /** Milliseconds since creation as an integer.
159         Behavior is undefined for durations longer than SK_MSecMax.
160     */
161     SkMSec elapsedMsInt() const;
162 private:
163     double fStartNanos;
164 };
165 
166 }  // namespace skiatest
167 
168 #define REPORTER_ASSERT(r, cond, ...)                              \
169     do {                                                           \
170         if (!(cond)) {                                             \
171             REPORT_FAILURE(r, #cond, SkStringPrintf(__VA_ARGS__)); \
172         }                                                          \
173     } while (0)
174 
175 #define ERRORF(r, ...)                                      \
176     do {                                                    \
177         REPORT_FAILURE(r, "", SkStringPrintf(__VA_ARGS__)); \
178     } while (0)
179 
180 #define INFOF(REPORTER, ...)         \
181     do {                             \
182         if ((REPORTER)->verbose()) { \
183             SkDebugf(__VA_ARGS__);   \
184         }                            \
185     } while (0)
186 
187 #define DEF_CONDITIONAL_TEST(name, reporter, condition)                                        \
188     static void test_##name(skiatest::Reporter*, const GrContextOptions&);                     \
189     skiatest::TestRegistry name##TestRegistry(                                                 \
190             skiatest::Test(#name, /*gpu=*/false, /*graphite=*/false, test_##name), condition); \
191     void test_##name(skiatest::Reporter* reporter, const GrContextOptions&)
192 
193 #define DEF_TEST(name, reporter) DEF_CONDITIONAL_TEST(name, reporter, true)
194 
195 #define DEF_TEST_DISABLED(name, reporter) DEF_CONDITIONAL_TEST(name, reporter, false)
196 
197 #ifdef SK_BUILD_FOR_UNIX
198     #define UNIX_ONLY_TEST DEF_TEST
199 #else
200     #define UNIX_ONLY_TEST DEF_TEST_DISABLED
201 #endif
202 
203 #define DEF_GRAPHITE_TEST(name, reporter)                                                   \
204     static void test_##name(skiatest::Reporter*);                                           \
205     static void test_graphite_##name(skiatest::Reporter* reporter,                          \
206                                      const GrContextOptions& /*unused*/) {                  \
207         test_##name(reporter);                                                              \
208     }                                                                                       \
209     skiatest::TestRegistry name##TestRegistry(                                              \
210             skiatest::Test(#name, /*gpu=*/false, /*graphite=*/true, test_graphite_##name)); \
211     void test_##name(skiatest::Reporter* reporter)
212 
213 #define DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, reporter, graphite_context)                    \
214     static void test_##name(skiatest::Reporter*, skgpu::Context*);                          \
215     static void test_graphite_contexts_##name(skiatest::Reporter* _reporter,                \
216                                               const GrContextOptions& /*unused*/) {         \
217         skiatest::graphite::RunWithGraphiteTestContexts(test_##name, _reporter);            \
218     }                                                                                       \
219     skiatest::TestRegistry name##TestRegistry(                                              \
220             skiatest::Test(#name, /*gpu=*/false, /*graphite=*/true,                         \
221                            test_graphite_contexts_##name));                                 \
222     void test_##name(skiatest::Reporter* reporter, skgpu::Context* graphite_context)
223 
224 #define DEF_GPUTEST(name, reporter, options)                                             \
225     static void test_##name(skiatest::Reporter*, const GrContextOptions&);               \
226     skiatest::TestRegistry name##TestRegistry(                                           \
227             skiatest::Test(#name, /*gpu=*/true, /*graphite=*/false, test_##name));       \
228     void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
229 
230 #define DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info,      \
231                                              options_filter, condition)                         \
232     static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo&);              \
233     static void test_gpu_contexts_##name(skiatest::Reporter* reporter,                          \
234                                          const GrContextOptions& options) {                     \
235         skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options);       \
236     }                                                                                           \
237     skiatest::TestRegistry name##TestRegistry(                                                  \
238             skiatest::Test(#name, /*gpu=*/true, /*graphite=*/false, test_gpu_contexts_##name,   \
239                            options_filter), condition);                                         \
240     void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info)
241 
242 #define DEF_CONDITIONAL_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info, condition)         \
243         DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr,      \
244                                              condition)
245 #define DEF_CONDITIONAL_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, condition)   \
246         DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name,                                                \
247                                              sk_gpu_test::GrContextFactory::IsRenderingContext,   \
248                                              reporter, context_info, nullptr, condition)
249 
250 #define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter) \
251         DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info,     \
252                                              options_filter, true)
253 #define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info)                          \
254         DEF_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr)
255 
256 #define DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info)                    \
257         DEF_GPUTEST_FOR_CONTEXTS(name, sk_gpu_test::GrContextFactory::IsRenderingContext,   \
258                                  reporter, context_info, nullptr)
259 #define DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(name, reporter, context_info)                       \
260         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsGLContextType,                          \
261                                  reporter, context_info, nullptr)
262 #define DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(name, reporter, context_info)                 \
263         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsRenderingGLContextType,                 \
264                                  reporter, context_info, nullptr)
265 #define DEF_GPUTEST_FOR_MOCK_CONTEXT(name, reporter, context_info)                          \
266         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMockContextType,                        \
267                                  reporter, context_info, nullptr)
268 #define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info)                        \
269         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType,                      \
270                                  reporter, context_info, nullptr)
271 #define DEF_GPUTEST_FOR_METAL_CONTEXT(name, reporter, context_info)                         \
272         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMetalContextType,                       \
273                                  reporter, context_info, nullptr)
274 #define DEF_GPUTEST_FOR_D3D_CONTEXT(name, reporter, context_info)                           \
275     DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsDirect3DContextType,                        \
276                              reporter, context_info, nullptr)
277 #define DEF_GPUTEST_FOR_DAWN_CONTEXT(name, reporter, context_info)                          \
278     DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsDawnContextType,                            \
279                              reporter, context_info, nullptr)
280 
281 #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER)                          \
282     do {                                                                   \
283         SkNullWStream testStream;                                          \
284         auto testDoc = SkPDF::MakeDocument(&testStream);                   \
285         if (!testDoc) {                                                    \
286             INFOF(REPORTER, "PDF disabled; %s test skipped.", #TEST_NAME); \
287             return;                                                        \
288         }                                                                  \
289     } while (false)
290 
291 #endif
292