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 "SkAtomics.h"
12 #include "SkCommonFlags.h"
13 #include "SkGraphics.h"
14 #include "SkOSFile.h"
15 #include "SkTArray.h"
16 #include "SkTaskGroup.h"
17 #include "SkTemplates.h"
18 #include "SkTime.h"
19 #include "Test.h"
20
21 #if SK_SUPPORT_GPU
22 #include "GrContext.h"
23 #include "GrContextFactory.h"
24 #endif
25
26 using namespace skiatest;
27
28 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
29
30 // need to explicitly declare this, or we get some weird infinite loop llist
31 template TestRegistry* TestRegistry::gHead;
32 void (*gVerboseFinalize)() = nullptr;
33
34 // The threads report back to this object when they are done.
35 class Status {
36 public:
Status(int total)37 explicit Status(int total)
38 : fDone(0), fTestCount(0), fFailCount(0), fTotal(total) {}
39 // Threadsafe.
endTest(const char * testName,bool success,SkMSec elapsed,int testCount)40 void endTest(const char* testName,
41 bool success,
42 SkMSec elapsed,
43 int testCount) {
44 const int done = 1 + sk_atomic_inc(&fDone);
45 for (int i = 0; i < testCount; ++i) {
46 sk_atomic_inc(&fTestCount);
47 }
48 if (!success) {
49 SkDebugf("\n---- %s FAILED", testName);
50 }
51
52 SkString prefix(kSkOverwriteLine);
53 SkString time;
54 if (FLAGS_verbose) {
55 prefix.printf("\n");
56 time.printf("%5dms ", elapsed);
57 }
58 SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(),
59 testName);
60 }
61
reportFailure()62 void reportFailure() { sk_atomic_inc(&fFailCount); }
63
testCount()64 int32_t testCount() { return fTestCount; }
failCount()65 int32_t failCount() { return fFailCount; }
66
67 private:
68 int32_t fDone; // atomic
69 int32_t fTestCount; // atomic
70 int32_t fFailCount; // atomic
71 const int fTotal;
72 };
73
74 class SkTestRunnable {
75 public:
SkTestRunnable(const Test & test,Status * status,GrContextFactory * grContextFactory=nullptr)76 SkTestRunnable(const Test& test,
77 Status* status,
78 GrContextFactory* grContextFactory = nullptr)
79 : fTest(test), fStatus(status), fGrContextFactory(grContextFactory) {}
80
operator ()()81 void operator()() {
82 struct TestReporter : public skiatest::Reporter {
83 public:
84 TestReporter() : fError(false), fTestCount(0) {}
85 void bumpTestCount() override { ++fTestCount; }
86 bool allowExtendedTest() const override {
87 return FLAGS_extendedTest;
88 }
89 bool verbose() const override { return FLAGS_veryVerbose; }
90 void reportFailed(const skiatest::Failure& failure) override {
91 SkDebugf("\nFAILED: %s", failure.toString().c_str());
92 fError = true;
93 }
94 bool fError;
95 int fTestCount;
96 } reporter;
97
98 const SkMSec start = SkTime::GetMSecs();
99 fTest.proc(&reporter, fGrContextFactory);
100 SkMSec elapsed = SkTime::GetMSecs() - start;
101 if (reporter.fError) {
102 fStatus->reportFailure();
103 }
104 fStatus->endTest(fTest.name, !reporter.fError, elapsed,
105 reporter.fTestCount);
106 }
107
108 private:
109 Test fTest;
110 Status* fStatus;
111 GrContextFactory* fGrContextFactory;
112 };
113
should_run(const char * testName,bool isGPUTest)114 static bool should_run(const char* testName, bool isGPUTest) {
115 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, testName)) {
116 return false;
117 }
118 if (!FLAGS_cpu && !isGPUTest) {
119 return false;
120 }
121 if (!FLAGS_gpu && isGPUTest) {
122 return false;
123 }
124 return true;
125 }
126
127 int test_main();
test_main()128 int test_main() {
129 SetupCrashHandler();
130
131 SkAutoGraphics ag;
132
133 {
134 SkString header("Skia UnitTests:");
135 if (!FLAGS_match.isEmpty()) {
136 header.appendf(" --match");
137 for (int index = 0; index < FLAGS_match.count(); ++index) {
138 header.appendf(" %s", FLAGS_match[index]);
139 }
140 }
141 SkString tmpDir = skiatest::GetTmpDir();
142 if (!tmpDir.isEmpty()) {
143 header.appendf(" --tmpDir %s", tmpDir.c_str());
144 }
145 SkString resourcePath = GetResourcePath();
146 if (!resourcePath.isEmpty()) {
147 header.appendf(" --resourcePath %s", resourcePath.c_str());
148 }
149 #ifdef SK_DEBUG
150 header.append(" SK_DEBUG");
151 #else
152 header.append(" SK_RELEASE");
153 #endif
154 if (FLAGS_veryVerbose) {
155 header.appendf("\n");
156 }
157 SkDebugf("%s", header.c_str());
158 }
159
160
161 // Count tests first.
162 int total = 0;
163 int toRun = 0;
164
165 for (const TestRegistry* iter = TestRegistry::Head(); iter;
166 iter = iter->next()) {
167 const Test& test = iter->factory();
168 if (should_run(test.name, test.needsGpu)) {
169 toRun++;
170 }
171 total++;
172 }
173
174 // Now run them.
175 int skipCount = 0;
176
177 SkTaskGroup::Enabler enabled(FLAGS_threads);
178 SkTaskGroup cpuTests;
179 SkTArray<const Test*> gpuTests;
180
181 Status status(toRun);
182 for (const TestRegistry* iter = TestRegistry::Head(); iter;
183 iter = iter->next()) {
184 const Test& test = iter->factory();
185 if (!should_run(test.name, test.needsGpu)) {
186 ++skipCount;
187 } else if (test.needsGpu) {
188 gpuTests.push_back(&test);
189 } else {
190 cpuTests.add(SkTestRunnable(test, &status));
191 }
192 }
193
194 GrContextFactory* grContextFactoryPtr = nullptr;
195 #if SK_SUPPORT_GPU
196 // Give GPU tests a context factory if that makes sense on this machine.
197 GrContextFactory grContextFactory;
198 grContextFactoryPtr = &grContextFactory;
199
200 #endif
201
202 // Run GPU tests on this thread.
203 for (int i = 0; i < gpuTests.count(); i++) {
204 SkTestRunnable(*gpuTests[i], &status, grContextFactoryPtr)();
205 }
206
207 // Block until threaded tests finish.
208 cpuTests.wait();
209
210 if (FLAGS_verbose) {
211 SkDebugf(
212 "\nFinished %d tests, %d failures, %d skipped. "
213 "(%d internal tests)",
214 toRun, status.failCount(), skipCount, status.testCount());
215 if (gVerboseFinalize) {
216 (*gVerboseFinalize)();
217 }
218 }
219
220 SkDebugf("\n");
221 return (status.failCount() == 0) ? 0 : 1;
222 }
223
224 #if !defined(SK_BUILD_FOR_IOS)
main(int argc,char ** argv)225 int main(int argc, char** argv) {
226 SkCommandLineFlags::Parse(argc, argv);
227 return test_main();
228 }
229 #endif
230