| Index: tests/skia_test.cpp
|
| diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
|
| index a1d4bf799bfcdeb31bcb0d305c3b31252a8a3038..26a7701a8def4c4e11ec81ff628bd858351cbf6a 100644
|
| --- a/tests/skia_test.cpp
|
| +++ b/tests/skia_test.cpp
|
| @@ -13,6 +13,7 @@
|
| #include "SkThreadPool.h"
|
| #include "SkTime.h"
|
| #include "Test.h"
|
| +#include "OverwriteLine.h"
|
|
|
| #if SK_SUPPORT_GPU
|
| #include "GrContext.h"
|
| @@ -20,121 +21,79 @@
|
|
|
| using namespace skiatest;
|
|
|
| +DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \
|
| + "Multiple matches may be separated by spaces.\n" \
|
| + "~ causes a matching test to always be skipped\n" \
|
| + "^ requires the start of the test to match\n" \
|
| + "$ requires the end of the test to match\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(single, z, false, "run tests on a single thread internally.");
|
| +DEFINE_bool2(verbose, v, false, "enable verbose output.");
|
| +DEFINE_int32(threads, SkThreadPool::kThreadPerCore,
|
| + "Run threadsafe tests on a threadpool with this many threads.");
|
| +
|
| // need to explicitly declare this, or we get some weird infinite loop llist
|
| template TestRegistry* TestRegistry::gHead;
|
|
|
| class Iter {
|
| public:
|
| - Iter(Reporter* r) : fReporter(r) {
|
| - r->ref();
|
| - this->reset();
|
| - }
|
| -
|
| - void reset() {
|
| - fReg = TestRegistry::Head();
|
| - }
|
| -
|
| - ~Iter() {
|
| - fReporter->unref();
|
| - }
|
| + Iter() { this->reset(); }
|
| + void reset() { fReg = TestRegistry::Head(); }
|
|
|
| - Test* next() {
|
| + Test* next(Reporter* r) {
|
| if (fReg) {
|
| TestRegistry::Factory fact = fReg->factory();
|
| fReg = fReg->next();
|
| Test* test = fact(NULL);
|
| - test->setReporter(fReporter);
|
| + test->setReporter(r);
|
| return test;
|
| }
|
| return NULL;
|
| }
|
|
|
| private:
|
| - Reporter* fReporter;
|
| const TestRegistry* fReg;
|
| };
|
|
|
| class DebugfReporter : public Reporter {
|
| public:
|
| - DebugfReporter(bool allowExtendedTest, bool allowThreaded, bool verbose)
|
| - : fNextIndex(0)
|
| - , fPending(0)
|
| - , fTotal(0)
|
| - , fAllowExtendedTest(allowExtendedTest)
|
| - , fAllowThreaded(allowThreaded)
|
| - , fVerbose(verbose) {
|
| - }
|
| + explicit DebugfReporter(int total) : fDone(0), fTotal(total) {}
|
|
|
| - void setTotal(int total) {
|
| - fTotal = total;
|
| - }
|
| -
|
| - virtual bool allowExtendedTest() const SK_OVERRIDE {
|
| - return fAllowExtendedTest;
|
| - }
|
| -
|
| - virtual bool allowThreaded() const SK_OVERRIDE {
|
| - return fAllowThreaded;
|
| - }
|
| -
|
| - virtual bool verbose() const SK_OVERRIDE {
|
| - return fVerbose;
|
| - }
|
| + virtual bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_extendedTest; }
|
| + virtual bool allowThreaded() const SK_OVERRIDE { return !FLAGS_single; }
|
| + virtual bool verbose() const SK_OVERRIDE { return FLAGS_verbose; }
|
|
|
| protected:
|
| - virtual void onStart(Test* test) {
|
| - SkAutoMutexAcquire lock(fStartEndMutex);
|
| - fNextIndex++;
|
| - fPending++;
|
| - SkDebugf("[%3d/%3d] (%d) %s\n", fNextIndex, fTotal, fPending, test->getName());
|
| + virtual void onReportFailed(const SkString& desc) SK_OVERRIDE {
|
| + SkDebugf("\nFAILED: %s", desc.c_str());
|
| }
|
|
|
| - virtual void onReportFailed(const SkString& desc) {
|
| - SkDebugf("\tFAILED: %s\n", desc.c_str());
|
| - }
|
| + virtual void onEnd(Test* test) SK_OVERRIDE {
|
| + const int done = 1 + sk_atomic_inc(&fDone);
|
|
|
| - virtual void onEnd(Test* test) {
|
| - SkAutoMutexAcquire lock(fStartEndMutex);
|
| if (!test->passed()) {
|
| - SkDebugf("---- %s FAILED\n", test->getName());
|
| + SkDebugf("\n---- %s FAILED", test->getName());
|
| }
|
|
|
| - fPending--;
|
| - if (fNextIndex == fTotal) {
|
| - // Just waiting on straggler tests. Shame them by printing their name and runtime.
|
| - SkDebugf(" (%d) %5.1fs %s\n",
|
| - fPending, test->elapsedMs() / 1e3, test->getName());
|
| + SkString prefix(kSkOverwriteLine);
|
| + SkString time;
|
| + if (FLAGS_verbose) {
|
| + prefix.printf("\n");
|
| + time.printf("%5dms ", test->elapsedMs());
|
| }
|
| + SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(), test->getName());
|
| }
|
|
|
| private:
|
| - SkMutex fStartEndMutex; // Guards fNextIndex and fPending.
|
| - int32_t fNextIndex;
|
| - int32_t fPending;
|
| -
|
| - // Once the tests get going, these are logically const.
|
| - int fTotal;
|
| - bool fAllowExtendedTest;
|
| - bool fAllowThreaded;
|
| - bool fVerbose;
|
| + int32_t fDone; // atomic
|
| + const int fTotal;
|
| };
|
|
|
| -DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \
|
| - "Multiple matches may be separated by spaces.\n" \
|
| - "~ causes a matching test to always be skipped\n" \
|
| - "^ requires the start of the test to match\n" \
|
| - "$ requires the end of the test to match\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(single, z, false, "run tests on a single thread internally.");
|
| -DEFINE_bool2(verbose, v, false, "enable verbose output.");
|
| -DEFINE_int32(threads, SkThreadPool::kThreadPerCore,
|
| - "Run threadsafe tests on a threadpool with this many threads.");
|
| -
|
| SkString Test::GetTmpDir() {
|
| const char* tmpDir = FLAGS_tmpDir.isEmpty() ? NULL : FLAGS_tmpDir[0];
|
| return SkString(tmpDir);
|
| @@ -197,18 +156,17 @@ int tool_main(int argc, char** argv) {
|
| header.append(" SK_RELEASE");
|
| #endif
|
| header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8);
|
| - SkDebugf("%s\n", header.c_str());
|
| + SkDebugf(header.c_str());
|
| }
|
|
|
| - DebugfReporter reporter(FLAGS_extendedTest, !FLAGS_single, FLAGS_verbose);
|
| - Iter iter(&reporter);
|
|
|
| // Count tests first.
|
| int total = 0;
|
| int toRun = 0;
|
| Test* test;
|
|
|
| - while ((test = iter.next()) != NULL) {
|
| + Iter iter;
|
| + while ((test = iter.next(NULL/*reporter not needed*/)) != NULL) {
|
| SkAutoTDelete<Test> owned(test);
|
|
|
| if(!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
|
| @@ -216,7 +174,6 @@ int tool_main(int argc, char** argv) {
|
| }
|
| total++;
|
| }
|
| - reporter.setTotal(toRun);
|
|
|
| // Now run them.
|
| iter.reset();
|
| @@ -225,8 +182,10 @@ int tool_main(int argc, char** argv) {
|
|
|
| SkThreadPool threadpool(FLAGS_threads);
|
| SkTArray<Test*> unsafeTests; // Always passes ownership to an SkTestRunnable
|
| +
|
| + DebugfReporter reporter(toRun);
|
| for (int i = 0; i < total; i++) {
|
| - SkAutoTDelete<Test> test(iter.next());
|
| + SkAutoTDelete<Test> test(iter.next(&reporter));
|
| if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
|
| ++skipCount;
|
| } else if (!test->isThreadsafe()) {
|
| @@ -244,15 +203,14 @@ int tool_main(int argc, char** argv) {
|
| // Block until threaded tests finish.
|
| threadpool.wait();
|
|
|
| - SkDebugf("Finished %d tests, %d failures, %d skipped.\n",
|
| - toRun, failCount, skipCount);
|
| - const int testCount = reporter.countTests();
|
| - if (FLAGS_verbose && testCount > 0) {
|
| - SkDebugf("Ran %d Internal tests.\n", testCount);
|
| + if (FLAGS_verbose) {
|
| + SkDebugf("\nFinished %d tests, %d failures, %d skipped. (%d internal tests)",
|
| + toRun, failCount, skipCount, reporter.countTests());
|
| }
|
| SkGraphics::Term();
|
| GpuTest::DestroyContexts();
|
|
|
| + SkDebugf("\n");
|
| return (failCount == 0) ? 0 : 1;
|
| }
|
|
|
|
|