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 "SkTScopedPtr.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) | 69 DebugfReporter(bool allowExtendedTest) |
66 : fIndex(0) | 70 : fNextIndex(0) |
67 , fTotal(0) | 71 , fTotal(0) |
68 , fAllowExtendedTest(allowExtendedTest) { | 72 , fAllowExtendedTest(allowExtendedTest) { |
69 } | 73 } |
70 | 74 |
71 void setIndexOfTotal(int index, int total) { | 75 void setTotal(int total) { |
72 fIndex = index; | |
73 fTotal = total; | 76 fTotal = total; |
74 } | 77 } |
75 | 78 |
76 virtual bool allowExtendedTest() const { | 79 virtual bool allowExtendedTest() const { |
77 return fAllowExtendedTest; | 80 return fAllowExtendedTest; |
78 } | 81 } |
79 | 82 |
80 protected: | 83 protected: |
81 virtual void onStart(Test* test) { | 84 virtual void onStart(Test* test) { |
82 SkDebugf("[%d/%d] %s...\n", fIndex+1, fTotal, test->getName()); | 85 const int index = sk_atomic_inc(&fNextIndex); |
86 SkDebugf("[%d/%d] %s...\n", index+1, fTotal, test->getName()); | |
83 } | 87 } |
84 virtual void onReport(const char desc[], Reporter::Result result) { | 88 virtual void onReport(const char desc[], Reporter::Result result) { |
85 SkDebugf("\t%s: %s\n", result2string(result), desc); | 89 SkDebugf("\t%s: %s\n", result2string(result), desc); |
86 } | 90 } |
87 virtual void onEnd(Test*) { | 91 |
88 if (!this->getCurrSuccess()) { | 92 virtual void onEnd(Test* test) { |
89 SkDebugf("---- FAILED\n"); | 93 if (!test->passed()) { |
94 SkDebugf("---- FAILED\n"); | |
90 } | 95 } |
91 } | 96 } |
97 | |
92 private: | 98 private: |
93 int fIndex, fTotal; | 99 int fNextIndex, fTotal; |
94 bool fAllowExtendedTest; | 100 bool fAllowExtendedTest; |
95 }; | 101 }; |
96 | 102 |
97 static const char* make_canonical_dir_path(const char* path, SkString* storage) { | 103 static const char* make_canonical_dir_path(const char* path, SkString* storage) { |
98 if (path) { | 104 if (path) { |
99 // clean it up so it always has a trailing searator | 105 // clean it up so it always has a trailing searator |
100 size_t len = strlen(path); | 106 size_t len = strlen(path); |
101 if (0 == len) { | 107 if (0 == len) { |
102 path = NULL; | 108 path = NULL; |
103 } else if (SkPATH_SEPARATOR != path[len - 1]) { | 109 } else if (SkPATH_SEPARATOR != path[len - 1]) { |
(...skipping 16 matching lines...) Expand all Loading... | |
120 | 126 |
121 const SkString& Test::GetResourcePath() { | 127 const SkString& Test::GetResourcePath() { |
122 return gResourcePath; | 128 return gResourcePath; |
123 } | 129 } |
124 | 130 |
125 DEFINE_string2(match, m, NULL, "substring of test name to run."); | 131 DEFINE_string2(match, m, NULL, "substring of test name to run."); |
126 DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); | 132 DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use."); |
127 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); | 133 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); |
128 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); | 134 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps."); |
129 DEFINE_bool2(verbose, v, false, "enable verbose output."); | 135 DEFINE_bool2(verbose, v, false, "enable verbose output."); |
136 DEFINE_int32(threads, 8, | |
137 "If >0, run threadsafe tests on a threadpool with this many threads ."); | |
138 | |
139 // Deletes self when run. | |
140 class SkTestRunnable : public SkRunnable { | |
141 public: | |
142 // Takes ownership of test. | |
143 SkTestRunnable(Test* test, int* failCount) : fTest(test), fFailCount(failCount ) {} | |
144 | |
145 virtual void run() { | |
146 fTest->run(); | |
147 if(!fTest->passed()) { | |
148 sk_atomic_inc(fFailCount); | |
149 } | |
150 SkDELETE(this); | |
151 } | |
152 | |
153 private: | |
154 SkTScopedPtr<Test> fTest; | |
155 int* fFailCount; | |
scroggo
2013/04/17 17:34:52
Shouldn't this be int32_t since it's passed to sk_
mtklein
2013/04/17 18:13:59
Done.
| |
156 }; | |
130 | 157 |
131 int tool_main(int argc, char** argv); | 158 int tool_main(int argc, char** argv); |
132 int tool_main(int argc, char** argv) { | 159 int tool_main(int argc, char** argv) { |
133 SkCommandLineFlags::SetUsage(""); | 160 SkCommandLineFlags::SetUsage(""); |
134 SkCommandLineFlags::Parse(argc, argv); | 161 SkCommandLineFlags::Parse(argc, argv); |
135 | 162 |
136 if (!FLAGS_tmpDir.isEmpty()) { | 163 if (!FLAGS_tmpDir.isEmpty()) { |
137 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); | 164 make_canonical_dir_path(FLAGS_tmpDir[0], &gTmpDir); |
138 } | 165 } |
139 if (!FLAGS_resourcePath.isEmpty()) { | 166 if (!FLAGS_resourcePath.isEmpty()) { |
(...skipping 25 matching lines...) Expand all Loading... | |
165 #ifdef SK_SCALAR_IS_FIXED | 192 #ifdef SK_SCALAR_IS_FIXED |
166 header.append(" SK_SCALAR_IS_FIXED"); | 193 header.append(" SK_SCALAR_IS_FIXED"); |
167 #else | 194 #else |
168 header.append(" SK_SCALAR_IS_FLOAT"); | 195 header.append(" SK_SCALAR_IS_FLOAT"); |
169 #endif | 196 #endif |
170 SkDebugf("%s\n", header.c_str()); | 197 SkDebugf("%s\n", header.c_str()); |
171 } | 198 } |
172 | 199 |
173 DebugfReporter reporter(FLAGS_extendedTest); | 200 DebugfReporter reporter(FLAGS_extendedTest); |
174 Iter iter(&reporter); | 201 Iter iter(&reporter); |
175 Test* test; | |
176 | 202 |
177 const int count = Iter::Count(); | 203 const int count = Iter::Count(); |
178 int index = 0; | 204 reporter.setTotal(count); |
179 int failCount = 0; | 205 int failCount = 0; |
scroggo
2013/04/17 17:34:52
int32_t?
mtklein
2013/04/17 18:13:59
Done.
| |
180 int skipCount = 0; | 206 int skipCount = 0; |
181 while ((test = iter.next()) != NULL) { | 207 |
182 reporter.setIndexOfTotal(index, count); | 208 SkTScopedPtr<SkThreadPool> threadpool(SkNEW_ARGS(SkThreadPool, (FLAGS_thread s))); |
209 SkTArray<Test*> unsafeTests; // Always passes ownership to an SkTestRunnabl e | |
210 for (int i = 0; i < count; i++) { | |
211 SkTScopedPtr<Test> test(iter.next()); | |
183 if (!FLAGS_match.isEmpty() && !strstr(test->getName(), FLAGS_match[0])) { | 212 if (!FLAGS_match.isEmpty() && !strstr(test->getName(), FLAGS_match[0])) { |
184 ++skipCount; | 213 ++skipCount; |
214 } else if (!test->isThreadsafe()) { | |
215 unsafeTests.push_back() = test.release(); | |
185 } else { | 216 } else { |
186 if (!test->run()) { | 217 threadpool->add(SkNEW_ARGS(SkTestRunnable, (test.release(), &failCou nt))); |
187 ++failCount; | |
188 } | |
189 } | 218 } |
190 SkDELETE(test); | |
191 index += 1; | |
192 } | 219 } |
193 | 220 |
221 // Run the tests that aren't threadsafe. | |
222 for (int i = 0; i < unsafeTests.count(); i++) { | |
223 SkNEW_ARGS(SkTestRunnable, (unsafeTests[i], &failCount))->run(); | |
scroggo
2013/04/17 17:34:52
Won't the destructor for SkTArray call the destruc
mtklein
2013/04/17 18:13:59
This is an SkTArray<Test*>. Does SkTArray delete
| |
224 } | |
225 | |
226 // Blocks until threaded tests finish. | |
227 threadpool.reset(); | |
228 | |
194 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", | 229 SkDebugf("Finished %d tests, %d failures, %d skipped.\n", |
195 count, failCount, skipCount); | 230 count, failCount, skipCount); |
196 int testCount = reporter.countTests(); | 231 int testCount = reporter.countTests(); |
197 if (FLAGS_verbose && testCount > 0) { | 232 if (FLAGS_verbose && testCount > 0) { |
198 SkDebugf("Ran %d Internal tests.\n", testCount); | 233 SkDebugf("Ran %d Internal tests.\n", testCount); |
199 } | 234 } |
200 #if SK_SUPPORT_GPU | 235 #if SK_SUPPORT_GPU |
201 | 236 |
202 #if GR_CACHE_STATS | 237 #if GR_CACHE_STATS |
203 GrContext *gr = GpuTest::GetContext(); | 238 GrContext *gr = GpuTest::GetContext(); |
204 | 239 |
205 gr->printCacheStats(); | 240 gr->printCacheStats(); |
206 #endif | 241 #endif |
207 | 242 |
208 #endif | 243 #endif |
209 | 244 |
210 SkGraphics::Term(); | 245 SkGraphics::Term(); |
211 GpuTest::DestroyContexts(); | 246 GpuTest::DestroyContexts(); |
212 | 247 |
213 return (failCount == 0) ? 0 : 1; | 248 return (failCount == 0) ? 0 : 1; |
214 } | 249 } |
215 | 250 |
216 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 251 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
217 int main(int argc, char * const argv[]) { | 252 int main(int argc, char * const argv[]) { |
218 return tool_main(argc, (char**) argv); | 253 return tool_main(argc, (char**) argv); |
219 } | 254 } |
220 #endif | 255 #endif |
OLD | NEW |