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 "SkCommandLineFlags.h" 12 #include "SkGraphics.h" 13 #include "SkOSFile.h" 14 #include "SkTArray.h" 15 #include "SkTemplates.h" 16 #include "SkThreadPool.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_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \ 28 "Multiple matches may be separated by spaces.\n" \ 29 "~ causes a matching test to always be skipped\n" \ 30 "^ requires the start of the test to match\n" \ 31 "$ requires the end of the test to match\n" \ 32 "^ and $ requires an exact match\n" \ 33 "If a test does not match any list entry,\n" \ 34 "it is skipped unless some list entry starts with ~"); 35 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); 36 DEFINE_bool2(leaks, l, false, "show leaked ref cnt'd objects."); 37 DEFINE_bool2(single, z, false, "run tests on a single thread internally."); 38 DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver."); 39 DEFINE_bool2(veryVerbose, V, false, "tell individual tests to be verbose."); 40 DEFINE_bool(cpu, true, "whether or not to run CPU tests."); 41 DEFINE_bool(gpu, true, "whether or not to run GPU tests."); 42 DEFINE_int32(threads, SkThreadPool::kThreadPerCore, 43 "Run threadsafe tests on a threadpool with this many threads."); 44 45 // need to explicitly declare this, or we get some weird infinite loop llist 46 template TestRegistry* TestRegistry::gHead; 47 48 class Iter { 49 public: 50 Iter() { this->reset(); } 51 void reset() { fReg = TestRegistry::Head(); } 52 53 Test* next(Reporter* r) { 54 if (fReg) { 55 TestRegistry::Factory fact = fReg->factory(); 56 fReg = fReg->next(); 57 Test* test = fact(NULL); 58 test->setReporter(r); 59 return test; 60 } 61 return NULL; 62 } 63 64 private: 65 const TestRegistry* fReg; 66 }; 67 68 class DebugfReporter : public Reporter { 69 public: 70 explicit DebugfReporter(int total) : fDone(0), fTotal(total) {} 71 72 virtual bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_extendedTest; } 73 virtual bool allowThreaded() const SK_OVERRIDE { return !FLAGS_single; } 74 virtual bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; } 75 76 protected: 77 virtual void onReportFailed(const SkString& desc) SK_OVERRIDE { 78 SkDebugf("\nFAILED: %s", desc.c_str()); 79 } 80 81 virtual void onEnd(Test* test) SK_OVERRIDE { 82 const int done = 1 + sk_atomic_inc(&fDone); 83 84 if (!test->passed()) { 85 SkDebugf("\n---- %s FAILED", test->getName()); 86 } 87 88 SkString prefix(kSkOverwriteLine); 89 SkString time; 90 if (FLAGS_verbose) { 91 prefix.printf("\n"); 92 time.printf("%5dms ", test->elapsedMs()); 93 } 94 SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(), test->getName()); 95 } 96 97 private: 98 int32_t fDone; // atomic 99 const int fTotal; 100 }; 101 102 // Deletes self when run. 103 class SkTestRunnable : public SkRunnable { 104 public: 105 // Takes ownership of test. 106 SkTestRunnable(Test* test, int32_t* failCount) : fTest(test), fFailCount(failCount) {} 107 108 virtual void run() { 109 fTest->run(); 110 if(!fTest->passed()) { 111 sk_atomic_inc(fFailCount); 112 } 113 SkDELETE(this); 114 } 115 116 private: 117 SkAutoTDelete<Test> fTest; 118 int32_t* fFailCount; 119 }; 120 121 static bool should_run(const char* testName, bool isGPUTest) { 122 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, testName)) { 123 return false; 124 } 125 if (!FLAGS_cpu && !isGPUTest) { 126 return false; 127 } 128 if (!FLAGS_gpu && isGPUTest) { 129 return false; 130 } 131 return true; 132 } 133 134 int tool_main(int argc, char** argv); 135 int tool_main(int argc, char** argv) { 136 SetupCrashHandler(); 137 SkCommandLineFlags::SetUsage(""); 138 SkCommandLineFlags::Parse(argc, argv); 139 140 #if SK_ENABLE_INST_COUNT 141 if (FLAGS_leaks) { 142 gPrintInstCount = true; 143 } 144 #endif 145 146 SkGraphics::Init(); 147 148 { 149 SkString header("Skia UnitTests:"); 150 if (!FLAGS_match.isEmpty()) { 151 header.appendf(" --match"); 152 for (int index = 0; index < FLAGS_match.count(); ++index) { 153 header.appendf(" %s", FLAGS_match[index]); 154 } 155 } 156 SkString tmpDir = Test::GetTmpDir(); 157 if (!tmpDir.isEmpty()) { 158 header.appendf(" --tmpDir %s", tmpDir.c_str()); 159 } 160 SkString resourcePath = GetResourcePath(); 161 if (!resourcePath.isEmpty()) { 162 header.appendf(" --resourcePath %s", resourcePath.c_str()); 163 } 164 #ifdef SK_DEBUG 165 header.append(" SK_DEBUG"); 166 #else 167 header.append(" SK_RELEASE"); 168 #endif 169 header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8); 170 if (FLAGS_veryVerbose) { 171 header.appendf("\n"); 172 } 173 SkDebugf(header.c_str()); 174 } 175 176 177 // Count tests first. 178 int total = 0; 179 int toRun = 0; 180 Test* test; 181 182 Iter iter; 183 while ((test = iter.next(NULL/*reporter not needed*/)) != NULL) { 184 SkAutoTDelete<Test> owned(test); 185 if (should_run(test->getName(), test->isGPUTest())) { 186 toRun++; 187 } 188 total++; 189 } 190 191 // Now run them. 192 iter.reset(); 193 int32_t failCount = 0; 194 int skipCount = 0; 195 196 SkThreadPool threadpool(FLAGS_threads); 197 SkTArray<Test*> gpuTests; // Always passes ownership to an SkTestRunnable 198 199 DebugfReporter reporter(toRun); 200 for (int i = 0; i < total; i++) { 201 SkAutoTDelete<Test> test(iter.next(&reporter)); 202 if (!should_run(test->getName(), test->isGPUTest())) { 203 ++skipCount; 204 } else if (test->isGPUTest()) { 205 gpuTests.push_back() = test.detach(); 206 } else { 207 threadpool.add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCount))); 208 } 209 } 210 211 #if SK_SUPPORT_GPU 212 // Give GPU tests a context factory if that makes sense on this machine. 213 GrContextFactory grContextFactory; 214 for (int i = 0; i < gpuTests.count(); i++) { 215 gpuTests[i]->setGrContextFactory(&grContextFactory); 216 } 217 #endif 218 219 // Run GPU tests on this thread. 220 for (int i = 0; i < gpuTests.count(); i++) { 221 SkNEW_ARGS(SkTestRunnable, (gpuTests[i], &failCount))->run(); 222 } 223 224 // Block until threaded tests finish. 225 threadpool.wait(); 226 227 if (FLAGS_verbose) { 228 SkDebugf("\nFinished %d tests, %d failures, %d skipped. (%d internal tests)", 229 toRun, failCount, skipCount, reporter.countTests()); 230 } 231 SkGraphics::Term(); 232 233 SkDebugf("\n"); 234 return (failCount == 0) ? 0 : 1; 235 } 236 237 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 238 int main(int argc, char * const argv[]) { 239 return tool_main(argc, (char**) argv); 240 } 241 #endif 242