blob: f82d75d036890303dd6a1432d800da2ee02eedff [file] [log] [blame]
borenet48087572015-04-02 12:16:36 -07001/*
2 * Copyright 2013 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
caryclark19eb3b22014-07-18 05:08:14 -07008#include "CrashHandler.h"
9// #include "OverwriteLine.h"
10#include "Resources.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000011#include "SkBitmap.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000012#include "SkCanvas.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000013#include "SkColor.h"
14#include "SkColorPriv.h"
caryclark19eb3b22014-07-18 05:08:14 -070015#include "SkCommandLineFlags.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000016#include "SkDevice.h"
caryclark19eb3b22014-07-18 05:08:14 -070017#include "SkForceLinking.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000018#include "SkGraphics.h"
caryclark@google.comcffbcc32013-06-04 17:59:42 +000019#include "SkImageDecoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000020#include "SkImageEncoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000021#include "SkOSFile.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000022#include "SkPathOpsDebug.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000023#include "SkPicture.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000024#include "SkRTConf.h"
reed89889b62014-10-29 12:36:45 -070025#include "SkRunnable.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000026#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000027#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000028#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000029#include "SkTArray.h"
30#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070031#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070032#include "SkTemplates.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000033#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000034
bungeman60e0fee2015-08-26 05:15:46 -070035#include <stdlib.h>
36
caryclark19eb3b22014-07-18 05:08:14 -070037__SK_FORCE_IMAGE_DECODER_LINKING;
caryclark@google.com07e97fc2013-07-08 17:17:02 +000038
caryclark19eb3b22014-07-18 05:08:14 -070039/* add local exceptions here */
40/* TODO : add command flag interface */
41const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000042 int directory;
43 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070044 bool blamePathOps;
45} skipOver[] = {
46 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
47 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
48 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
49 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
50 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070051 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070052 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
53 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
54 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
55 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
56 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
57 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
58 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
59 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
60 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
61 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
62 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
63 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
64 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
65 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000066};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000067
caryclark19eb3b22014-07-18 05:08:14 -070068size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070069
caryclark19eb3b22014-07-18 05:08:14 -070070
71/* customize file in/out here */
72/* TODO : add command flag interface */
73#define CHROME_VERSION "1e5dfa4-4a995df"
74#define SUMMARY_RUN 1
75
76#ifdef SK_BUILD_FOR_WIN
77 #define DRIVE_SPEC "D:"
78 #define PATH_SLASH "\\"
79#else
80 #define DRIVE_SPEC ""
81 #define PATH_SLASH "/"
82#endif
83
84#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
85#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
86#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
87#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
88
89static const char outOpDir[] = "opClip";
90static const char outOldDir[] = "oldClip";
91static const char outStatusDir[] = "statusTest";
92
93static SkString get_in_path(int dirNo, const char* filename) {
94 SkString path;
95 SkASSERT(dirNo);
96 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
97 if (!sk_exists(path.c_str())) {
98 SkDebugf("could not read %s\n", path.c_str());
99 return SkString();
100 }
101 if (filename) {
102 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -0700103 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -0700104 SkDebugf("could not read %s\n", path.c_str());
105 return SkString();
106 }
107 }
108 return path;
109}
mtklein406654b2014-09-03 15:34:37 -0700110
caryclark19eb3b22014-07-18 05:08:14 -0700111static void make_recursive_dir(const SkString& path) {
112 if (sk_exists(path.c_str())) {
113 return;
114 }
115 const char* pathStr = path.c_str();
116 int last = (int) path.size();
117 do {
118 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
119 ;
120 SkASSERT(last > 0);
121 SkString shorter(pathStr, last);
122 if (sk_mkdir(shorter.c_str())) {
123 break;
124 }
125 } while (true);
126 do {
127 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
128 ;
129 SkString shorter(pathStr, last);
130 SkAssertResult(sk_mkdir(shorter.c_str()));
131 } while (last < (int) path.size());
132}
133
134static SkString get_out_path(int dirNo, const char* dirName) {
135 SkString path;
136 SkASSERT(dirNo);
137 SkASSERT(dirName);
138 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
139 make_recursive_dir(path);
140 return path;
141}
mtklein406654b2014-09-03 15:34:37 -0700142
caryclark19eb3b22014-07-18 05:08:14 -0700143static SkString get_sum_path(const char* dirName) {
144 SkString path;
145 SkASSERT(dirName);
146 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
147 SkDebugf("%s\n", path.c_str());
148 make_recursive_dir(path);
149 return path;
150}
151
152static SkString make_png_name(const char* filename) {
153 SkString pngName = SkString(filename);
154 pngName.remove(pngName.size() - 3, 3);
155 pngName.append("png");
156 return pngName;
157}
158
159////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000160
161enum TestStep {
162 kCompareBits,
163 kEncodeFiles,
164};
165
166enum {
caryclarkdac1d172014-06-17 05:15:38 -0700167 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000168 kMaxFiles = 128,
169 kSmallLimit = 1000,
170};
171
172struct TestResult {
173 void init(int dirNo) {
174 fDirNo = dirNo;
175 sk_bzero(fFilename, sizeof(fFilename));
176 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000177 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000178 }
mtklein406654b2014-09-03 15:34:37 -0700179
caryclark19eb3b22014-07-18 05:08:14 -0700180 void init(int dirNo, const SkString& filename) {
181 fDirNo = dirNo;
182 strcpy(fFilename, filename.c_str());
183 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700184 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700185 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000186
187 SkString status() {
188 SkString outStr;
189 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
190 return outStr;
191 }
192
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000193 SkString progress() {
194 SkString outStr;
195 outStr.printf("dir=%d %s ", fDirNo, fFilename);
196 if (fPixelError) {
197 outStr.appendf(" err=%d", fPixelError);
198 }
199 if (fTime) {
200 outStr.appendf(" time=%d", fTime);
201 }
202 if (fScale != 1) {
203 outStr.appendf(" scale=%d", fScale);
204 }
205 outStr.appendf("\n");
206 return outStr;
207
208 }
209
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000210 void test(int dirNo, const SkString& filename) {
211 init(dirNo);
212 strcpy(fFilename, filename.c_str());
213 testOne();
214 }
215
216 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700217
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000218 char fFilename[kMaxLength];
219 TestStep fTestStep;
220 int fDirNo;
221 int fPixelError;
222 int fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000223 int fScale;
224};
225
226class SortByPixel : public TestResult {
227public:
228 bool operator<(const SortByPixel& rh) const {
229 return fPixelError < rh.fPixelError;
230 }
231};
232
233class SortByTime : public TestResult {
234public:
235 bool operator<(const SortByTime& rh) const {
236 return fTime < rh.fTime;
237 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000238};
239
caryclarkdac1d172014-06-17 05:15:38 -0700240class SortByName : public TestResult {
241public:
242 bool operator<(const SortByName& rh) const {
243 return strcmp(fFilename, rh.fFilename) < 0;
244 }
245};
246
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000247struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700248 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000249 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000250 }
251
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000252 SkTDArray<SortByPixel> fPixelWorst;
253 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000254 TestResult fResult;
255};
256
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000257struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000258 ~TestRunner();
259 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000260 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000261};
262
263class TestRunnable : public SkRunnable {
264public:
mtklein36352bf2015-03-25 18:17:31 -0700265 void run() override {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000266 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
267 (*fTestFun)(&fState);
268 }
269
270 TestState fState;
271 void (*fTestFun)(TestState*);
272};
273
caryclarkdac1d172014-06-17 05:15:38 -0700274
275class TestRunnableDir : public TestRunnable {
276public:
277 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700278 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700279 fTestFun = testFun;
280 }
281
282};
283
284class TestRunnableFile : public TestRunnable {
285public:
286 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700287 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700288 strcpy(fState.fResult.fFilename, name);
289 fTestFun = testFun;
290 }
291};
292
293class TestRunnableEncode : public TestRunnableFile {
294public:
295 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
296 : TestRunnableFile(testFun, dirNo, name, runner) {
297 fState.fResult.fTestStep = kEncodeFiles;
298 }
299};
300
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000301TestRunner::~TestRunner() {
302 for (int index = 0; index < fRunnables.count(); index++) {
halcanary385fe4d2015-08-26 13:07:48 -0700303 delete fRunnables[index];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000304 }
305}
306
307void TestRunner::render() {
mtklein00b621c2015-06-17 15:26:15 -0700308 // TODO: this doesn't really need to use SkRunnables any more.
309 // We can just write the code to run in the for-loop directly.
310 sk_parallel_for(fRunnables.count(), [&](int i) {
311 fRunnables[i]->run();
312 });
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000313}
314
315////////////////////////////////////////////////
316
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000317
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000318static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
319 const int kRowCount = 3;
320 const int kThreshold = 3;
321 int width = SkTMin(gr.width(), sk.width());
322 if (width < kRowCount) {
323 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000324 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000325 int height = SkTMin(gr.height(), sk.height());
326 if (height < kRowCount) {
327 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000328 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000329 int errorTotal = 0;
330 SkTArray<int, true> errorRows;
331 errorRows.push_back_n(width * kRowCount);
332 SkAutoLockPixels autoGr(gr);
333 SkAutoLockPixels autoSk(sk);
334 for (int y = 0; y < height; ++y) {
335 SkPMColor* grRow = gr.getAddr32(0, y);
336 SkPMColor* skRow = sk.getAddr32(0, y);
337 int* base = &errorRows[0];
338 int* cOut = &errorRows[y % kRowCount];
339 for (int x = 0; x < width; ++x) {
340 SkPMColor grColor = grRow[x];
341 SkPMColor skColor = skRow[x];
342 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
343 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
344 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
345 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
346 if (error < kThreshold || x < 2) {
347 continue;
348 }
349 if (base[x - 2] < kThreshold
350 || base[width + x - 2] < kThreshold
351 || base[width * 2 + x - 2] < kThreshold
352 || base[x - 1] < kThreshold
353 || base[width + x - 1] < kThreshold
354 || base[width * 2 + x - 1] < kThreshold
355 || base[x] < kThreshold
356 || base[width + x] < kThreshold
357 || base[width * 2 + x] < kThreshold) {
358 continue;
359 }
360 errorTotal += error;
361 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000362 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000363 return errorTotal;
364}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000365
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000366static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000367 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
368 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000369 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000370 int worstCount = data->fPixelWorst.count();
371 int pixelError = testResult.fPixelError;
372 if (pixelError > 0) {
373 for (int index = 0; index < worstCount; ++index) {
374 if (pixelError > data->fPixelWorst[index].fPixelError) {
375 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
376 return true;
377 }
378 }
379 }
380 int slowCount = data->fSlowest.count();
381 int time = testResult.fTime;
382 if (time > 0) {
383 for (int index = 0; index < slowCount; ++index) {
384 if (time > data->fSlowest[index].fTime) {
385 data->fSlowest[index] = *(SortByTime*) &testResult;
386 return true;
387 }
388 }
389 }
390 if (pixelError > 0 && worstCount < kMaxFiles) {
391 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
392 return true;
393 }
394 if (time > 0 && slowCount < kMaxFiles) {
395 *data->fSlowest.append() = *(SortByTime*) &testResult;
396 return true;
397 }
398 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000399}
400
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000401static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
402 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700403 SkScalar pWidth = pic->cullRect().width();
404 SkScalar pHeight = pic->cullRect().height();
405 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000406 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700407 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
408 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
409 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000410 canvas->clipRect(rect);
411 SkMSec start = SkTime::GetMSecs();
412 for (int x = 0; x < slices; ++x) {
413 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700414 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700415 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000416 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700417 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000418 }
419 SkMSec end = SkTime::GetMSecs();
420 canvas->restore();
421 return end - start;
422}
423
424static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
425 canvas->clear(SK_ColorWHITE);
426 if (scale != 1) {
427 canvas->save();
428 canvas->scale(1.0f / scale, 1.0f / scale);
429 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700430 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000431 if (scale != 1) {
432 canvas->restore();
433 }
434}
435
436static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700437 SkString outFile = get_sum_path(outDir);
438 outFile.appendf("%s%s", PATH_SLASH, pngName);
439 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000440 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
441 bitmap.width(), bitmap.height());
442 }
443}
444
445void TestResult::testOne() {
halcanary96fcdcc2015-08-27 07:41:13 -0700446 SkPicture* pic = nullptr;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000447 {
448 #if DEBUG_SHOW_TEST_NAME
449 if (fTestStep == kCompareBits) {
450 SkString testName(fFilename);
451 const char http[] = "http";
452 if (testName.startsWith(http)) {
453 testName.remove(0, sizeof(http) - 1);
454 }
455 while (testName.startsWith("_")) {
456 testName.remove(0, 1);
457 }
458 const char dotSkp[] = ".skp";
459 if (testName.endsWith(dotSkp)) {
460 size_t len = testName.size();
461 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
462 }
463 testName.prepend("skp");
464 testName.append("1");
465 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
466 } else if (fTestStep == kEncodeFiles) {
467 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
468 }
469 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700470 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000471 SkFILEStream stream(path.c_str());
472 if (!stream.isValid()) {
473 SkDebugf("invalid stream %s\n", path.c_str());
474 goto finish;
475 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000476 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000477 if (!pic) {
478 SkDebugf("unable to decode %s\n", fFilename);
479 goto finish;
480 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700481 SkScalar width = pic->cullRect().width();
482 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000483 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000484 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000485 while (width / fScale > 32767 || height / fScale > 32767) {
486 ++fScale;
487 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000488 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700489 int dimX = SkScalarCeilToInt(width / fScale);
490 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700491 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000492 break;
493 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000494 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000495 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000496 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700497 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000498 width, height);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000499 goto finish;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000500 }
501 oldBitmap.eraseColor(SK_ColorWHITE);
502 SkCanvas oldCanvas(oldBitmap);
503 oldCanvas.setAllowSimplifyClip(false);
504 opBitmap.eraseColor(SK_ColorWHITE);
505 SkCanvas opCanvas(opBitmap);
506 opCanvas.setAllowSimplifyClip(true);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000507 drawPict(pic, &oldCanvas, fScale);
508 drawPict(pic, &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000509 if (fTestStep == kCompareBits) {
510 fPixelError = similarBits(oldBitmap, opBitmap);
511 int oldTime = timePict(pic, &oldCanvas);
512 int opTime = timePict(pic, &opCanvas);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000513 fTime = SkTMax(0, oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000514 } else if (fTestStep == kEncodeFiles) {
515 SkString pngStr = make_png_name(fFilename);
516 const char* pngName = pngStr.c_str();
517 writePict(oldBitmap, outOldDir, pngName);
518 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000519 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000520 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000521finish:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000522 if (pic) {
523 pic->unref();
524 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000525}
526
caryclark19eb3b22014-07-18 05:08:14 -0700527DEFINE_string2(match, m, "PathOpsSkpClipThreaded",
528 "[~][^]substring[$] [...] of test name to run.\n"
529 "Multiple matches may be separated by spaces.\n"
530 "~ causes a matching test to always be skipped\n"
531 "^ requires the start of the test to match\n"
532 "$ requires the end of the test to match\n"
533 "^ and $ requires an exact match\n"
534 "If a test does not match any list entry,\n"
535 "it is skipped unless some list entry starts with ~");
halcanary96fcdcc2015-08-27 07:41:13 -0700536DEFINE_string2(dir, d, nullptr, "range of directories (e.g., 1-100)");
537DEFINE_string2(skp, s, nullptr, "skp to test");
caryclark19eb3b22014-07-18 05:08:14 -0700538DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
539DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only).");
caryclark19eb3b22014-07-18 05:08:14 -0700540DEFINE_bool2(verbose, v, false, "enable verbose output.");
541
542static bool verbose() {
543 return FLAGS_verbose;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000544}
545
caryclark19eb3b22014-07-18 05:08:14 -0700546class Dirs {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000547public:
caryclark19eb3b22014-07-18 05:08:14 -0700548 Dirs() {
549 reset();
550 sk_bzero(fRun, sizeof(fRun));
551 fSet = false;
552 }
553
554 int first() const {
555 int index = 0;
556 while (++index < kMaxDir) {
557 if (fRun[index]) {
558 return index;
559 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000560 }
caryclark19eb3b22014-07-18 05:08:14 -0700561 SkASSERT(0);
562 return -1;
563 }
564
565 int last() const {
566 int index = kMaxDir;
567 while (--index > 0 && !fRun[index])
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000568 ;
caryclark19eb3b22014-07-18 05:08:14 -0700569 return index;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000570 }
571
caryclark19eb3b22014-07-18 05:08:14 -0700572 int next() {
573 while (++fIndex < kMaxDir) {
574 if (fRun[fIndex]) {
575 return fIndex;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000576 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000577 }
caryclark19eb3b22014-07-18 05:08:14 -0700578 return -1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000579 }
580
caryclark19eb3b22014-07-18 05:08:14 -0700581 void reset() {
582 fIndex = -1;
583 }
584
585 void set(int start, int end) {
586 while (start < end) {
587 fRun[start++] = 1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000588 }
caryclark19eb3b22014-07-18 05:08:14 -0700589 fSet = true;
590 }
591
592 void setDefault() {
593 if (!fSet) {
594 set(1, 100);
595 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000596 }
597
598private:
caryclark19eb3b22014-07-18 05:08:14 -0700599 enum {
600 kMaxDir = 101
601 };
602 char fRun[kMaxDir];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000603 int fIndex;
caryclark19eb3b22014-07-18 05:08:14 -0700604 bool fSet;
605} gDirs;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000606
caryclark19eb3b22014-07-18 05:08:14 -0700607class Filenames {
608public:
609 Filenames()
610 : fIndex(-1) {
611 }
612
613 const char* next() {
614 while (fNames && ++fIndex < fNames->count()) {
615 return (*fNames)[fIndex];
616 }
halcanary96fcdcc2015-08-27 07:41:13 -0700617 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -0700618 }
mtklein406654b2014-09-03 15:34:37 -0700619
caryclark19eb3b22014-07-18 05:08:14 -0700620 void set(const SkCommandLineFlags::StringArray& names) {
621 fNames = &names;
622 }
623
624private:
625 int fIndex;
626 const SkCommandLineFlags::StringArray* fNames;
627} gNames;
628
mtklein406654b2014-09-03 15:34:37 -0700629static bool buildTestDir(int dirNo, int firstDirNo,
caryclark19eb3b22014-07-18 05:08:14 -0700630 SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
631 SkString dirName = get_out_path(dirNo, outStatusDir);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000632 if (!dirName.size()) {
633 return false;
634 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000635 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000636 SkString filename;
637 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700638 TestResult test;
639 test.init(dirNo);
640 SkString spaceFile(filename);
641 char* spaces = spaceFile.writable_str();
642 int spaceSize = (int) spaceFile.size();
643 for (int index = 0; index < spaceSize; ++index) {
644 if (spaces[index] == '.') {
645 spaces[index] = ' ';
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000646 }
647 }
caryclark19eb3b22014-07-18 05:08:14 -0700648 int success = sscanf(spaces, "%s %d %d skp", test.fFilename,
649 &test.fPixelError, &test.fTime);
650 if (success < 3) {
651 SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success);
652 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000653 }
caryclark19eb3b22014-07-18 05:08:14 -0700654 *tests[dirNo - firstDirNo].append() = test;
655 }
656 if (!sorted) {
657 return true;
658 }
659 SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo];
660 int count = testSet.count();
661 for (int index = 0; index < count; ++index) {
662 *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index];
663 }
664 if (sorted[dirNo - firstDirNo].count()) {
665 SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(),
666 sorted[dirNo - firstDirNo].end() - 1);
667 if (verbose()) {
668 SkDebugf("+");
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000669 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000670 }
671 return true;
672}
673
caryclark19eb3b22014-07-18 05:08:14 -0700674static void testSkpClip(TestState* data) {
675 data->fResult.testOne();
676 SkString statName(data->fResult.fFilename);
677 SkASSERT(statName.endsWith(".skp"));
678 statName.remove(statName.size() - 4, 4);
679 statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime);
680 SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir);
681 if (!statusFile.size()) {
682 SkDebugf("failed to create %s", statusFile.c_str());
683 return;
684 }
685 statusFile.appendf("%s%s", PATH_SLASH, statName.c_str());
halcanaryd76be9c2015-11-20 13:47:49 -0800686 FILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
caryclark19eb3b22014-07-18 05:08:14 -0700687 if (!file) {
688 SkDebugf("failed to create %s", statusFile.c_str());
689 return;
690 }
691 sk_fclose(file);
692 if (verbose()) {
693 if (data->fResult.fPixelError || data->fResult.fTime) {
694 SkDebugf("%s", data->fResult.progress().c_str());
695 } else {
696 SkDebugf(".");
697 }
698 }
699}
700
701bool Less(const SortByName& a, const SortByName& b);
702bool Less(const SortByName& a, const SortByName& b) {
703 return a < b;
704}
705
706static bool doOneDir(TestState* state, bool threaded) {
707 int dirNo = state->fResult.fDirNo;
halcanary96fcdcc2015-08-27 07:41:13 -0700708 SkString dirName = get_in_path(dirNo, nullptr);
caryclark19eb3b22014-07-18 05:08:14 -0700709 if (!dirName.size()) {
710 return false;
711 }
712 SkTDArray<TestResult> tests[1];
713 SkTDArray<SortByName*> sorted[1];
714 if (!buildTestDir(dirNo, dirNo, tests, sorted)) {
715 return false;
716 }
717 SkOSFile::Iter iter(dirName.c_str(), "skp");
718 SkString filename;
719 while (iter.next(&filename)) {
720 for (size_t index = 0; index < skipOverCount; ++index) {
721 if (skipOver[index].directory == dirNo
722 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
723 goto checkEarlyExit;
724 }
725 }
726 {
727 SortByName name;
728 name.init(dirNo);
729 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
730 int count = sorted[0].count();
731 int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name));
732 if (idx >= 0) {
733 SortByName* found = sorted[0][idx];
734 (void) addError(state, *found);
735 continue;
736 }
737 TestResult test;
738 test.init(dirNo, filename);
739 state->fResult = test;
740 testSkpClip(state);
741#if 0 // artificially limit to a few while debugging code
742 static int debugLimit = 0;
743 if (++debugLimit == 5) {
744 return true;
745 }
746#endif
747 }
748checkEarlyExit:
749 ;
750 }
751 return true;
752}
753
754static void initTest() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000755#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC
756 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
757 SK_CONF_SET("images.png.suppressDecoderWarnings", true);
758#endif
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000759}
760
caryclarkdac1d172014-06-17 05:15:38 -0700761static void testSkpClipEncode(TestState* data) {
762 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700763 if (verbose()) {
764 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700765 }
766}
767
caryclark19eb3b22014-07-18 05:08:14 -0700768static void encodeFound(TestState& state) {
769 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700770 if (state.fPixelWorst.count()) {
771 SkTDArray<SortByPixel*> worst;
772 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
773 *worst.append() = &state.fPixelWorst[index];
774 }
775 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
776 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
777 const TestResult& result = *worst[index];
778 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
779 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000780 }
caryclarkdac1d172014-06-17 05:15:38 -0700781 if (state.fSlowest.count()) {
782 SkTDArray<SortByTime*> slowest;
783 for (int index = 0; index < state.fSlowest.count(); ++index) {
784 *slowest.append() = &state.fSlowest[index];
785 }
786 if (slowest.count() > 0) {
787 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
788 for (int index = 0; index < slowest.count(); ++index) {
789 const TestResult& result = *slowest[index];
790 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
791 }
792 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000793 }
794 }
mtklein406654b2014-09-03 15:34:37 -0700795 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000796 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
797 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700798 SkString filename(result.fFilename);
799 if (!filename.endsWith(".skp")) {
800 filename.append(".skp");
801 }
halcanary385fe4d2015-08-26 13:07:48 -0700802 *testRunner.fRunnables.append() = new TestRunnableEncode(&testSkpClipEncode, result.fDirNo,
803 filename.c_str(), &testRunner);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000804 }
caryclarkdac1d172014-06-17 05:15:38 -0700805 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000806}
807
caryclark19eb3b22014-07-18 05:08:14 -0700808class Test {
809public:
810 Test() {}
811 virtual ~Test() {}
812
813 const char* getName() { onGetName(&fName); return fName.c_str(); }
814 void run() { onRun(); }
815
816protected:
817 virtual void onGetName(SkString*) = 0;
818 virtual void onRun() = 0;
819
820private:
821 SkString fName;
822};
823
824typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
825
halcanary385fe4d2015-08-26 13:07:48 -0700826#define DEF_TEST(name) \
827 static void test_##name(); \
828 class name##Class : public Test { \
829 public: \
830 static Test* Factory(void*) { return new name##Class; } \
831 \
832 protected: \
833 void onGetName(SkString* name) override { name->set(#name); } \
834 void onRun() override { test_##name(); } \
835 }; \
836 static TestRegistry gReg_##name##Class(name##Class::Factory); \
caryclark19eb3b22014-07-18 05:08:14 -0700837 static void test_##name()
838
839DEF_TEST(PathOpsSkpClip) {
840 gDirs.setDefault();
841 initTest();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000842 SkTArray<TestResult, true> errors;
843 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700844 state.init(0);
845 int dirNo;
846 gDirs.reset();
847 while ((dirNo = gDirs.next()) > 0) {
848 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000849 SkDebugf("dirNo=%d\n", dirNo);
850 }
851 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000852 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000853 break;
854 }
855 }
caryclark19eb3b22014-07-18 05:08:14 -0700856 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000857}
858
859static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000860 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000861}
862
caryclark19eb3b22014-07-18 05:08:14 -0700863DEF_TEST(PathOpsSkpClipThreaded) {
864 gDirs.setDefault();
865 initTest();
mtklein406654b2014-09-03 15:34:37 -0700866 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700867 int dirNo;
868 gDirs.reset();
869 while ((dirNo = gDirs.next()) > 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700870 *testRunner.fRunnables.append() = new TestRunnableDir(&testSkpClipMain, dirNo, &testRunner);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000871 }
872 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000873 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700874 state.init(0);
875 gDirs.reset();
876 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000877 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700878 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000879 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000880 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000881 }
caryclarkdac1d172014-06-17 05:15:38 -0700882 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
883 addError(&state, testState.fSlowest[inner]);
884 }
885 }
caryclark19eb3b22014-07-18 05:08:14 -0700886 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700887}
mtklein406654b2014-09-03 15:34:37 -0700888
caryclark19eb3b22014-07-18 05:08:14 -0700889static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
890 int firstDirNo = gDirs.first();
891 int dirNo;
892 while ((dirNo = gDirs.next()) > 0) {
893 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700894 return false;
895 }
caryclarkdac1d172014-06-17 05:15:38 -0700896 }
897 return true;
898}
899
caryclark19eb3b22014-07-18 05:08:14 -0700900DEF_TEST(PathOpsSkpClipUberThreaded) {
901 gDirs.setDefault();
902 const int firstDirNo = gDirs.next();
903 const int lastDirNo = gDirs.last();
904 initTest();
905 int dirCount = lastDirNo - firstDirNo + 1;
906 SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]);
907 SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]);
908 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700909 return;
910 }
mtklein406654b2014-09-03 15:34:37 -0700911 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700912 int dirNo;
913 gDirs.reset();
914 while ((dirNo = gDirs.next()) > 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700915 SkString dirName = get_in_path(dirNo, nullptr);
caryclarkdac1d172014-06-17 05:15:38 -0700916 if (!dirName.size()) {
917 continue;
918 }
919 SkOSFile::Iter iter(dirName.c_str(), "skp");
920 SkString filename;
921 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700922 for (size_t index = 0; index < skipOverCount; ++index) {
923 if (skipOver[index].directory == dirNo
924 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700925 goto checkEarlyExit;
926 }
927 }
caryclark19eb3b22014-07-18 05:08:14 -0700928 {
929 SortByName name;
930 name.init(dirNo);
931 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
932 int count = sorted.get()[dirNo - firstDirNo].count();
933 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
934 count, &name, sizeof(&name)) < 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700935 *testRunner.fRunnables.append() = new TestRunnableFile(
936 &testSkpClip, dirNo, filename.c_str(), &testRunner);
caryclark19eb3b22014-07-18 05:08:14 -0700937 }
caryclarkdac1d172014-06-17 05:15:38 -0700938 }
939 checkEarlyExit:
940 ;
941 }
942
943 }
944 testRunner.render();
caryclark19eb3b22014-07-18 05:08:14 -0700945 SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]);
halcanary96fcdcc2015-08-27 07:41:13 -0700946 if (!buildTests(results.get(), nullptr)) {
caryclarkdac1d172014-06-17 05:15:38 -0700947 return;
948 }
949 SkTDArray<TestResult> allResults;
950 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700951 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700952 allResults.append(array.count(), array.begin());
953 }
954 int allCount = allResults.count();
955 SkTDArray<SortByPixel*> pixels;
956 SkTDArray<SortByTime*> times;
957 for (int index = 0; index < allCount; ++index) {
958 *pixels.append() = (SortByPixel*) &allResults[index];
959 *times.append() = (SortByTime*) &allResults[index];
960 }
961 TestState state;
962 if (pixels.count()) {
963 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
964 for (int inner = 0; inner < kMaxFiles; ++inner) {
965 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
966 }
967 }
968 if (times.count()) {
969 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
970 for (int inner = 0; inner < kMaxFiles; ++inner) {
971 *state.fSlowest.append() = *times[allCount - inner - 1];
972 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000973 }
caryclark19eb3b22014-07-18 05:08:14 -0700974 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000975}
976
caryclark19eb3b22014-07-18 05:08:14 -0700977DEF_TEST(PathOpsSkpClipOneOff) {
978 const int testIndex = FLAGS_testIndex;
979 int dirNo = gDirs.next();
980 if (dirNo < 0) {
981 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000982 }
caryclark19eb3b22014-07-18 05:08:14 -0700983 const char* skp = gNames.next();
984 if (!skp) {
985 skp = skipOver[testIndex].filename;
986 }
987 initTest();
988 SkAssertResult(get_in_path(dirNo, skp).size());
989 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000990 TestResult state;
991 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700992 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000993 SkDebugf("%s", state.status().c_str());
994 }
995 state.fTestStep = kEncodeFiles;
996 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000997}
caryclark19eb3b22014-07-18 05:08:14 -0700998
999DEF_TEST(PathOpsTestSkipped) {
1000 for (size_t index = 0; index < skipOverCount; ++index) {
1001 const SkipOverTest& skip = skipOver[index];
1002 if (!skip.blamePathOps) {
1003 continue;
1004 }
1005 int dirNo = skip.directory;
1006 const char* skp = skip.filename;
1007 initTest();
1008 SkAssertResult(get_in_path(dirNo, skp).size());
1009 SkString filename(skp);
1010 TestResult state;
1011 state.test(dirNo, filename);
1012 if (verbose()) {
1013 SkDebugf("%s", state.status().c_str());
1014 }
1015 state.fTestStep = kEncodeFiles;
1016 state.testOne();
1017 }
1018}
1019
1020DEF_TEST(PathOpsCopyFails) {
1021 FLAGS_verbose = true;
1022 for (size_t index = 0; index < skipOverCount; ++index) {
1023 int dirNo = skipOver[index].directory;
1024 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1025 }
1026 for (size_t index = 0; index < skipOverCount; ++index) {
1027 int dirNo = skipOver[index].directory;
1028 const char* filename = skipOver[index].filename;
1029 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1030 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1031 }
1032}
1033
1034template TestRegistry* TestRegistry::gHead;
1035
1036class Iter {
1037public:
1038 Iter() { this->reset(); }
1039 void reset() { fReg = TestRegistry::Head(); }
1040
1041 Test* next() {
1042 if (fReg) {
1043 TestRegistry::Factory fact = fReg->factory();
1044 fReg = fReg->next();
halcanary96fcdcc2015-08-27 07:41:13 -07001045 Test* test = fact(nullptr);
caryclark19eb3b22014-07-18 05:08:14 -07001046 return test;
1047 }
halcanary96fcdcc2015-08-27 07:41:13 -07001048 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -07001049 }
1050
1051private:
1052 const TestRegistry* fReg;
1053};
1054
1055int tool_main(int argc, char** argv);
1056int tool_main(int argc, char** argv) {
1057 SetupCrashHandler();
1058 SkCommandLineFlags::SetUsage("");
1059 SkCommandLineFlags::Parse(argc, argv);
1060 SkGraphics::Init();
1061 SkString header("PathOps SkpClip:");
1062 if (!FLAGS_match.isEmpty()) {
1063 header.appendf(" --match");
1064 for (int index = 0; index < FLAGS_match.count(); ++index) {
1065 header.appendf(" %s", FLAGS_match[index]);
1066 }
1067 }
1068 if (!FLAGS_dir.isEmpty()) {
1069 int count = FLAGS_dir.count();
1070 for (int i = 0; i < count; ++i) {
1071 const char* range = FLAGS_dir[i];
1072 const char* dash = strchr(range, '-');
1073 if (!dash) {
1074 dash = strchr(range, ',');
1075 }
1076 int first = atoi(range);
1077 int last = dash ? atoi(dash + 1) : first;
1078 if (!first || !last) {
1079 SkDebugf("couldn't parse --dir %s\n", range);
1080 return 1;
1081 }
1082 gDirs.set(first, last);
1083 }
1084 }
1085 if (!FLAGS_skp.isEmpty()) {
1086 gNames.set(FLAGS_skp);
1087 }
1088#ifdef SK_DEBUG
1089 header.append(" SK_DEBUG");
1090#else
1091 header.append(" SK_RELEASE");
1092#endif
caryclark19eb3b22014-07-18 05:08:14 -07001093 if (FLAGS_verbose) {
1094 header.appendf("\n");
1095 }
kkinnunen297aaf92015-02-19 06:32:12 -08001096 SkDebugf("%s", header.c_str());
caryclark19eb3b22014-07-18 05:08:14 -07001097 Iter iter;
1098 Test* test;
halcanary96fcdcc2015-08-27 07:41:13 -07001099 while ((test = iter.next()) != nullptr) {
caryclark19eb3b22014-07-18 05:08:14 -07001100 SkAutoTDelete<Test> owned(test);
1101 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1102 test->run();
1103 }
1104 }
caryclark19eb3b22014-07-18 05:08:14 -07001105 return 0;
1106}
1107
borenet48087572015-04-02 12:16:36 -07001108#if !defined(SK_BUILD_FOR_IOS)
caryclark19eb3b22014-07-18 05:08:14 -07001109int main(int argc, char * const argv[]) {
1110 return tool_main(argc, (char**) argv);
1111}
1112#endif