blob: 0c866bd379cf4d3431239f2f7e1664b95f1783f4 [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 "SkGraphics.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000017#include "SkImageEncoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000018#include "SkOSFile.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000019#include "SkPathOpsDebug.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000020#include "SkPicture.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000021#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000022#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000023#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000024#include "SkTArray.h"
25#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070026#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070027#include "SkTemplates.h"
halcanary4e44efe2016-08-04 10:47:16 -070028#include "SkTSearch.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000029#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000030
bungeman60e0fee2015-08-26 05:15:46 -070031#include <stdlib.h>
32
caryclark19eb3b22014-07-18 05:08:14 -070033/* add local exceptions here */
34/* TODO : add command flag interface */
35const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000036 int directory;
37 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070038 bool blamePathOps;
39} skipOver[] = {
40 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
41 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
42 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
43 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
44 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070045 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070046 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
47 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
48 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
49 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
50 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
51 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
52 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
53 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
54 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
55 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
56 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
57 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
58 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
59 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000060};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000061
caryclark19eb3b22014-07-18 05:08:14 -070062size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070063
caryclark19eb3b22014-07-18 05:08:14 -070064
65/* customize file in/out here */
66/* TODO : add command flag interface */
67#define CHROME_VERSION "1e5dfa4-4a995df"
68#define SUMMARY_RUN 1
69
70#ifdef SK_BUILD_FOR_WIN
71 #define DRIVE_SPEC "D:"
72 #define PATH_SLASH "\\"
73#else
74 #define DRIVE_SPEC ""
75 #define PATH_SLASH "/"
76#endif
77
78#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
79#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
80#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
81#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
82
83static const char outOpDir[] = "opClip";
84static const char outOldDir[] = "oldClip";
85static const char outStatusDir[] = "statusTest";
86
87static SkString get_in_path(int dirNo, const char* filename) {
88 SkString path;
89 SkASSERT(dirNo);
90 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
91 if (!sk_exists(path.c_str())) {
92 SkDebugf("could not read %s\n", path.c_str());
93 return SkString();
94 }
95 if (filename) {
96 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -070097 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -070098 SkDebugf("could not read %s\n", path.c_str());
99 return SkString();
100 }
101 }
102 return path;
103}
mtklein406654b2014-09-03 15:34:37 -0700104
caryclark19eb3b22014-07-18 05:08:14 -0700105static void make_recursive_dir(const SkString& path) {
106 if (sk_exists(path.c_str())) {
107 return;
108 }
109 const char* pathStr = path.c_str();
110 int last = (int) path.size();
111 do {
112 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
113 ;
114 SkASSERT(last > 0);
115 SkString shorter(pathStr, last);
116 if (sk_mkdir(shorter.c_str())) {
117 break;
118 }
119 } while (true);
120 do {
121 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
122 ;
123 SkString shorter(pathStr, last);
124 SkAssertResult(sk_mkdir(shorter.c_str()));
125 } while (last < (int) path.size());
126}
127
128static SkString get_out_path(int dirNo, const char* dirName) {
129 SkString path;
130 SkASSERT(dirNo);
131 SkASSERT(dirName);
132 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
133 make_recursive_dir(path);
134 return path;
135}
mtklein406654b2014-09-03 15:34:37 -0700136
caryclark19eb3b22014-07-18 05:08:14 -0700137static SkString get_sum_path(const char* dirName) {
138 SkString path;
139 SkASSERT(dirName);
140 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
141 SkDebugf("%s\n", path.c_str());
142 make_recursive_dir(path);
143 return path;
144}
145
146static SkString make_png_name(const char* filename) {
147 SkString pngName = SkString(filename);
148 pngName.remove(pngName.size() - 3, 3);
149 pngName.append("png");
150 return pngName;
151}
152
153////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000154
155enum TestStep {
156 kCompareBits,
157 kEncodeFiles,
158};
159
160enum {
caryclarkdac1d172014-06-17 05:15:38 -0700161 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000162 kMaxFiles = 128,
163 kSmallLimit = 1000,
164};
165
166struct TestResult {
167 void init(int dirNo) {
168 fDirNo = dirNo;
169 sk_bzero(fFilename, sizeof(fFilename));
170 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000171 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000172 }
mtklein406654b2014-09-03 15:34:37 -0700173
caryclark19eb3b22014-07-18 05:08:14 -0700174 void init(int dirNo, const SkString& filename) {
175 fDirNo = dirNo;
176 strcpy(fFilename, filename.c_str());
177 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700178 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700179 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000180
181 SkString status() {
182 SkString outStr;
183 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
184 return outStr;
185 }
186
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000187 SkString progress() {
188 SkString outStr;
189 outStr.printf("dir=%d %s ", fDirNo, fFilename);
190 if (fPixelError) {
191 outStr.appendf(" err=%d", fPixelError);
192 }
193 if (fTime) {
194 outStr.appendf(" time=%d", fTime);
195 }
196 if (fScale != 1) {
197 outStr.appendf(" scale=%d", fScale);
198 }
199 outStr.appendf("\n");
200 return outStr;
201
202 }
203
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000204 void test(int dirNo, const SkString& filename) {
205 init(dirNo);
206 strcpy(fFilename, filename.c_str());
207 testOne();
208 }
209
210 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700211
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000212 char fFilename[kMaxLength];
213 TestStep fTestStep;
214 int fDirNo;
215 int fPixelError;
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700216 SkMSec fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000217 int fScale;
218};
219
220class SortByPixel : public TestResult {
221public:
222 bool operator<(const SortByPixel& rh) const {
223 return fPixelError < rh.fPixelError;
224 }
225};
226
227class SortByTime : public TestResult {
228public:
229 bool operator<(const SortByTime& rh) const {
230 return fTime < rh.fTime;
231 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000232};
233
caryclarkdac1d172014-06-17 05:15:38 -0700234class SortByName : public TestResult {
235public:
236 bool operator<(const SortByName& rh) const {
237 return strcmp(fFilename, rh.fFilename) < 0;
238 }
239};
240
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000241struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700242 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000243 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000244 }
245
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000246 SkTDArray<SortByPixel> fPixelWorst;
247 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000248 TestResult fResult;
249};
250
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000251struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000252 ~TestRunner();
253 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000254 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000255};
256
mtklein048494c2016-02-16 19:06:15 -0800257class TestRunnable {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000258public:
mtklein048494c2016-02-16 19:06:15 -0800259 void operator()() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000260 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
261 (*fTestFun)(&fState);
262 }
263
264 TestState fState;
265 void (*fTestFun)(TestState*);
266};
267
caryclarkdac1d172014-06-17 05:15:38 -0700268
269class TestRunnableDir : public TestRunnable {
270public:
271 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700272 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700273 fTestFun = testFun;
274 }
275
276};
277
278class TestRunnableFile : public TestRunnable {
279public:
280 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700281 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700282 strcpy(fState.fResult.fFilename, name);
283 fTestFun = testFun;
284 }
285};
286
287class TestRunnableEncode : public TestRunnableFile {
288public:
289 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
290 : TestRunnableFile(testFun, dirNo, name, runner) {
291 fState.fResult.fTestStep = kEncodeFiles;
292 }
293};
294
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000295TestRunner::~TestRunner() {
296 for (int index = 0; index < fRunnables.count(); index++) {
halcanary385fe4d2015-08-26 13:07:48 -0700297 delete fRunnables[index];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000298 }
299}
300
301void TestRunner::render() {
mtklein279c7862016-01-04 19:13:19 -0800302 SkTaskGroup().batch(fRunnables.count(), [&](int i) {
mtklein048494c2016-02-16 19:06:15 -0800303 (*fRunnables[i])();
mtklein00b621c2015-06-17 15:26:15 -0700304 });
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000305}
306
307////////////////////////////////////////////////
308
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000309
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000310static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
311 const int kRowCount = 3;
312 const int kThreshold = 3;
313 int width = SkTMin(gr.width(), sk.width());
314 if (width < kRowCount) {
315 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000316 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000317 int height = SkTMin(gr.height(), sk.height());
318 if (height < kRowCount) {
319 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000320 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000321 int errorTotal = 0;
322 SkTArray<int, true> errorRows;
323 errorRows.push_back_n(width * kRowCount);
324 SkAutoLockPixels autoGr(gr);
325 SkAutoLockPixels autoSk(sk);
326 for (int y = 0; y < height; ++y) {
327 SkPMColor* grRow = gr.getAddr32(0, y);
328 SkPMColor* skRow = sk.getAddr32(0, y);
329 int* base = &errorRows[0];
330 int* cOut = &errorRows[y % kRowCount];
331 for (int x = 0; x < width; ++x) {
332 SkPMColor grColor = grRow[x];
333 SkPMColor skColor = skRow[x];
334 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
335 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
336 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
337 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
338 if (error < kThreshold || x < 2) {
339 continue;
340 }
341 if (base[x - 2] < kThreshold
342 || base[width + x - 2] < kThreshold
343 || base[width * 2 + x - 2] < kThreshold
344 || base[x - 1] < kThreshold
345 || base[width + x - 1] < kThreshold
346 || base[width * 2 + x - 1] < kThreshold
347 || base[x] < kThreshold
348 || base[width + x] < kThreshold
349 || base[width * 2 + x] < kThreshold) {
350 continue;
351 }
352 errorTotal += error;
353 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000354 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000355 return errorTotal;
356}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000357
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000358static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000359 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
360 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000361 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000362 int worstCount = data->fPixelWorst.count();
363 int pixelError = testResult.fPixelError;
364 if (pixelError > 0) {
365 for (int index = 0; index < worstCount; ++index) {
366 if (pixelError > data->fPixelWorst[index].fPixelError) {
367 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
368 return true;
369 }
370 }
371 }
372 int slowCount = data->fSlowest.count();
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700373 SkMSec time = testResult.fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000374 if (time > 0) {
375 for (int index = 0; index < slowCount; ++index) {
376 if (time > data->fSlowest[index].fTime) {
377 data->fSlowest[index] = *(SortByTime*) &testResult;
378 return true;
379 }
380 }
381 }
382 if (pixelError > 0 && worstCount < kMaxFiles) {
383 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
384 return true;
385 }
386 if (time > 0 && slowCount < kMaxFiles) {
387 *data->fSlowest.append() = *(SortByTime*) &testResult;
388 return true;
389 }
390 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000391}
392
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000393static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
394 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700395 SkScalar pWidth = pic->cullRect().width();
396 SkScalar pHeight = pic->cullRect().height();
397 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000398 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700399 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
400 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
401 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000402 canvas->clipRect(rect);
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700403 double start = SkTime::GetMSecs();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000404 for (int x = 0; x < slices; ++x) {
405 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700406 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700407 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000408 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700409 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000410 }
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700411 double end = SkTime::GetMSecs();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000412 canvas->restore();
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700413 return static_cast<SkMSec>(end - start);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000414}
415
416static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
417 canvas->clear(SK_ColorWHITE);
418 if (scale != 1) {
419 canvas->save();
420 canvas->scale(1.0f / scale, 1.0f / scale);
421 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700422 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000423 if (scale != 1) {
424 canvas->restore();
425 }
426}
427
428static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700429 SkString outFile = get_sum_path(outDir);
430 outFile.appendf("%s%s", PATH_SLASH, pngName);
Hal Canarydb683012016-11-23 08:55:18 -0700431 if (!sk_tool_utils::EncodeImageToFile(outFile.c_str(), bitmap, SkEncodedImageFormat::kPNG, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000432 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
433 bitmap.width(), bitmap.height());
434 }
435}
436
437void TestResult::testOne() {
reedca2622b2016-03-18 07:25:55 -0700438 sk_sp<SkPicture> pic;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000439 {
440 #if DEBUG_SHOW_TEST_NAME
441 if (fTestStep == kCompareBits) {
442 SkString testName(fFilename);
443 const char http[] = "http";
444 if (testName.startsWith(http)) {
445 testName.remove(0, sizeof(http) - 1);
446 }
447 while (testName.startsWith("_")) {
448 testName.remove(0, 1);
449 }
450 const char dotSkp[] = ".skp";
451 if (testName.endsWith(dotSkp)) {
452 size_t len = testName.size();
453 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
454 }
455 testName.prepend("skp");
456 testName.append("1");
457 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
458 } else if (fTestStep == kEncodeFiles) {
459 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
460 }
461 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700462 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000463 SkFILEStream stream(path.c_str());
464 if (!stream.isValid()) {
465 SkDebugf("invalid stream %s\n", path.c_str());
reedca2622b2016-03-18 07:25:55 -0700466 return;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000467 }
reedca2622b2016-03-18 07:25:55 -0700468 pic = SkPicture::MakeFromStream(&stream);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000469 if (!pic) {
470 SkDebugf("unable to decode %s\n", fFilename);
reedca2622b2016-03-18 07:25:55 -0700471 return;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000472 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700473 SkScalar width = pic->cullRect().width();
474 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000475 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000476 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000477 while (width / fScale > 32767 || height / fScale > 32767) {
478 ++fScale;
479 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000480 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700481 int dimX = SkScalarCeilToInt(width / fScale);
482 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700483 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000484 break;
485 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000486 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000487 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000488 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700489 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000490 width, height);
reedca2622b2016-03-18 07:25:55 -0700491 return;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000492 }
493 oldBitmap.eraseColor(SK_ColorWHITE);
494 SkCanvas oldCanvas(oldBitmap);
495 oldCanvas.setAllowSimplifyClip(false);
496 opBitmap.eraseColor(SK_ColorWHITE);
497 SkCanvas opCanvas(opBitmap);
498 opCanvas.setAllowSimplifyClip(true);
reedca2622b2016-03-18 07:25:55 -0700499 drawPict(pic.get(), &oldCanvas, fScale);
500 drawPict(pic.get(), &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000501 if (fTestStep == kCompareBits) {
502 fPixelError = similarBits(oldBitmap, opBitmap);
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700503 SkMSec oldTime = timePict(pic.get(), &oldCanvas);
504 SkMSec opTime = timePict(pic.get(), &opCanvas);
505 fTime = SkTMax(static_cast<SkMSec>(0), oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000506 } else if (fTestStep == kEncodeFiles) {
507 SkString pngStr = make_png_name(fFilename);
508 const char* pngName = pngStr.c_str();
509 writePict(oldBitmap, outOldDir, pngName);
510 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000511 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000512 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000513}
514
caryclark19eb3b22014-07-18 05:08:14 -0700515DEFINE_string2(match, m, "PathOpsSkpClipThreaded",
516 "[~][^]substring[$] [...] of test name to run.\n"
517 "Multiple matches may be separated by spaces.\n"
518 "~ causes a matching test to always be skipped\n"
519 "^ requires the start of the test to match\n"
520 "$ requires the end of the test to match\n"
521 "^ and $ requires an exact match\n"
522 "If a test does not match any list entry,\n"
523 "it is skipped unless some list entry starts with ~");
halcanary96fcdcc2015-08-27 07:41:13 -0700524DEFINE_string2(dir, d, nullptr, "range of directories (e.g., 1-100)");
525DEFINE_string2(skp, s, nullptr, "skp to test");
caryclark19eb3b22014-07-18 05:08:14 -0700526DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
527DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only).");
caryclark19eb3b22014-07-18 05:08:14 -0700528DEFINE_bool2(verbose, v, false, "enable verbose output.");
529
530static bool verbose() {
531 return FLAGS_verbose;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000532}
533
caryclark19eb3b22014-07-18 05:08:14 -0700534class Dirs {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000535public:
caryclark19eb3b22014-07-18 05:08:14 -0700536 Dirs() {
537 reset();
538 sk_bzero(fRun, sizeof(fRun));
539 fSet = false;
540 }
541
542 int first() const {
543 int index = 0;
544 while (++index < kMaxDir) {
545 if (fRun[index]) {
546 return index;
547 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000548 }
caryclark19eb3b22014-07-18 05:08:14 -0700549 SkASSERT(0);
550 return -1;
551 }
552
553 int last() const {
554 int index = kMaxDir;
555 while (--index > 0 && !fRun[index])
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000556 ;
caryclark19eb3b22014-07-18 05:08:14 -0700557 return index;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000558 }
559
caryclark19eb3b22014-07-18 05:08:14 -0700560 int next() {
561 while (++fIndex < kMaxDir) {
562 if (fRun[fIndex]) {
563 return fIndex;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000564 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000565 }
caryclark19eb3b22014-07-18 05:08:14 -0700566 return -1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000567 }
568
caryclark19eb3b22014-07-18 05:08:14 -0700569 void reset() {
570 fIndex = -1;
571 }
572
573 void set(int start, int end) {
574 while (start < end) {
575 fRun[start++] = 1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000576 }
caryclark19eb3b22014-07-18 05:08:14 -0700577 fSet = true;
578 }
579
580 void setDefault() {
581 if (!fSet) {
582 set(1, 100);
583 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000584 }
585
586private:
caryclark19eb3b22014-07-18 05:08:14 -0700587 enum {
588 kMaxDir = 101
589 };
590 char fRun[kMaxDir];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000591 int fIndex;
caryclark19eb3b22014-07-18 05:08:14 -0700592 bool fSet;
593} gDirs;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000594
caryclark19eb3b22014-07-18 05:08:14 -0700595class Filenames {
596public:
597 Filenames()
598 : fIndex(-1) {
599 }
600
601 const char* next() {
602 while (fNames && ++fIndex < fNames->count()) {
603 return (*fNames)[fIndex];
604 }
halcanary96fcdcc2015-08-27 07:41:13 -0700605 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -0700606 }
mtklein406654b2014-09-03 15:34:37 -0700607
caryclark19eb3b22014-07-18 05:08:14 -0700608 void set(const SkCommandLineFlags::StringArray& names) {
609 fNames = &names;
610 }
611
612private:
613 int fIndex;
614 const SkCommandLineFlags::StringArray* fNames;
615} gNames;
616
mtklein406654b2014-09-03 15:34:37 -0700617static bool buildTestDir(int dirNo, int firstDirNo,
caryclark19eb3b22014-07-18 05:08:14 -0700618 SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
619 SkString dirName = get_out_path(dirNo, outStatusDir);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000620 if (!dirName.size()) {
621 return false;
622 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000623 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000624 SkString filename;
625 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700626 TestResult test;
627 test.init(dirNo);
628 SkString spaceFile(filename);
629 char* spaces = spaceFile.writable_str();
630 int spaceSize = (int) spaceFile.size();
631 for (int index = 0; index < spaceSize; ++index) {
632 if (spaces[index] == '.') {
633 spaces[index] = ' ';
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000634 }
635 }
caryclark19eb3b22014-07-18 05:08:14 -0700636 int success = sscanf(spaces, "%s %d %d skp", test.fFilename,
637 &test.fPixelError, &test.fTime);
638 if (success < 3) {
639 SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success);
640 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000641 }
caryclark19eb3b22014-07-18 05:08:14 -0700642 *tests[dirNo - firstDirNo].append() = test;
643 }
644 if (!sorted) {
645 return true;
646 }
647 SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo];
648 int count = testSet.count();
649 for (int index = 0; index < count; ++index) {
650 *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index];
651 }
652 if (sorted[dirNo - firstDirNo].count()) {
653 SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(),
654 sorted[dirNo - firstDirNo].end() - 1);
655 if (verbose()) {
656 SkDebugf("+");
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000657 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000658 }
659 return true;
660}
661
caryclark19eb3b22014-07-18 05:08:14 -0700662static void testSkpClip(TestState* data) {
663 data->fResult.testOne();
664 SkString statName(data->fResult.fFilename);
665 SkASSERT(statName.endsWith(".skp"));
666 statName.remove(statName.size() - 4, 4);
667 statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime);
668 SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir);
669 if (!statusFile.size()) {
670 SkDebugf("failed to create %s", statusFile.c_str());
671 return;
672 }
673 statusFile.appendf("%s%s", PATH_SLASH, statName.c_str());
halcanaryd76be9c2015-11-20 13:47:49 -0800674 FILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
caryclark19eb3b22014-07-18 05:08:14 -0700675 if (!file) {
676 SkDebugf("failed to create %s", statusFile.c_str());
677 return;
678 }
679 sk_fclose(file);
680 if (verbose()) {
681 if (data->fResult.fPixelError || data->fResult.fTime) {
682 SkDebugf("%s", data->fResult.progress().c_str());
683 } else {
684 SkDebugf(".");
685 }
686 }
687}
688
689bool Less(const SortByName& a, const SortByName& b);
690bool Less(const SortByName& a, const SortByName& b) {
691 return a < b;
692}
693
694static bool doOneDir(TestState* state, bool threaded) {
695 int dirNo = state->fResult.fDirNo;
halcanary96fcdcc2015-08-27 07:41:13 -0700696 SkString dirName = get_in_path(dirNo, nullptr);
caryclark19eb3b22014-07-18 05:08:14 -0700697 if (!dirName.size()) {
698 return false;
699 }
700 SkTDArray<TestResult> tests[1];
701 SkTDArray<SortByName*> sorted[1];
702 if (!buildTestDir(dirNo, dirNo, tests, sorted)) {
703 return false;
704 }
705 SkOSFile::Iter iter(dirName.c_str(), "skp");
706 SkString filename;
707 while (iter.next(&filename)) {
708 for (size_t index = 0; index < skipOverCount; ++index) {
709 if (skipOver[index].directory == dirNo
710 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
711 goto checkEarlyExit;
712 }
713 }
714 {
715 SortByName name;
716 name.init(dirNo);
717 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
718 int count = sorted[0].count();
719 int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name));
720 if (idx >= 0) {
721 SortByName* found = sorted[0][idx];
722 (void) addError(state, *found);
723 continue;
724 }
725 TestResult test;
726 test.init(dirNo, filename);
727 state->fResult = test;
728 testSkpClip(state);
729#if 0 // artificially limit to a few while debugging code
730 static int debugLimit = 0;
731 if (++debugLimit == 5) {
732 return true;
733 }
734#endif
735 }
736checkEarlyExit:
737 ;
738 }
739 return true;
740}
741
caryclarkdac1d172014-06-17 05:15:38 -0700742static void testSkpClipEncode(TestState* data) {
743 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700744 if (verbose()) {
745 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700746 }
747}
748
caryclark19eb3b22014-07-18 05:08:14 -0700749static void encodeFound(TestState& state) {
750 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700751 if (state.fPixelWorst.count()) {
752 SkTDArray<SortByPixel*> worst;
753 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
754 *worst.append() = &state.fPixelWorst[index];
755 }
756 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
757 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
758 const TestResult& result = *worst[index];
759 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
760 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000761 }
caryclarkdac1d172014-06-17 05:15:38 -0700762 if (state.fSlowest.count()) {
763 SkTDArray<SortByTime*> slowest;
764 for (int index = 0; index < state.fSlowest.count(); ++index) {
765 *slowest.append() = &state.fSlowest[index];
766 }
767 if (slowest.count() > 0) {
768 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
769 for (int index = 0; index < slowest.count(); ++index) {
770 const TestResult& result = *slowest[index];
771 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
772 }
773 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000774 }
775 }
mtklein406654b2014-09-03 15:34:37 -0700776 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000777 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
778 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700779 SkString filename(result.fFilename);
780 if (!filename.endsWith(".skp")) {
781 filename.append(".skp");
782 }
halcanary385fe4d2015-08-26 13:07:48 -0700783 *testRunner.fRunnables.append() = new TestRunnableEncode(&testSkpClipEncode, result.fDirNo,
784 filename.c_str(), &testRunner);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000785 }
caryclarkdac1d172014-06-17 05:15:38 -0700786 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000787}
788
caryclark19eb3b22014-07-18 05:08:14 -0700789class Test {
790public:
791 Test() {}
792 virtual ~Test() {}
793
794 const char* getName() { onGetName(&fName); return fName.c_str(); }
795 void run() { onRun(); }
796
797protected:
798 virtual void onGetName(SkString*) = 0;
799 virtual void onRun() = 0;
800
801private:
802 SkString fName;
803};
804
805typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
806
halcanary385fe4d2015-08-26 13:07:48 -0700807#define DEF_TEST(name) \
808 static void test_##name(); \
809 class name##Class : public Test { \
810 public: \
811 static Test* Factory(void*) { return new name##Class; } \
812 \
813 protected: \
814 void onGetName(SkString* name) override { name->set(#name); } \
815 void onRun() override { test_##name(); } \
816 }; \
817 static TestRegistry gReg_##name##Class(name##Class::Factory); \
caryclark19eb3b22014-07-18 05:08:14 -0700818 static void test_##name()
819
820DEF_TEST(PathOpsSkpClip) {
821 gDirs.setDefault();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000822 SkTArray<TestResult, true> errors;
823 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700824 state.init(0);
825 int dirNo;
826 gDirs.reset();
827 while ((dirNo = gDirs.next()) > 0) {
828 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000829 SkDebugf("dirNo=%d\n", dirNo);
830 }
831 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000832 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000833 break;
834 }
835 }
caryclark19eb3b22014-07-18 05:08:14 -0700836 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000837}
838
839static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000840 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000841}
842
caryclark19eb3b22014-07-18 05:08:14 -0700843DEF_TEST(PathOpsSkpClipThreaded) {
844 gDirs.setDefault();
mtklein406654b2014-09-03 15:34:37 -0700845 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700846 int dirNo;
847 gDirs.reset();
848 while ((dirNo = gDirs.next()) > 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700849 *testRunner.fRunnables.append() = new TestRunnableDir(&testSkpClipMain, dirNo, &testRunner);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000850 }
851 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000852 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700853 state.init(0);
854 gDirs.reset();
855 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000856 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700857 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000858 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000859 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000860 }
caryclarkdac1d172014-06-17 05:15:38 -0700861 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
862 addError(&state, testState.fSlowest[inner]);
863 }
864 }
caryclark19eb3b22014-07-18 05:08:14 -0700865 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700866}
mtklein406654b2014-09-03 15:34:37 -0700867
caryclark19eb3b22014-07-18 05:08:14 -0700868static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
869 int firstDirNo = gDirs.first();
870 int dirNo;
871 while ((dirNo = gDirs.next()) > 0) {
872 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700873 return false;
874 }
caryclarkdac1d172014-06-17 05:15:38 -0700875 }
876 return true;
877}
878
caryclark19eb3b22014-07-18 05:08:14 -0700879DEF_TEST(PathOpsSkpClipUberThreaded) {
880 gDirs.setDefault();
881 const int firstDirNo = gDirs.next();
882 const int lastDirNo = gDirs.last();
caryclark19eb3b22014-07-18 05:08:14 -0700883 int dirCount = lastDirNo - firstDirNo + 1;
Ben Wagner7ecc5962016-11-02 17:07:33 -0400884 std::unique_ptr<SkTDArray<TestResult>[]> tests(new SkTDArray<TestResult>[dirCount]);
885 std::unique_ptr<SkTDArray<SortByName*>[]> sorted(new SkTDArray<SortByName*>[dirCount]);
caryclark19eb3b22014-07-18 05:08:14 -0700886 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700887 return;
888 }
mtklein406654b2014-09-03 15:34:37 -0700889 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700890 int dirNo;
891 gDirs.reset();
892 while ((dirNo = gDirs.next()) > 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700893 SkString dirName = get_in_path(dirNo, nullptr);
caryclarkdac1d172014-06-17 05:15:38 -0700894 if (!dirName.size()) {
895 continue;
896 }
897 SkOSFile::Iter iter(dirName.c_str(), "skp");
898 SkString filename;
899 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700900 for (size_t index = 0; index < skipOverCount; ++index) {
901 if (skipOver[index].directory == dirNo
902 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700903 goto checkEarlyExit;
904 }
905 }
caryclark19eb3b22014-07-18 05:08:14 -0700906 {
907 SortByName name;
908 name.init(dirNo);
909 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
910 int count = sorted.get()[dirNo - firstDirNo].count();
911 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
912 count, &name, sizeof(&name)) < 0) {
halcanary385fe4d2015-08-26 13:07:48 -0700913 *testRunner.fRunnables.append() = new TestRunnableFile(
914 &testSkpClip, dirNo, filename.c_str(), &testRunner);
caryclark19eb3b22014-07-18 05:08:14 -0700915 }
caryclarkdac1d172014-06-17 05:15:38 -0700916 }
917 checkEarlyExit:
918 ;
919 }
920
921 }
922 testRunner.render();
Ben Wagner7ecc5962016-11-02 17:07:33 -0400923 std::unique_ptr<SkTDArray<TestResult>[]> results(new SkTDArray<TestResult>[dirCount]);
halcanary96fcdcc2015-08-27 07:41:13 -0700924 if (!buildTests(results.get(), nullptr)) {
caryclarkdac1d172014-06-17 05:15:38 -0700925 return;
926 }
927 SkTDArray<TestResult> allResults;
928 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700929 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700930 allResults.append(array.count(), array.begin());
931 }
932 int allCount = allResults.count();
933 SkTDArray<SortByPixel*> pixels;
934 SkTDArray<SortByTime*> times;
935 for (int index = 0; index < allCount; ++index) {
936 *pixels.append() = (SortByPixel*) &allResults[index];
937 *times.append() = (SortByTime*) &allResults[index];
938 }
939 TestState state;
940 if (pixels.count()) {
941 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
942 for (int inner = 0; inner < kMaxFiles; ++inner) {
943 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
944 }
945 }
946 if (times.count()) {
947 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
948 for (int inner = 0; inner < kMaxFiles; ++inner) {
949 *state.fSlowest.append() = *times[allCount - inner - 1];
950 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000951 }
caryclark19eb3b22014-07-18 05:08:14 -0700952 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000953}
954
caryclark19eb3b22014-07-18 05:08:14 -0700955DEF_TEST(PathOpsSkpClipOneOff) {
956 const int testIndex = FLAGS_testIndex;
957 int dirNo = gDirs.next();
958 if (dirNo < 0) {
959 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000960 }
caryclark19eb3b22014-07-18 05:08:14 -0700961 const char* skp = gNames.next();
962 if (!skp) {
963 skp = skipOver[testIndex].filename;
964 }
caryclark19eb3b22014-07-18 05:08:14 -0700965 SkAssertResult(get_in_path(dirNo, skp).size());
966 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000967 TestResult state;
968 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700969 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000970 SkDebugf("%s", state.status().c_str());
971 }
972 state.fTestStep = kEncodeFiles;
973 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000974}
caryclark19eb3b22014-07-18 05:08:14 -0700975
976DEF_TEST(PathOpsTestSkipped) {
977 for (size_t index = 0; index < skipOverCount; ++index) {
978 const SkipOverTest& skip = skipOver[index];
979 if (!skip.blamePathOps) {
980 continue;
981 }
982 int dirNo = skip.directory;
983 const char* skp = skip.filename;
caryclark19eb3b22014-07-18 05:08:14 -0700984 SkAssertResult(get_in_path(dirNo, skp).size());
985 SkString filename(skp);
986 TestResult state;
987 state.test(dirNo, filename);
988 if (verbose()) {
989 SkDebugf("%s", state.status().c_str());
990 }
991 state.fTestStep = kEncodeFiles;
992 state.testOne();
993 }
994}
995
996DEF_TEST(PathOpsCopyFails) {
997 FLAGS_verbose = true;
998 for (size_t index = 0; index < skipOverCount; ++index) {
999 int dirNo = skipOver[index].directory;
1000 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1001 }
1002 for (size_t index = 0; index < skipOverCount; ++index) {
1003 int dirNo = skipOver[index].directory;
1004 const char* filename = skipOver[index].filename;
1005 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1006 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1007 }
1008}
1009
1010template TestRegistry* TestRegistry::gHead;
1011
1012class Iter {
1013public:
1014 Iter() { this->reset(); }
1015 void reset() { fReg = TestRegistry::Head(); }
1016
1017 Test* next() {
1018 if (fReg) {
1019 TestRegistry::Factory fact = fReg->factory();
1020 fReg = fReg->next();
halcanary96fcdcc2015-08-27 07:41:13 -07001021 Test* test = fact(nullptr);
caryclark19eb3b22014-07-18 05:08:14 -07001022 return test;
1023 }
halcanary96fcdcc2015-08-27 07:41:13 -07001024 return nullptr;
caryclark19eb3b22014-07-18 05:08:14 -07001025 }
1026
1027private:
1028 const TestRegistry* fReg;
1029};
1030
1031int tool_main(int argc, char** argv);
1032int tool_main(int argc, char** argv) {
1033 SetupCrashHandler();
1034 SkCommandLineFlags::SetUsage("");
1035 SkCommandLineFlags::Parse(argc, argv);
1036 SkGraphics::Init();
1037 SkString header("PathOps SkpClip:");
1038 if (!FLAGS_match.isEmpty()) {
1039 header.appendf(" --match");
1040 for (int index = 0; index < FLAGS_match.count(); ++index) {
1041 header.appendf(" %s", FLAGS_match[index]);
1042 }
1043 }
1044 if (!FLAGS_dir.isEmpty()) {
1045 int count = FLAGS_dir.count();
1046 for (int i = 0; i < count; ++i) {
1047 const char* range = FLAGS_dir[i];
1048 const char* dash = strchr(range, '-');
1049 if (!dash) {
1050 dash = strchr(range, ',');
1051 }
1052 int first = atoi(range);
1053 int last = dash ? atoi(dash + 1) : first;
1054 if (!first || !last) {
1055 SkDebugf("couldn't parse --dir %s\n", range);
1056 return 1;
1057 }
1058 gDirs.set(first, last);
1059 }
1060 }
1061 if (!FLAGS_skp.isEmpty()) {
1062 gNames.set(FLAGS_skp);
1063 }
1064#ifdef SK_DEBUG
1065 header.append(" SK_DEBUG");
1066#else
1067 header.append(" SK_RELEASE");
1068#endif
caryclark19eb3b22014-07-18 05:08:14 -07001069 if (FLAGS_verbose) {
1070 header.appendf("\n");
1071 }
kkinnunen297aaf92015-02-19 06:32:12 -08001072 SkDebugf("%s", header.c_str());
caryclark19eb3b22014-07-18 05:08:14 -07001073 Iter iter;
1074 Test* test;
halcanary96fcdcc2015-08-27 07:41:13 -07001075 while ((test = iter.next()) != nullptr) {
Ben Wagner145dbcd2016-11-03 14:40:50 -04001076 std::unique_ptr<Test> owned(test);
caryclark19eb3b22014-07-18 05:08:14 -07001077 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1078 test->run();
1079 }
1080 }
caryclark19eb3b22014-07-18 05:08:14 -07001081 return 0;
1082}
1083
borenet48087572015-04-02 12:16:36 -07001084#if !defined(SK_BUILD_FOR_IOS)
caryclark19eb3b22014-07-18 05:08:14 -07001085int main(int argc, char * const argv[]) {
1086 return tool_main(argc, (char**) argv);
1087}
1088#endif