| Index: tests/skia_test.cpp
|
| diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
|
| index cf446d21052f922800eb34a0f4186a6fdca3575c..2aca99d4a101ef03fa50aa5d3b704c3ea99d5f2f 100644
|
| --- a/tests/skia_test.cpp
|
| +++ b/tests/skia_test.cpp
|
| @@ -10,11 +10,13 @@
|
| #include "Resources.h"
|
| #include "SkCommonFlags.h"
|
| #include "SkGraphics.h"
|
| +#include "SkInstCnt.h"
|
| #include "SkOSFile.h"
|
| #include "SkRunnable.h"
|
| #include "SkTArray.h"
|
| #include "SkTaskGroup.h"
|
| #include "SkTemplates.h"
|
| +#include "SkThread.h"
|
| #include "SkTime.h"
|
| #include "Test.h"
|
|
|
| @@ -30,78 +32,86 @@ DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
|
| // need to explicitly declare this, or we get some weird infinite loop llist
|
| template TestRegistry* TestRegistry::gHead;
|
|
|
| -class Iter {
|
| +// The threads report back to this object when they are done.
|
| +class Status {
|
| public:
|
| - Iter() { this->reset(); }
|
| - void reset() { fReg = TestRegistry::Head(); }
|
| -
|
| - Test* next(Reporter* r) {
|
| - if (fReg) {
|
| - TestRegistry::Factory fact = fReg->factory();
|
| - fReg = fReg->next();
|
| - Test* test = fact(NULL);
|
| - test->setReporter(r);
|
| - return test;
|
| - }
|
| - return NULL;
|
| - }
|
| -
|
| -private:
|
| - const TestRegistry* fReg;
|
| -};
|
| -
|
| -class DebugfReporter : public Reporter {
|
| -public:
|
| - explicit DebugfReporter(int total) : fDone(0), fTotal(total) {}
|
| -
|
| - bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_extendedTest; }
|
| - bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
|
| -
|
| -protected:
|
| - void onReportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
|
| - SkString desc;
|
| - failure.getFailureString(&desc);
|
| - SkDebugf("\nFAILED: %s", desc.c_str());
|
| - }
|
| -
|
| - void onEnd(Test* test) SK_OVERRIDE {
|
| + explicit Status(int total)
|
| + : fDone(0), fTestCount(0), fFailCount(0), fTotal(total) {}
|
| + // Threadsafe.
|
| + void endTest(const char* testName,
|
| + bool success,
|
| + SkMSec elapsed,
|
| + int testCount) {
|
| const int done = 1 + sk_atomic_inc(&fDone);
|
| -
|
| - if (!test->passed()) {
|
| - SkDebugf("\n---- %s FAILED", test->getName());
|
| + for (int i = 0; i < testCount; ++i) {
|
| + sk_atomic_inc(&fTestCount);
|
| + }
|
| + if (!success) {
|
| + SkDebugf("\n---- %s FAILED", testName);
|
| }
|
|
|
| SkString prefix(kSkOverwriteLine);
|
| SkString time;
|
| if (FLAGS_verbose) {
|
| prefix.printf("\n");
|
| - time.printf("%5dms ", test->elapsedMs());
|
| + time.printf("%5dms ", elapsed);
|
| }
|
| - SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(), test->getName());
|
| + SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(),
|
| + testName);
|
| }
|
|
|
| + void reportFailure() { sk_atomic_inc(&fFailCount); }
|
| +
|
| + int32_t testCount() { return fTestCount; }
|
| + int32_t failCount() { return fFailCount; }
|
| +
|
| private:
|
| int32_t fDone; // atomic
|
| + int32_t fTestCount; // atomic
|
| + int32_t fFailCount; // atomic
|
| const int fTotal;
|
| };
|
|
|
| // Deletes self when run.
|
| class SkTestRunnable : public SkRunnable {
|
| public:
|
| - // Takes ownership of test.
|
| - SkTestRunnable(Test* test, int32_t* failCount) : fTest(test), fFailCount(failCount) {}
|
| + SkTestRunnable(const Test& test,
|
| + Status* status,
|
| + GrContextFactory* grContextFactory = NULL)
|
| + : fTest(test), fStatus(status), fGrContextFactory(grContextFactory) {}
|
|
|
| virtual void run() {
|
| - fTest->run();
|
| - if(!fTest->passed()) {
|
| - sk_atomic_inc(fFailCount);
|
| + struct TestReporter : public skiatest::Reporter {
|
| + public:
|
| + TestReporter() : fError(false), fTestCount(0) {}
|
| + void bumpTestCount() SK_OVERRIDE { ++fTestCount; }
|
| + bool allowExtendedTest() const SK_OVERRIDE {
|
| + return FLAGS_extendedTest;
|
| + }
|
| + bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
|
| + void reportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
|
| + SkDebugf("\nFAILED: %s", failure.toString().c_str());
|
| + fError = true;
|
| + }
|
| + bool fError;
|
| + int fTestCount;
|
| + } reporter;
|
| +
|
| + const SkMSec start = SkTime::GetMSecs();
|
| + fTest.proc(&reporter, fGrContextFactory);
|
| + SkMSec elapsed = SkTime::GetMSecs() - start;
|
| + if (reporter.fError) {
|
| + fStatus->reportFailure();
|
| }
|
| + fStatus->endTest(fTest.name, !reporter.fError, elapsed,
|
| + reporter.fTestCount);
|
| SkDELETE(this);
|
| }
|
|
|
| private:
|
| - SkAutoTDelete<Test> fTest;
|
| - int32_t* fFailCount;
|
| + Test fTest;
|
| + Status* fStatus;
|
| + GrContextFactory* fGrContextFactory;
|
| };
|
|
|
| static bool should_run(const char* testName, bool isGPUTest) {
|
| @@ -137,7 +147,7 @@ int test_main() {
|
| header.appendf(" %s", FLAGS_match[index]);
|
| }
|
| }
|
| - SkString tmpDir = Test::GetTmpDir();
|
| + SkString tmpDir = skiatest::GetTmpDir();
|
| if (!tmpDir.isEmpty()) {
|
| header.appendf(" --tmpDir %s", tmpDir.c_str());
|
| }
|
| @@ -161,61 +171,62 @@ int test_main() {
|
| // Count tests first.
|
| int total = 0;
|
| int toRun = 0;
|
| - Test* test;
|
|
|
| - Iter iter;
|
| - while ((test = iter.next(NULL/*reporter not needed*/)) != NULL) {
|
| - SkAutoTDelete<Test> owned(test);
|
| - if (should_run(test->getName(), test->isGPUTest())) {
|
| + for (const TestRegistry* iter = TestRegistry::Head(); iter;
|
| + iter = iter->next()) {
|
| + const Test& test = iter->factory();
|
| + if (should_run(test.name, test.needsGpu)) {
|
| toRun++;
|
| }
|
| total++;
|
| }
|
|
|
| // Now run them.
|
| - iter.reset();
|
| - int32_t failCount = 0;
|
| int skipCount = 0;
|
|
|
| SkTaskGroup::Enabler enabled(FLAGS_threads);
|
| SkTaskGroup cpuTests;
|
| - SkTArray<Test*> gpuTests; // Always passes ownership to an SkTestRunnable
|
| + SkTArray<const Test*> gpuTests;
|
|
|
| - DebugfReporter reporter(toRun);
|
| - for (int i = 0; i < total; i++) {
|
| - SkAutoTDelete<Test> test(iter.next(&reporter));
|
| - if (!should_run(test->getName(), test->isGPUTest())) {
|
| + Status status(toRun);
|
| + for (const TestRegistry* iter = TestRegistry::Head(); iter;
|
| + iter = iter->next()) {
|
| + const Test& test = iter->factory();
|
| + if (!should_run(test.name, test.needsGpu)) {
|
| ++skipCount;
|
| - } else if (test->isGPUTest()) {
|
| - gpuTests.push_back() = test.detach();
|
| + } else if (test.needsGpu) {
|
| + gpuTests.push_back(&test);
|
| } else {
|
| - cpuTests.add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCount)));
|
| + cpuTests.add(SkNEW_ARGS(SkTestRunnable, (test, &status)));
|
| }
|
| }
|
|
|
| + GrContextFactory* grContextFactoryPtr = NULL;
|
| #if SK_SUPPORT_GPU
|
| // Give GPU tests a context factory if that makes sense on this machine.
|
| GrContextFactory grContextFactory;
|
| - for (int i = 0; i < gpuTests.count(); i++) {
|
| - gpuTests[i]->setGrContextFactory(&grContextFactory);
|
| - }
|
| + grContextFactoryPtr = &grContextFactory;
|
| +
|
| #endif
|
|
|
| // Run GPU tests on this thread.
|
| for (int i = 0; i < gpuTests.count(); i++) {
|
| - SkNEW_ARGS(SkTestRunnable, (gpuTests[i], &failCount))->run();
|
| + SkNEW_ARGS(SkTestRunnable, (*gpuTests[i], &status, grContextFactoryPtr))
|
| + ->run();
|
| }
|
|
|
| // Block until threaded tests finish.
|
| cpuTests.wait();
|
|
|
| if (FLAGS_verbose) {
|
| - SkDebugf("\nFinished %d tests, %d failures, %d skipped. (%d internal tests)",
|
| - toRun, failCount, skipCount, reporter.countTests());
|
| + SkDebugf(
|
| + "\nFinished %d tests, %d failures, %d skipped. "
|
| + "(%d internal tests)",
|
| + toRun, status.failCount(), skipCount, status.testCount());
|
| }
|
|
|
| SkDebugf("\n");
|
| - return (failCount == 0) ? 0 : 1;
|
| + return (status.failCount() == 0) ? 0 : 1;
|
| }
|
|
|
| #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
|
|
|