Simplify skiatest framework.

skiatest::Test class is now a simple struct.  Some
functionalty, such as counting errors or timing is now
handled elsewhere.

skiatest:Reporter is now a simpler abstract class.  The two
implementations handle test errors.

DM and pathops_unittest updated.

Review URL: https://codereview.chromium.org/830513004
diff --git a/dm/DM.cpp b/dm/DM.cpp
index dad1f8b..45d20b8 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -29,7 +29,6 @@
         "'--blacklist gpu skp _' will blacklist all SKPs drawn into the gpu config.\n"
         "'--blacklist gpu skp _ 8888 gm aarects' will also blacklist the aarects GM on 8888.");
 
-
 __SK_FORCE_IMAGE_DECODER_LINKING;
 using namespace DM;
 
@@ -362,51 +361,46 @@
 
 // Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
 
-static struct : public skiatest::Reporter {
-    void onReportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
-        SkString s;
-        failure.getFailureString(&s);
-        fail(s);
-        JsonWriter::AddTestFailure(failure);
-    }
-    bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_pathOpsExtended; }
-    bool verbose()           const SK_OVERRIDE { return FLAGS_veryVerbose; }
-} gTestReporter;
-
-static SkTArray<SkAutoTDelete<skiatest::Test>, kMemcpyOK> gCPUTests, gGPUTests;
+static SkTDArray<skiatest::Test> gCPUTests, gGPUTests;
 
 static void gather_tests() {
     if (!FLAGS_tests) {
         return;
     }
-    for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
-        SkAutoTDelete<skiatest::Test> test(r->factory()(NULL));
-        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
+    for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r;
+         r = r->next()) {
+        // Despite its name, factory() is returning a reference to
+        // link-time static const POD data.
+        const skiatest::Test& test = r->factory();
+        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test.name)) {
             continue;
         }
-
-        test->setReporter(&gTestReporter);
-        if (test->isGPUTest() && gpu_supported()) {
-            gGPUTests.push_back().reset(test.detach());
-        } else if (!test->isGPUTest() && FLAGS_cpu) {
-            gCPUTests.push_back().reset(test.detach());
+        if (test.needsGpu && gpu_supported()) {
+            gGPUTests.push(test);
+        } else if (!test.needsGpu && FLAGS_cpu) {
+            gCPUTests.push(test);
         }
     }
 }
 
