From 6bd250a2a340348434b7b16bd4e4b5da0f598e3e Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Tue, 25 Feb 2014 19:32:15 +0000 Subject: [PATCH] Let DM run unit tests. - refactor GYPs and a few flags - make GPU tests grab a thread-local GrContextFactory when needed as we do in DM for GMs - add a few more UI features to make DM more like tests I believe this makes the program 'tests' obsolete. It should be somewhat faster to run the two sets together than running the old binaries serially: - serial: tests 20s (3m18s CPU), dm 21s (3m01s CPU) - together: 27s (6m21s CPU) Next up is to incorporate benches. I'm only planning there on a single-pass sanity check, so that won't obsolete the program 'bench' just yet. Tested: out/Debug/tests && out/Debug/dm && echo ok BUG=skia: R=reed@google.com, bsalomon@google.com, mtklein@google.com, tfarina@chromium.org Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/178273002 git-svn-id: http://skia.googlecode.com/svn/trunk@13586 2bbb7eff-a529-9590-31e7-b0007b416f81 --- dm/DM.cpp | 96 +++++++++++++++-------- dm/DMGpuTask.cpp | 19 +---- dm/DMGpuTask.h | 1 + dm/DMReporter.cpp | 16 ++-- dm/DMReporter.h | 7 +- dm/DMTask.cpp | 11 ++- dm/DMTask.h | 2 +- dm/DMTaskRunner.cpp | 28 ++++++- dm/DMTaskRunner.h | 12 ++- dm/DMTestTask.cpp | 34 +++++++++ dm/DMTestTask.h | 50 ++++++++++++ gyp/dm.gyp | 8 +- gyp/tests.gyp | 177 +------------------------------------------ gyp/tests.gypi | 180 ++++++++++++++++++++++++++++++++++++++++++++ tests/Test.cpp | 29 +++---- tests/Test.h | 14 +++- tests/skia_test.cpp | 30 +++----- 17 files changed, 429 insertions(+), 285 deletions(-) create mode 100644 dm/DMTestTask.cpp create mode 100644 dm/DMTestTask.h create mode 100644 gyp/tests.gypi diff --git a/dm/DM.cpp b/dm/DM.cpp index 8a4a38209a..ee53e9d99f 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -7,26 +7,29 @@ #include "SkForceLinking.h" #include "SkGraphics.h" #include "SkString.h" +#include "Test.h" #include "gm.h" +#include "DMCpuTask.h" +#include "DMGpuTask.h" #include "DMReporter.h" #include "DMTask.h" #include "DMTaskRunner.h" -#include "DMCpuTask.h" -#include "DMGpuTask.h" +#include "DMTestTask.h" #include "DMWriteTask.h" #include using skiagm::GM; using skiagm::GMRegistry; +using skiatest::Test; +using skiatest::TestRegistry; -DEFINE_int32(cpuThreads, -1, "Threads for CPU work. Default NUM_CPUS."); -DEFINE_int32(gpuThreads, 1, "Threads for GPU work."); +DEFINE_int32(threads, -1, "Threads for CPU work. Default NUM_CPUS."); DEFINE_string2(expectations, r, "", "If a directory, compare generated images against images under this path. " "If a file, compare generated images against JSON expectations at this path."); -DEFINE_string(resources, "resources", "Path to resources directory."); +DEFINE_string2(resources, i, "resources", "Path to resources directory."); DEFINE_string(match, "", "[~][^]substring[$] [...] of GM name to run.\n" "Multiple matches may be separated by spaces.\n" "~ causes a matching GM to always be skipped\n" @@ -37,6 +40,10 @@ DEFINE_string(match, "", "[~][^]substring[$] [...] of GM name to run.\n" "it is skipped unless some list entry starts with ~"); DEFINE_string(config, "565 8888 gpu", "Options: 565 8888 gpu msaa4 msaa16 gpunull gpudebug angle mesa"); // TODO(mtklein): pdf +DEFINE_bool(leaks, false, "Print leaked instance-counted objects at exit?"); + +DEFINE_bool(gms, true, "Run GMs?"); +DEFINE_bool(tests, true, "Run tests?"); __SK_FORCE_IMAGE_DECODER_LINKING; @@ -48,11 +55,11 @@ static SkString lowercase(SkString s) { return s; } -static void kick_off_tasks(const SkTDArray& gms, - const SkTArray& configs, - const DM::Expectations& expectations, - DM::Reporter* reporter, - DM::TaskRunner* tasks) { +static void kick_off_gms(const SkTDArray& gms, + const SkTArray& configs, + const DM::Expectations& expectations, + DM::Reporter* reporter, + DM::TaskRunner* tasks) { const SkColorType _565 = kRGB_565_SkColorType; const SkColorType _8888 = kPMColor_SkColorType; const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType; @@ -93,6 +100,14 @@ static void kick_off_tasks(const SkTDArray& gms, #undef START } +static void kick_off_tests(const SkTDArray& tests, + DM::Reporter* reporter, + DM::TaskRunner* tasks) { + for (int i = 0; i < tests.count(); i++) { + tasks->add(SkNEW_ARGS(DM::TestTask, (reporter, tasks, tests[i]))); + } +} + static void report_failures(const DM::Reporter& reporter) { SkTArray failures; reporter.getFailures(&failures); @@ -109,40 +124,57 @@ static void report_failures(const DM::Reporter& reporter) { int tool_main(int argc, char** argv); int tool_main(int argc, char** argv) { +#if SK_ENABLE_INST_COUNT + gPrintInstCount = FLAGS_leaks; +#endif SkGraphics::Init(); - SkCommandLineFlags::Parse(argc, argv); GM::SetResourcePath(FLAGS_resources[0]); + Test::SetResourcePath(FLAGS_resources[0]); + SkTArray configs; - for (int i = 0; i < FLAGS_config.count(); i++) { - SkStrSplit(FLAGS_config[i], ", ", &configs); - } - SkTDArray gms; - for (const GMRegistry* reg = GMRegistry::Head(); reg != NULL; reg = reg->next()) { - SkAutoTDelete gmForName(reg->factory()(NULL)); - if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gmForName->shortName())) { - *gms.append() = reg->factory(); - } - } - SkDebugf("%d GMs x %d configs\n", gms.count(), configs.count()); - SkAutoTDelete expectations(SkNEW(DM::NoExpectations)); - if (FLAGS_expectations.count() > 0) { - const char* path = FLAGS_expectations[0]; - if (sk_isdir(path)) { - expectations.reset(SkNEW_ARGS(DM::WriteTask::Expectations, (path))); - } else { - expectations.reset(SkNEW_ARGS(DM::JsonExpectations, (path))); + + if (FLAGS_gms) { + for (int i = 0; i < FLAGS_config.count(); i++) { + SkStrSplit(FLAGS_config[i], ", ", &configs); + } + + for (const GMRegistry* reg = GMRegistry::Head(); reg != NULL; reg = reg->next()) { + SkAutoTDelete gmForName(reg->factory()(NULL)); + if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gmForName->shortName())) { + *gms.append() = reg->factory(); + } + } + + if (FLAGS_expectations.count() > 0) { + const char* path = FLAGS_expectations[0]; + if (sk_isdir(path)) { + expectations.reset(SkNEW_ARGS(DM::WriteTask::Expectations, (path))); + } else { + expectations.reset(SkNEW_ARGS(DM::JsonExpectations, (path))); + } } } + SkTDArray tests; + if (FLAGS_tests) { + for (const TestRegistry* reg = TestRegistry::Head(); reg != NULL; reg = reg->next()) { + SkAutoTDelete testForName(reg->factory()(NULL)); + if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, testForName->getName())) { + *tests.append() = reg->factory(); + } + } + } + + SkDebugf("%d GMs x %d configs, %d tests\n", gms.count(), configs.count(), tests.count()); DM::Reporter reporter; - DM::TaskRunner tasks(FLAGS_cpuThreads, FLAGS_gpuThreads); - kick_off_tasks(gms, configs, *expectations, &reporter, &tasks); + DM::TaskRunner tasks(FLAGS_threads); + kick_off_gms(gms, configs, *expectations, &reporter, &tasks); + kick_off_tests(tests, &reporter, &tasks); tasks.wait(); - reporter.updateStatusLine(); SkDebugf("\n"); report_failures(reporter); diff --git a/dm/DMGpuTask.cpp b/dm/DMGpuTask.cpp index f787e2544f..3a4708b8db 100644 --- a/dm/DMGpuTask.cpp +++ b/dm/DMGpuTask.cpp @@ -18,6 +18,7 @@ GpuTask::GpuTask(const char* name, GrContextFactory::GLContextType contextType, int sampleCount) : Task(reporter, taskRunner) + , fTaskRunner(taskRunner) , fGM(gmFactory(NULL)) , fName(UnderJoin(fGM->shortName(), name)) , fExpectations(expectations) @@ -26,24 +27,12 @@ GpuTask::GpuTask(const char* name, , fSampleCount(sampleCount) {} -static void* new_gr_context_factory() { - return SkNEW(GrContextFactory); -} - -static void delete_gr_context_factory(void* factory) { - SkDELETE((GrContextFactory*) factory); -} - -static GrContextFactory* get_gr_factory() { - return reinterpret_cast(SkTLS::Get(&new_gr_context_factory, - &delete_gr_context_factory)); -} - void GpuTask::draw() { - GrContext* gr = get_gr_factory()->get(fContextType); // Will be owned by device. SkImageInfo info = SkImageInfo::Make(SkScalarCeilToInt(fGM->width()), SkScalarCeilToInt(fGM->height()), - fColorType, kPremul_SkAlphaType); + fColorType, + kPremul_SkAlphaType); + GrContext* gr = fTaskRunner->getGrContextFactory()->get(fContextType); // Owned by surface. SkAutoTUnref surface(SkSurface::NewRenderTarget(gr, info, fSampleCount)); SkCanvas* canvas = surface->getCanvas(); diff --git a/dm/DMGpuTask.h b/dm/DMGpuTask.h index a3fe52b751..1380e443d4 100644 --- a/dm/DMGpuTask.h +++ b/dm/DMGpuTask.h @@ -32,6 +32,7 @@ public: virtual SkString name() const SK_OVERRIDE { return fName; } private: + TaskRunner* fTaskRunner; SkAutoTDelete fGM; const SkString fName; const Expectations& fExpectations; diff --git a/dm/DMReporter.cpp b/dm/DMReporter.cpp index 0fd83e5bb6..1ff64c57cc 100644 --- a/dm/DMReporter.cpp +++ b/dm/DMReporter.cpp @@ -3,21 +3,27 @@ #include "SkCommandLineFlags.h" #include "OverwriteLine.h" -DEFINE_bool(quiet, false, "If true, don't print status updates."); +DEFINE_bool2(quiet, q, false, "If true, don't print status updates."); +DEFINE_bool2(verbose, v, false, "If true, print status updates one-per-line."); namespace DM { -void Reporter::updateStatusLine() const { +void Reporter::finish(SkString name) { + sk_atomic_inc(&fFinished); + if (FLAGS_quiet) { return; } SkString status; - status.printf("%s%d tasks left", kSkOverwriteLine, this->started() - this->finished()); + status.printf("%s%d tasks left", + FLAGS_verbose ? "\n" : kSkOverwriteLine, + this->started() - this->finished()); const int failed = this->failed(); if (failed > 0) { status.appendf(", %d failed", failed); } + status.appendf("\t[%s done]", name.c_str()); SkDebugf(status.c_str()); } @@ -26,9 +32,9 @@ int32_t Reporter::failed() const { return fFailures.count(); } -void Reporter::fail(SkString name) { +void Reporter::fail(SkString msg) { SkAutoMutexAcquire writer(&fMutex); - fFailures.push_back(name); + fFailures.push_back(msg); } void Reporter::getFailures(SkTArray* failures) const { diff --git a/dm/DMReporter.h b/dm/DMReporter.h index 4f4ad432d5..2bb4702178 100644 --- a/dm/DMReporter.h +++ b/dm/DMReporter.h @@ -7,7 +7,6 @@ #include "SkTypes.h" // Used to report status changes including failures. All public methods are threadsafe. - namespace DM { class Reporter : SkNoncopyable { @@ -15,15 +14,13 @@ public: Reporter() : fStarted(0), fFinished(0) {} void start() { sk_atomic_inc(&fStarted); } - void finish() { sk_atomic_inc(&fFinished); } - void fail(SkString name); + void finish(SkString name); + void fail(SkString msg); int32_t started() const { return fStarted; } int32_t finished() const { return fFinished; } int32_t failed() const; - void updateStatusLine() const; - void getFailures(SkTArray*) const; private: diff --git a/dm/DMTask.cpp b/dm/DMTask.cpp index a5c75f0f8a..2f009f0670 100644 --- a/dm/DMTask.cpp +++ b/dm/DMTask.cpp @@ -26,8 +26,7 @@ void Task::run() { if (!this->shouldSkip()) { this->draw(); } - fReporter->finish(); - fReporter->updateStatusLine(); + fReporter->finish(this->name()); delete this; } @@ -39,8 +38,12 @@ void Task::spawnChild(Task* task) { } } -void Task::fail() { - fReporter->fail(this->name()); +void Task::fail(const char* msg) { + SkString failure(this->name()); + if (msg) { + failure.appendf(": %s", msg); + } + fReporter->fail(failure); } } // namespace DM diff --git a/dm/DMTask.h b/dm/DMTask.h index 0d3ef74cc3..638a939304 100644 --- a/dm/DMTask.h +++ b/dm/DMTask.h @@ -34,7 +34,7 @@ public: protected: void spawnChild(Task* task); - void fail(); + void fail(const char* msg = NULL); private: // Both unowned. diff --git a/dm/DMTaskRunner.cpp b/dm/DMTaskRunner.cpp index 22269a4d70..bd53ce615a 100644 --- a/dm/DMTaskRunner.cpp +++ b/dm/DMTaskRunner.cpp @@ -3,10 +3,21 @@ namespace DM { -TaskRunner::TaskRunner(int cputhreads, int gpuThreads) + +TaskRunner::TaskRunner(int cputhreads) : fMain(cputhreads) - , fGpu(gpuThreads) - {} + , fGpu(1) { + // Enqueue a task on the GPU thread to create a GrContextFactory. + struct Create : public SkRunnable { + Create(GrContextFactory** ptr) : fPtr(ptr) {} + void run() SK_OVERRIDE { + *fPtr = SkNEW(GrContextFactory); + delete this; + } + GrContextFactory** fPtr; + }; + fGpu.add(SkNEW_ARGS(Create, (&fGrContextFactory))); +} void TaskRunner::add(Task* task) { if (task->usesGpu()) { @@ -17,6 +28,17 @@ void TaskRunner::add(Task* task) { } void TaskRunner::wait() { + // Enqueue a task on the GPU thread to destroy the GrContextFactory. + struct Delete : public SkRunnable { + Delete(GrContextFactory* ptr) : fPtr(ptr) {} + void run() SK_OVERRIDE { + delete fPtr; + delete this; + } + GrContextFactory* fPtr; + }; + fGpu.add(SkNEW_ARGS(Delete, (fGrContextFactory))); + // These wait calls block until the threadpool is done. We don't allow // children to spawn new GPU tasks so we can wait for that first knowing // we'll never try to add to it later. Same can't be said of fMain: fGpu diff --git a/dm/DMTaskRunner.h b/dm/DMTaskRunner.h index 5d7b320d6c..8af1b63719 100644 --- a/dm/DMTaskRunner.h +++ b/dm/DMTaskRunner.h @@ -1,12 +1,12 @@ #ifndef DMTaskRunner_DEFINED #define DMTaskRunner_DEFINED +#include "GrContextFactory.h" #include "SkThreadPool.h" #include "SkTypes.h" -// TaskRunner runs Tasks on one of two threadpools depending on the Task's usesGpu() method. -// This lets us drive the GPU with a small number of threads (e.g. 2 or 4 can be faster than 1) -// while not swamping it with requests from the full fleet of threads that CPU-bound tasks run on. +// TaskRunner runs Tasks on one of two threadpools depending on the Task's usesGpu() method. This +// lets us drive the GPU from a single thread while parallelizing CPU-bound work. namespace DM { @@ -14,13 +14,17 @@ class Task; class TaskRunner : SkNoncopyable { public: - TaskRunner(int cputhreads, int gpuThreads); + explicit TaskRunner(int cputhreads); void add(Task* task); void wait(); + // This can only be safely called from a GPU task's draw() method. + GrContextFactory* getGrContextFactory() const { return fGrContextFactory; } + private: SkThreadPool fMain, fGpu; + GrContextFactory* fGrContextFactory; // Created and destroyed on fGpu threadpool. }; } // namespace DM diff --git a/dm/DMTestTask.cpp b/dm/DMTestTask.cpp new file mode 100644 index 0000000000..7a5f8cf9f9 --- /dev/null +++ b/dm/DMTestTask.cpp @@ -0,0 +1,34 @@ +#include "DMTestTask.h" +#include "DMUtil.h" +#include "SkCommandLineFlags.h" + +DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests."); +DEFINE_bool2(pathOpsSingleThread, z, false, "Disallow pathOps tests from using threads."); +DEFINE_bool2(pathOpsVerbose, V, false, "Tell pathOps tests to be verbose."); + +namespace DM { + +TestTask::TestTask(Reporter* reporter, + TaskRunner* taskRunner, + skiatest::TestRegistry::Factory factory) + : Task(reporter, taskRunner) + , fTaskRunner(taskRunner) + , fTest(factory(NULL)) + , fName(UnderJoin("test", fTest->getName())) {} + +void TestTask::draw() { + if (this->usesGpu()) { + fTest->setGrContextFactory(fTaskRunner->getGrContextFactory()); + } + fTest->setReporter(&fTestReporter); + fTest->run(); + if (!fTest->passed()) { + this->fail(fTestReporter.failure()); + } +} + +bool TestTask::TestReporter::allowExtendedTest() const { return FLAGS_pathOpsExtended; } +bool TestTask::TestReporter::allowThreaded() const { return !FLAGS_pathOpsSingleThread; } +bool TestTask::TestReporter::verbose() const { return FLAGS_pathOpsVerbose; } + +} // namespace DM diff --git a/dm/DMTestTask.h b/dm/DMTestTask.h new file mode 100644 index 0000000000..a4903ee717 --- /dev/null +++ b/dm/DMTestTask.h @@ -0,0 +1,50 @@ +#ifndef DMTestTask_DEFINED +#define DMTestTask_DEFINED + +#include "DMReporter.h" +#include "DMTask.h" +#include "DMTaskRunner.h" +#include "SkString.h" +#include "SkTemplates.h" +#include "Test.h" + +// Runs a unit test. +namespace DM { + +class TestTask : public Task { +public: + TestTask(Reporter*, TaskRunner*, skiatest::TestRegistry::Factory); + + virtual void draw() SK_OVERRIDE; + virtual bool usesGpu() const SK_OVERRIDE { return fTest->isGPUTest(); } + virtual bool shouldSkip() const SK_OVERRIDE { return false; } + virtual SkString name() const SK_OVERRIDE { return fName; } + +private: + class TestReporter : public skiatest::Reporter { + public: + TestReporter() {} + + const char* failure() const { return fFailure.c_str(); } + + private: + virtual bool allowExtendedTest() const SK_OVERRIDE; + virtual bool allowThreaded() const SK_OVERRIDE; + virtual bool verbose() const SK_OVERRIDE; + + virtual void onReportFailed(const SkString& desc) SK_OVERRIDE { + fFailure = desc; + } + + SkString fFailure; + }; + + TaskRunner* fTaskRunner; + TestReporter fTestReporter; + SkAutoTDelete fTest; + const SkString fName; +}; + +} // namespace DM + +#endif // DMTestTask_DEFINED diff --git a/gyp/dm.gyp b/gyp/dm.gyp index 3cc51a09ba..55f5f9bd14 100644 --- a/gyp/dm.gyp +++ b/gyp/dm.gyp @@ -9,6 +9,7 @@ 'include_dirs': [ '../dm', '../gm', + '../tests', '../src/images', '../src/lazy', '../src/core', @@ -18,7 +19,11 @@ '../src/utils/debugger', '../tools', ], - 'includes': [ 'gmslides.gypi' ], + 'includes': [ + 'gmslides.gypi', + 'pathops_unittest.gypi', + 'tests.gypi', + ], 'sources': [ '../dm/DM.cpp', '../dm/DMCpuTask.cpp', @@ -30,6 +35,7 @@ '../dm/DMSerializeTask.cpp', '../dm/DMTask.cpp', '../dm/DMTaskRunner.cpp', + '../dm/DMTestTask.cpp', '../dm/DMTileGridTask.cpp', '../dm/DMUtil.cpp', '../dm/DMWriteTask.cpp', diff --git a/gyp/tests.gyp b/gyp/tests.gyp index 39a51237ff..d0a898c41e 100644 --- a/gyp/tests.gyp +++ b/gyp/tests.gyp @@ -7,187 +7,12 @@ { 'target_name': 'tests', 'type': 'executable', - 'include_dirs' : [ - '../src/core', - '../src/effects', - '../src/image', - '../src/lazy', - '../src/images', - '../src/pathops', - '../src/pdf', - '../src/pipe/utils', - '../src/utils', - '../src/utils/debugger', - '../tools/', - - # Needed for TDStackNesterTest. - '../experimental/PdfViewer', - '../experimental/PdfViewer/src', - ], 'includes': [ 'pathops_unittest.gypi', + 'tests.gypi', ], 'sources': [ - '../tests/AAClipTest.cpp', - '../tests/ARGBImageEncoderTest.cpp', - '../tests/AndroidPaintTest.cpp', - '../tests/AnnotationTest.cpp', - '../tests/AtomicTest.cpp', - '../tests/BBoxHierarchyTest.cpp', - '../tests/BitSetTest.cpp', - '../tests/BitmapCopyTest.cpp', - '../tests/BitmapGetColorTest.cpp', - '../tests/BitmapHasherTest.cpp', - '../tests/BitmapHeapTest.cpp', - '../tests/BitmapTest.cpp', - '../tests/BlitRowTest.cpp', - '../tests/BlurTest.cpp', - '../tests/CachedDecodingPixelRefTest.cpp', - '../tests/CanvasStateTest.cpp', - '../tests/CanvasTest.cpp', - '../tests/ChecksumTest.cpp', - '../tests/ClampRangeTest.cpp', - '../tests/ClipCacheTest.cpp', - '../tests/ClipCubicTest.cpp', - '../tests/ClipStackTest.cpp', - '../tests/ClipperTest.cpp', - '../tests/ColorFilterTest.cpp', - '../tests/ColorPrivTest.cpp', - '../tests/ColorTest.cpp', - '../tests/DataRefTest.cpp', - '../tests/DeferredCanvasTest.cpp', - '../tests/DequeTest.cpp', - '../tests/DeviceLooperTest.cpp', - '../tests/DiscardableMemoryPool.cpp', - '../tests/DiscardableMemoryTest.cpp', - '../tests/DocumentTest.cpp', - '../tests/DrawBitmapRectTest.cpp', - '../tests/DrawPathTest.cpp', - '../tests/DrawTextTest.cpp', - '../tests/DynamicHashTest.cpp', - '../tests/EmptyPathTest.cpp', - '../tests/ErrorTest.cpp', - '../tests/FillPathTest.cpp', - '../tests/FitsInTest.cpp', - '../tests/FlatDataTest.cpp', - '../tests/FlateTest.cpp', - '../tests/FontHostStreamTest.cpp', - '../tests/FontHostTest.cpp', - '../tests/FontMgrTest.cpp', - '../tests/FontNamesTest.cpp', - '../tests/FrontBufferedStreamTest.cpp', - '../tests/GLInterfaceValidation.cpp', - '../tests/GLProgramsTest.cpp', - '../tests/GeometryTest.cpp', - '../tests/GifTest.cpp', - '../tests/GpuBitmapCopyTest.cpp', - '../tests/GpuColorFilterTest.cpp', - '../tests/GpuDrawPathTest.cpp', - '../tests/GrBinHashKeyTest.cpp', - '../tests/GrContextFactoryTest.cpp', - '../tests/GrDrawTargetTest.cpp', - '../tests/GrMemoryPoolTest.cpp', - '../tests/GrRedBlackTreeTest.cpp', - '../tests/GrSurfaceTest.cpp', - '../tests/GrTBSearchTest.cpp', - '../tests/GradientTest.cpp', - '../tests/HashCacheTest.cpp', - '../tests/ImageCacheTest.cpp', - '../tests/ImageDecodingTest.cpp', - '../tests/ImageFilterTest.cpp', - '../tests/InfRectTest.cpp', - '../tests/JpegTest.cpp', - '../tests/LListTest.cpp', - '../tests/LayerDrawLooperTest.cpp', - '../tests/MD5Test.cpp', - '../tests/MallocPixelRefTest.cpp', - '../tests/MathTest.cpp', - '../tests/Matrix44Test.cpp', - '../tests/MatrixClipCollapseTest.cpp', - '../tests/MatrixTest.cpp', - '../tests/MemoryTest.cpp', - '../tests/MemsetTest.cpp', - '../tests/MessageBusTest.cpp', - '../tests/MetaDataTest.cpp', - '../tests/MipMapTest.cpp', - '../tests/OSPathTest.cpp', - '../tests/OnceTest.cpp', - '../tests/PDFPrimitivesTest.cpp', - '../tests/PackBitsTest.cpp', - '../tests/PaintTest.cpp', - '../tests/ParsePathTest.cpp', - '../tests/PathCoverageTest.cpp', - '../tests/PathMeasureTest.cpp', - '../tests/PathTest.cpp', - '../tests/PathUtilsTest.cpp', - '../tests/PictureTest.cpp', - '../tests/PictureUtilsTest.cpp', - '../tests/PipeTest.cpp', - '../tests/PixelRefTest.cpp', - '../tests/PointTest.cpp', - '../tests/PremulAlphaRoundTripTest.cpp', - '../tests/QuickRejectTest.cpp', - '../tests/RTreeTest.cpp', - '../tests/RandomTest.cpp', - '../tests/ReadPixelsTest.cpp', - '../tests/ReadWriteAlphaTest.cpp', - '../tests/Reader32Test.cpp', - '../tests/RefCntTest.cpp', - '../tests/RefDictTest.cpp', - '../tests/RegionTest.cpp', - '../tests/ResourceCacheTest.cpp', - '../tests/RoundRectTest.cpp', - '../tests/RuntimeConfigTest.cpp', - '../tests/SHA1Test.cpp', - '../tests/ScalarTest.cpp', - '../tests/SerializationTest.cpp', - '../tests/ShaderImageFilterTest.cpp', - '../tests/ShaderOpacityTest.cpp', - '../tests/SkBase64Test.cpp', - '../tests/SortTest.cpp', - '../tests/SrcOverTest.cpp', - '../tests/StreamTest.cpp', - '../tests/StringTest.cpp', - '../tests/StrokeTest.cpp', - '../tests/SurfaceTest.cpp', - '../tests/TLSTest.cpp', - '../tests/TSetTest.cpp', - '../tests/Test.cpp', - '../tests/Test.h', - '../tests/TestSize.cpp', - '../tests/TileGridTest.cpp', - '../tests/TracingTest.cpp', - '../tests/ToUnicode.cpp', - '../tests/Typeface.cpp', - '../tests/UnicodeTest.cpp', - '../tests/UnitTestTest.cpp', - '../tests/UtilsTest.cpp', - '../tests/WArrayTest.cpp', - '../tests/WritePixelsTest.cpp', - '../tests/Writer32Test.cpp', - '../tests/XfermodeTest.cpp', '../tests/skia_test.cpp', - - '../experimental/PdfViewer/src/SkTDStackNester.h', - '../tests/TDStackNesterTest.cpp', - - # Needed for PipeTest. - '../src/pipe/utils/SamplePipeControllers.cpp', - - # Needed for MatrixClipCollapse test. - '../src/utils/debugger/SkDrawCommand.h', - '../src/utils/debugger/SkDrawCommand.cpp', - '../src/utils/debugger/SkDebugCanvas.h', - '../src/utils/debugger/SkDebugCanvas.cpp', - '../src/utils/debugger/SkObjectParser.h', - '../src/utils/debugger/SkObjectParser.cpp', - ], - 'dependencies': [ - 'skia_lib.gyp:skia_lib', - 'flags.gyp:flags', - 'experimental.gyp:experimental', - 'pdf.gyp:pdf', - 'tools.gyp:picture_utils', ], 'conditions': [ [ 'skia_gpu == 1', { diff --git a/gyp/tests.gypi b/gyp/tests.gypi new file mode 100644 index 0000000000..50bd651425 --- /dev/null +++ b/gyp/tests.gypi @@ -0,0 +1,180 @@ +{ + 'include_dirs': [ + '../src/core', + '../src/effects', + '../src/image', + '../src/lazy', + '../src/images', + '../src/pathops', + '../src/pdf', + '../src/pipe/utils', + '../src/utils', + '../src/utils/debugger', + '../tools/', + + # Needed for TDStackNesterTest. + '../experimental/PdfViewer', + '../experimental/PdfViewer/src', + ], + 'dependencies': [ + 'skia_lib.gyp:skia_lib', + 'experimental.gyp:experimental', + 'flags.gyp:flags', + 'pdf.gyp:pdf', + 'tools.gyp:picture_utils', + ], + 'sources': [ + '../tests/Test.cpp', + '../tests/Test.h', + + '../tests/AAClipTest.cpp', + '../tests/ARGBImageEncoderTest.cpp', + '../tests/AndroidPaintTest.cpp', + '../tests/AnnotationTest.cpp', + '../tests/AtomicTest.cpp', + '../tests/BBoxHierarchyTest.cpp', + '../tests/BitSetTest.cpp', + '../tests/BitmapCopyTest.cpp', + '../tests/BitmapGetColorTest.cpp', + '../tests/BitmapHasherTest.cpp', + '../tests/BitmapHeapTest.cpp', + '../tests/BitmapTest.cpp', + '../tests/BlitRowTest.cpp', + '../tests/BlurTest.cpp', + '../tests/CachedDecodingPixelRefTest.cpp', + '../tests/CanvasStateTest.cpp', + '../tests/CanvasTest.cpp', + '../tests/ChecksumTest.cpp', + '../tests/ClampRangeTest.cpp', + '../tests/ClipCacheTest.cpp', + '../tests/ClipCubicTest.cpp', + '../tests/ClipStackTest.cpp', + '../tests/ClipperTest.cpp', + '../tests/ColorFilterTest.cpp', + '../tests/ColorPrivTest.cpp', + '../tests/ColorTest.cpp', + '../tests/DataRefTest.cpp', + '../tests/DeferredCanvasTest.cpp', + '../tests/DequeTest.cpp', + '../tests/DeviceLooperTest.cpp', + '../tests/DiscardableMemoryPool.cpp', + '../tests/DiscardableMemoryTest.cpp', + '../tests/DocumentTest.cpp', + '../tests/DrawBitmapRectTest.cpp', + '../tests/DrawPathTest.cpp', + '../tests/DrawTextTest.cpp', + '../tests/DynamicHashTest.cpp', + '../tests/EmptyPathTest.cpp', + '../tests/ErrorTest.cpp', + '../tests/FillPathTest.cpp', + '../tests/FitsInTest.cpp', + '../tests/FlatDataTest.cpp', + '../tests/FlateTest.cpp', + '../tests/FontHostStreamTest.cpp', + '../tests/FontHostTest.cpp', + '../tests/FontMgrTest.cpp', + '../tests/FontNamesTest.cpp', + '../tests/FrontBufferedStreamTest.cpp', + '../tests/GLInterfaceValidation.cpp', + '../tests/GLProgramsTest.cpp', + '../tests/GeometryTest.cpp', + '../tests/GifTest.cpp', + '../tests/GpuBitmapCopyTest.cpp', + '../tests/GpuColorFilterTest.cpp', + '../tests/GpuDrawPathTest.cpp', + '../tests/GrBinHashKeyTest.cpp', + '../tests/GrContextFactoryTest.cpp', + '../tests/GrDrawTargetTest.cpp', + '../tests/GrMemoryPoolTest.cpp', + '../tests/GrRedBlackTreeTest.cpp', + '../tests/GrSurfaceTest.cpp', + '../tests/GrTBSearchTest.cpp', + '../tests/GradientTest.cpp', + '../tests/HashCacheTest.cpp', + '../tests/ImageCacheTest.cpp', + '../tests/ImageDecodingTest.cpp', + '../tests/ImageFilterTest.cpp', + '../tests/InfRectTest.cpp', + '../tests/JpegTest.cpp', + '../tests/LListTest.cpp', + '../tests/LayerDrawLooperTest.cpp', + '../tests/MD5Test.cpp', + '../tests/MallocPixelRefTest.cpp', + '../tests/MathTest.cpp', + '../tests/Matrix44Test.cpp', + '../tests/MatrixClipCollapseTest.cpp', + '../tests/MatrixTest.cpp', + '../tests/MemoryTest.cpp', + '../tests/MemsetTest.cpp', + '../tests/MessageBusTest.cpp', + '../tests/MetaDataTest.cpp', + '../tests/MipMapTest.cpp', + '../tests/OSPathTest.cpp', + '../tests/OnceTest.cpp', + '../tests/PDFPrimitivesTest.cpp', + '../tests/PackBitsTest.cpp', + '../tests/PaintTest.cpp', + '../tests/ParsePathTest.cpp', + '../tests/PathCoverageTest.cpp', + '../tests/PathMeasureTest.cpp', + '../tests/PathTest.cpp', + '../tests/PathUtilsTest.cpp', + '../tests/PictureTest.cpp', + '../tests/PictureUtilsTest.cpp', + '../tests/PixelRefTest.cpp', + '../tests/PointTest.cpp', + '../tests/PremulAlphaRoundTripTest.cpp', + '../tests/QuickRejectTest.cpp', + '../tests/RTreeTest.cpp', + '../tests/RandomTest.cpp', + '../tests/ReadPixelsTest.cpp', + '../tests/ReadWriteAlphaTest.cpp', + '../tests/Reader32Test.cpp', + '../tests/RefCntTest.cpp', + '../tests/RefDictTest.cpp', + '../tests/RegionTest.cpp', + '../tests/ResourceCacheTest.cpp', + '../tests/RoundRectTest.cpp', + '../tests/RuntimeConfigTest.cpp', + '../tests/SHA1Test.cpp', + '../tests/ScalarTest.cpp', + '../tests/SerializationTest.cpp', + '../tests/ShaderImageFilterTest.cpp', + '../tests/ShaderOpacityTest.cpp', + '../tests/SkBase64Test.cpp', + '../tests/SortTest.cpp', + '../tests/SrcOverTest.cpp', + '../tests/StreamTest.cpp', + '../tests/StringTest.cpp', + '../tests/StrokeTest.cpp', + '../tests/SurfaceTest.cpp', + '../tests/TLSTest.cpp', + '../tests/TSetTest.cpp', + '../tests/TestSize.cpp', + '../tests/TileGridTest.cpp', + '../tests/ToUnicode.cpp', + '../tests/TracingTest.cpp', + '../tests/Typeface.cpp', + '../tests/UnicodeTest.cpp', + '../tests/UnitTestTest.cpp', + '../tests/UtilsTest.cpp', + '../tests/WArrayTest.cpp', + '../tests/WritePixelsTest.cpp', + '../tests/Writer32Test.cpp', + '../tests/XfermodeTest.cpp', + + '../tests/MatrixClipCollapseTest.cpp', + '../src/utils/debugger/SkDrawCommand.h', + '../src/utils/debugger/SkDrawCommand.cpp', + '../src/utils/debugger/SkDebugCanvas.h', + '../src/utils/debugger/SkDebugCanvas.cpp', + '../src/utils/debugger/SkObjectParser.h', + '../src/utils/debugger/SkObjectParser.cpp', + + '../tests/PipeTest.cpp', + '../src/pipe/utils/SamplePipeControllers.cpp', + + '../tests/TDStackNesterTest.cpp', + '../experimental/PdfViewer/src/SkTDStackNester.h', + ], +} diff --git a/tests/Test.cpp b/tests/Test.cpp index daa23b132c..95b2f91c0c 100644 --- a/tests/Test.cpp +++ b/tests/Test.cpp @@ -7,6 +7,7 @@ */ #include "Test.h" +#include "SkCommandLineFlags.h" #include "SkError.h" #include "SkString.h" #include "SkTArray.h" @@ -19,6 +20,8 @@ class GrContext; #endif +DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); + using namespace skiatest; Reporter::Reporter() : fTestCount(0) { @@ -114,23 +117,15 @@ void Test::run() { } -/////////////////////////////////////////////////////////////////////////////// - -#if SK_SUPPORT_GPU -#include "GrContextFactory.h" -GrContextFactory gGrContextFactory; -#endif - -GrContextFactory* GpuTest::GetGrContextFactory() { -#if SK_SUPPORT_GPU - return &gGrContextFactory; -#else - return NULL; -#endif +SkString Test::GetTmpDir() { + const char* tmpDir = FLAGS_tmpDir.isEmpty() ? NULL : FLAGS_tmpDir[0]; + return SkString(tmpDir); } -void GpuTest::DestroyContexts() { -#if SK_SUPPORT_GPU - gGrContextFactory.destroyContexts(); -#endif +static const char* gResourcePath = NULL; +void Test::SetResourcePath(const char* resourcePath) { gResourcePath = resourcePath; } + +SkString Test::GetResourcePath() { + return SkString(gResourcePath); } + diff --git a/tests/Test.h b/tests/Test.h index 0a9c306b15..a175e374a8 100644 --- a/tests/Test.h +++ b/tests/Test.h @@ -62,9 +62,11 @@ namespace skiatest { static SkString GetTmpDir(); + static void SetResourcePath(const char*); static SkString GetResourcePath(); virtual bool isGPUTest() const { return false; } + virtual void setGrContextFactory(GrContextFactory* factory) {} protected: virtual void onGetName(SkString*) = 0; @@ -80,10 +82,14 @@ namespace skiatest { class GpuTest : public Test{ public: GpuTest() : Test() {} - static GrContextFactory* GetGrContextFactory(); - static void DestroyContexts(); + virtual bool isGPUTest() const { return true; } - private: + virtual void setGrContextFactory(GrContextFactory* factory) { + fGrContextFactory = factory; + } + + protected: + GrContextFactory* fGrContextFactory; // Unowned. }; typedef SkTRegistry TestRegistry; @@ -162,7 +168,7 @@ namespace skiatest { name->set(#name); \ } \ virtual void onRun(Reporter* r) SK_OVERRIDE { \ - name(r, GetGrContextFactory()); \ + name(r, fGrContextFactory); \ } \ }; \ static TestRegistry gReg_##name##Class(name##Class::Factory); \ diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp index 48d87719d5..050a241ccd 100644 --- a/tests/skia_test.cpp +++ b/tests/skia_test.cpp @@ -17,6 +17,7 @@ #if SK_SUPPORT_GPU #include "GrContext.h" +#include "GrContextFactory.h" #endif using namespace skiatest; @@ -29,8 +30,6 @@ DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" "^ and $ requires an exact match\n" \ "If a test does not match any list entry,\n" \ "it is skipped unless some list entry starts with ~"); -DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); -DEFINE_string2(resourcePath, i, "resources", "directory for test resources."); DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); DEFINE_bool2(leaks, l, false, "show leaked ref cnt'd objects."); DEFINE_bool2(single, z, false, "run tests on a single thread internally."); @@ -40,6 +39,7 @@ DEFINE_bool(cpu, true, "whether or not to run CPU tests."); DEFINE_bool(gpu, true, "whether or not to run GPU tests."); DEFINE_int32(threads, SkThreadPool::kThreadPerCore, "Run threadsafe tests on a threadpool with this many threads."); +DEFINE_string2(resourcePath, i, "resources", "directory for test resources."); // need to explicitly declare this, or we get some weird infinite loop llist template TestRegistry* TestRegistry::gHead; @@ -98,16 +98,6 @@ private: const int fTotal; }; -SkString Test::GetTmpDir() { - const char* tmpDir = FLAGS_tmpDir.isEmpty() ? NULL : FLAGS_tmpDir[0]; - return SkString(tmpDir); -} - -SkString Test::GetResourcePath() { - const char* resourcePath = FLAGS_resourcePath.isEmpty() ? NULL : FLAGS_resourcePath[0]; - return SkString(resourcePath); -} - // Deletes self when run. class SkTestRunnable : public SkRunnable { public: @@ -144,6 +134,7 @@ int tool_main(int argc, char** argv); int tool_main(int argc, char** argv) { SkCommandLineFlags::SetUsage(""); SkCommandLineFlags::Parse(argc, argv); + Test::SetResourcePath(FLAGS_resourcePath[0]); #if SK_ENABLE_INST_COUNT if (FLAGS_leaks) { @@ -199,7 +190,7 @@ int tool_main(int argc, char** argv) { int skipCount = 0; SkThreadPool threadpool(FLAGS_threads); - SkTArray unsafeTests; // Always passes ownership to an SkTestRunnable + SkTArray gpuTests; // Always passes ownership to an SkTestRunnable DebugfReporter reporter(toRun); for (int i = 0; i < total; i++) { @@ -207,16 +198,20 @@ int tool_main(int argc, char** argv) { if (!should_run(test->getName(), test->isGPUTest())) { ++skipCount; } else if (test->isGPUTest()) { - unsafeTests.push_back() = test.detach(); + gpuTests.push_back() = test.detach(); } else { threadpool.add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCount))); } } - // Run the tests that aren't threadsafe. - for (int i = 0; i < unsafeTests.count(); i++) { - SkNEW_ARGS(SkTestRunnable, (unsafeTests[i], &failCount))->run(); +#if SK_SUPPORT_GPU + GrContextFactory grContextFactory; + // Run GPU tests on this thread. + for (int i = 0; i < gpuTests.count(); i++) { + gpuTests[i]->setGrContextFactory(&grContextFactory); + SkNEW_ARGS(SkTestRunnable, (gpuTests[i], &failCount))->run(); } +#endif // Block until threaded tests finish. threadpool.wait(); @@ -226,7 +221,6 @@ int tool_main(int argc, char** argv) { toRun, failCount, skipCount, reporter.countTests()); } SkGraphics::Term(); - GpuTest::DestroyContexts(); SkDebugf("\n"); return (failCount == 0) ? 0 : 1;