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