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