blob: 3c958f1bece4937c57f3c58d37dbca5f43cfeb7b [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"
caryclark19eb3b22014-07-18 05:08:14 -070016#include "SkForceLinking.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000017#include "SkGraphics.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000018#include "SkImageEncoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000019#include "SkOSFile.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000020#include "SkPathOpsDebug.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000021#include "SkPicture.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000022#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000023#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000024#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000025#include "SkTArray.h"
26#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070027#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070028#include "SkTemplates.h"
halcanary4e44efe2016-08-04 10:47:16 -070029#include "SkTSearch.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000030#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000031
bungeman60e0fee2015-08-26 05:15:46 -070032#include <stdlib.h>
33
caryclark19eb3b22014-07-18 05:08:14 -070034/* add local exceptions here */
35/* TODO : add command flag interface */
36const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000037 int directory;
38 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070039 bool blamePathOps;
40} skipOver[] = {
41 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
42 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
43 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
44 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
45 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070046 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070047 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
48 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
49 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
50 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
51 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
52 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
53 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
54 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
55 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
56 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
57 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
58 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
59 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
60 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000061};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000062
caryclark19eb3b22014-07-18 05:08:14 -070063size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070064
caryclark19eb3b22014-07-18 05:08:14 -070065
66/* customize file in/out here */
67/* TODO : add command flag interface */
68#define CHROME_VERSION "1e5dfa4-4a995df"
69#define SUMMARY_RUN 1
70
71#ifdef SK_BUILD_FOR_WIN
72 #define DRIVE_SPEC "D:"
73 #define PATH_SLASH "\\"
74#else
75 #define DRIVE_SPEC ""
76 #define PATH_SLASH "/"
77#endif
78
79#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
80#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
81#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
82#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
83
84static const char outOpDir[] = "opClip";
85static const char outOldDir[] = "oldClip";
86static const char outStatusDir[] = "statusTest";
87
88static SkString get_in_path(int dirNo, const char* filename) {
89 SkString path;
90 SkASSERT(dirNo);
91 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
92 if (!sk_exists(path.c_str())) {
93 SkDebugf("could not read %s\n", path.c_str());
94 return SkString();
95 }
96 if (filename) {
97 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -070098 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -070099 SkDebugf("could not read %s\n", path.c_str());
100 return SkString();
101 }
102 }
103 return path;
104}
mtklein406654b2014-09-03 15:34:37 -0700105
caryclark19eb3b22014-07-18 05:08:14 -0700106static void make_recursive_dir(const SkString& path) {
107 if (sk_exists(path.c_str())) {
108 return;
109 }
110 const char* pathStr = path.c_str();
111 int last = (int) path.size();
112 do {
113 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
114 ;
115 SkASSERT(last > 0);
116 SkString shorter(pathStr, last);
117 if (sk_mkdir(shorter.c_str())) {
118 break;
119 }
120 } while (true);
121 do {
122 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
123 ;
124 SkString shorter(pathStr, last);
125 SkAssertResult(sk_mkdir(shorter.c_str()));
126 } while (last < (int) path.size());
127}
128
129static SkString get_out_path(int dirNo, const char* dirName) {
130 SkString path;
131 SkASSERT(dirNo);
132 SkASSERT(dirName);
133 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
134 make_recursive_dir(path);
135 return path;
136}
mtklein406654b2014-09-03 15:34:37 -0700137
caryclark19eb3b22014-07-18 05:08:14 -0700138static SkString get_sum_path(const char* dirName) {
139 SkString path;
140 SkASSERT(dirName);
141 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
142 SkDebugf("%s\n", path.c_str());
143 make_recursive_dir(path);
144 return path;
145}
146
147static SkString make_png_name(const char* filename) {
148 SkString pngName = SkString(filename);
149 pngName.remove(pngName.size() - 3, 3);
150 pngName.append("png");
151 return pngName;
152}
153
154////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000155
156enum TestStep {
157 kCompareBits,
158 kEncodeFiles,
159};
160
161enum {
caryclarkdac1d172014-06-17 05:15:38 -0700162 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000163 kMaxFiles = 128,
164 kSmallLimit = 1000,
165};
166
167struct TestResult {
168 void init(int dirNo) {
169 fDirNo = dirNo;
170 sk_bzero(fFilename, sizeof(fFilename));
171 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000172 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000173 }
mtklein406654b2014-09-03 15:34:37 -0700174
caryclark19eb3b22014-07-18 05:08:14 -0700175 void init(int dirNo, const SkString& filename) {
176 fDirNo = dirNo;
177 strcpy(fFilename, filename.c_str());
178 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700179 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700180 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000181
182 SkString status() {
183 SkString outStr;
184 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
185 return outStr;
186 }
187
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000188 SkString progress() {
189 SkString outStr;
190 outStr.printf("dir=%d %s ", fDirNo, fFilename);
191 if (fPixelError) {
192 outStr.appendf(" err=%d", fPixelError);
193 }
194 if (fTime) {
195 outStr.appendf(" time=%d", fTime);
196 }
197 if (fScale != 1) {
198 outStr.appendf(" scale=%d", fScale);
199 }
200 outStr.appendf("\n");
201 return outStr;
202
203 }
204
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000205 void test(int dirNo, const SkString& filename) {
206 init(dirNo);
207 strcpy(fFilename, filename.c_str());
208 testOne();
209 }
210
211 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700212
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000213 char fFilename[kMaxLength];
214 TestStep fTestStep;
215 int fDirNo;
216 int fPixelError;
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700217 SkMSec fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000218 int fScale;
219};
220
221class SortByPixel : public TestResult {
222public:
223 bool operator<(const SortByPixel& rh) const {
224 return fPixelError < rh.fPixelError;
225 }
226};
227
228class SortByTime : public TestResult {
229public:
230 bool operator<(const SortByTime& rh) const {
231 return fTime < rh.fTime;
232 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000233};
234
caryclarkdac1d172014-06-17 05:15:38 -0700235class SortByName : public TestResult {
236public:
237 bool operator<(const SortByName& rh) const {
238 return strcmp(fFilename, rh.fFilename) < 0;
239 }
240};
241
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000242struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700243 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000244 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000245 }
246
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000247 SkTDArray<SortByPixel> fPixelWorst;
248 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000249 TestResult fResult;
250};
251
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000252struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000253 ~TestRunner();
254 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000255 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000256};
257
mtklein048494c2016-02-16 19:06:15 -0800258class TestRunnable {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000259public:
mtklein048494c2016-02-16 19:06:15 -0800260 void operator()() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000261 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
262 (*fTestFun)(&fState);
263 }
264
265 TestState fState;
266 void (*fTestFun)(TestState*);
267};
268
caryclarkdac1d172014-06-17 05:15:38 -0700269
270class TestRunnableDir : public TestRunnable {
271public:
272 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700273 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700274 fTestFun = testFun;
275 }
276
277};
278
279class TestRunnableFile : public TestRunnable {
280public:
281 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700282 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700283 strcpy(fState.fResult.fFilename, name);
284 fTestFun = testFun;
285 }
286};
287
288class TestRunnableEncode : public TestRunnableFile {
289public:
290 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
291 : TestRunnableFile(testFun, dirNo, name, runner) {
292 fState.fResult.fTestStep = kEncodeFiles;
293 }
294};
295
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000296TestRunner::~TestRunner() {
297 for (int index = 0; index < fRunnables.count(); index++) {
halcanary385fe4d2015-08-26 13:07:48 -0700298 delete fRunnables[index];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000299 }
300}
301
302void TestRunner::render() {
mtklein279c7862016-01-04 19:13:19 -0800303 SkTaskGroup().batch(fRunnables.count(), [&](int i) {
mtklein048494c2016-02-16 19:06:15 -0800304 (*fRunnables[i])();
mtklein00b621c2015-06-17 15:26:15 -0700305 });
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000306}
307
308////////////////////////////////////////////////
309
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000310
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000311static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
312 const int kRowCount = 3;
313 const int kThreshold = 3;
314 int width = SkTMin(gr.width(), sk.width());
315 if (width < kRowCount) {
316 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000317 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000318 int height = SkTMin(gr.height(), sk.height());
319 if (height < kRowCount) {
320 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000321 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000322 int errorTotal = 0;
323 SkTArray<int, true> errorRows;
324 errorRows.push_back_n(width * kRowCount);
325 SkAutoLockPixels autoGr(gr);
326 SkAutoLockPixels autoSk(sk);
327 for (int y = 0; y < height; ++y) {
328 SkPMColor* grRow = gr.getAddr32(0, y);
329 SkPMColor* skRow = sk.getAddr32(0, y);
330 int* base = &errorRows[0];
331 int* cOut = &errorRows[y % kRowCount];
332 for (int x = 0; x < width; ++x) {
333 SkPMColor grColor = grRow[x];
334 SkPMColor skColor = skRow[x];
335 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
336 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
337 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
338 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
339 if (error < kThreshold || x < 2) {
340 continue;
341 }
342 if (base[x - 2] < kThreshold
343 || base[width + x - 2] < kThreshold
344 || base[width * 2 + x - 2] < kThreshold
345 || base[x - 1] < kThreshold
346 || base[width + x - 1] < kThreshold
347 || base[width * 2 + x - 1] < kThreshold
348 || base[x] < kThreshold
349 || base[width + x] < kThreshold
350 || base[width * 2 + x] < kThreshold) {
351 continue;
352 }
353 errorTotal += error;
354 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000355 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000356 return errorTotal;
357}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000358
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000359static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000360 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
361 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000362 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000363 int worstCount = data->fPixelWorst.count();
364 int pixelError = testResult.fPixelError;
365 if (pixelError > 0) {
366 for (int index = 0; index < worstCount; ++index) {
367 if (pixelError > data->fPixelWorst[index].fPixelError) {
368 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
369 return true;
370 }
371 }
372 }
373 int slowCount = data->fSlowest.count();
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700374 SkMSec time = testResult.fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000375 if (time > 0) {
376 for (int index = 0; index < slowCount; ++index) {
377 if (time > data->fSlowest[index].fTime) {
378 data->fSlowest[index] = *(SortByTime*) &testResult;
379 return true;
380 }
381 }
382 }
383 if (pixelError > 0 && worstCount < kMaxFiles) {
384 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
385 return true;
386 }
387 if (time > 0 && slowCount < kMaxFiles) {
388 *data->fSlowest.append() = *(SortByTime*) &testResult;
389 return true;
390 }
391 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000392}
393
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000394static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
395 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700396 SkScalar pWidth = pic->cullRect().width();
397 SkScalar pHeight = pic->cullRect().height();
398 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000399 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700400 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
401 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
402 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000403 canvas->clipRect(rect);
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700404 double start = SkTime::GetMSecs();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000405 for (int x = 0; x < slices; ++x) {
406 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700407 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700408 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000409 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700410 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000411 }
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700412 double end = SkTime::GetMSecs();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000413 canvas->restore();
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700414 return static_cast<SkMSec>(end - start);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000415}
416
417static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
418 canvas->clear(SK_ColorWHITE);
419 if (scale != 1) {
420 canvas->save();
421 canvas->scale(1.0f / scale, 1.0f / scale);
422 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700423 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000424 if (scale != 1) {
425 canvas->restore();
426 }
427}
428
429static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700430 SkString outFile = get_sum_path(outDir);
431 outFile.appendf("%s%s", PATH_SLASH, pngName);
432 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000433 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
434 bitmap.width(), bitmap.height());
435 }
436}
437
438void TestResult::testOne() {
reedca2622b2016-03-18 07:25:55 -0700439 sk_sp<SkPicture> pic;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000440 {
441 #if DEBUG_SHOW_TEST_NAME
442 if (fTestStep == kCompareBits) {
443 SkString testName(fFilename);
444 const char http[] = "http";
445 if (testName.startsWith(http)) {
446 testName.remove(0, sizeof(http) - 1);
447 }
448 while (testName.startsWith("_")) {
449 testName.remove(0, 1);
450 }
451 const char dotSkp[] = ".skp";
452 if (testName.endsWith(dotSkp)) {
453 size_t len = testName.size();
454 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
455 }
456 testName.prepend("skp");
457 testName.append("1");
458 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
459 } else if (fTestStep == kEncodeFiles) {
460 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
461 }
462 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700463 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000464 SkFILEStream stream(path.c_str());
465 if (!stream.isValid()) {
466 SkDebugf("invalid stream %s\n", path.c_str());
reedca2622b2016-03-18 07:25:55 -0700467 return;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000468 }
reedca2622b2016-03-18 07:25:55 -0700469 pic = SkPicture::MakeFromStream(&stream);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000470 if (!pic) {
471 SkDebugf("unable to decode %s\n", fFilename);
reedca2622b2016-03-18 07:25:55 -0700472 return;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000473 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700474 SkScalar width = pic->cullRect().width();
475 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000476 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000477 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000478 while (width / fScale > 32767 || height / fScale > 32767) {
479 ++fScale;
480 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000481 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700482 int dimX = SkScalarCeilToInt(width / fScale);
483 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700484 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000485 break;
486 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000487 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000488 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000489 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700490 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000491 width, height);
reedca2622b2016-03-18 07:25:55 -0700492 return;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000493 }
494 oldBitmap.eraseColor(SK_ColorWHITE);
495 SkCanvas oldCanvas(oldBitmap);
496 oldCanvas.setAllowSimplifyClip(false);
497 opBitmap.eraseColor(SK_ColorWHITE);
498 SkCanvas opCanvas(opBitmap);
499 opCanvas.setAllowSimplifyClip(true);
reedca2622b2016-03-18 07:25:55 -0700500 drawPict(pic.get(), &oldCanvas, fScale);
501 drawPict(pic.get(), &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000502 if (fTestStep == kCompareBits) {
503 fPixelError = similarBits(oldBitmap, opBitmap);
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700504 SkMSec oldTime = timePict(pic.get(), &oldCanvas);
505 SkMSec opTime = timePict(pic.get(), &opCanvas);
506 fTime = SkTMax(static_cast<SkMSec>(0), oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000507 } else if (fTestStep == kEncodeFiles) {
508 SkString pngStr = make_png_name(fFilename);
509 const char* pngName = pngStr.c_str();
510 writePict(oldBitmap, outOldDir, pngName);
511 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000512 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000513 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000514}
515
caryclark19eb3b22014-07-18 05:08:14 -0700516DEFINE_string2(match, m, "PathOpsSkpClipThreaded",
517 "[~][^]substring[$] [...] of test name to run.\n"
518 "Multiple matches may be separated by spaces.\n"
519 "~ causes a matching test to always be skipped\n"
520 "^ requires the start of the test to match\n"
521 "$ requires the end of the test to match\n"
522 "^ and $ requires an exact match\n"
523 "If a test does not match any list entry,\n"
524 "it is skipped unless some list entry starts with ~");
halcanary96fcdcc2015-08-27 07:41:13 -0700525DEFINE_string2(dir, d, nullptr, "range of directories (e.g., 1-100)");
526DEFINE_string2(skp, s, nullptr, "skp to test");
caryclark19eb3b22014-07-18 05:08:14 -0700527DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
528DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only).");
caryclark19eb3b22014-07-18 05:08:14 -0700529DEFINE_bool2(verbose, v, false, "enable verbose output.");
530
531static bool verbose() {
532 return FLAGS_verbose;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000533}
534
caryclark19eb3b22014-07-18 05:08:14 -0700535class Dirs {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000536public:
caryclark19eb3b22014-07-18 05:08:14 -0700537 Dirs() {
538 reset();
539 sk_bzero(fRun, sizeof(fRun));
540 fSet = false;
541 }
542
543 int first() const {
544 int index = 0;
545 while (++index < kMaxDir) {
546 if (fRun[index]) {
547 return index;
548 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000549 }
caryclark19eb3b22014-07-18 05:08:14 -0700550 SkASSERT(0);
551 return -1;
552 }
553
554 int last() const {
555 int index = kMaxDir;
556 while (--index > 0 && !fRun[index])
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000557 ;
caryclark19eb3b22014-07-18 05:08:14 -0700558 return index;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000559 }
560
caryclark19eb3b22014-07-18 05:08:14 -0700561 int next() {
562 while (++fIndex < kMaxDir) {
563 if (fRun[fIndex]) {
564 return fIndex;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000565 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000566 }
caryclark19eb3b22014-07-18 05:08:14 -0700567 return -1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000568 }
569
caryclark19eb3b22014-07-18 05:08:14 -0700570 void reset() {
571 fIndex = -1;
572 }
573
574 void set(int start, int end) {
575 while (start < end) {
576 fRun[start++] = 1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000577 }
caryclark19eb3b22014-07-18 05:08:14 -0700578 fSet = true;
579 }
580
581 void setDefault() {
582 if (!fSet) {
583 set(1, 100);
584 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000585 }
586
587private:
caryclark19eb3b22014-07-18 05:08:14 -0700588 enum {
589 kMaxDir = 101
590 };
591 char fRun[kMaxDir];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000592 int fIndex;
caryclark19eb3b22014-07-18 05:08:14 -0700593 bool fSet;
594} gDirs;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000595
caryclark19eb3b22014-07-18 05:08:14 -0700596class Filenames {
597public:
598 Filenames()
599 : fIndex(-1) {
600 }
601
602 const char* next() {
603 while (fNames && ++fIndex < fNames->count()) {
604 return (*fNames)[fIndex];
605 }
halcanary96fcdcc2015-08-27 07:41:13 -0700606 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -0700607 }
mtklein406654b2014-09-03 15:34:37 -0700608
caryclark19eb3b22014-07-18 05:08:14 -0700609 void set(const SkCommandLineFlags::StringArray& names) {
610 fNames = &names;
611 }
612
613private:
614 int fIndex;
615 const SkCommandLineFlags::StringArray* fNames;
616} gNames;
617
mtklein406654b2014-09-03 15:34:37 -0700618static bool buildTestDir(int dirNo, int firstDirNo,
caryclark19eb3b22014-07-18 05:08:14 -0700619 SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
620 SkString dirName = get_out_path(dirNo, outStatusDir);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000621 if (!dirName.size()) {
622 return false;
623 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000624 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000625 SkString filename;
626 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700627 TestResult test;
628 test.init(dirNo);
629 SkString spaceFile(filename);
630 char* spaces = spaceFile.writable_str();
631 int spaceSize = (int) spaceFile.size();
632 for (int index = 0; index < spaceSize; ++index) {
633 if (spaces[index] == '.') {
634 spaces[index] = ' ';
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000635 }
636 }
caryclark19eb3b22014-07-18 05:08:14 -0700637 int success = sscanf(spaces, "%s %d %d skp", test.fFilename,
638 &test.fPixelError, &test.fTime);
639 if (success < 3) {
640 SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success);
641 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000642 }
caryclark19eb3b22014-07-18 05:08:14 -0700643 *tests[dirNo - firstDirNo].append() = test;
644 }
645 if (!sorted) {
646 return true;
647 }
648 SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo];
649 int count = testSet.count();
650 for (int index = 0; index < count; ++index) {
651 *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index];
652 }
653 if (sorted[dirNo - firstDirNo].count()) {
654 SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(),
655 sorted[dirNo - firstDirNo].end() - 1);
656 if (verbose()) {
657 SkDebugf("+");
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000658 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000659 }
660 return true;
661}
662
caryclark19eb3b22014-07-18 05:08:14 -0700663static void testSkpClip(TestState* data) {
664 data->fResult.testOne();
665 SkString statName(data->fResult.fFilename);
666 SkASSERT(statName.endsWith(".skp"));
667 statName.remove(statName.size() - 4, 4);
668 statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime);
669 SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir);
670 if (!statusFile.size()) {
671 SkDebugf("failed to create %s", statusFile.c_str());
672 return;
673 }
674 statusFile.appendf("%s%s", PATH_SLASH, statName.c_str());
halcanaryd76be9c2015-11-20 13:47:49 -0800675 FILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
caryclark19eb3b22014-07-18 05:08:14 -0700676 if (!file) {
677 SkDebugf("failed to create %s", statusFile.c_str());
678 return;
679 }
680 sk_fclose(file);
681 if (verbose()) {
682 if (data->fResult.fPixelError || data->fResult.fTime) {
683 SkDebugf("%s", data->fResult.progress().c_str());
684 } else {
685 SkDebugf(".");
686 }
687 }
688}
689
690bool Less(const SortByName& a, const SortByName& b);
691bool Less(const SortByName& a, const SortByName& b) {
692 return a < b;
693}
694
695static bool doOneDir(TestState* state, bool threaded) {
696 int dirNo = state->fResult.fDirNo;
halcanary96fcdcc2015-08-27 07:41:13 -0700697 SkString dirName = get_in_path(dirNo, nullptr);
caryclark19eb3b22014-07-18 05:08:14 -0700698 if (!dirName.size()) {
699 return false;
700 }
701 SkTDArray<TestResult> tests[1];
702 SkTDArray<SortByName*> sorted[1];
703 if (!buildTestDir(dirNo, dirNo, tests, sorted)) {
704 return false;
705 }
706 SkOSFile::Iter iter(dirName.c_str(), "skp");
707 SkString filename;
708 while (iter.next(&filename)) {
709 for (size_t index = 0; index < skipOverCount; ++index) {
710 if (skipOver[index].directory == dirNo
711 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
712 goto checkEarlyExit;
713 }
714 }
715 {
716 SortByName name;
717 name.init(dirNo);
718 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
719 int count = sorted[0].count();
720 int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name));
721 if (idx >= 0) {
722 SortByName* found = sorted[0][idx];
723 (void) addError(state, *found);
724 continue;
725 }
726 TestResult test;
727 test.init(dirNo, filename);
728 state->fResult = test;
729 testSkpClip(state);
730#if 0 // artificially limit to a few while debugging code
731 static int debugLimit = 0;
732 if (++debugLimit == 5) {
733 return true;
734 }
735#endif
736 }
737checkEarlyExit:
738 ;
739 }
740 return true;
741}
742
caryclarkdac1d172014-06-17 05:15:38 -0700743static void testSkpClipEncode(TestState* data) {
744 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700745 if (verbose()) {
746 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700747 }
748}
749
caryclark19eb3b22014-07-18 05:08:14 -0700750static void encodeFound(TestState& state) {
751 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700752 if (state.fPixelWorst.count()) {
753 SkTDArray<SortByPixel*> worst;
754 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
755 *worst.append() = &state.fPixelWorst[index];
756 }
757 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
758 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
759 const TestResult& result = *worst[index];
760 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
761 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000762 }
caryclarkdac1d172014-06-17 05:15:38 -0700763 if (state.fSlowest.count()) {
764 SkTDArray<SortByTime*> slowest;
765 for (int index = 0; index < state.fSlowest.count(); ++index) {
766 *slowest.append() = &state.fSlowest[index];
767 }
768 if (slowest.count() > 0) {
769 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
770 for (int index = 0; index < slowest.count(); ++index) {
771 const TestResult& result = *slowest[index];
772 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
773 }
774 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000775 }
776 }
mtklein406654b2014-09-03 15:34:37 -0700777 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000778 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
779 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700780 SkString filename(result.fFilename);
781 if (!filename.endsWith(".skp")) {
782 filename.append(".skp");
783 }
halcanary385fe4d2015-08-26 13:07:48 -0700784 *testRunner.fRunnables.append() = new TestRunnableEncode(&testSkpClipEncode, result.fDirNo,
785 filename.c_str(), &testRunner);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000786 }
caryclarkdac1d172014-06-17 05:15:38 -0700787 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000788}
789
caryclark19eb3b22014-07-18 05:08:14 -0700790class Test {
791public:
792 Test() {}
793 virtual ~Test() {}
794
795 const char* getName() { onGetName(&fName); return fName.c_str(); }
796 void run() { onRun(); }
797
798protected:
799 virtual void onGetName(SkString*) = 0;
800 virtual void onRun() = 0;
801
802private:
803 SkString fName;
804};
805
806typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
807
halcanary385fe4d2015-08-26 13:07:48 -0700808#define DEF_TEST(name) \
809 static void test_##name(); \
810 class name##Class : public Test { \
811 public: \
812 static Test* Factory(void*) { return new name##Class; } \
813 \
814 protected: \
815 void onGetName(SkString* name) override { name->set(#name); } \
816 void onRun() override { test_##name(); } \
817 }; \
818 static TestRegistry gReg_##name##Class(name##Class::Factory); \
caryclark19eb3b22014-07-18 05:08:14 -0700819 static void test_##name()
820
821DEF_TEST(PathOpsSkpClip) {
822 gDirs.setDefault();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000823 SkTArray<TestResult, true> errors;
824 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700825 state.init(0);
826 int dirNo;
827 gDirs.reset();
828 while ((dirNo = gDirs.next()) > 0) {
829 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000830 SkDebugf("dirNo=%d\n", dirNo);
831 }
832 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000833 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000834 break;
835 }
836 }
caryclark19eb3b22014-07-18 05:08:14 -0700837 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000838}
839
840static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000841 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000842}
843
caryclark19eb3b22014-07-18 05:08:14 -0700844DEF_TEST(PathOpsSkpClipThreaded) {
845 gDirs.setDefault();
mtklein406654b2014-09-03 15:34:37 -0700846 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700847 int dirNo;
848 gDirs.reset();
849 while ((dirNo = gDirs.next()) > 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700850 *testRunner.fRunnables.append() = new TestRunnableDir(&testSkpClipMain, dirNo, &testRunner);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000851 }
852 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000853 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700854 state.init(0);
855 gDirs.reset();
856 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000857 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700858 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000859 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000860 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000861 }
caryclarkdac1d172014-06-17 05:15:38 -0700862 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
863 addError(&state, testState.fSlowest[inner]);
864 }
865 }
caryclark19eb3b22014-07-18 05:08:14 -0700866 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700867}
mtklein406654b2014-09-03 15:34:37 -0700868
caryclark19eb3b22014-07-18 05:08:14 -0700869static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
870 int firstDirNo = gDirs.first();
871 int dirNo;
872 while ((dirNo = gDirs.next()) > 0) {
873 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700874 return false;
875 }
caryclarkdac1d172014-06-17 05:15:38 -0700876 }
877 return true;
878}
879
caryclark19eb3b22014-07-18 05:08:14 -0700880DEF_TEST(PathOpsSkpClipUberThreaded) {
881 gDirs.setDefault();
882 const int firstDirNo = gDirs.next();
883 const int lastDirNo = gDirs.last();
caryclark19eb3b22014-07-18 05:08:14 -0700884 int dirCount = lastDirNo - firstDirNo + 1;
885 SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]);
886 SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]);
887 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700888 return;
889 }
mtklein406654b2014-09-03 15:34:37 -0700890 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700891 int dirNo;
892 gDirs.reset();
893 while ((dirNo = gDirs.next()) > 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700894 SkString dirName = get_in_path(dirNo, nullptr);
caryclarkdac1d172014-06-17 05:15:38 -0700895 if (!dirName.size()) {
896 continue;
897 }
898 SkOSFile::Iter iter(dirName.c_str(), "skp");
899 SkString filename;
900 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700901 for (size_t index = 0; index < skipOverCount; ++index) {
902 if (skipOver[index].directory == dirNo
903 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700904 goto checkEarlyExit;
905 }
906 }
caryclark19eb3b22014-07-18 05:08:14 -0700907 {
908 SortByName name;
909 name.init(dirNo);
910 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
911 int count = sorted.get()[dirNo - firstDirNo].count();
912 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
913 count, &name, sizeof(&name)) < 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700914 *testRunner.fRunnables.append() = new TestRunnableFile(
915 &testSkpClip, dirNo, filename.c_str(), &testRunner);
caryclark19eb3b22014-07-18 05:08:14 -0700916 }
caryclarkdac1d172014-06-17 05:15:38 -0700917 }
918 checkEarlyExit:
919 ;
920 }
921
922 }
923 testRunner.render();
caryclark19eb3b22014-07-18 05:08:14 -0700924 SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]);
halcanary96fcdcc2015-08-27 07:41:13 -0700925 if (!buildTests(results.get(), nullptr)) {
caryclarkdac1d172014-06-17 05:15:38 -0700926 return;
927 }
928 SkTDArray<TestResult> allResults;
929 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700930 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700931 allResults.append(array.count(), array.begin());
932 }
933 int allCount = allResults.count();
934 SkTDArray<SortByPixel*> pixels;
935 SkTDArray<SortByTime*> times;
936 for (int index = 0; index < allCount; ++index) {
937 *pixels.append() = (SortByPixel*) &allResults[index];
938 *times.append() = (SortByTime*) &allResults[index];
939 }
940 TestState state;
941 if (pixels.count()) {
942 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
943 for (int inner = 0; inner < kMaxFiles; ++inner) {
944 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
945 }
946 }
947 if (times.count()) {
948 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
949 for (int inner = 0; inner < kMaxFiles; ++inner) {
950 *state.fSlowest.append() = *times[allCount - inner - 1];
951 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000952 }
caryclark19eb3b22014-07-18 05:08:14 -0700953 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000954}
955
caryclark19eb3b22014-07-18 05:08:14 -0700956DEF_TEST(PathOpsSkpClipOneOff) {
957 const int testIndex = FLAGS_testIndex;
958 int dirNo = gDirs.next();
959 if (dirNo < 0) {
960 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000961 }
caryclark19eb3b22014-07-18 05:08:14 -0700962 const char* skp = gNames.next();
963 if (!skp) {
964 skp = skipOver[testIndex].filename;
965 }
caryclark19eb3b22014-07-18 05:08:14 -0700966 SkAssertResult(get_in_path(dirNo, skp).size());
967 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000968 TestResult state;
969 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700970 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000971 SkDebugf("%s", state.status().c_str());
972 }
973 state.fTestStep = kEncodeFiles;
974 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000975}
caryclark19eb3b22014-07-18 05:08:14 -0700976
977DEF_TEST(PathOpsTestSkipped) {
978 for (size_t index = 0; index < skipOverCount; ++index) {
979 const SkipOverTest& skip = skipOver[index];
980 if (!skip.blamePathOps) {
981 continue;
982 }
983 int dirNo = skip.directory;
984 const char* skp = skip.filename;
caryclark19eb3b22014-07-18 05:08:14 -0700985 SkAssertResult(get_in_path(dirNo, skp).size());
986 SkString filename(skp);
987 TestResult state;
988 state.test(dirNo, filename);
989 if (verbose()) {
990 SkDebugf("%s", state.status().c_str());
991 }
992 state.fTestStep = kEncodeFiles;
993 state.testOne();
994 }
995}
996
997DEF_TEST(PathOpsCopyFails) {
998 FLAGS_verbose = true;
999 for (size_t index = 0; index < skipOverCount; ++index) {
1000 int dirNo = skipOver[index].directory;
1001 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1002 }
1003 for (size_t index = 0; index < skipOverCount; ++index) {
1004 int dirNo = skipOver[index].directory;
1005 const char* filename = skipOver[index].filename;
1006 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1007 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1008 }
1009}
1010
1011template TestRegistry* TestRegistry::gHead;
1012
1013class Iter {
1014public:
1015 Iter() { this->reset(); }
1016 void reset() { fReg = TestRegistry::Head(); }
1017
1018 Test* next() {
1019 if (fReg) {
1020 TestRegistry::Factory fact = fReg->factory();
1021 fReg = fReg->next();
halcanary96fcdcc2015-08-27 07:41:13 -07001022 Test* test = fact(nullptr);
caryclark19eb3b22014-07-18 05:08:14 -07001023 return test;
1024 }
halcanary96fcdcc2015-08-27 07:41:13 -07001025 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -07001026 }
1027
1028private:
1029 const TestRegistry* fReg;
1030};
1031
1032int tool_main(int argc, char** argv);
1033int tool_main(int argc, char** argv) {
1034 SetupCrashHandler();
1035 SkCommandLineFlags::SetUsage("");
1036 SkCommandLineFlags::Parse(argc, argv);
1037 SkGraphics::Init();
1038 SkString header("PathOps SkpClip:");
1039 if (!FLAGS_match.isEmpty()) {
1040 header.appendf(" --match");
1041 for (int index = 0; index < FLAGS_match.count(); ++index) {
1042 header.appendf(" %s", FLAGS_match[index]);
1043 }
1044 }
1045 if (!FLAGS_dir.isEmpty()) {
1046 int count = FLAGS_dir.count();
1047 for (int i = 0; i < count; ++i) {
1048 const char* range = FLAGS_dir[i];
1049 const char* dash = strchr(range, '-');
1050 if (!dash) {
1051 dash = strchr(range, ',');
1052 }
1053 int first = atoi(range);
1054 int last = dash ? atoi(dash + 1) : first;
1055 if (!first || !last) {
1056 SkDebugf("couldn't parse --dir %s\n", range);
1057 return 1;
1058 }
1059 gDirs.set(first, last);
1060 }
1061 }
1062 if (!FLAGS_skp.isEmpty()) {
1063 gNames.set(FLAGS_skp);
1064 }
1065#ifdef SK_DEBUG
1066 header.append(" SK_DEBUG");
1067#else
1068 header.append(" SK_RELEASE");
1069#endif
caryclark19eb3b22014-07-18 05:08:14 -07001070 if (FLAGS_verbose) {
1071 header.appendf("\n");
1072 }
kkinnunen297aaf92015-02-19 06:32:12 -08001073 SkDebugf("%s", header.c_str());
caryclark19eb3b22014-07-18 05:08:14 -07001074 Iter iter;
1075 Test* test;
halcanary96fcdcc2015-08-27 07:41:13 -07001076 while ((test = iter.next()) != nullptr) {
caryclark19eb3b22014-07-18 05:08:14 -07001077 SkAutoTDelete<Test> owned(test);
1078 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1079 test->run();
1080 }
1081 }
caryclark19eb3b22014-07-18 05:08:14 -07001082 return 0;
1083}
1084
borenet48087572015-04-02 12:16:36 -07001085#if !defined(SK_BUILD_FOR_IOS)
caryclark19eb3b22014-07-18 05:08:14 -07001086int main(int argc, char * const argv[]) {
1087 return tool_main(argc, (char**) argv);
1088}
1089#endif