Add support for conditional unit tests.

DEF_CONDITIONAL_TEST and DEF_CONDITIONAL_GPUTEST_FOR_xxxx_CONTEXTS will
allow unit tests to be considered or ignored based on a passed-in
boolean condition. DEF_TEST_DISABLED is now implemented as a conditional
test hard-coded with a "false" condition.

This allows macros (such as SKSL_TEST) to add unit tests based on the
result of a comparison.

Change-Id: Ic5325569009cfce768ba8942907c1d3e7d69ca1c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/517516
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2022-03-07 17:54:21 -05:00 committed by SkCQ
parent e3444c8bf9
commit 5e9388d170
3 changed files with 84 additions and 35 deletions

View File

@ -99,7 +99,7 @@ struct Test {
}
};
typedef sk_tools::Registry<Test> TestRegistry;
using TestRegistry = sk_tools::Registry<Test>;
/*
Use the following macros to make use of the skiatest classes, e.g.
@ -184,20 +184,15 @@ private:
} \
} while (0)
#define DEF_TEST(name, reporter) \
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu*/ false, /*graphite*/ false, test_##name)); \
#define DEF_CONDITIONAL_TEST(name, reporter, condition) \
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu=*/false, /*graphite=*/false, test_##name), condition); \
void test_##name(skiatest::Reporter* reporter, const GrContextOptions&)
#define DEF_TEST_DISABLED(name, reporter) \
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu*/ false, /*graphite*/ false, test_##name)); \
void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) { \
/* SkDebugf("Disabled:"#name "\n"); */ \
} \
void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
#define DEF_TEST(name, reporter) DEF_CONDITIONAL_TEST(name, reporter, true)
#define DEF_TEST_DISABLED(name, reporter) DEF_CONDITIONAL_TEST(name, reporter, false)
#ifdef SK_BUILD_FOR_UNIX
#define UNIX_ONLY_TEST DEF_TEST
@ -212,7 +207,7 @@ private:
test_##name(reporter); \
} \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu*/ false, /*graphite*/ true, test_graphite_##name)); \
skiatest::Test(#name, /*gpu=*/false, /*graphite=*/true, test_graphite_##name)); \
void test_##name(skiatest::Reporter* reporter)
#define DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, reporter, graphite_context) \
@ -222,26 +217,39 @@ private:
skiatest::graphite::RunWithGraphiteTestContexts(test_##name, _reporter); \
} \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu*/ false, /*graphite*/ true, \
skiatest::Test(#name, /*gpu=*/false, /*graphite=*/true, \
test_graphite_contexts_##name)); \
void test_##name(skiatest::Reporter* reporter, skgpu::Context* graphite_context)
#define DEF_GPUTEST(name, reporter, options) \
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu*/ true, /*graphite*/ false, test_##name)); \
skiatest::Test(#name, /*gpu=*/true, /*graphite=*/false, test_##name)); \
void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
#define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter) \
#define DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, \
options_filter, condition) \
static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo&); \
static void test_gpu_contexts_##name(skiatest::Reporter* reporter, \
const GrContextOptions& options) { \
skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options); \
} \
skiatest::TestRegistry name##TestRegistry( \
skiatest::Test(#name, /*gpu*/ true, /*graphite*/ false, test_gpu_contexts_##name, options_filter)); \
skiatest::Test(#name, /*gpu=*/true, /*graphite=*/false, test_gpu_contexts_##name, \
options_filter), condition); \
void test_##name(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& context_info)
#define DEF_CONDITIONAL_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info, condition) \
DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr, \
condition)
#define DEF_CONDITIONAL_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, condition) \
DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, \
sk_gpu_test::GrContextFactory::IsRenderingContext, \
reporter, context_info, nullptr, condition)
#define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter) \
DEF_CONDITIONAL_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, \
options_filter, true)
#define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, context_info) \
DEF_GPUTEST_FOR_CONTEXTS(name, nullptr, reporter, context_info, nullptr)

View File

@ -15,6 +15,16 @@ DEF_TEST(TestNormal, reporter) {
REPORTER_ASSERT(reporter, reporter);
}
// This is an example of a conditional test with a true condition.
DEF_CONDITIONAL_TEST(TestTrueCondition, reporter, 1 == 1) {
REPORTER_ASSERT(reporter, reporter);
}
// This is an example of a conditional test with a false condition.
DEF_CONDITIONAL_TEST(TestFalseCondition, reporter, 1 == 0) {
ERRORF(reporter, "DEF_CONDITIONAL_TEST executed a test with a false condition");
}
// This is an example of a GPU test that uses GrContextOptions to do the test.
DEF_GPUTEST(TestGpuFactory, reporter, factory) {
REPORTER_ASSERT(reporter, reporter);
@ -40,3 +50,27 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(TestMockContext, reporter, ctxInfo) {
REPORTER_ASSERT(reporter, reporter);
REPORTER_ASSERT(reporter, ctxInfo.directContext());
}
// Conditional GPU tests will only execute if the provided condition parameter is true.
DEF_CONDITIONAL_GPUTEST_FOR_ALL_CONTEXTS(TestGpuAllContextsWithTrueCondition,
reporter, ctxInfo, true) {
REPORTER_ASSERT(reporter, reporter);
REPORTER_ASSERT(reporter, ctxInfo.directContext());
}
DEF_CONDITIONAL_GPUTEST_FOR_ALL_CONTEXTS(TestGpuAllContextsWithFalseCondition,
reporter, ctxInfo, false) {
ERRORF(reporter, "DEF_CONDITIONAL_GPUTEST_FOR_ALL_CONTEXTS ran with a false condition");
}
DEF_CONDITIONAL_GPUTEST_FOR_RENDERING_CONTEXTS(TestGpuRenderingContextsWithTrueCondition,
reporter, ctxInfo, true) {
REPORTER_ASSERT(reporter, reporter);
REPORTER_ASSERT(reporter, ctxInfo.directContext());
}
DEF_CONDITIONAL_GPUTEST_FOR_RENDERING_CONTEXTS(TestGpuRenderingContextsWithFalseCondition,
reporter, ctxInfo, false) {
ERRORF(reporter, "DEF_CONDITIONAL_GPUTEST_FOR_RENDERING_CONTEXTS ran with a false condition");
}

View File

@ -13,27 +13,17 @@
namespace sk_tools {
/** Template class that registers itself (in the constructor) into a linked-list
and provides a function-pointer. This can be used to auto-register a set of
services, e.g. a set of image codecs.
/**
* Template class that registers itself (in the constructor) into a linked-list
* and provides a function-pointer. This can be used to auto-register a set of
* services, e.g. a set of image codecs.
*/
template <typename T> class Registry : SkNoncopyable {
public:
explicit Registry(T value) : fValue(value) {
#ifdef SK_BUILD_FOR_ANDROID
// work-around for double-initialization bug
{
Registry* reg = gHead;
while (reg) {
if (reg == this) {
return;
}
reg = reg->fChain;
}
explicit Registry(T value, bool condition = true) : fValue(value) {
if (condition) {
this->linkToRegistryHead();
}
#endif
fChain = gHead;
gHead = this;
}
static const Registry* Head() { return gHead; }
@ -54,6 +44,23 @@ public:
};
private:
void linkToRegistryHead() {
#ifdef SK_BUILD_FOR_ANDROID
// work-around for double-initialization bug
{
Registry* reg = gHead;
while (reg) {
if (reg == this) {
return;
}
reg = reg->fChain;
}
}
#endif
fChain = gHead;
gHead = this;
}
T fValue;
Registry* fChain;