Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "CrashHandler.h"
      9 #include "OverwriteLine.h"
     10 #include "Resources.h"
     11 #include "SkCommonFlags.h"
     12 #include "SkGraphics.h"
     13 #include "SkOSFile.h"
     14 #include "SkTArray.h"
     15 #include "SkTaskGroup.h"
     16 #include "SkTemplates.h"
     17 #include "SkTime.h"
     18 #include "Test.h"
     19 
     20 #if SK_SUPPORT_GPU
     21 #include "GrContext.h"
     22 #include "GrContextFactory.h"
     23 #endif
     24 
     25 using namespace skiatest;
     26 
     27 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
     28 
     29 // need to explicitly declare this, or we get some weird infinite loop llist
     30 template TestRegistry* TestRegistry::gHead;
     31 
     32 class Iter {
     33 public:
     34     Iter() { this->reset(); }
     35     void reset() { fReg = TestRegistry::Head(); }
     36 
     37     Test* next(Reporter* r) {
     38         if (fReg) {
     39             TestRegistry::Factory fact = fReg->factory();
     40             fReg = fReg->next();
     41             Test* test = fact(NULL);
     42             test->setReporter(r);
     43             return test;
     44         }
     45         return NULL;
     46     }
     47 
     48 private:
     49     const TestRegistry* fReg;
     50 };
     51 
     52 class DebugfReporter : public Reporter {
     53 public:
     54     explicit DebugfReporter(int total) : fDone(0), fTotal(total) {}
     55 
     56     virtual bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_extendedTest; }
     57     virtual bool verbose()           const SK_OVERRIDE { return FLAGS_veryVerbose; }
     58 
     59 protected:
     60     virtual void onReportFailed(const SkString& desc) SK_OVERRIDE {
     61         SkDebugf("\nFAILED: %s", desc.c_str());
     62     }
     63 
     64     virtual void onEnd(Test* test) SK_OVERRIDE {
     65         const int done = 1 + sk_atomic_inc(&fDone);
     66 
     67         if (!test->passed()) {
     68             SkDebugf("\n---- %s FAILED", test->getName());
     69         }
     70 
     71         SkString prefix(kSkOverwriteLine);
     72         SkString time;
     73         if (FLAGS_verbose) {
     74             prefix.printf("\n");
     75             time.printf("%5dms ", test->elapsedMs());
     76         }
     77         SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(), test->getName());
     78     }
     79 
     80 private:
     81     int32_t fDone;  // atomic
     82     const int fTotal;
     83 };
     84 
     85 // Deletes self when run.
     86 class SkTestRunnable : public SkRunnable {
     87 public:
     88   // Takes ownership of test.
     89   SkTestRunnable(Test* test, int32_t* failCount) : fTest(test), fFailCount(failCount) {}
     90 
     91   virtual void run() {
     92       fTest->run();
     93       if(!fTest->passed()) {
     94           sk_atomic_inc(fFailCount);
     95       }
     96       SkDELETE(this);
     97   }
     98 
     99 private:
    100     SkAutoTDelete<Test> fTest;
    101     int32_t* fFailCount;
    102 };
    103 
    104 static bool should_run(const char* testName, bool isGPUTest) {
    105     if (SkCommandLineFlags::ShouldSkip(FLAGS_match, testName)) {
    106         return false;
    107     }
    108     if (!FLAGS_cpu && !isGPUTest) {
    109         return false;
    110     }
    111     if (!FLAGS_gpu && isGPUTest) {
    112         return false;
    113     }
    114     return true;
    115 }
    116 
    117 int test_main();
    118 int test_main() {
    119     SetupCrashHandler();
    120 
    121 #if SK_ENABLE_INST_COUNT
    122     if (FLAGS_leaks) {
    123         gPrintInstCount = true;
    124     }
    125 #endif
    126 
    127     SkGraphics::Init();
    128 
    129     {
    130         SkString header("Skia UnitTests:");
    131         if (!FLAGS_match.isEmpty()) {
    132             header.appendf(" --match");
    133             for (int index = 0; index < FLAGS_match.count(); ++index) {
    134                 header.appendf(" %s", FLAGS_match[index]);
    135             }
    136         }
    137         SkString tmpDir = Test::GetTmpDir();
    138         if (!tmpDir.isEmpty()) {
    139             header.appendf(" --tmpDir %s", tmpDir.c_str());
    140         }
    141         SkString resourcePath = GetResourcePath();
    142         if (!resourcePath.isEmpty()) {
    143             header.appendf(" --resourcePath %s", resourcePath.c_str());
    144         }
    145 #ifdef SK_DEBUG
    146         header.append(" SK_DEBUG");
    147 #else
    148         header.append(" SK_RELEASE");
    149 #endif
    150         header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8);
    151         if (FLAGS_veryVerbose) {
    152             header.appendf("\n");
    153         }
    154         SkDebugf(header.c_str());
    155     }
    156 
    157 
    158     // Count tests first.
    159     int total = 0;
    160     int toRun = 0;
    161     Test* test;
    162 
    163     Iter iter;
    164     while ((test = iter.next(NULL/*reporter not needed*/)) != NULL) {
    165         SkAutoTDelete<Test> owned(test);
    166         if (should_run(test->getName(), test->isGPUTest())) {
    167             toRun++;
    168         }
    169         total++;
    170     }
    171 
    172     // Now run them.
    173     iter.reset();
    174     int32_t failCount = 0;
    175     int skipCount = 0;
    176 
    177     SkTaskGroup::Enabler enabled(FLAGS_threads);
    178     SkTaskGroup cpuTests;
    179     SkTArray<Test*> gpuTests;  // Always passes ownership to an SkTestRunnable
    180 
    181     DebugfReporter reporter(toRun);
    182     for (int i = 0; i < total; i++) {
    183         SkAutoTDelete<Test> test(iter.next(&reporter));
    184         if (!should_run(test->getName(), test->isGPUTest())) {
    185             ++skipCount;
    186         } else if (test->isGPUTest()) {
    187             gpuTests.push_back() = test.detach();
    188         } else {
    189             cpuTests.add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCount)));
    190         }
    191     }
    192 
    193 #if SK_SUPPORT_GPU
    194     // Give GPU tests a context factory if that makes sense on this machine.
    195     GrContextFactory grContextFactory;
    196     for (int i = 0; i < gpuTests.count(); i++) {
    197         gpuTests[i]->setGrContextFactory(&grContextFactory);
    198     }
    199 #endif
    200 
    201     // Run GPU tests on this thread.
    202     for (int i = 0; i < gpuTests.count(); i++) {
    203         SkNEW_ARGS(SkTestRunnable, (gpuTests[i], &failCount))->run();
    204     }
    205 
    206     // Block until threaded tests finish.
    207     cpuTests.wait();
    208 
    209     if (FLAGS_verbose) {
    210         SkDebugf("\nFinished %d tests, %d failures, %d skipped. (%d internal tests)",
    211                  toRun, failCount, skipCount, reporter.countTests());
    212     }
    213     SkGraphics::Term();
    214 
    215     SkDebugf("\n");
    216     return (failCount == 0) ? 0 : 1;
    217 }
    218 
    219 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
    220 int main(int argc, char** argv) {
    221     SkCommandLineFlags::Parse(argc, argv);
    222     return test_main();
    223 }
    224 #endif
    225