-static void run_test(SkAutoTDelete<skiatest::Test>* t) {
+static void run_test(skiatest::Test* test) {
+    struct : public skiatest::Reporter {
+        void reportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
+            fail(failure.toString());
+            JsonWriter::AddTestFailure(failure);
+        }
+        bool allowExtendedTest() const SK_OVERRIDE {
+            return FLAGS_pathOpsExtended;
+        }
+        bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
+    } reporter;
     WallTimer timer;
     timer.start();
-    skiatest::Test* test = t->get();
     if (!FLAGS_dryRun) {
-        test->setGrContextFactory(GetThreadLocalGrContextFactory());
-        test->run();
-        if (!test->passed()) {
-            fail(SkStringPrintf("test %s failed", test->getName()));
-        }
+        test->proc(&reporter, GetThreadLocalGrContextFactory());
     }
     timer.end();
-    done(timer.fWall, "unit", "test", test->getName());
+    done(timer.fWall, "unit", "test", test->name);
 }
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
diff --git a/tests/DataRefTest.cpp b/tests/DataRefTest.cpp
index 6a58c16..099e909 100644
--- a/tests/DataRefTest.cpp
+++ b/tests/DataRefTest.cpp
@@ -174,7 +174,7 @@
 }
 
 static void test_files(skiatest::Reporter* reporter) {
-    SkString tmpDir = skiatest::Test::GetTmpDir();
+    SkString tmpDir = skiatest::GetTmpDir();
     if (tmpDir.isEmpty()) {
         return;
     }
diff --git a/tests/DocumentTest.cpp b/tests/DocumentTest.cpp
index 97aefcb..8bfb502 100644
--- a/tests/DocumentTest.cpp
+++ b/tests/DocumentTest.cpp
@@ -29,7 +29,7 @@
 }
 
 static void test_abortWithFile(skiatest::Reporter* reporter) {
-    SkString tmpDir = skiatest::Test::GetTmpDir();
+    SkString tmpDir = skiatest::GetTmpDir();
 
     if (tmpDir.isEmpty()) {
         return;  // TODO(edisonn): unfortunatelly this pattern is used in other
@@ -58,7 +58,7 @@
 }
 
 static void test_file(skiatest::Reporter* reporter) {
-    SkString tmpDir = skiatest::Test::GetTmpDir();
+    SkString tmpDir = skiatest::GetTmpDir();
     if (tmpDir.isEmpty()) {
         return;  // TODO(edisonn): unfortunatelly this pattern is used in other
                  // tests, but if GetTmpDir() starts returning and empty dir
diff --git a/tests/LListTest.cpp b/tests/LListTest.cpp
index 9826072..34bbb4d 100644
--- a/tests/LListTest.cpp
+++ b/tests/LListTest.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkInstCnt.h"
 #include "SkRandom.h"
 #include "SkTInternalLList.h"
 #include "SkTLList.h"
diff --git a/tests/MetaDataTest.cpp b/tests/MetaDataTest.cpp
index 8ed1e49..9d8d5dd 100644
--- a/tests/MetaDataTest.cpp
+++ b/tests/MetaDataTest.cpp
@@ -7,6 +7,7 @@
 
 #include "SkMetaData.h"
 #include "Test.h"
+#include "SkRefCnt.h"
 
 static void test_ptrs(skiatest::Reporter* reporter) {
     SkRefCnt ref;
diff --git a/tests/StreamTest.cpp b/tests/StreamTest.cpp
index ce391a3..ab0af14 100644
--- a/tests/StreamTest.cpp
+++ b/tests/StreamTest.cpp
@@ -130,7 +130,7 @@
     }
     delete[] dst;
 
-    SkString tmpDir = skiatest::Test::GetTmpDir();
+    SkString tmpDir = skiatest::GetTmpDir();
     if (!tmpDir.isEmpty()) {
         test_filestreams(reporter, tmpDir.c_str());
     }
diff --git a/tests/Test.cpp b/tests/Test.cpp
index cf06869..c8c40cd 100644
--- a/tests/Test.cpp
+++ b/tests/Test.cpp
@@ -10,109 +10,29 @@
 #include "SkCommandLineFlags.h"
 #include "SkError.h"
 #include "SkString.h"
-#include "SkTArray.h"
 #include "SkTime.h"
 
-#if SK_SUPPORT_GPU
-#include "GrContext.h"
-#include "gl/SkGLContext.h"
-#else
-class GrContext;
-#endif
+DEFINE_string2(tmpDir, t, NULL, "Temp directory to use.");
 
-DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use.");
+void skiatest::Reporter::bumpTestCount() {}
 
-using namespace skiatest;
+bool skiatest::Reporter::allowExtendedTest() const { return false; }
 
-Reporter::Reporter() : fTestCount(0) {
-}
+bool skiatest::Reporter::verbose() const { return false; }
 
-void Reporter::startTest(Test* test) {
-    this->onStart(test);
-}
-
-void Reporter::reportFailed(const skiatest::Failure& failure) {
-    this->onReportFailed(failure);
-}
-
-void Reporter::endTest(Test* test) {
-    this->onEnd(test);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-Test::Test() : fReporter(NULL), fPassed(true) {}
-
-Test::~Test() {
-    SkSafeUnref(fReporter);
-}
-
-void Test::setReporter(Reporter* r) {
-    SkRefCnt_SafeAssign(fReporter, r);
-}
-
-const char* Test::getName() {
-    if (fName.size() == 0) {
-        this->onGetName(&fName);
+SkString skiatest::Failure::toString() const {
+    SkString result = SkStringPrintf("%s:%d\t", this->fileName, this->lineNo);
+    if (!this->message.isEmpty()) {
+        result.append(this->message);
+        if (strlen(this->condition) > 0) {
+            result.append(": ");
+        }
     }
-    return fName.c_str();
+    result.append(this->condition);
+    return result;
 }
 
-class LocalReporter : public Reporter {
-public:
-    explicit LocalReporter(Reporter* reporterToMimic) : fReporter(reporterToMimic) {}
-
-    int numFailures() const { return fFailures.count(); }
-    const skiatest::Failure& failure(int i) const { return fFailures[i]; }
-
-protected:
-    void onReportFailed(const Failure& failure) SK_OVERRIDE {
-        fFailures.push_back(failure);
-    }
-
-    // Proxy down to fReporter.  We assume these calls are threadsafe.
-    bool allowExtendedTest() const SK_OVERRIDE {
-        return fReporter->allowExtendedTest();
-    }
-
-    void bumpTestCount() SK_OVERRIDE {
-        fReporter->bumpTestCount();
-    }
-
-    bool verbose() const SK_OVERRIDE {
-        return fReporter->verbose();
-    }
-
-private:
-    Reporter* fReporter;  // Unowned.
-    SkTArray<skiatest::Failure> fFailures;
-};
-
-void Test::run() {
-    // Clear the Skia error callback before running any test, to ensure that tests
-    // don't have unintended side effects when running more than one.
-    SkSetErrorCallback( NULL, NULL );
-
-    // Tell (likely shared) fReporter that this test has started.
-    fReporter->startTest(this);
-
-    const SkMSec start = SkTime::GetMSecs();
-    // Run the test into a LocalReporter so we know if it's passed or failed without interference
-    // from other tests that might share fReporter.
-    LocalReporter local(fReporter);
-    this->onRun(&local);
-    fPassed = local.numFailures() == 0;
-    fElapsed = SkTime::GetMSecs() - start;
-
-    // Now tell fReporter about any failures and wrap up.
-    for (int i = 0; i < local.numFailures(); i++) {
-      fReporter->reportFailed(local.failure(i));
-    }
-    fReporter->endTest(this);
-
-}
-
-SkString Test::GetTmpDir() {
+SkString skiatest::GetTmpDir() {
     const char* tmpDir = FLAGS_tmpDir.isEmpty() ? NULL : FLAGS_tmpDir[0];
     return SkString(tmpDir);
 }
diff --git a/tests/Test.h b/tests/Test.h
index 4f838f5..ed5de0f 100644
--- a/tests/Test.h
+++ b/tests/Test.h
@@ -8,122 +8,48 @@
 #ifndef skiatest_Test_DEFINED
 #define skiatest_Test_DEFINED
 
-#include "SkRefCnt.h"
 #include "SkString.h"
 #include "SkTRegistry.h"
-#include "SkThread.h"
 #include "SkTypes.h"
 
 class GrContextFactory;
 
 namespace skiatest {
 
-    class Test;
+SkString GetTmpDir();
 
-    /**
-     *  Information about a single failure from a Test.
-     *
-     *  Not intended to be created/modified directly. To create one, use one of
-     *
-     *  REPORTER_ASSERT
-     *  REPORTER_ASSERT_MESSAGE
-     *  ERRORF
-     *
-     *  described in more detail further down in this file.
-     */
-    struct Failure {
-        const char* fileName;
-        int lineNo;
-        const char* condition;
-        SkString message;
+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;
+};
 
-        // Helper to combine the failure info into one string.
-        void getFailureString(SkString* result) const {
-            if (!result) {
-                return;
-            }
-            result->printf("%s:%d\t", fileName, lineNo);
-            if (!message.isEmpty()) {
-                result->append(message);
-                if (strlen(condition) > 0) {
-                    result->append(": ");
-                }
-            }
-            result->append(condition);
-        }
-    };
+class Reporter : SkNoncopyable {
+public:
+    virtual ~Reporter() {}
+    virtual void bumpTestCount();
+    virtual void reportFailed(const skiatest::Failure&) = 0;
+    virtual bool allowExtendedTest() const;
+    virtual bool verbose() const;
+};
 
+#define REPORT_FAILURE(reporter, cond, message) \
+    reporter->reportFailed(skiatest::Failure(__FILE__, __LINE__, cond, message))
 
-    class Reporter : public SkRefCnt {
-    public:
-        SK_DECLARE_INST_COUNT(Reporter)
-        Reporter();
+typedef void (*TestProc)(skiatest::Reporter*, GrContextFactory*);
 
-        int countTests() const { return fTestCount; }
+struct Test {
+    Test(const char* n, bool g, TestProc p) : name(n), needsGpu(g), proc(p) {}
+    const char* name;
+    bool needsGpu;
+    TestProc proc;
+};
 
-        void startTest(Test*);
-        void reportFailed(const Failure&);
-        void endTest(Test*);
-
-        virtual bool allowExtendedTest() const { return false; }
-        virtual bool verbose() const { return false; }
-        virtual void bumpTestCount() { sk_atomic_inc(&fTestCount); }
-
-    protected:
-        virtual void onStart(Test*) {}
-        virtual void onReportFailed(const Failure&) {}
-        virtual void onEnd(Test*) {}
-
-    private:
-        int32_t fTestCount;
-
-        typedef SkRefCnt INHERITED;
-    };
-
-    class Test {
-    public:
-        Test();
-        virtual ~Test();
-
-        Reporter* getReporter() const { return fReporter; }
-        void setReporter(Reporter*);
-
-        const char* getName();
-        void run();
-        bool passed() const { return fPassed; }
-        SkMSec elapsedMs() const { return fElapsed; }
-
-        static SkString GetTmpDir();
-
-        virtual bool isGPUTest() const { return false; }
-        virtual void setGrContextFactory(GrContextFactory* factory) {}
-
-    protected:
-        virtual void onGetName(SkString*) = 0;
-        virtual void onRun(Reporter*) = 0;
-
-    private:
-        Reporter*   fReporter;
-        SkString    fName;
-        bool        fPassed;
-        SkMSec      fElapsed;
-    };
-
-    class GpuTest : public Test{
-    public:
-        GpuTest() : Test(), fGrContextFactory(NULL) {}
-
-        virtual bool isGPUTest() const { return true; }
-        virtual void setGrContextFactory(GrContextFactory* factory) {
-            fGrContextFactory = factory;
-        }
-
-    protected:
-        GrContextFactory* fGrContextFactory;  // Unowned.
-    };
-
-    typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
-}  // namespace skiatest
+typedef SkTRegistry<Test> TestRegistry;
 
 /*
     Use the following macros to make use of the skiatest classes, e.g.
@@ -143,66 +69,37 @@
         ...
     }
 */
+}  // namespace skiatest
 
-#define REPORTER_ASSERT(r, cond)                                        \
-    do {                                                                \
-        if (!(cond)) {                                                  \
-            skiatest::Failure failure = { __FILE__, __LINE__,           \
-                                          #cond, SkString() };          \
-            r->reportFailed(failure);                                   \
-        }                                                               \
-    } while(0)
+#define REPORTER_ASSERT(r, cond)                  \
+    do {                                          \
+        if (!(cond)) {                            \
+            REPORT_FAILURE(r, #cond, SkString()); \
+        }                                         \
+    } while (0)
 
-#define REPORTER_ASSERT_MESSAGE(r, cond, message)                       \
-    do {                                                                \
-        if (!(cond)) {                                                  \
-            skiatest::Failure failure = { __FILE__, __LINE__,           \
-                                          #cond, SkString(message) };   \
-            r->reportFailed(failure);                                   \
-        }                                                               \
-    } while(0)
+#define REPORTER_ASSERT_MESSAGE(r, cond, message)        \
+    do {                                                 \
+        if (!(cond)) {                                   \
+            REPORT_FAILURE(r, #cond, SkString(message)); \
+        }                                                \
+    } while (0)
 
-#define ERRORF(r, ...)                                                  \
-    do {                                                                \
-        SkString desc;                                                  \
-        desc.appendf(__VA_ARGS__) ;                                     \
-        skiatest::Failure failure = { __FILE__, __LINE__,               \
-                                      "", SkString(desc) };             \
-        r->reportFailed(failure);                                       \
-    } while(0)
+#define ERRORF(r, ...)                                      \
+    do {                                                    \
+        REPORT_FAILURE(r, "", SkStringPrintf(__VA_ARGS__)); \
+    } while (0)
 
-#define DEF_TEST(name, reporter)                                        \
-    static void test_##name(skiatest::Reporter*);                       \
-    namespace skiatest {                                                \
-    class name##Class : public Test {                                   \
-    public:                                                             \
-        static Test* Factory(void*) { return SkNEW(name##Class); }      \
-    protected:                                                          \
-        void onGetName(SkString* name) SK_OVERRIDE {            \
-            name->set(#name);                                           \
-        }                                                               \
-        void onRun(Reporter* r) SK_OVERRIDE { test_##name(r); } \
-    };                                                                  \
-    static TestRegistry gReg_##name##Class(name##Class::Factory);       \
-    }                                                                   \
-    static void test_##name(skiatest::Reporter* reporter)
+#define DEF_TEST(name, reporter)                                     \
+    static void test_##name(skiatest::Reporter*, GrContextFactory*); \
+    skiatest::TestRegistry name##TestRegistry(                       \
+            skiatest::Test(#name, false, test_##name));              \
+    void test_##name(skiatest::Reporter* reporter, GrContextFactory*)
 
-#define DEF_GPUTEST(name, reporter, factory)                          \
-    static void test_##name(skiatest::Reporter*, GrContextFactory*);  \
-    namespace skiatest {                                              \
-    class name##Class : public GpuTest {                              \
-    public:                                                           \
-        static Test* Factory(void*) { return SkNEW(name##Class); }    \
-    protected:                                                        \
-        void onGetName(SkString* name) SK_OVERRIDE {          \
-            name->set(#name);                                         \
-        }                                                             \
-        void onRun(Reporter* r) SK_OVERRIDE {                 \
-            test_##name(r, fGrContextFactory);                        \
-        }                                                             \
-    };                                                                \
-    static TestRegistry gReg_##name##Class(name##Class::Factory);     \
-    }                                                                 \
-    static void test_##name(skiatest::Reporter* reporter, GrContextFactory* factory)
+#define DEF_GPUTEST(name, reporter, factory)                         \
+    static void test_##name(skiatest::Reporter*, GrContextFactory*); \
+    skiatest::TestRegistry name##TestRegistry(                       \
+            skiatest::Test(#name, true, test_##name));               \
+    void test_##name(skiatest::Reporter* reporter, GrContextFactory* factory)
 
 #endif
diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
index cf446d2..2aca99d 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 @@
 // 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 @@
                 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 @@
     // 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)