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 "SkAtomics.h"
     12 #include "SkCommonFlags.h"
     13 #include "SkGraphics.h"
     14 #include "SkOSFile.h"
     15 #include "SkTArray.h"
     16 #include "SkTaskGroup.h"
     17 #include "SkTemplates.h"
     18 #include "SkTime.h"
     19 #include "Test.h"
     20 
     21 #if SK_SUPPORT_GPU
     22 #include "GrContext.h"
     23 #include "GrContextFactory.h"
     24 #endif
     25 
     26 using namespace skiatest;
     27 
     28 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
     29 
     30 // need to explicitly declare this, or we get some weird infinite loop llist
     31 template TestRegistry* TestRegistry::gHead;
     32 void (*gVerboseFinalize)() = nullptr;
     33 
     34 // The threads report back to this object when they are done.
     35 class Status {
     36 public:
     37     explicit Status(int total)
     38         : fDone(0), fTestCount(0), fFailCount(0), fTotal(total) {}
     39     // Threadsafe.
     40     void endTest(const char* testName,
     41                  bool success,
     42                  SkMSec elapsed,
     43                  int testCount) {
     44         const int done = 1 + sk_atomic_inc(&fDone);
     45         for (int i = 0; i < testCount; ++i) {
     46             sk_atomic_inc(&fTestCount);
     47         }
     48         if (!success) {
     49             SkDebugf("\n---- %s FAILED", testName);
     50         }
     51 
     52         SkString prefix(kSkOverwriteLine);
     53         SkString time;
     54         if (FLAGS_verbose) {
     55             prefix.printf("\n");
     56             time.printf("%5dms ", elapsed);
     57         }
     58         SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(),
     59                  testName);
     60     }
     61 
     62     void reportFailure() { sk_atomic_inc(&fFailCount); }
     63 
     64     int32_t testCount() { return fTestCount; }
     65     int32_t failCount() { return fFailCount; }
     66 
     67 private:
     68     int32_t fDone;  // atomic
     69     int32_t fTestCount;  // atomic
     70     int32_t fFailCount;  // atomic
     71     const int fTotal;
     72 };
     73 
     74 class SkTestRunnable {
     75 public:
     76     SkTestRunnable(const Test& test,
     77                    Status* status,
     78                    GrContextFactory* grContextFactory = nullptr)
     79         : fTest(test), fStatus(status), fGrContextFactory(grContextFactory) {}
     80 
     81   void operator()() {
     82       struct TestReporter : public skiatest::Reporter {
     83       public:
     84           TestReporter() : fError(false), fTestCount(0) {}
     85           void bumpTestCount() override { ++fTestCount; }
     86           bool allowExtendedTest() const override {
     87               return FLAGS_extendedTest;
     88           }
     89           bool verbose() const override { return FLAGS_veryVerbose; }
     90           void reportFailed(const skiatest::Failure& failure) override {
     91               SkDebugf("\nFAILED: %s", failure.toString().c_str());
     92               fError = true;
     93           }
     94           bool fError;
     95           int fTestCount;
     96       } reporter;
     97 
     98       const SkMSec start = SkTime::GetMSecs();
     99       fTest.proc(&reporter, fGrContextFactory);
    100       SkMSec elapsed = SkTime::GetMSecs() - start;
    101       if (reporter.fError) {
    102           fStatus->reportFailure();
    103       }
    104       fStatus->endTest(fTest.name, !reporter.fError, elapsed,
    105                        reporter.fTestCount);
    106   }
    107 
    108 private:
    109     Test fTest;
    110     Status* fStatus;
    111     GrContextFactory* fGrContextFactory;
    112 };
    113 
    114 static bool should_run(const char* testName, bool isGPUTest) {
    115     if (SkCommandLineFlags::ShouldSkip(FLAGS_match, testName)) {
    116         return false;
    117     }
    118     if (!FLAGS_cpu && !isGPUTest) {
    119         return false;
    120     }
    121     if (!FLAGS_gpu && isGPUTest) {
    122         return false;
    123     }
    124     return true;
    125 }
    126 
    127 int test_main();
    128 int test_main() {
    129     SetupCrashHandler();
    130 
    131     SkAutoGraphics ag;
    132 
    133     {
    134         SkString header("Skia UnitTests:");
    135         if (!FLAGS_match.isEmpty()) {
    136             header.appendf(" --match");
    137             for (int index = 0; index < FLAGS_match.count(); ++index) {
    138                 header.appendf(" %s", FLAGS_match[index]);
    139             }
    140         }
    141         SkString tmpDir = skiatest::GetTmpDir();
    142         if (!tmpDir.isEmpty()) {
    143             header.appendf(" --tmpDir %s", tmpDir.c_str());
    144         }
    145         SkString resourcePath = GetResourcePath();
    146         if (!resourcePath.isEmpty()) {
    147             header.appendf(" --resourcePath %s", resourcePath.c_str());
    148         }
    149 #ifdef SK_DEBUG
    150         header.append(" SK_DEBUG");
    151 #else
    152         header.append(" SK_RELEASE");
    153 #endif
    154         if (FLAGS_veryVerbose) {
    155             header.appendf("\n");
    156         }
    157         SkDebugf("%s", header.c_str());
    158     }
    159 
    160 
    161     // Count tests first.
    162     int total = 0;
    163     int toRun = 0;
    164 
    165     for (const TestRegistry* iter = TestRegistry::Head(); iter;
    166          iter = iter->next()) {
    167         const Test& test = iter->factory();
    168         if (should_run(test.name, test.needsGpu)) {
    169             toRun++;
    170         }
    171         total++;
    172     }
    173 
    174     // Now run them.
    175     int skipCount = 0;
    176 
    177     SkTaskGroup::Enabler enabled(FLAGS_threads);
    178     SkTaskGroup cpuTests;
    179     SkTArray<const Test*> gpuTests;
    180 
    181     Status status(toRun);
    182     for (const TestRegistry* iter = TestRegistry::Head(); iter;
    183          iter = iter->next()) {
    184         const Test& test = iter->factory();
    185         if (!should_run(test.name, test.needsGpu)) {
    186             ++skipCount;
    187         } else if (test.needsGpu) {
    188             gpuTests.push_back(&test);
    189         } else {
    190             cpuTests.add(SkTestRunnable(test, &status));
    191         }
    192     }
    193 
    194     GrContextFactory* grContextFactoryPtr = nullptr;
    195 #if SK_SUPPORT_GPU
    196     // Give GPU tests a context factory if that makes sense on this machine.
    197     GrContextFactory grContextFactory;
    198     grContextFactoryPtr = &grContextFactory;
    199 
    200 #endif
    201 
    202     // Run GPU tests on this thread.
    203     for (int i = 0; i < gpuTests.count(); i++) {
    204         SkTestRunnable(*gpuTests[i], &status, grContextFactoryPtr)();
    205     }
    206 
    207     // Block until threaded tests finish.
    208     cpuTests.wait();
    209 
    210     if (FLAGS_verbose) {
    211         SkDebugf(
    212                 "\nFinished %d tests, %d failures, %d skipped. "
    213                 "(%d internal tests)",
    214                 toRun, status.failCount(), skipCount, status.testCount());
    215         if (gVerboseFinalize) {
    216             (*gVerboseFinalize)();
    217         }
    218     }
    219 
    220     SkDebugf("\n");
    221     return (status.failCount() == 0) ? 0 : 1;
    222 }
    223 
    224 #if !defined(SK_BUILD_FOR_IOS)
    225 int main(int argc, char** argv) {
    226     SkCommandLineFlags::Parse(argc, argv);
    227     return test_main();
    228 }
    229 #endif
    230