• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
Iter()50     Iter() { this->reset(); }
reset()51     void reset() { fReg = TestRegistry::Head(); }
52 
next(Reporter * r)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:
DebugfReporter(int total)70     explicit DebugfReporter(int total) : fDone(0), fTotal(total) {}
71 
allowExtendedTest() const72     virtual bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_extendedTest; }
allowThreaded() const73     virtual bool allowThreaded()     const SK_OVERRIDE { return !FLAGS_single; }
verbose() const74     virtual bool verbose()           const SK_OVERRIDE { return FLAGS_veryVerbose; }
75 
76 protected:
onReportFailed(const SkString & desc)77     virtual void onReportFailed(const SkString& desc) SK_OVERRIDE {
78         SkDebugf("\nFAILED: %s", desc.c_str());
79     }
80 
onEnd(Test * test)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.
SkTestRunnable(Test * test,int32_t * failCount)106   SkTestRunnable(Test* test, int32_t* failCount) : fTest(test), fFailCount(failCount) {}
107 
run()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 
should_run(const char * testName,bool isGPUTest)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);
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)
main(int argc,char * const argv[])238 int main(int argc, char * const argv[]) {
239     return tool_main(argc, (char**) argv);
240 }
241 #endif
242