blob: 326abb66c7c52e6fa6cb63f7054caebbe0ffee1b [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"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000025#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000026#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000027#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000028#include "SkTArray.h"
29#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070030#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070031#include "SkTemplates.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000032#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000033
bungeman60e0fee2015-08-26 05:15:46 -070034#include <stdlib.h>
35
caryclark19eb3b22014-07-18 05:08:14 -070036__SK_FORCE_IMAGE_DECODER_LINKING;
caryclark@google.com07e97fc2013-07-08 17:17:02 +000037
caryclark19eb3b22014-07-18 05:08:14 -070038/* add local exceptions here */
39/* TODO : add command flag interface */
40const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000041 int directory;
42 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070043 bool blamePathOps;
44} skipOver[] = {
45 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
46 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
47 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
48 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
49 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070050 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070051 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
52 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
53 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
54 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
55 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
56 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
57 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
58 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
59 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
60 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
61 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
62 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
63 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
64 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000065};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000066
caryclark19eb3b22014-07-18 05:08:14 -070067size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070068
caryclark19eb3b22014-07-18 05:08:14 -070069
70/* customize file in/out here */
71/* TODO : add command flag interface */
72#define CHROME_VERSION "1e5dfa4-4a995df"
73#define SUMMARY_RUN 1
74
75#ifdef SK_BUILD_FOR_WIN
76 #define DRIVE_SPEC "D:"
77 #define PATH_SLASH "\\"
78#else
79 #define DRIVE_SPEC ""
80 #define PATH_SLASH "/"
81#endif
82
83#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
84#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
85#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
86#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
87
88static const char outOpDir[] = "opClip";
89static const char outOldDir[] = "oldClip";
90static const char outStatusDir[] = "statusTest";
91
92static SkString get_in_path(int dirNo, const char* filename) {
93 SkString path;
94 SkASSERT(dirNo);
95 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
96 if (!sk_exists(path.c_str())) {
97 SkDebugf("could not read %s\n", path.c_str());
98 return SkString();
99 }
100 if (filename) {
101 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -0700102 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -0700103 SkDebugf("could not read %s\n", path.c_str());
104 return SkString();
105 }
106 }
107 return path;
108}
mtklein406654b2014-09-03 15:34:37 -0700109
caryclark19eb3b22014-07-18 05:08:14 -0700110static void make_recursive_dir(const SkString& path) {
111 if (sk_exists(path.c_str())) {
112 return;
113 }
114 const char* pathStr = path.c_str();
115 int last = (int) path.size();
116 do {
117 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
118 ;
119 SkASSERT(last > 0);
120 SkString shorter(pathStr, last);
121 if (sk_mkdir(shorter.c_str())) {
122 break;
123 }
124 } while (true);
125 do {
126 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
127 ;
128 SkString shorter(pathStr, last);
129 SkAssertResult(sk_mkdir(shorter.c_str()));
130 } while (last < (int) path.size());
131}
132
133static SkString get_out_path(int dirNo, const char* dirName) {
134 SkString path;
135 SkASSERT(dirNo);
136 SkASSERT(dirName);
137 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
138 make_recursive_dir(path);
139 return path;
140}
mtklein406654b2014-09-03 15:34:37 -0700141
caryclark19eb3b22014-07-18 05:08:14 -0700142static SkString get_sum_path(const char* dirName) {
143 SkString path;
144 SkASSERT(dirName);
145 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
146 SkDebugf("%s\n", path.c_str());
147 make_recursive_dir(path);
148 return path;
149}
150
151static SkString make_png_name(const char* filename) {
152 SkString pngName = SkString(filename);
153 pngName.remove(pngName.size() - 3, 3);
154 pngName.append("png");
155 return pngName;
156}
157
158////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000159
160enum TestStep {
161 kCompareBits,
162 kEncodeFiles,
163};
164
165enum {
caryclarkdac1d172014-06-17 05:15:38 -0700166 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000167 kMaxFiles = 128,
168 kSmallLimit = 1000,
169};
170
171struct TestResult {
172 void init(int dirNo) {
173 fDirNo = dirNo;
174 sk_bzero(fFilename, sizeof(fFilename));
175 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000176 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000177 }
mtklein406654b2014-09-03 15:34:37 -0700178
caryclark19eb3b22014-07-18 05:08:14 -0700179 void init(int dirNo, const SkString& filename) {
180 fDirNo = dirNo;
181 strcpy(fFilename, filename.c_str());
182 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700183 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700184 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000185
186 SkString status() {
187 SkString outStr;
188 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
189 return outStr;
190 }
191
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000192 SkString progress() {
193 SkString outStr;
194 outStr.printf("dir=%d %s ", fDirNo, fFilename);
195 if (fPixelError) {
196 outStr.appendf(" err=%d", fPixelError);
197 }
198 if (fTime) {
199 outStr.appendf(" time=%d", fTime);
200 }
201 if (fScale != 1) {
202 outStr.appendf(" scale=%d", fScale);
203 }
204 outStr.appendf("\n");
205 return outStr;
206
207 }
208
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000209 void test(int dirNo, const SkString& filename) {
210 init(dirNo);
211 strcpy(fFilename, filename.c_str());
212 testOne();
213 }
214
215 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700216
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000217 char fFilename[kMaxLength];
218 TestStep fTestStep;
219 int fDirNo;
220 int fPixelError;
221 int fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000222 int fScale;
223};
224
225class SortByPixel : public TestResult {
226public:
227 bool operator<(const SortByPixel& rh) const {
228 return fPixelError < rh.fPixelError;
229 }
230};
231
232class SortByTime : public TestResult {
233public:
234 bool operator<(const SortByTime& rh) const {
235 return fTime < rh.fTime;
236 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000237};
238
caryclarkdac1d172014-06-17 05:15:38 -0700239class SortByName : public TestResult {
240public:
241 bool operator<(const SortByName& rh) const {
242 return strcmp(fFilename, rh.fFilename) < 0;
243 }
244};
245
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000246struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700247 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000248 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000249 }
250
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000251 SkTDArray<SortByPixel> fPixelWorst;
252 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000253 TestResult fResult;
254};
255
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000256struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000257 ~TestRunner();
258 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000259 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000260};
261
mtklein048494c2016-02-16 19:06:15 -0800262class TestRunnable {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000263public:
mtklein048494c2016-02-16 19:06:15 -0800264 void operator()() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000265 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
266 (*fTestFun)(&fState);
267 }
268
269 TestState fState;
270 void (*fTestFun)(TestState*);
271};
272
caryclarkdac1d172014-06-17 05:15:38 -0700273
274class TestRunnableDir : public TestRunnable {
275public:
276 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700277 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700278 fTestFun = testFun;
279 }
280
281};
282
283class TestRunnableFile : public TestRunnable {
284public:
285 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700286 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700287 strcpy(fState.fResult.fFilename, name);
288 fTestFun = testFun;
289 }
290};
291
292class TestRunnableEncode : public TestRunnableFile {
293public:
294 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
295 : TestRunnableFile(testFun, dirNo, name, runner) {
296 fState.fResult.fTestStep = kEncodeFiles;
297 }
298};
299
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000300TestRunner::~TestRunner() {
301 for (int index = 0; index < fRunnables.count(); index++) {
halcanary385fe4d2015-08-26 13:07:48 -0700302 delete fRunnables[index];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000303 }
304}
305
306void TestRunner::render() {
mtklein279c7862016-01-04 19:13:19 -0800307 SkTaskGroup().batch(fRunnables.count(), [&](int i) {
mtklein048494c2016-02-16 19:06:15 -0800308 (*fRunnables[i])();
mtklein00b621c2015-06-17 15:26:15 -0700309 });
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000310}
311
312////////////////////////////////////////////////
313
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000314
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000315static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
316 const int kRowCount = 3;
317 const int kThreshold = 3;
318 int width = SkTMin(gr.width(), sk.width());
319 if (width < kRowCount) {
320 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000321 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000322 int height = SkTMin(gr.height(), sk.height());
323 if (height < kRowCount) {
324 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000325 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000326 int errorTotal = 0;
327 SkTArray<int, true> errorRows;
328 errorRows.push_back_n(width * kRowCount);
329 SkAutoLockPixels autoGr(gr);
330 SkAutoLockPixels autoSk(sk);
331 for (int y = 0; y < height; ++y) {
332 SkPMColor* grRow = gr.getAddr32(0, y);
333 SkPMColor* skRow = sk.getAddr32(0, y);
334 int* base = &errorRows[0];
335 int* cOut = &errorRows[y % kRowCount];
336 for (int x = 0; x < width; ++x) {
337 SkPMColor grColor = grRow[x];
338 SkPMColor skColor = skRow[x];
339 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
340 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
341 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
342 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
343 if (error < kThreshold || x < 2) {
344 continue;
345 }
346 if (base[x - 2] < kThreshold
347 || base[width + x - 2] < kThreshold
348 || base[width * 2 + x - 2] < kThreshold
349 || base[x - 1] < kThreshold
350 || base[width + x - 1] < kThreshold
351 || base[width * 2 + x - 1] < kThreshold
352 || base[x] < kThreshold
353 || base[width + x] < kThreshold
354 || base[width * 2 + x] < kThreshold) {
355 continue;
356 }
357 errorTotal += error;
358 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000359 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000360 return errorTotal;
361}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000362
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000363static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000364 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
365 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000366 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000367 int worstCount = data->fPixelWorst.count();
368 int pixelError = testResult.fPixelError;
369 if (pixelError > 0) {
370 for (int index = 0; index < worstCount; ++index) {
371 if (pixelError > data->fPixelWorst[index].fPixelError) {
372 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
373 return true;
374 }
375 }
376 }
377 int slowCount = data->fSlowest.count();
378 int time = testResult.fTime;
379 if (time > 0) {
380 for (int index = 0; index < slowCount; ++index) {
381 if (time > data->fSlowest[index].fTime) {
382 data->fSlowest[index] = *(SortByTime*) &testResult;
383 return true;
384 }
385 }
386 }
387 if (pixelError > 0 && worstCount < kMaxFiles) {
388 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
389 return true;
390 }
391 if (time > 0 && slowCount < kMaxFiles) {
392 *data->fSlowest.append() = *(SortByTime*) &testResult;
393 return true;
394 }
395 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000396}
397
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000398static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
399 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700400 SkScalar pWidth = pic->cullRect().width();
401 SkScalar pHeight = pic->cullRect().height();
402 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000403 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700404 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
405 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
406 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000407 canvas->clipRect(rect);
408 SkMSec start = SkTime::GetMSecs();
409 for (int x = 0; x < slices; ++x) {
410 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700411 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700412 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000413 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700414 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000415 }
416 SkMSec end = SkTime::GetMSecs();
417 canvas->restore();
418 return end - start;
419}
420
421static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
422 canvas->clear(SK_ColorWHITE);
423 if (scale != 1) {
424 canvas->save();
425 canvas->scale(1.0f / scale, 1.0f / scale);
426 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700427 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000428 if (scale != 1) {
429 canvas->restore();
430 }
431}
432
433static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700434 SkString outFile = get_sum_path(outDir);
435 outFile.appendf("%s%s", PATH_SLASH, pngName);
436 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000437 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
438 bitmap.width(), bitmap.height());
439 }
440}
441
442void TestResult::testOne() {
halcanary96fcdcc2015-08-27 07:41:13 -0700443 SkPicture* pic = nullptr;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000444 {
445 #if DEBUG_SHOW_TEST_NAME
446 if (fTestStep == kCompareBits) {
447 SkString testName(fFilename);
448 const char http[] = "http";
449 if (testName.startsWith(http)) {
450 testName.remove(0, sizeof(http) - 1);
451 }
452 while (testName.startsWith("_")) {
453 testName.remove(0, 1);
454 }
455 const char dotSkp[] = ".skp";
456 if (testName.endsWith(dotSkp)) {
457 size_t len = testName.size();
458 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
459 }
460 testName.prepend("skp");
461 testName.append("1");
462 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
463 } else if (fTestStep == kEncodeFiles) {
464 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
465 }
466 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700467 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000468 SkFILEStream stream(path.c_str());
469 if (!stream.isValid()) {
470 SkDebugf("invalid stream %s\n", path.c_str());
471 goto finish;
472 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000473 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000474 if (!pic) {
475 SkDebugf("unable to decode %s\n", fFilename);
476 goto finish;
477 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700478 SkScalar width = pic->cullRect().width();
479 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000480 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000481 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000482 while (width / fScale > 32767 || height / fScale > 32767) {
483 ++fScale;
484 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000485 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700486 int dimX = SkScalarCeilToInt(width / fScale);
487 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700488 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000489 break;
490 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000491 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000492 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000493 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700494 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000495 width, height);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000496 goto finish;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000497 }
498 oldBitmap.eraseColor(SK_ColorWHITE);
499 SkCanvas oldCanvas(oldBitmap);
500 oldCanvas.setAllowSimplifyClip(false);
501 opBitmap.eraseColor(SK_ColorWHITE);
502 SkCanvas opCanvas(opBitmap);
503 opCanvas.setAllowSimplifyClip(true);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000504 drawPict(pic, &oldCanvas, fScale);
505 drawPict(pic, &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000506 if (fTestStep == kCompareBits) {
507 fPixelError = similarBits(oldBitmap, opBitmap);
508 int oldTime = timePict(pic, &oldCanvas);
509 int opTime = timePict(pic, &opCanvas);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000510 fTime = SkTMax(0, oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000511 } else if (fTestStep == kEncodeFiles) {
512 SkString pngStr = make_png_name(fFilename);
513 const char* pngName = pngStr.c_str();
514 writePict(oldBitmap, outOldDir, pngName);
515 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000516 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000517 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000518finish:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000519 if (pic) {
520 pic->unref();
521 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000522}
523
caryclark19eb3b22014-07-18 05:08:14 -0700524DEFINE_string2(match, m, "PathOpsSkpClipThreaded",
525 "[~][^]substring[$] [...] of test name to run.\n"
526 "Multiple matches may be separated by spaces.\n"
527 "~ causes a matching test to always be skipped\n"
528 "^ requires the start of the test to match\n"
529 "$ requires the end of the test to match\n"
530 "^ and $ requires an exact match\n"
531 "If a test does not match any list entry,\n"
532 "it is skipped unless some list entry starts with ~");
halcanary96fcdcc2015-08-27 07:41:13 -0700533DEFINE_string2(dir, d, nullptr, "range of directories (e.g., 1-100)");
534DEFINE_string2(skp, s, nullptr, "skp to test");
caryclark19eb3b22014-07-18 05:08:14 -0700535DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
536DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only).");
caryclark19eb3b22014-07-18 05:08:14 -0700537DEFINE_bool2(verbose, v, false, "enable verbose output.");
538
539static bool verbose() {
540 return FLAGS_verbose;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000541}
542
caryclark19eb3b22014-07-18 05:08:14 -0700543class Dirs {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000544public:
caryclark19eb3b22014-07-18 05:08:14 -0700545 Dirs() {
546 reset();
547 sk_bzero(fRun, sizeof(fRun));
548 fSet = false;
549 }
550
551 int first() const {
552 int index = 0;
553 while (++index < kMaxDir) {
554 if (fRun[index]) {
555 return index;
556 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000557 }
caryclark19eb3b22014-07-18 05:08:14 -0700558 SkASSERT(0);
559 return -1;
560 }
561
562 int last() const {
563 int index = kMaxDir;
564 while (--index > 0 && !fRun[index])
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000565 ;
caryclark19eb3b22014-07-18 05:08:14 -0700566 return index;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000567 }
568
caryclark19eb3b22014-07-18 05:08:14 -0700569 int next() {
570 while (++fIndex < kMaxDir) {
571 if (fRun[fIndex]) {
572 return fIndex;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000573 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000574 }
caryclark19eb3b22014-07-18 05:08:14 -0700575 return -1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000576 }
577
caryclark19eb3b22014-07-18 05:08:14 -0700578 void reset() {
579 fIndex = -1;
580 }
581
582 void set(int start, int end) {
583 while (start < end) {
584 fRun[start++] = 1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000585 }
caryclark19eb3b22014-07-18 05:08:14 -0700586 fSet = true;
587 }
588
589 void setDefault() {
590 if (!fSet) {
591 set(1, 100);
592 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000593 }
594
595private:
caryclark19eb3b22014-07-18 05:08:14 -0700596 enum {
597 kMaxDir = 101
598 };
599 char fRun[kMaxDir];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000600 int fIndex;
caryclark19eb3b22014-07-18 05:08:14 -0700601 bool fSet;
602} gDirs;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000603
caryclark19eb3b22014-07-18 05:08:14 -0700604class Filenames {
605public:
606 Filenames()
607 : fIndex(-1) {
608 }
609
610 const char* next() {
611 while (fNames && ++fIndex < fNames->count()) {
612 return (*fNames)[fIndex];
613 }
halcanary96fcdcc2015-08-27 07:41:13 -0700614 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -0700615 }
mtklein406654b2014-09-03 15:34:37 -0700616
caryclark19eb3b22014-07-18 05:08:14 -0700617 void set(const SkCommandLineFlags::StringArray& names) {
618 fNames = &names;
619 }
620
621private:
622 int fIndex;
623 const SkCommandLineFlags::StringArray* fNames;
624} gNames;
625
mtklein406654b2014-09-03 15:34:37 -0700626static bool buildTestDir(int dirNo, int firstDirNo,
caryclark19eb3b22014-07-18 05:08:14 -0700627 SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
628 SkString dirName = get_out_path(dirNo, outStatusDir);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000629 if (!dirName.size()) {
630 return false;
631 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000632 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000633 SkString filename;
634 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700635 TestResult test;
636 test.init(dirNo);
637 SkString spaceFile(filename);
638 char* spaces = spaceFile.writable_str();
639 int spaceSize = (int) spaceFile.size();
640 for (int index = 0; index < spaceSize; ++index) {
641 if (spaces[index] == '.') {
642 spaces[index] = ' ';
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000643 }
644 }
caryclark19eb3b22014-07-18 05:08:14 -0700645 int success = sscanf(spaces, "%s %d %d skp", test.fFilename,
646 &test.fPixelError, &test.fTime);
647 if (success < 3) {
648 SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success);
649 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000650 }
caryclark19eb3b22014-07-18 05:08:14 -0700651 *tests[dirNo - firstDirNo].append() = test;
652 }
653 if (!sorted) {
654 return true;
655 }
656 SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo];
657 int count = testSet.count();
658 for (int index = 0; index < count; ++index) {
659 *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index];
660 }
661 if (sorted[dirNo - firstDirNo].count()) {
662 SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(),
663 sorted[dirNo - firstDirNo].end() - 1);
664 if (verbose()) {
665 SkDebugf("+");
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000666 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000667 }
668 return true;
669}
670
caryclark19eb3b22014-07-18 05:08:14 -0700671static void testSkpClip(TestState* data) {
672 data->fResult.testOne();
673 SkString statName(data->fResult.fFilename);
674 SkASSERT(statName.endsWith(".skp"));
675 statName.remove(statName.size() - 4, 4);
676 statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime);
677 SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir);
678 if (!statusFile.size()) {
679 SkDebugf("failed to create %s", statusFile.c_str());
680 return;
681 }
682 statusFile.appendf("%s%s", PATH_SLASH, statName.c_str());
halcanaryd76be9c2015-11-20 13:47:49 -0800683 FILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
caryclark19eb3b22014-07-18 05:08:14 -0700684 if (!file) {
685 SkDebugf("failed to create %s", statusFile.c_str());
686 return;
687 }
688 sk_fclose(file);
689 if (verbose()) {
690 if (data->fResult.fPixelError || data->fResult.fTime) {
691 SkDebugf("%s", data->fResult.progress().c_str());
692 } else {
693 SkDebugf(".");
694 }
695 }
696}
697
698bool Less(const SortByName& a, const SortByName& b);
699bool Less(const SortByName& a, const SortByName& b) {
700 return a < b;
701}
702
703static bool doOneDir(TestState* state, bool threaded) {
704 int dirNo = state->fResult.fDirNo;
halcanary96fcdcc2015-08-27 07:41:13 -0700705 SkString dirName = get_in_path(dirNo, nullptr);
caryclark19eb3b22014-07-18 05:08:14 -0700706 if (!dirName.size()) {
707 return false;
708 }
709 SkTDArray<TestResult> tests[1];
710 SkTDArray<SortByName*> sorted[1];
711 if (!buildTestDir(dirNo, dirNo, tests, sorted)) {
712 return false;
713 }
714 SkOSFile::Iter iter(dirName.c_str(), "skp");
715 SkString filename;
716 while (iter.next(&filename)) {
717 for (size_t index = 0; index < skipOverCount; ++index) {
718 if (skipOver[index].directory == dirNo
719 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
720 goto checkEarlyExit;
721 }
722 }
723 {
724 SortByName name;
725 name.init(dirNo);
726 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
727 int count = sorted[0].count();
728 int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name));
729 if (idx >= 0) {
730 SortByName* found = sorted[0][idx];
731 (void) addError(state, *found);
732 continue;
733 }
734 TestResult test;
735 test.init(dirNo, filename);
736 state->fResult = test;
737 testSkpClip(state);
738#if 0 // artificially limit to a few while debugging code
739 static int debugLimit = 0;
740 if (++debugLimit == 5) {
741 return true;
742 }
743#endif
744 }
745checkEarlyExit:
746 ;
747 }
748 return true;
749}
750
751static void initTest() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000752#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC
753 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
754 SK_CONF_SET("images.png.suppressDecoderWarnings", true);
755#endif
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000756}
757
caryclarkdac1d172014-06-17 05:15:38 -0700758static void testSkpClipEncode(TestState* data) {
759 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700760 if (verbose()) {
761 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700762 }
763}
764
caryclark19eb3b22014-07-18 05:08:14 -0700765static void encodeFound(TestState& state) {
766 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700767 if (state.fPixelWorst.count()) {
768 SkTDArray<SortByPixel*> worst;
769 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
770 *worst.append() = &state.fPixelWorst[index];
771 }
772 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
773 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
774 const TestResult& result = *worst[index];
775 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
776 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000777 }
caryclarkdac1d172014-06-17 05:15:38 -0700778 if (state.fSlowest.count()) {
779 SkTDArray<SortByTime*> slowest;
780 for (int index = 0; index < state.fSlowest.count(); ++index) {
781 *slowest.append() = &state.fSlowest[index];
782 }
783 if (slowest.count() > 0) {
784 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
785 for (int index = 0; index < slowest.count(); ++index) {
786 const TestResult& result = *slowest[index];
787 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
788 }
789 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000790 }
791 }
mtklein406654b2014-09-03 15:34:37 -0700792 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000793 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
794 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700795 SkString filename(result.fFilename);
796 if (!filename.endsWith(".skp")) {
797 filename.append(".skp");
798 }
halcanary385fe4d2015-08-26 13:07:48 -0700799 *testRunner.fRunnables.append() = new TestRunnableEncode(&testSkpClipEncode, result.fDirNo,
800 filename.c_str(), &testRunner);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000801 }
caryclarkdac1d172014-06-17 05:15:38 -0700802 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000803}
804
caryclark19eb3b22014-07-18 05:08:14 -0700805class Test {
806public:
807 Test() {}
808 virtual ~Test() {}
809
810 const char* getName() { onGetName(&fName); return fName.c_str(); }
811 void run() { onRun(); }
812
813protected:
814 virtual void onGetName(SkString*) = 0;
815 virtual void onRun() = 0;
816
817private:
818 SkString fName;
819};
820
821typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
822
halcanary385fe4d2015-08-26 13:07:48 -0700823#define DEF_TEST(name) \
824 static void test_##name(); \
825 class name##Class : public Test { \
826 public: \
827 static Test* Factory(void*) { return new name##Class; } \
828 \
829 protected: \
830 void onGetName(SkString* name) override { name->set(#name); } \
831 void onRun() override { test_##name(); } \
832 }; \
833 static TestRegistry gReg_##name##Class(name##Class::Factory); \
caryclark19eb3b22014-07-18 05:08:14 -0700834 static void test_##name()
835
836DEF_TEST(PathOpsSkpClip) {
837 gDirs.setDefault();
838 initTest();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000839 SkTArray<TestResult, true> errors;
840 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700841 state.init(0);
842 int dirNo;
843 gDirs.reset();
844 while ((dirNo = gDirs.next()) > 0) {
845 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000846 SkDebugf("dirNo=%d\n", dirNo);
847 }
848 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000849 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000850 break;
851 }
852 }
caryclark19eb3b22014-07-18 05:08:14 -0700853 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000854}
855
856static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000857 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000858}
859
caryclark19eb3b22014-07-18 05:08:14 -0700860DEF_TEST(PathOpsSkpClipThreaded) {
861 gDirs.setDefault();
862 initTest();
mtklein406654b2014-09-03 15:34:37 -0700863 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700864 int dirNo;
865 gDirs.reset();
866 while ((dirNo = gDirs.next()) > 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700867 *testRunner.fRunnables.append() = new TestRunnableDir(&testSkpClipMain, dirNo, &testRunner);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000868 }
869 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000870 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700871 state.init(0);
872 gDirs.reset();
873 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000874 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700875 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000876 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000877 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000878 }
caryclarkdac1d172014-06-17 05:15:38 -0700879 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
880 addError(&state, testState.fSlowest[inner]);
881 }
882 }
caryclark19eb3b22014-07-18 05:08:14 -0700883 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700884}
mtklein406654b2014-09-03 15:34:37 -0700885
caryclark19eb3b22014-07-18 05:08:14 -0700886static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
887 int firstDirNo = gDirs.first();
888 int dirNo;
889 while ((dirNo = gDirs.next()) > 0) {
890 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700891 return false;
892 }
caryclarkdac1d172014-06-17 05:15:38 -0700893 }
894 return true;
895}
896
caryclark19eb3b22014-07-18 05:08:14 -0700897DEF_TEST(PathOpsSkpClipUberThreaded) {
898 gDirs.setDefault();
899 const int firstDirNo = gDirs.next();
900 const int lastDirNo = gDirs.last();
901 initTest();
902 int dirCount = lastDirNo - firstDirNo + 1;
903 SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]);
904 SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]);
905 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700906 return;
907 }
mtklein406654b2014-09-03 15:34:37 -0700908 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700909 int dirNo;
910 gDirs.reset();
911 while ((dirNo = gDirs.next()) > 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700912 SkString dirName = get_in_path(dirNo, nullptr);
caryclarkdac1d172014-06-17 05:15:38 -0700913 if (!dirName.size()) {
914 continue;
915 }
916 SkOSFile::Iter iter(dirName.c_str(), "skp");
917 SkString filename;
918 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700919 for (size_t index = 0; index < skipOverCount; ++index) {
920 if (skipOver[index].directory == dirNo
921 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700922 goto checkEarlyExit;
923 }
924 }
caryclark19eb3b22014-07-18 05:08:14 -0700925 {
926 SortByName name;
927 name.init(dirNo);
928 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
929 int count = sorted.get()[dirNo - firstDirNo].count();
930 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
931 count, &name, sizeof(&name)) < 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700932 *testRunner.fRunnables.append() = new TestRunnableFile(
933 &testSkpClip, dirNo, filename.c_str(), &testRunner);
caryclark19eb3b22014-07-18 05:08:14 -0700934 }
caryclarkdac1d172014-06-17 05:15:38 -0700935 }
936 checkEarlyExit:
937 ;
938 }
939
940 }
941 testRunner.render();
caryclark19eb3b22014-07-18 05:08:14 -0700942 SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]);
halcanary96fcdcc2015-08-27 07:41:13 -0700943 if (!buildTests(results.get(), nullptr)) {
caryclarkdac1d172014-06-17 05:15:38 -0700944 return;
945 }
946 SkTDArray<TestResult> allResults;
947 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700948 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700949 allResults.append(array.count(), array.begin());
950 }
951 int allCount = allResults.count();
952 SkTDArray<SortByPixel*> pixels;
953 SkTDArray<SortByTime*> times;
954 for (int index = 0; index < allCount; ++index) {
955 *pixels.append() = (SortByPixel*) &allResults[index];
956 *times.append() = (SortByTime*) &allResults[index];
957 }
958 TestState state;
959 if (pixels.count()) {
960 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
961 for (int inner = 0; inner < kMaxFiles; ++inner) {
962 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
963 }
964 }
965 if (times.count()) {
966 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
967 for (int inner = 0; inner < kMaxFiles; ++inner) {
968 *state.fSlowest.append() = *times[allCount - inner - 1];
969 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000970 }
caryclark19eb3b22014-07-18 05:08:14 -0700971 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000972}
973
caryclark19eb3b22014-07-18 05:08:14 -0700974DEF_TEST(PathOpsSkpClipOneOff) {
975 const int testIndex = FLAGS_testIndex;
976 int dirNo = gDirs.next();
977 if (dirNo < 0) {
978 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000979 }
caryclark19eb3b22014-07-18 05:08:14 -0700980 const char* skp = gNames.next();
981 if (!skp) {
982 skp = skipOver[testIndex].filename;
983 }
984 initTest();
985 SkAssertResult(get_in_path(dirNo, skp).size());
986 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000987 TestResult state;
988 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700989 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000990 SkDebugf("%s", state.status().c_str());
991 }
992 state.fTestStep = kEncodeFiles;
993 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000994}
caryclark19eb3b22014-07-18 05:08:14 -0700995
996DEF_TEST(PathOpsTestSkipped) {
997 for (size_t index = 0; index < skipOverCount; ++index) {
998 const SkipOverTest& skip = skipOver[index];
999 if (!skip.blamePathOps) {
1000 continue;
1001 }
1002 int dirNo = skip.directory;
1003 const char* skp = skip.filename;
1004 initTest();
1005 SkAssertResult(get_in_path(dirNo, skp).size());
1006 SkString filename(skp);
1007 TestResult state;
1008 state.test(dirNo, filename);
1009 if (verbose()) {
1010 SkDebugf("%s", state.status().c_str());
1011 }
1012 state.fTestStep = kEncodeFiles;
1013 state.testOne();
1014 }
1015}
1016
1017DEF_TEST(PathOpsCopyFails) {
1018 FLAGS_verbose = true;
1019 for (size_t index = 0; index < skipOverCount; ++index) {
1020 int dirNo = skipOver[index].directory;
1021 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1022 }
1023 for (size_t index = 0; index < skipOverCount; ++index) {
1024 int dirNo = skipOver[index].directory;
1025 const char* filename = skipOver[index].filename;
1026 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1027 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1028 }
1029}
1030
1031template TestRegistry* TestRegistry::gHead;
1032
1033class Iter {
1034public:
1035 Iter() { this->reset(); }
1036 void reset() { fReg = TestRegistry::Head(); }
1037
1038 Test* next() {
1039 if (fReg) {
1040 TestRegistry::Factory fact = fReg->factory();
1041 fReg = fReg->next();
halcanary96fcdcc2015-08-27 07:41:13 -07001042 Test* test = fact(nullptr);
caryclark19eb3b22014-07-18 05:08:14 -07001043 return test;
1044 }
halcanary96fcdcc2015-08-27 07:41:13 -07001045 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -07001046 }
1047
1048private:
1049 const TestRegistry* fReg;
1050};
1051
1052int tool_main(int argc, char** argv);
1053int tool_main(int argc, char** argv) {
1054 SetupCrashHandler();
1055 SkCommandLineFlags::SetUsage("");
1056 SkCommandLineFlags::Parse(argc, argv);
1057 SkGraphics::Init();
1058 SkString header("PathOps SkpClip:");
1059 if (!FLAGS_match.isEmpty()) {
1060 header.appendf(" --match");
1061 for (int index = 0; index < FLAGS_match.count(); ++index) {
1062 header.appendf(" %s", FLAGS_match[index]);
1063 }
1064 }
1065 if (!FLAGS_dir.isEmpty()) {
1066 int count = FLAGS_dir.count();
1067 for (int i = 0; i < count; ++i) {
1068 const char* range = FLAGS_dir[i];
1069 const char* dash = strchr(range, '-');
1070 if (!dash) {
1071 dash = strchr(range, ',');
1072 }
1073 int first = atoi(range);
1074 int last = dash ? atoi(dash + 1) : first;
1075 if (!first || !last) {
1076 SkDebugf("couldn't parse --dir %s\n", range);
1077 return 1;
1078 }
1079 gDirs.set(first, last);
1080 }
1081 }
1082 if (!FLAGS_skp.isEmpty()) {
1083 gNames.set(FLAGS_skp);
1084 }
1085#ifdef SK_DEBUG
1086 header.append(" SK_DEBUG");
1087#else
1088 header.append(" SK_RELEASE");
1089#endif
caryclark19eb3b22014-07-18 05:08:14 -07001090 if (FLAGS_verbose) {
1091 header.appendf("\n");
1092 }
kkinnunen297aaf92015-02-19 06:32:12 -08001093 SkDebugf("%s", header.c_str());
caryclark19eb3b22014-07-18 05:08:14 -07001094 Iter iter;
1095 Test* test;
halcanary96fcdcc2015-08-27 07:41:13 -07001096 while ((test = iter.next()) != nullptr) {
caryclark19eb3b22014-07-18 05:08:14 -07001097 SkAutoTDelete<Test> owned(test);
1098 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1099 test->run();
1100 }
1101 }
caryclark19eb3b22014-07-18 05:08:14 -07001102 return 0;
1103}
1104
borenet48087572015-04-02 12:16:36 -07001105#if !defined(SK_BUILD_FOR_IOS)
caryclark19eb3b22014-07-18 05:08:14 -07001106int main(int argc, char * const argv[]) {
1107 return tool_main(argc, (char**) argv);
1108}
1109#endif