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