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 "SkRunnable.h" |
| 11 #include "SkThreadPool.h" |
| 12 #include "SkTArray.h" |
| 13 #include "SkTemplates.h" |
10 #include "Test.h" | 14 #include "Test.h" |
11 #include "SkOSFile.h" | 15 #include "SkOSFile.h" |
12 | 16 |
13 #if SK_SUPPORT_GPU | 17 #if SK_SUPPORT_GPU |
14 #include "GrContext.h" | 18 #include "GrContext.h" |
15 #endif | 19 #endif |
16 | 20 |
17 using namespace skiatest; | 21 using namespace skiatest; |
18 | 22 |
19 // need to explicitly declare this, or we get some weird infinite loop llist | 23 // need to explicitly declare this, or we get some weird infinite loop llist |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 const TestRegistry* fReg; | 60 const TestRegistry* fReg; |
57 }; | 61 }; |
58 | 62 |
59 static const char* result2string(Reporter::Result result) { | 63 static const char* result2string(Reporter::Result result) { |
60 return result == Reporter::kPassed ? "passed" : "FAILED"; | 64 return result == Reporter::kPassed ? "passed" : "FAILED"; |
61 } | 65 } |
62 | 66 |
63 class DebugfReporter : public Reporter { | 67 class DebugfReporter : public Reporter { |
64 public: | 68 public: |
65 DebugfReporter(bool allowExtendedTest, bool allowThreaded) | 69 DebugfReporter(bool allowExtendedTest, bool allowThreaded) |
66 : fIndex(0) | 70 : fNextIndex(0) |
67 , fTotal(0) | 71 , fTotal(0) |
68 , fAllowExtendedTest(allowExtendedTest) | 72 , fAllowExtendedTest(allowExtendedTest) |
69 , fAllowThreaded(allowThreaded) { | 73 , fAllowThreaded(allowThreaded) { |
70 } | 74 } |
71 | 75 |
72 void setIndexOfTotal(int index, int total) { | 76 void setTotal(int total) { |
73 fIndex = index; | |
74 fTotal = total; | 77 fTotal = total; |
75 } | 78 } |
76 | 79 |
77 virtual bool allowExtendedTest() const { | 80 virtual bool allowExtendedTest() const { |
78 return fAllowExtendedTest; | 81 return fAllowExtendedTest; |
79 } | 82 } |
80 | 83 |
81 virtual bool allowThreaded() const { | 84 virtual bool allowThreaded() const { |
82 return fAllowThreaded; | 85 return fAllowThreaded; |
83 } | 86 } |
84 | 87 |
85 protected: | 88 protected: |
86 virtual void onStart(Test* test) { | 89 virtual void onStart(Test* test) { |
87 SkDebugf("[%d/%d] %s...\n", fIndex+1, fTotal, test->getName()); | 90 const int index = sk_atomic_inc(&fNextIndex); |
| 91 SkDebugf("[%d/%d] %s...\n", index+1, fTotal, test->getName()); |
88 } | 92 } |
89 virtual void onReport(const char desc[], Reporter::Result result) { | 93 virtual void onReport(const char desc[], Reporter::Result result) { |
90 SkDebugf("\t%s: %s\n", result2string(result), desc); | 94 SkDebugf("\t%s: %s\n", result2string(result), desc); |
91 } | 95 } |
92 virtual void onEnd(Test*) { | 96 |
93 if (!this->getCurrSuccess()) { | 97 virtual void onEnd(Test* test) { |
94 SkDebugf("---- FAILED\n"); | 98 if (!test->passed()) { |
| 99 SkDebugf("---- FAILED\n"); |
95 } | 100 } |
96 } | 101 } |
| 102 |
97 private: | 103 private: |
98 int fIndex, fTotal; | 104 int32_t fNextIndex; |
| 105 int fTotal; |
99 bool fAllowExtendedTest; | 106 bool fAllowExtendedTest; |
100 bool fAllowThreaded; | 107 bool fAllowThreaded; |
101 }; | 108 }; |
102 | 109 |
103 static const char* make_canonical_dir_path(const char* path, SkString* storage)
{ | 110 static const char* make_canonical_dir_path(const char* path, SkString* storage)
{ |
104 if (path) { | 111 if (path) { |
105 // clean it up so it always has a trailing searator | 112 // clean it up so it always has a trailing searator |
106 size_t len = strlen(path); | 113 size_t len = strlen(path); |
107 if (0 == len) { | 114 if (0 == len) { |
108 path = NULL; | 115 path = NULL; |
(...skipping 16 matching lines...) Expand all Loading... |
125 static SkString gResourcePath; | 132 static SkString gResourcePath; |
126 | 133 |
127 const SkString& Test::GetResourcePath() { | 134 const SkString& Test::GetResourcePath() { |
128 return gResourcePath; | 135 return gResourcePath; |
129 } | 136 } |
130 | 137 |
131 DEFINE_string2(match, m, NULL, "substring of test name to run."); | 138 DEFINE_string2(match, m, NULL, "substring of test name to run."); |
132 DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); | 139 DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); |
133 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); | 140 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); |
134 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); | 141 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); |
135 DEFINE_bool2(threaded, z, false, "allow tests to use multiple threads."); | 142 DEFINE_bool2(threaded, z, false, "allow tests to use multiple threads internally
."); |
136 DEFINE_bool2(verbose, v, false, "enable verbose output."); | 143 DEFINE_bool2(verbose, v, false, "enable verbose output."); |
| 144 DEFINE_int32(threads, 8, |
| 145 "If >0, run threadsafe tests on a threadpool with this many threads
."); |
| 146 |
| 147 // Deletes self when run. |
| 148 class SkTestRunnable : public SkRunnable { |
| 149 public: |
| 150 // Takes ownership of test. |
| 151 SkTestRunnable(Test* test, int32_t* failCount) : fTest(test), fFailCount(failC
ount) {} |
| 152 |
| 153 virtual void run() { |
| 154 fTest->run(); |
| 155 if(!fTest->passed()) { |
| 156 sk_atomic_inc(fFailCount); |
| 157 } |
| 158 SkDELETE(this); |
| 159 } |
| 160 |
| 161 private: |
| 162 SkAutoTDelete<Test> fTest; |
| 163 int32_t* fFailCount; |
| 164 }; |
137 | 165 |
138 int tool_main(int argc, char** argv); | 166 int tool_main(int argc, char** argv); |
139 int tool_main(int argc, char** argv) { | 167 int tool_main(int argc, char** argv) { |
140 SkCommandLineFlags::SetUsage(""); | 168 SkCommandLineFlags::SetUsage(""); |
141 SkCommandLineFlags::Parse(argc, argv); | 169 SkCommandLineFlags::Parse(argc, argv); |
142 | 170 |
143 if (!FLAGS_tmpDir.isEmpty()) { | 171 if (!FLAGS_tmpDir.isEmpty()) { |
144 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); | 172 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); |
145 } | 173 } |
146 if (!FLAGS_resourcePath.isEmpty()) { | 174 if (!FLAGS_resourcePath.isEmpty()) { |
(...skipping 25 matching lines...) Expand all Loading... |
172 #ifdef SK_SCALAR_IS_FIXED | 200 #ifdef SK_SCALAR_IS_FIXED |
173 header.append(" SK_SCALAR_IS_FIXED"); | 201 header.append(" SK_SCALAR_IS_FIXED"); |
174 #else | 202 #else |
175 header.append(" SK_SCALAR_IS_FLOAT"); | 203 header.append(" SK_SCALAR_IS_FLOAT"); |
176 #endif | 204 #endif |
177 SkDebugf("%s\n", header.c_str()); | 205 SkDebugf("%s\n", header.c_str()); |
178 } | 206 } |
179 | 207 |
180 DebugfReporter reporter(FLAGS_extendedTest, FLAGS_threaded); | 208 DebugfReporter reporter(FLAGS_extendedTest, FLAGS_threaded); |
181 Iter iter(&reporter); | 209 Iter iter(&reporter); |
182 Test* test; | |
183 | 210 |
184 const int count = Iter::Count(); | 211 const int count = Iter::Count(); |
185 int index = 0; | 212 reporter.setTotal(count); |
186 int failCount = 0; | 213 int32_t failCount = 0; |
187 int skipCount = 0; | 214 int skipCount = 0; |
188 while ((test = iter.next()) != NULL) { | 215 |
189 reporter.setIndexOfTotal(index, count); | 216 SkAutoTDelete<SkThreadPool> threadpool(SkNEW_ARGS(SkThreadPool, (FLAGS_threa
ds))); |
| 217 SkTArray<Test*> unsafeTests; // Always passes ownership to an SkTestRunnabl
e |
| 218 for (int i = 0; i < count; i++) { |
| 219 SkAutoTDelete<Test> test(iter.next()); |
190 if (!FLAGS_match.isEmpty() && !strstr(test->getName(), FLAGS_match[0]))
{ | 220 if (!FLAGS_match.isEmpty() && !strstr(test->getName(), FLAGS_match[0]))
{ |
191 ++skipCount; | 221 ++skipCount; |
| 222 } else if (!test->isThreadsafe()) { |
| 223 unsafeTests.push_back() = test.detach(); |
192 } else { | 224 } else { |
193 if (!test->run()) { | 225 threadpool->add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCoun
t))); |
194 ++failCount; | |
195 } | |
196 } | 226 } |
197 SkDELETE(test); | |
198 index += 1; | |
199 } | 227 } |
200 | 228 |
| 229 // Run the tests that aren't threadsafe. |
| 230 for (int i = 0; i < unsafeTests.count(); i++) { |
| 231 SkNEW_ARGS(SkTestRunnable, (unsafeTests[i], &failCount))->run(); |
| 232 } |
| 233 |
| 234 // Blocks until threaded tests finish. |
| 235 threadpool.free(); |
| 236 |
201 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", | 237 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", |
202 count, failCount, skipCount); | 238 count, failCount, skipCount); |
203 int testCount = reporter.countTests(); | 239 const int testCount = reporter.countTests(); |
204 if (FLAGS_verbose && testCount > 0) { | 240 if (FLAGS_verbose && testCount > 0) { |
205 SkDebugf("Ran %d Internal tests.\n", testCount); | 241 SkDebugf("Ran %d Internal tests.\n", testCount); |
206 } | 242 } |
207 #if SK_SUPPORT_GPU | 243 #if SK_SUPPORT_GPU |
208 | 244 |
209 #if GR_CACHE_STATS | 245 #if GR_CACHE_STATS |
210 GrContext *gr = GpuTest::GetContext(); | 246 GrContext *gr = GpuTest::GetContext(); |
211 | 247 |
212 gr->printCacheStats(); | 248 gr->printCacheStats(); |
213 #endif | 249 #endif |
214 | 250 |
215 #endif | 251 #endif |
216 | 252 |
217 SkGraphics::Term(); | 253 SkGraphics::Term(); |
218 GpuTest::DestroyContexts(); | 254 GpuTest::DestroyContexts(); |
219 | 255 |
220 return (failCount == 0) ? 0 : 1; | 256 return (failCount == 0) ? 0 : 1; |
221 } | 257 } |
222 | 258 |
223 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 259 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
224 int main(int argc, char * const argv[]) { | 260 int main(int argc, char * const argv[]) { |
225 return tool_main(argc, (char**) argv); | 261 return tool_main(argc, (char**) argv); |
226 } | 262 } |
227 #endif | 263 #endif |
OLD | NEW |