OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCommandLineFlags.h" | 8 #include "SkCommandLineFlags.h" |
9 #include "SkGraphics.h" | 9 #include "SkGraphics.h" |
| 10 #include "SkOSFile.h" |
10 #include "SkRunnable.h" | 11 #include "SkRunnable.h" |
11 #include "SkThreadPool.h" | |
12 #include "SkTArray.h" | 12 #include "SkTArray.h" |
13 #include "SkTemplates.h" | 13 #include "SkTemplates.h" |
| 14 #include "SkThreadPool.h" |
| 15 #include "SkTime.h" |
14 #include "Test.h" | 16 #include "Test.h" |
15 #include "SkOSFile.h" | |
16 | 17 |
17 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
18 #include "GrContext.h" | 19 #include "GrContext.h" |
19 #endif | 20 #endif |
20 | 21 |
21 using namespace skiatest; | 22 using namespace skiatest; |
22 | 23 |
23 // need to explicitly declare this, or we get some weird infinite loop llist | 24 // need to explicitly declare this, or we get some weird infinite loop llist |
24 template TestRegistry* TestRegistry::gHead; | 25 template TestRegistry* TestRegistry::gHead; |
25 | 26 |
26 class Iter { | 27 class Iter { |
27 public: | 28 public: |
28 Iter(Reporter* r) : fReporter(r) { | 29 Iter(Reporter* r) : fReporter(r) { |
29 r->ref(); | 30 r->ref(); |
| 31 this->reset(); |
| 32 } |
| 33 |
| 34 void reset() { |
30 fReg = TestRegistry::Head(); | 35 fReg = TestRegistry::Head(); |
31 } | 36 } |
32 | 37 |
33 ~Iter() { | 38 ~Iter() { |
34 fReporter->unref(); | 39 fReporter->unref(); |
35 } | 40 } |
36 | 41 |
37 Test* next() { | 42 Test* next() { |
38 if (fReg) { | 43 if (fReg) { |
39 TestRegistry::Factory fact = fReg->factory(); | 44 TestRegistry::Factory fact = fReg->factory(); |
40 fReg = fReg->next(); | 45 fReg = fReg->next(); |
41 Test* test = fact(NULL); | 46 Test* test = fact(NULL); |
42 test->setReporter(fReporter); | 47 test->setReporter(fReporter); |
43 return test; | 48 return test; |
44 } | 49 } |
45 return NULL; | 50 return NULL; |
46 } | 51 } |
47 | 52 |
48 static int Count() { | |
49 const TestRegistry* reg = TestRegistry::Head(); | |
50 int count = 0; | |
51 while (reg) { | |
52 count += 1; | |
53 reg = reg->next(); | |
54 } | |
55 return count; | |
56 } | |
57 | |
58 private: | 53 private: |
59 Reporter* fReporter; | 54 Reporter* fReporter; |
60 const TestRegistry* fReg; | 55 const TestRegistry* fReg; |
61 }; | 56 }; |
62 | 57 |
63 static const char* result2string(Reporter::Result result) { | 58 static const char* result2string(Reporter::Result result) { |
64 return result == Reporter::kPassed ? "passed" : "FAILED"; | 59 return result == Reporter::kPassed ? "passed" : "FAILED"; |
65 } | 60 } |
66 | 61 |
67 class DebugfReporter : public Reporter { | 62 class DebugfReporter : public Reporter { |
68 public: | 63 public: |
69 DebugfReporter(bool allowExtendedTest, bool allowThreaded) | 64 DebugfReporter(bool allowExtendedTest, bool allowThreaded) |
70 : fNextIndex(0) | 65 : fNextIndex(0) |
| 66 , fPending(0) |
71 , fTotal(0) | 67 , fTotal(0) |
72 , fAllowExtendedTest(allowExtendedTest) | 68 , fAllowExtendedTest(allowExtendedTest) |
73 , fAllowThreaded(allowThreaded) { | 69 , fAllowThreaded(allowThreaded) { |
74 } | 70 } |
75 | 71 |
76 void setTotal(int total) { | 72 void setTotal(int total) { |
77 fTotal = total; | 73 fTotal = total; |
78 } | 74 } |
79 | 75 |
80 virtual bool allowExtendedTest() const { | 76 virtual bool allowExtendedTest() const { |
81 return fAllowExtendedTest; | 77 return fAllowExtendedTest; |
82 } | 78 } |
83 | 79 |
84 virtual bool allowThreaded() const { | 80 virtual bool allowThreaded() const { |
85 return fAllowThreaded; | 81 return fAllowThreaded; |
86 } | 82 } |
87 | 83 |
88 protected: | 84 protected: |
89 virtual void onStart(Test* test) { | 85 virtual void onStart(Test* test) { |
90 const int index = sk_atomic_inc(&fNextIndex); | 86 const int index = sk_atomic_inc(&fNextIndex); |
91 SkDebugf("[%d/%d] %s...\n", index+1, fTotal, test->getName()); | 87 sk_atomic_inc(&fPending); |
| 88 SkDebugf("[%3d/%3d] (%d) %s\n", index+1, fTotal, fPending, test->getName
()); |
92 } | 89 } |
93 virtual void onReport(const char desc[], Reporter::Result result) { | 90 virtual void onReport(const char desc[], Reporter::Result result) { |
94 SkDebugf("\t%s: %s\n", result2string(result), desc); | 91 SkDebugf("\t%s: %s\n", result2string(result), desc); |
95 } | 92 } |
96 | 93 |
97 virtual void onEnd(Test* test) { | 94 virtual void onEnd(Test* test) { |
98 if (!test->passed()) { | 95 if (!test->passed()) { |
99 SkDebugf("---- FAILED\n"); | 96 SkDebugf("---- %s FAILED\n", test->getName()); |
| 97 } |
| 98 |
| 99 sk_atomic_dec(&fPending); |
| 100 if (fNextIndex == fTotal) { |
| 101 // Just waiting on straggler tests. Shame them by printing their na
me and runtime. |
| 102 SkDebugf(" (%d) %5.1fs %s\n", |
| 103 fPending, test->elapsedMs() / 1e3, test->getName()); |
100 } | 104 } |
101 } | 105 } |
102 | 106 |
103 private: | 107 private: |
104 int32_t fNextIndex; | 108 int32_t fNextIndex; |
| 109 int32_t fPending; |
105 int fTotal; | 110 int fTotal; |
106 bool fAllowExtendedTest; | 111 bool fAllowExtendedTest; |
107 bool fAllowThreaded; | 112 bool fAllowThreaded; |
108 }; | 113 }; |
109 | 114 |
110 static const char* make_canonical_dir_path(const char* path, SkString* storage)
{ | 115 static const char* make_canonical_dir_path(const char* path, SkString* storage)
{ |
111 if (path) { | 116 if (path) { |
112 // clean it up so it always has a trailing searator | 117 // clean it up so it always has a trailing searator |
113 size_t len = strlen(path); | 118 size_t len = strlen(path); |
114 if (0 == len) { | 119 if (0 == len) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 sk_atomic_inc(fFailCount); | 161 sk_atomic_inc(fFailCount); |
157 } | 162 } |
158 SkDELETE(this); | 163 SkDELETE(this); |
159 } | 164 } |
160 | 165 |
161 private: | 166 private: |
162 SkAutoTDelete<Test> fTest; | 167 SkAutoTDelete<Test> fTest; |
163 int32_t* fFailCount; | 168 int32_t* fFailCount; |
164 }; | 169 }; |
165 | 170 |
| 171 static bool shouldSkip(const char* testName) { |
| 172 return !FLAGS_match.isEmpty() && !strstr(testName, FLAGS_match[0]); |
| 173 } |
| 174 |
166 int tool_main(int argc, char** argv); | 175 int tool_main(int argc, char** argv); |
167 int tool_main(int argc, char** argv) { | 176 int tool_main(int argc, char** argv) { |
168 SkCommandLineFlags::SetUsage(""); | 177 SkCommandLineFlags::SetUsage(""); |
169 SkCommandLineFlags::Parse(argc, argv); | 178 SkCommandLineFlags::Parse(argc, argv); |
170 | 179 |
171 if (!FLAGS_tmpDir.isEmpty()) { | 180 if (!FLAGS_tmpDir.isEmpty()) { |
172 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); | 181 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); |
173 } | 182 } |
174 if (!FLAGS_resourcePath.isEmpty()) { | 183 if (!FLAGS_resourcePath.isEmpty()) { |
175 make_canonical_dir_path(FLAGS_resourcePath[0], &gResourcePath); | 184 make_canonical_dir_path(FLAGS_resourcePath[0], &gResourcePath); |
(...skipping 25 matching lines...) Expand all Loading... |
201 header.append(" SK_SCALAR_IS_FIXED"); | 210 header.append(" SK_SCALAR_IS_FIXED"); |
202 #else | 211 #else |
203 header.append(" SK_SCALAR_IS_FLOAT"); | 212 header.append(" SK_SCALAR_IS_FLOAT"); |
204 #endif | 213 #endif |
205 SkDebugf("%s\n", header.c_str()); | 214 SkDebugf("%s\n", header.c_str()); |
206 } | 215 } |
207 | 216 |
208 DebugfReporter reporter(FLAGS_extendedTest, FLAGS_threaded); | 217 DebugfReporter reporter(FLAGS_extendedTest, FLAGS_threaded); |
209 Iter iter(&reporter); | 218 Iter iter(&reporter); |
210 | 219 |
211 const int count = Iter::Count(); | 220 // Count tests first. |
212 reporter.setTotal(count); | 221 int total = 0; |
| 222 int toRun = 0; |
| 223 Test* test; |
| 224 while ((test = iter.next()) != NULL) { |
| 225 SkAutoTDelete<Test> owned(test); |
| 226 if(!shouldSkip(test->getName())) { |
| 227 toRun++; |
| 228 } |
| 229 total++; |
| 230 } |
| 231 reporter.setTotal(toRun); |
| 232 |
| 233 // Now run them. |
| 234 iter.reset(); |
213 int32_t failCount = 0; | 235 int32_t failCount = 0; |
214 int skipCount = 0; | 236 int skipCount = 0; |
215 | 237 |
216 SkAutoTDelete<SkThreadPool> threadpool(SkNEW_ARGS(SkThreadPool, (FLAGS_threa
ds))); | 238 SkAutoTDelete<SkThreadPool> threadpool(SkNEW_ARGS(SkThreadPool, (FLAGS_threa
ds))); |
217 SkTArray<Test*> unsafeTests; // Always passes ownership to an SkTestRunnabl
e | 239 SkTArray<Test*> unsafeTests; // Always passes ownership to an SkTestRunnabl
e |
218 for (int i = 0; i < count; i++) { | 240 for (int i = 0; i < total; i++) { |
219 SkAutoTDelete<Test> test(iter.next()); | 241 SkAutoTDelete<Test> test(iter.next()); |
220 if (!FLAGS_match.isEmpty() && !strstr(test->getName(), FLAGS_match[0]))
{ | 242 if (shouldSkip(test->getName())) { |
221 ++skipCount; | 243 ++skipCount; |
222 } else if (!test->isThreadsafe()) { | 244 } else if (!test->isThreadsafe()) { |
223 unsafeTests.push_back() = test.detach(); | 245 unsafeTests.push_back() = test.detach(); |
224 } else { | 246 } else { |
225 threadpool->add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCoun
t))); | 247 threadpool->add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCoun
t))); |
226 } | 248 } |
227 } | 249 } |
228 | 250 |
229 // Run the tests that aren't threadsafe. | 251 // Run the tests that aren't threadsafe. |
230 for (int i = 0; i < unsafeTests.count(); i++) { | 252 for (int i = 0; i < unsafeTests.count(); i++) { |
231 SkNEW_ARGS(SkTestRunnable, (unsafeTests[i], &failCount))->run(); | 253 SkNEW_ARGS(SkTestRunnable, (unsafeTests[i], &failCount))->run(); |
232 } | 254 } |
233 | 255 |
234 // Blocks until threaded tests finish. | 256 // Blocks until threaded tests finish. |
235 threadpool.free(); | 257 threadpool.free(); |
236 | 258 |
237 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", | 259 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", |
238 count, failCount, skipCount); | 260 toRun, failCount, skipCount); |
239 const int testCount = reporter.countTests(); | 261 const int testCount = reporter.countTests(); |
240 if (FLAGS_verbose && testCount > 0) { | 262 if (FLAGS_verbose && testCount > 0) { |
241 SkDebugf("Ran %d Internal tests.\n", testCount); | 263 SkDebugf("Ran %d Internal tests.\n", testCount); |
242 } | 264 } |
243 #if SK_SUPPORT_GPU | 265 #if SK_SUPPORT_GPU |
244 | 266 |
245 #if GR_CACHE_STATS | 267 #if GR_CACHE_STATS |
246 GrContext *gr = GpuTest::GetContext(); | 268 GrContext *gr = GpuTest::GetContext(); |
247 | 269 |
248 gr->printCacheStats(); | 270 gr->printCacheStats(); |
249 #endif | 271 #endif |
250 | 272 |
251 #endif | 273 #endif |
252 | 274 |
253 SkGraphics::Term(); | 275 SkGraphics::Term(); |
254 GpuTest::DestroyContexts(); | 276 GpuTest::DestroyContexts(); |
255 | 277 |
256 return (failCount == 0) ? 0 : 1; | 278 return (failCount == 0) ? 0 : 1; |
257 } | 279 } |
258 | 280 |
259 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 281 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
260 int main(int argc, char * const argv[]) { | 282 int main(int argc, char * const argv[]) { |
261 return tool_main(argc, (char**) argv); | 283 return tool_main(argc, (char**) argv); |
262 } | 284 } |
263 #endif | 285 #endif |
OLD | NEW |