2011-07-28 14:26:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
2009-02-27 16:24:51 +00:00
|
|
|
#ifndef skiatest_Test_DEFINED
|
|
|
|
#define skiatest_Test_DEFINED
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkString.h"
|
|
|
|
#include "include/core/SkTypes.h"
|
|
|
|
#include "src/core/SkClipOpPriv.h"
|
|
|
|
#include "src/core/SkTraceEvent.h"
|
|
|
|
#include "tools/Registry.h"
|
|
|
|
#include "tools/gpu/GrContextFactory.h"
|
2011-08-16 15:45:58 +00:00
|
|
|
|
2009-02-27 16:24:51 +00:00
|
|
|
namespace skiatest {
|
2009-04-02 16:59:40 +00:00
|
|
|
|
2015-01-20 17:30:20 +00:00
|
|
|
SkString GetTmpDir();
|
|
|
|
|
|
|
|
struct Failure {
|
|
|
|
Failure(const char* f, int l, const char* c, const SkString& m)
|
|
|
|
: fileName(f), lineNo(l), condition(c), message(m) {}
|
|
|
|
const char* fileName;
|
|
|
|
int lineNo;
|
|
|
|
const char* condition;
|
|
|
|
SkString message;
|
|
|
|
SkString toString() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Reporter : SkNoncopyable {
|
|
|
|
public:
|
|
|
|
virtual ~Reporter() {}
|
|
|
|
virtual void bumpTestCount();
|
|
|
|
virtual void reportFailed(const skiatest::Failure&) = 0;
|
|
|
|
virtual bool allowExtendedTest() const;
|
|
|
|
virtual bool verbose() const;
|
2016-10-04 14:01:04 +00:00
|
|
|
virtual void* stats() const { return nullptr; }
|
2016-12-05 16:35:07 +00:00
|
|
|
|
2019-02-07 14:54:30 +00:00
|
|
|
void reportFailedWithContext(const skiatest::Failure&);
|
|
|
|
|
2016-12-05 16:35:07 +00:00
|
|
|
void push(const SkString& message) {
|
|
|
|
fContextStack.push_back(message);
|
|
|
|
}
|
|
|
|
void pop() {
|
|
|
|
fContextStack.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SkTArray<SkString> fContextStack;
|
2015-01-20 17:30:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define REPORT_FAILURE(reporter, cond, message) \
|
2016-12-05 16:35:07 +00:00
|
|
|
reporter->reportFailedWithContext(skiatest::Failure(__FILE__, __LINE__, cond, message))
|
|
|
|
|
|
|
|
class ReporterContext : SkNoncopyable {
|
|
|
|
public:
|
|
|
|
ReporterContext(Reporter* reporter, const SkString& message) : fReporter(reporter) {
|
|
|
|
fReporter->push(message);
|
|
|
|
}
|
|
|
|
~ReporterContext() {
|
|
|
|
fReporter->pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Reporter* fReporter;
|
|
|
|
};
|
2015-01-20 17:30:20 +00:00
|
|
|
|
2017-11-15 20:48:03 +00:00
|
|
|
typedef void (*TestProc)(skiatest::Reporter*, const GrContextOptions&);
|
2017-10-30 18:02:48 +00:00
|
|
|
typedef void (*ContextOptionsProc)(GrContextOptions*);
|
2015-01-20 17:30:20 +00:00
|
|
|
|
|
|
|
struct Test {
|
2017-10-30 18:02:48 +00:00
|
|
|
Test(const char* n, bool g, TestProc p, ContextOptionsProc optionsProc = nullptr)
|
|
|
|
: name(n), needsGpu(g), proc(p), fContextOptionsProc(optionsProc) {}
|
2015-01-20 17:30:20 +00:00
|
|
|
const char* name;
|
|
|
|
bool needsGpu;
|
|
|
|
TestProc proc;
|
2017-10-30 18:02:48 +00:00
|
|
|
ContextOptionsProc fContextOptionsProc;
|
|
|
|
|
|
|
|
void modifyGrContextOptions(GrContextOptions* options) {
|
|
|
|
if (fContextOptionsProc) {
|
|
|
|
(*fContextOptionsProc)(options);
|
|
|
|
}
|
|
|
|
}
|
2017-07-24 19:21:31 +00:00
|
|
|
|
2017-11-15 20:48:03 +00:00
|
|
|
void run(skiatest::Reporter* r, const GrContextOptions& options) const {
|
2017-07-24 19:21:31 +00:00
|
|
|
TRACE_EVENT1("test", TRACE_FUNC, "name", this->name/*these are static*/);
|
2017-11-15 20:48:03 +00:00
|
|
|
this->proc(r, options);
|
2017-07-24 19:21:31 +00:00
|
|
|
}
|
2015-01-20 17:30:20 +00:00
|
|
|
};
|
|
|
|
|
2017-01-11 18:58:55 +00:00
|
|
|
typedef sk_tools::Registry<Test> TestRegistry;
|
2014-01-14 21:04:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Use the following macros to make use of the skiatest classes, e.g.
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "tests/Test.h"
|
2014-01-14 21:04:37 +00:00
|
|
|
|
|
|
|
DEF_TEST(TestName, reporter) {
|
|
|
|
...
|
|
|
|
REPORTER_ASSERT(reporter, x == 15);
|
|
|
|
...
|
2018-01-29 14:50:47 +00:00
|
|
|
REPORTER_ASSERT(reporter, x == 15, "x should be 15");
|
2014-01-14 21:04:37 +00:00
|
|
|
...
|
|
|
|
if (x != 15) {
|
|
|
|
ERRORF(reporter, "x should be 15, but is %d", x);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
...
|
|
|
|
}
|
|
|
|
*/
|
2016-04-06 21:02:39 +00:00
|
|
|
|
|
|
|
using GrContextFactoryContextType = sk_gpu_test::GrContextFactory::ContextType;
|
2016-04-05 19:59:06 +00:00
|
|
|
|
|
|
|
typedef void GrContextTestFn(Reporter*, const sk_gpu_test::ContextInfo&);
|
2016-04-06 21:02:39 +00:00
|
|
|
typedef bool GrContextTypeFilterFn(GrContextFactoryContextType);
|
|
|
|
|
|
|
|
extern bool IsGLContextType(GrContextFactoryContextType);
|
2016-04-11 21:21:33 +00:00
|
|
|
extern bool IsVulkanContextType(GrContextFactoryContextType);
|
2018-07-17 17:28:20 +00:00
|
|
|
extern bool IsMetalContextType(GrContextFactoryContextType);
|
2020-06-19 15:13:26 +00:00
|
|
|
extern bool IsDirect3DContextType(GrContextFactoryContextType);
|
2016-04-06 21:02:39 +00:00
|
|
|
extern bool IsRenderingGLContextType(GrContextFactoryContextType);
|
2019-10-24 14:23:26 +00:00
|
|
|
extern bool IsRenderingGLOrMetalContextType(GrContextFactoryContextType);
|
2019-03-26 15:10:11 +00:00
|
|
|
extern bool IsMockContextType(GrContextFactoryContextType);
|
2017-11-15 20:48:03 +00:00
|
|
|
void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*,
|
|
|
|
const GrContextOptions&);
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
|
|
|
|
/** Timer provides wall-clock duration since its creation. */
|
|
|
|
class Timer {
|
|
|
|
public:
|
|
|
|
/** Starts the timer. */
|
|
|
|
Timer();
|
|
|
|
|
|
|
|
/** Nanoseconds since creation. */
|
|
|
|
double elapsedNs() const;
|
|
|
|
|
|
|
|
/** Milliseconds since creation. */
|
|
|
|
double elapsedMs() const;
|
|
|
|
|
|
|
|
/** Milliseconds since creation as an integer.
|
|
|
|
Behavior is undefined for durations longer than SK_MSecMax.
|
|
|
|
*/
|
|
|
|
SkMSec elapsedMsInt() const;
|
|
|
|
private:
|
|
|
|
double fStartNanos;
|
|
|
|
};
|
|
|
|
|
2015-01-20 17:30:20 +00:00
|
|
|
} // namespace skiatest
|
2009-02-27 16:24:51 +00:00
|
|
|
|
2020-05-12 14:41:04 +00:00
|
|
|
static inline SkString reporter_string() { return {}; }
|
|
|
|
/// Prevent security warnings when using a non-literal string i.e. not a format string.
|
|
|
|
static inline SkString reporter_string(const char* s) { return SkString(s); }
|
|
|
|
template<typename... Args>
|
|
|
|
static inline SkString reporter_string(const char* fmt, Args... args) {
|
|
|
|
return SkStringPrintf(fmt, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define REPORTER_ASSERT(r, cond, ...) \
|
|
|
|
do { \
|
|
|
|
if (!(cond)) { \
|
|
|
|
REPORT_FAILURE(r, #cond, reporter_string(__VA_ARGS__)); \
|
|
|
|
} \
|
2015-01-20 17:30:20 +00:00
|
|
|
} while (0)
|
|
|
|
|
2020-05-12 14:41:04 +00:00
|
|
|
#define ERRORF(r, ...) \
|
|
|
|
do { \
|
|
|
|
REPORT_FAILURE(r, "", reporter_string(__VA_ARGS__)); \
|
2015-01-20 17:30:20 +00:00
|
|
|
} while (0)
|
|
|
|
|
2016-02-25 01:59:16 +00:00
|
|
|
#define INFOF(REPORTER, ...) \
|
|
|
|
do { \
|
|
|
|
if ((REPORTER)->verbose()) { \
|
|
|
|
SkDebugf(__VA_ARGS__); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2017-11-15 20:48:03 +00:00
|
|
|
#define DEF_TEST(name, reporter) \
|
|
|
|
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
|
|
|
|
skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
|
|
|
|
void test_##name(skiatest::Reporter* reporter, const GrContextOptions&)
|
2015-01-20 17:30:20 +00:00
|
|
|
|
2017-11-15 20:48:03 +00:00
|
|
|
#define DEF_GPUTEST(name, reporter, options) \
|
|
|
|
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
|
|
|
|
skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, true, test_##name)); \
|
|
|
|
void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
|
2014-01-14 21:04:37 +00:00
|
|
|
|
2017-10-30 18:02:48 +00:00
|
|
|
#define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter) \
|
2017-11-15 20:48:03 +00:00
|
|
|
static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo& context_info); \
|
2017-10-30 18:02:48 +00:00
|
|
|
static void test_gpu_contexts_##name(skiatest::Reporter* reporter, \
|
2017-11-15 20:48:03 +00:00
|
|
|
const GrContextOptions& options) { \
|
|
|
|
skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options); \
|
2017-10-30 18:02:48 +00:00
|
|
|
} \
|
|
|
|
skiatest::TestRegistry name##TestRegistry( \
|
|
|
|
skiatest::Test(#name, true, test_gpu_contexts_##name, options_filter)); \
|
2017-11-15 20:48:03 +00:00
|
|
|
void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info)
|
2016-04-05 19:59:06 +00:00
|
|
|
|
2016-04-11 21:40:50 +00:00
|
|
|
#define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info) \
|
2017-10-30 18:02:48 +00:00
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr)
|
|
|
|
|
2016-04-12 16:59:58 +00:00
|
|
|
#define DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info) \
|
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, sk_gpu_test::GrContextFactory::IsRenderingContext, \
|
2017-10-30 18:02:48 +00:00
|
|
|
reporter, context_info, nullptr)
|
2016-04-06 21:02:39 +00:00
|
|
|
#define DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(name, reporter, context_info) \
|
2017-10-30 18:02:48 +00:00
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsGLContextType, \
|
|
|
|
reporter, context_info, nullptr)
|
2016-04-06 21:02:39 +00:00
|
|
|
#define DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(name, reporter, context_info) \
|
2017-10-30 18:02:48 +00:00
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsRenderingGLContextType, \
|
|
|
|
reporter, context_info, nullptr)
|
2019-03-26 15:10:11 +00:00
|
|
|
#define DEF_GPUTEST_FOR_MOCK_CONTEXT(name, reporter, context_info) \
|
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMockContextType, \
|
|
|
|
reporter, context_info, nullptr)
|
2016-04-11 21:21:33 +00:00
|
|
|
#define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info) \
|
2017-10-30 18:02:48 +00:00
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType, \
|
|
|
|
reporter, context_info, nullptr)
|
2018-07-17 17:28:20 +00:00
|
|
|
#define DEF_GPUTEST_FOR_METAL_CONTEXT(name, reporter, context_info) \
|
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMetalContextType, \
|
|
|
|
reporter, context_info, nullptr)
|
2020-06-19 15:13:26 +00:00
|
|
|
#define DEF_GPUTEST_FOR_D3D_CONTEXT(name, reporter, context_info) \
|
|
|
|
DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsDirect3DContextType, \
|
|
|
|
reporter, context_info, nullptr)
|
Generate list of GPU contexts outside SurfaceTest tests
Add support for feeding the tests with contexts directly to the unit
test framework.
This fixes the problem where tests are more complex than needed just in
order to run the test code with multiple backends.
Also makes it possible to change the logic how contexts are
created. Instead of direct numbering, the different testable contexts
may be generated from filtered cross-product of context options. For
example: currently NVPR is a type of context. However, it could be also
an on/off feature of any context. In order to test this kind of context,
the enumeration can not be just of context type. It's simpler
to move the enumeration out of the tests.
A test targeting both normal and GPU backends would look like:
static void test_obj_behavior(skiatest::Reporter* reporter,
SkObj* obj, [other params] ) {
... test with obj and param ..
}
DEF_TEST(ObjBehavior, reporter) {
for (auto& object : generate_object) {
for (auto& other_param : generate_other_variant) {
test_obj_behavior(reporter, object, other_param);
}
}
}
#if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_ALL_CONTEXTS(ObjBehavior_Gpu, reporter, context) {
for (auto& object : generate_gpu_object) {
for (auto& other_param : generate_other_variant) {
test_obj_behavior(reporter, object, other_param);
}
}
}
#endif
Uses the feature in SurfaceTests as an example.
Moves SkSurface -related tests from ImageTest to SurfaceTest.
BUG=skia:2992
Review URL: https://codereview.chromium.org/1446453003
2015-11-20 21:32:24 +00:00
|
|
|
|
2016-04-27 14:45:18 +00:00
|
|
|
#define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER) \
|
|
|
|
do { \
|
2019-01-07 15:00:48 +00:00
|
|
|
SkNullWStream testStream; \
|
|
|
|
auto testDoc = SkPDF::MakeDocument(&testStream); \
|
2016-04-27 14:45:18 +00:00
|
|
|
if (!testDoc) { \
|
|
|
|
INFOF(REPORTER, "PDF disabled; %s test skipped.", #TEST_NAME); \
|
|
|
|
return; \
|
|
|
|
} \
|
2015-08-11 20:35:12 +00:00
|
|
|
} while (false)
|
|
|
|
|
2009-02-27 16:24:51 +00:00
|
|
|
#endif
|