blob: 6d66a69e6dbcca09da3f8d357e22f7559b39c49f [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"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000019#include "SkImageEncoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000020#include "SkOSFile.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000021#include "SkPathOpsDebug.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000022#include "SkPicture.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000023#include "SkRTConf.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000024#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000025#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000026#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000027#include "SkTArray.h"
28#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070029#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070030#include "SkTemplates.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000031#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000032
bungeman60e0fee2015-08-26 05:15:46 -070033#include <stdlib.h>
34
caryclark19eb3b22014-07-18 05:08:14 -070035/* add local exceptions here */
36/* TODO : add command flag interface */
37const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000038 int directory;
39 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070040 bool blamePathOps;
41} skipOver[] = {
42 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
43 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
44 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
45 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
46 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070047 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070048 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
49 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
50 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
51 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
52 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
53 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
54 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
55 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
56 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
57 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
58 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
59 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
60 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
61 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000062};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000063
caryclark19eb3b22014-07-18 05:08:14 -070064size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070065
caryclark19eb3b22014-07-18 05:08:14 -070066
67/* customize file in/out here */
68/* TODO : add command flag interface */
69#define CHROME_VERSION "1e5dfa4-4a995df"
70#define SUMMARY_RUN 1
71
72#ifdef SK_BUILD_FOR_WIN
73 #define DRIVE_SPEC "D:"
74 #define PATH_SLASH "\\"
75#else
76 #define DRIVE_SPEC ""
77 #define PATH_SLASH "/"
78#endif
79
80#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
81#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
82#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
83#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
84
85static const char outOpDir[] = "opClip";
86static const char outOldDir[] = "oldClip";
87static const char outStatusDir[] = "statusTest";
88
89static SkString get_in_path(int dirNo, const char* filename) {
90 SkString path;
91 SkASSERT(dirNo);
92 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
93 if (!sk_exists(path.c_str())) {
94 SkDebugf("could not read %s\n", path.c_str());
95 return SkString();
96 }
97 if (filename) {
98 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -070099 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -0700100 SkDebugf("could not read %s\n", path.c_str());
101 return SkString();
102 }
103 }
104 return path;
105}
mtklein406654b2014-09-03 15:34:37 -0700106
caryclark19eb3b22014-07-18 05:08:14 -0700107static void make_recursive_dir(const SkString& path) {
108 if (sk_exists(path.c_str())) {
109 return;
110 }
111 const char* pathStr = path.c_str();
112 int last = (int) path.size();
113 do {
114 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
115 ;
116 SkASSERT(last > 0);
117 SkString shorter(pathStr, last);
118 if (sk_mkdir(shorter.c_str())) {
119 break;
120 }
121 } while (true);
122 do {
123 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
124 ;
125 SkString shorter(pathStr, last);
126 SkAssertResult(sk_mkdir(shorter.c_str()));
127 } while (last < (int) path.size());
128}
129
130static SkString get_out_path(int dirNo, const char* dirName) {
131 SkString path;
132 SkASSERT(dirNo);
133 SkASSERT(dirName);
134 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
135 make_recursive_dir(path);
136 return path;
137}
mtklein406654b2014-09-03 15:34:37 -0700138
caryclark19eb3b22014-07-18 05:08:14 -0700139static SkString get_sum_path(const char* dirName) {
140 SkString path;
141 SkASSERT(dirName);
142 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
143 SkDebugf("%s\n", path.c_str());
144 make_recursive_dir(path);
145 return path;
146}
147
148static SkString make_png_name(const char* filename) {
149 SkString pngName = SkString(filename);
150 pngName.remove(pngName.size() - 3, 3);
151 pngName.append("png");
152 return pngName;
153}
154
155////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000156
157enum TestStep {
158 kCompareBits,
159 kEncodeFiles,
160};
161
162enum {
caryclarkdac1d172014-06-17 05:15:38 -0700163 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000164 kMaxFiles = 128,
165 kSmallLimit = 1000,
166};
167
168struct TestResult {
169 void init(int dirNo) {
170 fDirNo = dirNo;
171 sk_bzero(fFilename, sizeof(fFilename));
172 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000173 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000174 }
mtklein406654b2014-09-03 15:34:37 -0700175
caryclark19eb3b22014-07-18 05:08:14 -0700176 void init(int dirNo, const SkString& filename) {
177 fDirNo = dirNo;
178 strcpy(fFilename, filename.c_str());
179 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700180 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700181 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000182
183 SkString status() {
184 SkString outStr;
185 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
186 return outStr;
187 }
188
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000189 SkString progress() {
190 SkString outStr;
191 outStr.printf("dir=%d %s ", fDirNo, fFilename);
192 if (fPixelError) {
193 outStr.appendf(" err=%d", fPixelError);
194 }
195 if (fTime) {
196 outStr.appendf(" time=%d", fTime);
197 }
198 if (fScale != 1) {
199 outStr.appendf(" scale=%d", fScale);
200 }
201 outStr.appendf("\n");
202 return outStr;
203
204 }
205
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000206 void test(int dirNo, const SkString& filename) {
207 init(dirNo);
208 strcpy(fFilename, filename.c_str());
209 testOne();
210 }
211
212 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700213
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000214 char fFilename[kMaxLength];
215 TestStep fTestStep;
216 int fDirNo;
217 int fPixelError;
218 int fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000219 int fScale;
220};
221
222class SortByPixel : public TestResult {
223public:
224 bool operator<(const SortByPixel& rh) const {
225 return fPixelError < rh.fPixelError;
226 }
227};
228
229class SortByTime : public TestResult {
230public:
231 bool operator<(const SortByTime& rh) const {
232 return fTime < rh.fTime;
233 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000234};
235
caryclarkdac1d172014-06-17 05:15:38 -0700236class SortByName : public TestResult {
237public:
238 bool operator<(const SortByName& rh) const {
239 return strcmp(fFilename, rh.fFilename) < 0;
240 }
241};
242
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000243struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700244 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000245 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000246 }
247
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000248 SkTDArray<SortByPixel> fPixelWorst;
249 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000250 TestResult fResult;
251};
252
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000253struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000254 ~TestRunner();
255 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000256 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000257};
258
mtklein048494c2016-02-16 19:06:15 -0800259class TestRunnable {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000260public:
mtklein048494c2016-02-16 19:06:15 -0800261 void operator()() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000262 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
263 (*fTestFun)(&fState);
264 }
265
266 TestState fState;
267 void (*fTestFun)(TestState*);
268};
269
caryclarkdac1d172014-06-17 05:15:38 -0700270
271class TestRunnableDir : public TestRunnable {
272public:
273 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700274 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700275 fTestFun = testFun;
276 }
277
278};
279
280class TestRunnableFile : public TestRunnable {
281public:
282 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700283 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700284 strcpy(fState.fResult.fFilename, name);
285 fTestFun = testFun;
286 }
287};
288
289class TestRunnableEncode : public TestRunnableFile {
290public:
291 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
292 : TestRunnableFile(testFun, dirNo, name, runner) {
293 fState.fResult.fTestStep = kEncodeFiles;
294 }
295};
296
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000297TestRunner::~TestRunner() {
298 for (int index = 0; index < fRunnables.count(); index++) {
halcanary385fe4d2015-08-26 13:07:48 -0700299 delete fRunnables[index];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000300 }
301}
302
303void TestRunner::render() {
mtklein279c7862016-01-04 19:13:19 -0800304 SkTaskGroup().batch(fRunnables.count(), [&](int i) {
mtklein048494c2016-02-16 19:06:15 -0800305 (*fRunnables[i])();
mtklein00b621c2015-06-17 15:26:15 -0700306 });
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000307}
308
309////////////////////////////////////////////////
310
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000311
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000312static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
313 const int kRowCount = 3;
314 const int kThreshold = 3;
315 int width = SkTMin(gr.width(), sk.width());
316 if (width < kRowCount) {
317 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000318 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000319 int height = SkTMin(gr.height(), sk.height());
320 if (height < kRowCount) {
321 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000322 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000323 int errorTotal = 0;
324 SkTArray<int, true> errorRows;
325 errorRows.push_back_n(width * kRowCount);
326 SkAutoLockPixels autoGr(gr);
327 SkAutoLockPixels autoSk(sk);
328 for (int y = 0; y < height; ++y) {
329 SkPMColor* grRow = gr.getAddr32(0, y);
330 SkPMColor* skRow = sk.getAddr32(0, y);
331 int* base = &errorRows[0];
332 int* cOut = &errorRows[y % kRowCount];
333 for (int x = 0; x < width; ++x) {
334 SkPMColor grColor = grRow[x];
335 SkPMColor skColor = skRow[x];
336 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
337 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
338 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
339 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
340 if (error < kThreshold || x < 2) {
341 continue;
342 }
343 if (base[x - 2] < kThreshold
344 || base[width + x - 2] < kThreshold
345 || base[width * 2 + x - 2] < kThreshold
346 || base[x - 1] < kThreshold
347 || base[width + x - 1] < kThreshold
348 || base[width * 2 + x - 1] < kThreshold
349 || base[x] < kThreshold
350 || base[width + x] < kThreshold
351 || base[width * 2 + x] < kThreshold) {
352 continue;
353 }
354 errorTotal += error;
355 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000356 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000357 return errorTotal;
358}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000359
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000360static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000361 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
362 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000363 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000364 int worstCount = data->fPixelWorst.count();
365 int pixelError = testResult.fPixelError;
366 if (pixelError > 0) {
367 for (int index = 0; index < worstCount; ++index) {
368 if (pixelError > data->fPixelWorst[index].fPixelError) {
369 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
370 return true;
371 }
372 }
373 }
374 int slowCount = data->fSlowest.count();
375 int time = testResult.fTime;
376 if (time > 0) {
377 for (int index = 0; index < slowCount; ++index) {
378 if (time > data->fSlowest[index].fTime) {
379 data->fSlowest[index] = *(SortByTime*) &testResult;
380 return true;
381 }
382 }
383 }
384 if (pixelError > 0 && worstCount < kMaxFiles) {
385 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
386 return true;
387 }
388 if (time > 0 && slowCount < kMaxFiles) {
389 *data->fSlowest.append() = *(SortByTime*) &testResult;
390 return true;
391 }
392 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000393}
394
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000395static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
396 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700397 SkScalar pWidth = pic->cullRect().width();
398 SkScalar pHeight = pic->cullRect().height();
399 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000400 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700401 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
402 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
403 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000404 canvas->clipRect(rect);
405 SkMSec start = SkTime::GetMSecs();
406 for (int x = 0; x < slices; ++x) {
407 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700408 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700409 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000410 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700411 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000412 }
413 SkMSec end = SkTime::GetMSecs();
414 canvas->restore();
415 return end - start;
416}
417
418static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
419 canvas->clear(SK_ColorWHITE);
420 if (scale != 1) {
421 canvas->save();
422 canvas->scale(1.0f / scale, 1.0f / scale);
423 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700424 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000425 if (scale != 1) {
426 canvas->restore();
427 }
428}
429
430static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700431 SkString outFile = get_sum_path(outDir);
432 outFile.appendf("%s%s", PATH_SLASH, pngName);
433 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000434 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
435 bitmap.width(), bitmap.height());
436 }
437}
438
439void TestResult::testOne() {
halcanary96fcdcc2015-08-27 07:41:13 -0700440 SkPicture* pic = nullptr;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000441 {
442 #if DEBUG_SHOW_TEST_NAME
443 if (fTestStep == kCompareBits) {
444 SkString testName(fFilename);
445 const char http[] = "http";
446 if (testName.startsWith(http)) {
447 testName.remove(0, sizeof(http) - 1);
448 }
449 while (testName.startsWith("_")) {
450 testName.remove(0, 1);
451 }
452 const char dotSkp[] = ".skp";
453 if (testName.endsWith(dotSkp)) {
454 size_t len = testName.size();
455 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
456 }
457 testName.prepend("skp");
458 testName.append("1");
459 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
460 } else if (fTestStep == kEncodeFiles) {
461 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
462 }
463 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700464 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000465 SkFILEStream stream(path.c_str());
466 if (!stream.isValid()) {
467 SkDebugf("invalid stream %s\n", path.c_str());
468 goto finish;
469 }
msarett7f7ec202016-03-01 12:12:27 -0800470 pic = SkPicture::CreateFromStream(&stream);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000471 if (!pic) {
472 SkDebugf("unable to decode %s\n", fFilename);
473 goto finish;
474 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700475 SkScalar width = pic->cullRect().width();
476 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000477 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000478 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000479 while (width / fScale > 32767 || height / fScale > 32767) {
480 ++fScale;
481 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000482 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700483 int dimX = SkScalarCeilToInt(width / fScale);
484 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700485 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000486 break;
487 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000488 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000489 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000490 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700491 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000492 width, height);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000493 goto finish;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000494 }
495 oldBitmap.eraseColor(SK_ColorWHITE);
496 SkCanvas oldCanvas(oldBitmap);
497 oldCanvas.setAllowSimplifyClip(false);
498 opBitmap.eraseColor(SK_ColorWHITE);
499 SkCanvas opCanvas(opBitmap);
500 opCanvas.setAllowSimplifyClip(true);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000501 drawPict(pic, &oldCanvas, fScale);
502 drawPict(pic, &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000503 if (fTestStep == kCompareBits) {
504 fPixelError = similarBits(oldBitmap, opBitmap);
505 int oldTime = timePict(pic, &oldCanvas);
506 int opTime = timePict(pic, &opCanvas);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000507 fTime = SkTMax(0, oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000508 } else if (fTestStep == kEncodeFiles) {
509 SkString pngStr = make_png_name(fFilename);
510 const char* pngName = pngStr.c_str();
511 writePict(oldBitmap, outOldDir, pngName);
512 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000513 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000514 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000515finish:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000516 if (pic) {
517 pic->unref();
518 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000519}
520
caryclark19eb3b22014-07-18 05:08:14 -0700521DEFINE_string2(match, m, "PathOpsSkpClipThreaded",
522 "[~][^]substring[$] [...] of test name to run.\n"
523 "Multiple matches may be separated by spaces.\n"
524 "~ causes a matching test to always be skipped\n"
525 "^ requires the start of the test to match\n"
526 "$ requires the end of the test to match\n"
527 "^ and $ requires an exact match\n"
528 "If a test does not match any list entry,\n"
529 "it is skipped unless some list entry starts with ~");
halcanary96fcdcc2015-08-27 07:41:13 -0700530DEFINE_string2(dir, d, nullptr, "range of directories (e.g., 1-100)");
531DEFINE_string2(skp, s, nullptr, "skp to test");
caryclark19eb3b22014-07-18 05:08:14 -0700532DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
533DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only).");
caryclark19eb3b22014-07-18 05:08:14 -0700534DEFINE_bool2(verbose, v, false, "enable verbose output.");
535
536static bool verbose() {
537 return FLAGS_verbose;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000538}
539
caryclark19eb3b22014-07-18 05:08:14 -0700540class Dirs {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000541public:
caryclark19eb3b22014-07-18 05:08:14 -0700542 Dirs() {
543 reset();
544 sk_bzero(fRun, sizeof(fRun));
545 fSet = false;
546 }
547
548 int first() const {
549 int index = 0;
550 while (++index < kMaxDir) {
551 if (fRun[index]) {
552 return index;
553 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000554 }
caryclark19eb3b22014-07-18 05:08:14 -0700555 SkASSERT(0);
556 return -1;
557 }
558
559 int last() const {
560 int index = kMaxDir;
561 while (--index > 0 && !fRun[index])
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000562 ;
caryclark19eb3b22014-07-18 05:08:14 -0700563 return index;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000564 }
565
caryclark19eb3b22014-07-18 05:08:14 -0700566 int next() {
567 while (++fIndex < kMaxDir) {
568 if (fRun[fIndex]) {
569 return fIndex;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000570 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000571 }
caryclark19eb3b22014-07-18 05:08:14 -0700572 return -1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000573 }
574
caryclark19eb3b22014-07-18 05:08:14 -0700575 void reset() {
576 fIndex = -1;
577 }
578
579 void set(int start, int end) {
580 while (start < end) {
581 fRun[start++] = 1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000582 }
caryclark19eb3b22014-07-18 05:08:14 -0700583 fSet = true;
584 }
585
586 void setDefault() {
587 if (!fSet) {
588 set(1, 100);
589 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000590 }
591
592private:
caryclark19eb3b22014-07-18 05:08:14 -0700593 enum {
594 kMaxDir = 101
595 };
596 char fRun[kMaxDir];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000597 int fIndex;
caryclark19eb3b22014-07-18 05:08:14 -0700598 bool fSet;
599} gDirs;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000600
caryclark19eb3b22014-07-18 05:08:14 -0700601class Filenames {
602public:
603 Filenames()
604 : fIndex(-1) {
605 }
606
607 const char* next() {
608 while (fNames && ++fIndex < fNames->count()) {
609 return (*fNames)[fIndex];
610 }
halcanary96fcdcc2015-08-27 07:41:13 -0700611 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -0700612 }
mtklein406654b2014-09-03 15:34:37 -0700613
caryclark19eb3b22014-07-18 05:08:14 -0700614 void set(const SkCommandLineFlags::StringArray& names) {
615 fNames = &names;
616 }
617
618private:
619 int fIndex;
620 const SkCommandLineFlags::StringArray* fNames;
621} gNames;
622
mtklein406654b2014-09-03 15:34:37 -0700623static bool buildTestDir(int dirNo, int firstDirNo,
caryclark19eb3b22014-07-18 05:08:14 -0700624 SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
625 SkString dirName = get_out_path(dirNo, outStatusDir);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000626 if (!dirName.size()) {
627 return false;
628 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000629 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000630 SkString filename;
631 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700632 TestResult test;
633 test.init(dirNo);
634 SkString spaceFile(filename);
635 char* spaces = spaceFile.writable_str();
636 int spaceSize = (int) spaceFile.size();
637 for (int index = 0; index < spaceSize; ++index) {
638 if (spaces[index] == '.') {
639 spaces[index] = ' ';
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000640 }
641 }
caryclark19eb3b22014-07-18 05:08:14 -0700642 int success = sscanf(spaces, "%s %d %d skp", test.fFilename,
643 &test.fPixelError, &test.fTime);
644 if (success < 3) {
645 SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success);
646 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000647 }
caryclark19eb3b22014-07-18 05:08:14 -0700648 *tests[dirNo - firstDirNo].append() = test;
649 }
650 if (!sorted) {
651 return true;
652 }
653 SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo];
654 int count = testSet.count();
655 for (int index = 0; index < count; ++index) {
656 *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index];
657 }
658 if (sorted[dirNo - firstDirNo].count()) {
659 SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(),
660 sorted[dirNo - firstDirNo].end() - 1);
661 if (verbose()) {
662 SkDebugf("+");
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000663 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000664 }
665 return true;
666}
667
caryclark19eb3b22014-07-18 05:08:14 -0700668static void testSkpClip(TestState* data) {
669 data->fResult.testOne();
670 SkString statName(data->fResult.fFilename);
671 SkASSERT(statName.endsWith(".skp"));
672 statName.remove(statName.size() - 4, 4);
673 statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime);
674 SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir);
675 if (!statusFile.size()) {
676 SkDebugf("failed to create %s", statusFile.c_str());
677 return;
678 }
679 statusFile.appendf("%s%s", PATH_SLASH, statName.c_str());
halcanaryd76be9c2015-11-20 13:47:49 -0800680 FILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
caryclark19eb3b22014-07-18 05:08:14 -0700681 if (!file) {
682 SkDebugf("failed to create %s", statusFile.c_str());
683 return;
684 }
685 sk_fclose(file);
686 if (verbose()) {
687 if (data->fResult.fPixelError || data->fResult.fTime) {
688 SkDebugf("%s", data->fResult.progress().c_str());
689 } else {
690 SkDebugf(".");
691 }
692 }
693}
694
695bool Less(const SortByName& a, const SortByName& b);
696bool Less(const SortByName& a, const SortByName& b) {
697 return a < b;
698}
699
700static bool doOneDir(TestState* state, bool threaded) {
701 int dirNo = state->fResult.fDirNo;
halcanary96fcdcc2015-08-27 07:41:13 -0700702 SkString dirName = get_in_path(dirNo, nullptr);
caryclark19eb3b22014-07-18 05:08:14 -0700703 if (!dirName.size()) {
704 return false;
705 }
706 SkTDArray<TestResult> tests[1];
707 SkTDArray<SortByName*> sorted[1];
708 if (!buildTestDir(dirNo, dirNo, tests, sorted)) {
709 return false;
710 }
711 SkOSFile::Iter iter(dirName.c_str(), "skp");
712 SkString filename;
713 while (iter.next(&filename)) {
714 for (size_t index = 0; index < skipOverCount; ++index) {
715 if (skipOver[index].directory == dirNo
716 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
717 goto checkEarlyExit;
718 }
719 }
720 {
721 SortByName name;
722 name.init(dirNo);
723 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
724 int count = sorted[0].count();
725 int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name));
726 if (idx >= 0) {
727 SortByName* found = sorted[0][idx];
728 (void) addError(state, *found);
729 continue;
730 }
731 TestResult test;
732 test.init(dirNo, filename);
733 state->fResult = test;
734 testSkpClip(state);
735#if 0 // artificially limit to a few while debugging code
736 static int debugLimit = 0;
737 if (++debugLimit == 5) {
738 return true;
739 }
740#endif
741 }
742checkEarlyExit:
743 ;
744 }
745 return true;
746}
747
748static void initTest() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000749#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC
750 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
751 SK_CONF_SET("images.png.suppressDecoderWarnings", true);
752#endif
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000753}
754
caryclarkdac1d172014-06-17 05:15:38 -0700755static void testSkpClipEncode(TestState* data) {
756 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700757 if (verbose()) {
758 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700759 }
760}
761
caryclark19eb3b22014-07-18 05:08:14 -0700762static void encodeFound(TestState& state) {
763 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700764 if (state.fPixelWorst.count()) {
765 SkTDArray<SortByPixel*> worst;
766 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
767 *worst.append() = &state.fPixelWorst[index];
768 }
769 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
770 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
771 const TestResult& result = *worst[index];
772 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
773 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000774 }
caryclarkdac1d172014-06-17 05:15:38 -0700775 if (state.fSlowest.count()) {
776 SkTDArray<SortByTime*> slowest;
777 for (int index = 0; index < state.fSlowest.count(); ++index) {
778 *slowest.append() = &state.fSlowest[index];
779 }
780 if (slowest.count() > 0) {
781 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
782 for (int index = 0; index < slowest.count(); ++index) {
783 const TestResult& result = *slowest[index];
784 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
785 }
786 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000787 }
788 }
mtklein406654b2014-09-03 15:34:37 -0700789 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000790 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
791 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700792 SkString filename(result.fFilename);
793 if (!filename.endsWith(".skp")) {
794 filename.append(".skp");
795 }
halcanary385fe4d2015-08-26 13:07:48 -0700796 *testRunner.fRunnables.append() = new TestRunnableEncode(&testSkpClipEncode, result.fDirNo,
797 filename.c_str(), &testRunner);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000798 }
caryclarkdac1d172014-06-17 05:15:38 -0700799 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000800}
801
caryclark19eb3b22014-07-18 05:08:14 -0700802class Test {
803public:
804 Test() {}
805 virtual ~Test() {}
806
807 const char* getName() { onGetName(&fName); return fName.c_str(); }
808 void run() { onRun(); }
809
810protected:
811 virtual void onGetName(SkString*) = 0;
812 virtual void onRun() = 0;
813
814private:
815 SkString fName;
816};
817
818typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
819
halcanary385fe4d2015-08-26 13:07:48 -0700820#define DEF_TEST(name) \
821 static void test_##name(); \
822 class name##Class : public Test { \
823 public: \
824 static Test* Factory(void*) { return new name##Class; } \
825 \
826 protected: \
827 void onGetName(SkString* name) override { name->set(#name); } \
828 void onRun() override { test_##name(); } \
829 }; \
830 static TestRegistry gReg_##name##Class(name##Class::Factory); \
caryclark19eb3b22014-07-18 05:08:14 -0700831 static void test_##name()
832
833DEF_TEST(PathOpsSkpClip) {
834 gDirs.setDefault();
835 initTest();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000836 SkTArray<TestResult, true> errors;
837 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700838 state.init(0);
839 int dirNo;
840 gDirs.reset();
841 while ((dirNo = gDirs.next()) > 0) {
842 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000843 SkDebugf("dirNo=%d\n", dirNo);
844 }
845 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000846 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000847 break;
848 }
849 }
caryclark19eb3b22014-07-18 05:08:14 -0700850 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000851}
852
853static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000854 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000855}
856
caryclark19eb3b22014-07-18 05:08:14 -0700857DEF_TEST(PathOpsSkpClipThreaded) {
858 gDirs.setDefault();
859 initTest();
mtklein406654b2014-09-03 15:34:37 -0700860 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700861 int dirNo;
862 gDirs.reset();
863 while ((dirNo = gDirs.next()) > 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700864 *testRunner.fRunnables.append() = new TestRunnableDir(&testSkpClipMain, dirNo, &testRunner);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000865 }
866 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000867 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700868 state.init(0);
869 gDirs.reset();
870 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000871 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700872 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000873 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000874 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000875 }
caryclarkdac1d172014-06-17 05:15:38 -0700876 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
877 addError(&state, testState.fSlowest[inner]);
878 }
879 }
caryclark19eb3b22014-07-18 05:08:14 -0700880 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700881}
mtklein406654b2014-09-03 15:34:37 -0700882
caryclark19eb3b22014-07-18 05:08:14 -0700883static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
884 int firstDirNo = gDirs.first();
885 int dirNo;
886 while ((dirNo = gDirs.next()) > 0) {
887 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700888 return false;
889 }
caryclarkdac1d172014-06-17 05:15:38 -0700890 }
891 return true;
892}
893
caryclark19eb3b22014-07-18 05:08:14 -0700894DEF_TEST(PathOpsSkpClipUberThreaded) {
895 gDirs.setDefault();
896 const int firstDirNo = gDirs.next();
897 const int lastDirNo = gDirs.last();
898 initTest();
899 int dirCount = lastDirNo - firstDirNo + 1;
900 SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]);
901 SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]);
902 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700903 return;
904 }
mtklein406654b2014-09-03 15:34:37 -0700905 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700906 int dirNo;
907 gDirs.reset();
908 while ((dirNo = gDirs.next()) > 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700909 SkString dirName = get_in_path(dirNo, nullptr);
caryclarkdac1d172014-06-17 05:15:38 -0700910 if (!dirName.size()) {
911 continue;
912 }
913 SkOSFile::Iter iter(dirName.c_str(), "skp");
914 SkString filename;
915 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700916 for (size_t index = 0; index < skipOverCount; ++index) {
917 if (skipOver[index].directory == dirNo
918 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700919 goto checkEarlyExit;
920 }
921 }
caryclark19eb3b22014-07-18 05:08:14 -0700922 {
923 SortByName name;
924 name.init(dirNo);
925 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
926 int count = sorted.get()[dirNo - firstDirNo].count();
927 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
928 count, &name, sizeof(&name)) < 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700929 *testRunner.fRunnables.append() = new TestRunnableFile(
930 &testSkpClip, dirNo, filename.c_str(), &testRunner);
caryclark19eb3b22014-07-18 05:08:14 -0700931 }
caryclarkdac1d172014-06-17 05:15:38 -0700932 }
933 checkEarlyExit:
934 ;
935 }
936
937 }
938 testRunner.render();
caryclark19eb3b22014-07-18 05:08:14 -0700939 SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]);
halcanary96fcdcc2015-08-27 07:41:13 -0700940 if (!buildTests(results.get(), nullptr)) {
caryclarkdac1d172014-06-17 05:15:38 -0700941 return;
942 }
943 SkTDArray<TestResult> allResults;
944 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700945 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700946 allResults.append(array.count(), array.begin());
947 }
948 int allCount = allResults.count();
949 SkTDArray<SortByPixel*> pixels;
950 SkTDArray<SortByTime*> times;
951 for (int index = 0; index < allCount; ++index) {
952 *pixels.append() = (SortByPixel*) &allResults[index];
953 *times.append() = (SortByTime*) &allResults[index];
954 }
955 TestState state;
956 if (pixels.count()) {
957 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
958 for (int inner = 0; inner < kMaxFiles; ++inner) {
959 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
960 }
961 }
962 if (times.count()) {
963 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
964 for (int inner = 0; inner < kMaxFiles; ++inner) {
965 *state.fSlowest.append() = *times[allCount - inner - 1];
966 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000967 }
caryclark19eb3b22014-07-18 05:08:14 -0700968 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000969}
970
caryclark19eb3b22014-07-18 05:08:14 -0700971DEF_TEST(PathOpsSkpClipOneOff) {
972 const int testIndex = FLAGS_testIndex;
973 int dirNo = gDirs.next();
974 if (dirNo < 0) {
975 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000976 }
caryclark19eb3b22014-07-18 05:08:14 -0700977 const char* skp = gNames.next();
978 if (!skp) {
979 skp = skipOver[testIndex].filename;
980 }
981 initTest();
982 SkAssertResult(get_in_path(dirNo, skp).size());
983 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000984 TestResult state;
985 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700986 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000987 SkDebugf("%s", state.status().c_str());
988 }
989 state.fTestStep = kEncodeFiles;
990 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000991}
caryclark19eb3b22014-07-18 05:08:14 -0700992
993DEF_TEST(PathOpsTestSkipped) {
994 for (size_t index = 0; index < skipOverCount; ++index) {
995 const SkipOverTest& skip = skipOver[index];
996 if (!skip.blamePathOps) {
997 continue;
998 }
999 int dirNo = skip.directory;
1000 const char* skp = skip.filename;
1001 initTest();
1002 SkAssertResult(get_in_path(dirNo, skp).size());
1003 SkString filename(skp);
1004 TestResult state;
1005 state.test(dirNo, filename);
1006 if (verbose()) {
1007 SkDebugf("%s", state.status().c_str());
1008 }
1009 state.fTestStep = kEncodeFiles;
1010 state.testOne();
1011 }
1012}
1013
1014DEF_TEST(PathOpsCopyFails) {
1015 FLAGS_verbose = true;
1016 for (size_t index = 0; index < skipOverCount; ++index) {
1017 int dirNo = skipOver[index].directory;
1018 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1019 }
1020 for (size_t index = 0; index < skipOverCount; ++index) {
1021 int dirNo = skipOver[index].directory;
1022 const char* filename = skipOver[index].filename;
1023 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1024 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1025 }
1026}
1027
1028template TestRegistry* TestRegistry::gHead;
1029
1030class Iter {
1031public:
1032 Iter() { this->reset(); }
1033 void reset() { fReg = TestRegistry::Head(); }
1034
1035 Test* next() {
1036 if (fReg) {
1037 TestRegistry::Factory fact = fReg->factory();
1038 fReg = fReg->next();
halcanary96fcdcc2015-08-27 07:41:13 -07001039 Test* test = fact(nullptr);
caryclark19eb3b22014-07-18 05:08:14 -07001040 return test;
1041 }
halcanary96fcdcc2015-08-27 07:41:13 -07001042 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -07001043 }
1044
1045private:
1046 const TestRegistry* fReg;
1047};
1048
1049int tool_main(int argc, char** argv);
1050int tool_main(int argc, char** argv) {
1051 SetupCrashHandler();
1052 SkCommandLineFlags::SetUsage("");
1053 SkCommandLineFlags::Parse(argc, argv);
1054 SkGraphics::Init();
1055 SkString header("PathOps SkpClip:");
1056 if (!FLAGS_match.isEmpty()) {
1057 header.appendf(" --match");
1058 for (int index = 0; index < FLAGS_match.count(); ++index) {
1059 header.appendf(" %s", FLAGS_match[index]);
1060 }
1061 }
1062 if (!FLAGS_dir.isEmpty()) {
1063 int count = FLAGS_dir.count();
1064 for (int i = 0; i < count; ++i) {
1065 const char* range = FLAGS_dir[i];
1066 const char* dash = strchr(range, '-');
1067 if (!dash) {
1068 dash = strchr(range, ',');
1069 }
1070 int first = atoi(range);
1071 int last = dash ? atoi(dash + 1) : first;
1072 if (!first || !last) {
1073 SkDebugf("couldn't parse --dir %s\n", range);
1074 return 1;
1075 }
1076 gDirs.set(first, last);
1077 }
1078 }
1079 if (!FLAGS_skp.isEmpty()) {
1080 gNames.set(FLAGS_skp);
1081 }
1082#ifdef SK_DEBUG
1083 header.append(" SK_DEBUG");
1084#else
1085 header.append(" SK_RELEASE");
1086#endif
caryclark19eb3b22014-07-18 05:08:14 -07001087 if (FLAGS_verbose) {
1088 header.appendf("\n");
1089 }
kkinnunen297aaf92015-02-19 06:32:12 -08001090 SkDebugf("%s", header.c_str());
caryclark19eb3b22014-07-18 05:08:14 -07001091 Iter iter;
1092 Test* test;
halcanary96fcdcc2015-08-27 07:41:13 -07001093 while ((test = iter.next()) != nullptr) {
caryclark19eb3b22014-07-18 05:08:14 -07001094 SkAutoTDelete<Test> owned(test);
1095 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1096 test->run();
1097 }
1098 }
caryclark19eb3b22014-07-18 05:08:14 -07001099 return 0;
1100}
1101
borenet48087572015-04-02 12:16:36 -07001102#if !defined(SK_BUILD_FOR_IOS)
caryclark19eb3b22014-07-18 05:08:14 -07001103int main(int argc, char * const argv[]) {
1104 return tool_main(argc, (char**) argv);
1105}
1106#endif