skia_test.cpp revision 16cfe40276bfb0a4d98c9ad995b8e5b134a49b19
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 "SkCommandLineFlags.h" 9#include "SkGraphics.h" 10#include "Test.h" 11#include "SkOSFile.h" 12 13#if SK_SUPPORT_GPU 14#include "GrContext.h" 15#endif 16 17using namespace skiatest; 18 19// need to explicitly declare this, or we get some weird infinite loop llist 20template TestRegistry* TestRegistry::gHead; 21 22class Iter { 23public: 24 Iter(Reporter* r) : fReporter(r) { 25 r->ref(); 26 fReg = TestRegistry::Head(); 27 } 28 29 ~Iter() { 30 fReporter->unref(); 31 } 32 33 Test* next() { 34 if (fReg) { 35 TestRegistry::Factory fact = fReg->factory(); 36 fReg = fReg->next(); 37 Test* test = fact(NULL); 38 test->setReporter(fReporter); 39 return test; 40 } 41 return NULL; 42 } 43 44 static int Count() { 45 const TestRegistry* reg = TestRegistry::Head(); 46 int count = 0; 47 while (reg) { 48 count += 1; 49 reg = reg->next(); 50 } 51 return count; 52 } 53 54private: 55 Reporter* fReporter; 56 const TestRegistry* fReg; 57}; 58 59static const char* result2string(Reporter::Result result) { 60 return result == Reporter::kPassed ? "passed" : "FAILED"; 61} 62 63class DebugfReporter : public Reporter { 64public: 65 DebugfReporter(bool allowExtendedTest, bool allowThreaded) 66 : fIndex(0) 67 , fTotal(0) 68 , fAllowExtendedTest(allowExtendedTest) 69 , fAllowThreaded(allowThreaded) { 70 } 71 72 void setIndexOfTotal(int index, int total) { 73 fIndex = index; 74 fTotal = total; 75 } 76 77 virtual bool allowExtendedTest() const { 78 return fAllowExtendedTest; 79 } 80 81 virtual bool allowThreaded() const { 82 return fAllowThreaded; 83 } 84 85protected: 86 virtual void onStart(Test* test) { 87 SkDebugf("[%d/%d] %s...\n", fIndex+1, fTotal, test->getName()); 88 } 89 virtual void onReport(const char desc[], Reporter::Result result) { 90 SkDebugf("\t%s: %s\n", result2string(result), desc); 91 } 92 virtual void onEnd(Test*) { 93 if (!this->getCurrSuccess()) { 94 SkDebugf("---- FAILED\n"); 95 } 96 } 97private: 98 int fIndex, fTotal; 99 bool fAllowExtendedTest; 100 bool fAllowThreaded; 101}; 102 103static const char* make_canonical_dir_path(const char* path, SkString* storage) { 104 if (path) { 105 // clean it up so it always has a trailing searator 106 size_t len = strlen(path); 107 if (0 == len) { 108 path = NULL; 109 } else if (SkPATH_SEPARATOR != path[len - 1]) { 110 // resize to len + 1, to make room for searator 111 storage->set(path, len + 1); 112 storage->writable_str()[len] = SkPATH_SEPARATOR; 113 path = storage->c_str(); 114 } 115 } 116 return path; 117} 118 119static SkString gTmpDir; 120 121const SkString& Test::GetTmpDir() { 122 return gTmpDir; 123} 124 125static SkString gResourcePath; 126 127const SkString& Test::GetResourcePath() { 128 return gResourcePath; 129} 130 131DEFINE_string2(match, m, NULL, "substring of test name to run."); 132DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); 133DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); 134DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); 135DEFINE_bool2(threaded, z, false, "allow tests to use multiple threads."); 136DEFINE_bool2(verbose, v, false, "enable verbose output."); 137 138int tool_main(int argc, char** argv); 139int tool_main(int argc, char** argv) { 140 SkCommandLineFlags::SetUsage(""); 141 SkCommandLineFlags::Parse(argc, argv); 142 143 if (!FLAGS_tmpDir.isEmpty()) { 144 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); 145 } 146 if (!FLAGS_resourcePath.isEmpty()) { 147 make_canonical_dir_path(FLAGS_resourcePath[0], &gResourcePath); 148 } 149 150#if SK_ENABLE_INST_COUNT 151 gPrintInstCount = true; 152#endif 153 154 SkGraphics::Init(); 155 156 { 157 SkString header("Skia UnitTests:"); 158 if (!FLAGS_match.isEmpty()) { 159 header.appendf(" --match %s", FLAGS_match[0]); 160 } 161 if (!gTmpDir.isEmpty()) { 162 header.appendf(" --tmpDir %s", gTmpDir.c_str()); 163 } 164 if (!gResourcePath.isEmpty()) { 165 header.appendf(" --resourcePath %s", gResourcePath.c_str()); 166 } 167#ifdef SK_DEBUG 168 header.append(" SK_DEBUG"); 169#else 170 header.append(" SK_RELEASE"); 171#endif 172#ifdef SK_SCALAR_IS_FIXED 173 header.append(" SK_SCALAR_IS_FIXED"); 174#else 175 header.append(" SK_SCALAR_IS_FLOAT"); 176#endif 177 SkDebugf("%s\n", header.c_str()); 178 } 179 180 DebugfReporter reporter(FLAGS_extendedTest, FLAGS_threaded); 181 Iter iter(&reporter); 182 Test* test; 183 184 const int count = Iter::Count(); 185 int index = 0; 186 int failCount = 0; 187 int skipCount = 0; 188 while ((test = iter.next()) != NULL) { 189 reporter.setIndexOfTotal(index, count); 190 if (!FLAGS_match.isEmpty() && !strstr(test->getName(), FLAGS_match[0])) { 191 ++skipCount; 192 } else { 193 if (!test->run()) { 194 ++failCount; 195 } 196 } 197 SkDELETE(test); 198 index += 1; 199 } 200 201 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", 202 count, failCount, skipCount); 203 int testCount = reporter.countTests(); 204 if (FLAGS_verbose && testCount > 0) { 205 SkDebugf("Ran %d Internal tests.\n", testCount); 206 } 207#if SK_SUPPORT_GPU 208 209#if GR_CACHE_STATS 210 GrContext *gr = GpuTest::GetContext(); 211 212 gr->printCacheStats(); 213#endif 214 215#endif 216 217 SkGraphics::Term(); 218 GpuTest::DestroyContexts(); 219 220 return (failCount == 0) ? 0 : 1; 221} 222 223#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 224int main(int argc, char * const argv[]) { 225 return tool_main(argc, (char**) argv); 226} 227#endif 228