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