blob: b8142cd654b6697c567bdd9187769c4c75c9c652 [file] [log] [blame]
caryclark19eb3b22014-07-18 05:08:14 -07001#include "CrashHandler.h"
2// #include "OverwriteLine.h"
3#include "Resources.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +00004#include "SkBitmap.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +00005#include "SkCanvas.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +00006#include "SkColor.h"
7#include "SkColorPriv.h"
caryclark19eb3b22014-07-18 05:08:14 -07008#include "SkCommandLineFlags.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +00009#include "SkDevice.h"
caryclark19eb3b22014-07-18 05:08:14 -070010#include "SkForceLinking.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000011#include "SkGraphics.h"
caryclark@google.comcffbcc32013-06-04 17:59:42 +000012#include "SkImageDecoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000013#include "SkImageEncoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000014#include "SkOSFile.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000015#include "SkPathOpsDebug.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000016#include "SkPicture.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000017#include "SkRTConf.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000018#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000019#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000020#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000021#include "SkTArray.h"
22#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070023#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070024#include "SkTemplates.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000025#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000026
caryclark19eb3b22014-07-18 05:08:14 -070027__SK_FORCE_IMAGE_DECODER_LINKING;
caryclark@google.com07e97fc2013-07-08 17:17:02 +000028
caryclark19eb3b22014-07-18 05:08:14 -070029/* add local exceptions here */
30/* TODO : add command flag interface */
31const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000032 int directory;
33 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070034 bool blamePathOps;
35} skipOver[] = {
36 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
37 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
38 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
39 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
40 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070041 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070042 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
43 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
44 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
45 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
46 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
47 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
48 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
49 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
50 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
51 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
52 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
53 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
54 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
55 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000056};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000057
caryclark19eb3b22014-07-18 05:08:14 -070058size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070059
caryclark19eb3b22014-07-18 05:08:14 -070060
61/* customize file in/out here */
62/* TODO : add command flag interface */
63#define CHROME_VERSION "1e5dfa4-4a995df"
64#define SUMMARY_RUN 1
65
66#ifdef SK_BUILD_FOR_WIN
67 #define DRIVE_SPEC "D:"
68 #define PATH_SLASH "\\"
69#else
70 #define DRIVE_SPEC ""
71 #define PATH_SLASH "/"
72#endif
73
74#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
75#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
76#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
77#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
78
79static const char outOpDir[] = "opClip";
80static const char outOldDir[] = "oldClip";
81static const char outStatusDir[] = "statusTest";
82
83static SkString get_in_path(int dirNo, const char* filename) {
84 SkString path;
85 SkASSERT(dirNo);
86 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
87 if (!sk_exists(path.c_str())) {
88 SkDebugf("could not read %s\n", path.c_str());
89 return SkString();
90 }
91 if (filename) {
92 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -070093 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -070094 SkDebugf("could not read %s\n", path.c_str());
95 return SkString();
96 }
97 }
98 return path;
99}
mtklein406654b2014-09-03 15:34:37 -0700100
caryclark19eb3b22014-07-18 05:08:14 -0700101static void make_recursive_dir(const SkString& path) {
102 if (sk_exists(path.c_str())) {
103 return;
104 }
105 const char* pathStr = path.c_str();
106 int last = (int) path.size();
107 do {
108 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
109 ;
110 SkASSERT(last > 0);
111 SkString shorter(pathStr, last);
112 if (sk_mkdir(shorter.c_str())) {
113 break;
114 }
115 } while (true);
116 do {
117 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
118 ;
119 SkString shorter(pathStr, last);
120 SkAssertResult(sk_mkdir(shorter.c_str()));
121 } while (last < (int) path.size());
122}
123
124static SkString get_out_path(int dirNo, const char* dirName) {
125 SkString path;
126 SkASSERT(dirNo);
127 SkASSERT(dirName);
128 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
129 make_recursive_dir(path);
130 return path;
131}
mtklein406654b2014-09-03 15:34:37 -0700132
caryclark19eb3b22014-07-18 05:08:14 -0700133static SkString get_sum_path(const char* dirName) {
134 SkString path;
135 SkASSERT(dirName);
136 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
137 SkDebugf("%s\n", path.c_str());
138 make_recursive_dir(path);
139 return path;
140}
141
142static SkString make_png_name(const char* filename) {
143 SkString pngName = SkString(filename);
144 pngName.remove(pngName.size() - 3, 3);
145 pngName.append("png");
146 return pngName;
147}
148
149////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000150
151enum TestStep {
152 kCompareBits,
153 kEncodeFiles,
154};
155
156enum {
caryclarkdac1d172014-06-17 05:15:38 -0700157 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000158 kMaxFiles = 128,
159 kSmallLimit = 1000,
160};
161
162struct TestResult {
163 void init(int dirNo) {
164 fDirNo = dirNo;
165 sk_bzero(fFilename, sizeof(fFilename));
166 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000167 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000168 }
mtklein406654b2014-09-03 15:34:37 -0700169
caryclark19eb3b22014-07-18 05:08:14 -0700170 void init(int dirNo, const SkString& filename) {
171 fDirNo = dirNo;
172 strcpy(fFilename, filename.c_str());
173 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700174 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700175 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000176
177 SkString status() {
178 SkString outStr;
179 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
180 return outStr;
181 }
182
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000183 SkString progress() {
184 SkString outStr;
185 outStr.printf("dir=%d %s ", fDirNo, fFilename);
186 if (fPixelError) {
187 outStr.appendf(" err=%d", fPixelError);
188 }
189 if (fTime) {
190 outStr.appendf(" time=%d", fTime);
191 }
192 if (fScale != 1) {
193 outStr.appendf(" scale=%d", fScale);
194 }
195 outStr.appendf("\n");
196 return outStr;
197
198 }
199
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000200 void test(int dirNo, const SkString& filename) {
201 init(dirNo);
202 strcpy(fFilename, filename.c_str());
203 testOne();
204 }
205
206 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700207
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000208 char fFilename[kMaxLength];
209 TestStep fTestStep;
210 int fDirNo;
211 int fPixelError;
212 int fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000213 int fScale;
214};
215
216class SortByPixel : public TestResult {
217public:
218 bool operator<(const SortByPixel& rh) const {
219 return fPixelError < rh.fPixelError;
220 }
221};
222
223class SortByTime : public TestResult {
224public:
225 bool operator<(const SortByTime& rh) const {
226 return fTime < rh.fTime;
227 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000228};
229
caryclarkdac1d172014-06-17 05:15:38 -0700230class SortByName : public TestResult {
231public:
232 bool operator<(const SortByName& rh) const {
233 return strcmp(fFilename, rh.fFilename) < 0;
234 }
235};
236
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000237struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700238 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000239 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000240 }
241
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000242 SkTDArray<SortByPixel> fPixelWorst;
243 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000244 TestResult fResult;
245};
246
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000247struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000248 ~TestRunner();
249 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000250 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000251};
252
253class TestRunnable : public SkRunnable {
254public:
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000255 virtual void run() SK_OVERRIDE {
256 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
257 (*fTestFun)(&fState);
258 }
259
260 TestState fState;
261 void (*fTestFun)(TestState*);
262};
263
caryclarkdac1d172014-06-17 05:15:38 -0700264
265class TestRunnableDir : public TestRunnable {
266public:
267 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700268 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700269 fTestFun = testFun;
270 }
271
272};
273
274class TestRunnableFile : public TestRunnable {
275public:
276 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700277 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700278 strcpy(fState.fResult.fFilename, name);
279 fTestFun = testFun;
280 }
281};
282
283class TestRunnableEncode : public TestRunnableFile {
284public:
285 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
286 : TestRunnableFile(testFun, dirNo, name, runner) {
287 fState.fResult.fTestStep = kEncodeFiles;
288 }
289};
290
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000291TestRunner::~TestRunner() {
292 for (int index = 0; index < fRunnables.count(); index++) {
293 SkDELETE(fRunnables[index]);
294 }
295}
296
297void TestRunner::render() {
mtklein406654b2014-09-03 15:34:37 -0700298 SkTaskGroup tg;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000299 for (int index = 0; index < fRunnables.count(); ++ index) {
mtklein406654b2014-09-03 15:34:37 -0700300 tg.add(fRunnables[index]);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000301 }
302}
303
304////////////////////////////////////////////////
305
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000306
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000307static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
308 const int kRowCount = 3;
309 const int kThreshold = 3;
310 int width = SkTMin(gr.width(), sk.width());
311 if (width < kRowCount) {
312 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000313 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000314 int height = SkTMin(gr.height(), sk.height());
315 if (height < kRowCount) {
316 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000317 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000318 int errorTotal = 0;
319 SkTArray<int, true> errorRows;
320 errorRows.push_back_n(width * kRowCount);
321 SkAutoLockPixels autoGr(gr);
322 SkAutoLockPixels autoSk(sk);
323 for (int y = 0; y < height; ++y) {
324 SkPMColor* grRow = gr.getAddr32(0, y);
325 SkPMColor* skRow = sk.getAddr32(0, y);
326 int* base = &errorRows[0];
327 int* cOut = &errorRows[y % kRowCount];
328 for (int x = 0; x < width; ++x) {
329 SkPMColor grColor = grRow[x];
330 SkPMColor skColor = skRow[x];
331 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
332 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
333 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
334 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
335 if (error < kThreshold || x < 2) {
336 continue;
337 }
338 if (base[x - 2] < kThreshold
339 || base[width + x - 2] < kThreshold
340 || base[width * 2 + x - 2] < kThreshold
341 || base[x - 1] < kThreshold
342 || base[width + x - 1] < kThreshold
343 || base[width * 2 + x - 1] < kThreshold
344 || base[x] < kThreshold
345 || base[width + x] < kThreshold
346 || base[width * 2 + x] < kThreshold) {
347 continue;
348 }
349 errorTotal += error;
350 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000351 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000352 return errorTotal;
353}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000354
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000355static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000356 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
357 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000358 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000359 int worstCount = data->fPixelWorst.count();
360 int pixelError = testResult.fPixelError;
361 if (pixelError > 0) {
362 for (int index = 0; index < worstCount; ++index) {
363 if (pixelError > data->fPixelWorst[index].fPixelError) {
364 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
365 return true;
366 }
367 }
368 }
369 int slowCount = data->fSlowest.count();
370 int time = testResult.fTime;
371 if (time > 0) {
372 for (int index = 0; index < slowCount; ++index) {
373 if (time > data->fSlowest[index].fTime) {
374 data->fSlowest[index] = *(SortByTime*) &testResult;
375 return true;
376 }
377 }
378 }
379 if (pixelError > 0 && worstCount < kMaxFiles) {
380 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
381 return true;
382 }
383 if (time > 0 && slowCount < kMaxFiles) {
384 *data->fSlowest.append() = *(SortByTime*) &testResult;
385 return true;
386 }
387 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000388}
389
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000390static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
391 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700392 SkScalar pWidth = pic->cullRect().width();
393 SkScalar pHeight = pic->cullRect().height();
394 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000395 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700396 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
397 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
398 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000399 canvas->clipRect(rect);
400 SkMSec start = SkTime::GetMSecs();
401 for (int x = 0; x < slices; ++x) {
402 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700403 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700404 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000405 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700406 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000407 }
408 SkMSec end = SkTime::GetMSecs();
409 canvas->restore();
410 return end - start;
411}
412
413static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
414 canvas->clear(SK_ColorWHITE);
415 if (scale != 1) {
416 canvas->save();
417 canvas->scale(1.0f / scale, 1.0f / scale);
418 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700419 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000420 if (scale != 1) {
421 canvas->restore();
422 }
423}
424
425static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700426 SkString outFile = get_sum_path(outDir);
427 outFile.appendf("%s%s", PATH_SLASH, pngName);
428 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000429 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
430 bitmap.width(), bitmap.height());
431 }
432}
433
434void TestResult::testOne() {
435 SkPicture* pic = NULL;
436 {
437 #if DEBUG_SHOW_TEST_NAME
438 if (fTestStep == kCompareBits) {
439 SkString testName(fFilename);
440 const char http[] = "http";
441 if (testName.startsWith(http)) {
442 testName.remove(0, sizeof(http) - 1);
443 }
444 while (testName.startsWith("_")) {
445 testName.remove(0, 1);
446 }
447 const char dotSkp[] = ".skp";
448 if (testName.endsWith(dotSkp)) {
449 size_t len = testName.size();
450 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
451 }
452 testName.prepend("skp");
453 testName.append("1");
454 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
455 } else if (fTestStep == kEncodeFiles) {
456 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
457 }
458 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700459 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000460 SkFILEStream stream(path.c_str());
461 if (!stream.isValid()) {
462 SkDebugf("invalid stream %s\n", path.c_str());
463 goto finish;
464 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000465 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000466 if (!pic) {
467 SkDebugf("unable to decode %s\n", fFilename);
468 goto finish;
469 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700470 SkScalar width = pic->cullRect().width();
471 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000472 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000473 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000474 while (width / fScale > 32767 || height / fScale > 32767) {
475 ++fScale;
476 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000477 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700478 int dimX = SkScalarCeilToInt(width / fScale);
479 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700480 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000481 break;
482 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000483 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000484 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000485 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700486 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000487 width, height);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000488 goto finish;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000489 }
490 oldBitmap.eraseColor(SK_ColorWHITE);
491 SkCanvas oldCanvas(oldBitmap);
492 oldCanvas.setAllowSimplifyClip(false);
493 opBitmap.eraseColor(SK_ColorWHITE);
494 SkCanvas opCanvas(opBitmap);
495 opCanvas.setAllowSimplifyClip(true);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000496 drawPict(pic, &oldCanvas, fScale);
497 drawPict(pic, &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000498 if (fTestStep == kCompareBits) {
499 fPixelError = similarBits(oldBitmap, opBitmap);
500 int oldTime = timePict(pic, &oldCanvas);
501 int opTime = timePict(pic, &opCanvas);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000502 fTime = SkTMax(0, oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000503 } else if (fTestStep == kEncodeFiles) {
504 SkString pngStr = make_png_name(fFilename);
505 const char* pngName = pngStr.c_str();
506 writePict(oldBitmap, outOldDir, pngName);
507 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000508 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000509 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000510finish:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000511 if (pic) {
512 pic->unref();
513 }
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 ~");
525DEFINE_string2(dir, d, NULL, "range of directories (e.g., 1-100)");
526DEFINE_string2(skp, s, NULL, "skp to test");
527DEFINE_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 }
606 return NULL;
607 }
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());
675 SkFILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
676 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;
697 SkString dirName = get_in_path(dirNo, NULL);
698 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
743static void initTest() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000744#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC
745 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
746 SK_CONF_SET("images.png.suppressDecoderWarnings", true);
747#endif
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000748}
749
caryclarkdac1d172014-06-17 05:15:38 -0700750static void testSkpClipEncode(TestState* data) {
751 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700752 if (verbose()) {
753 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700754 }
755}
756
caryclark19eb3b22014-07-18 05:08:14 -0700757static void encodeFound(TestState& state) {
758 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700759 if (state.fPixelWorst.count()) {
760 SkTDArray<SortByPixel*> worst;
761 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
762 *worst.append() = &state.fPixelWorst[index];
763 }
764 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
765 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
766 const TestResult& result = *worst[index];
767 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
768 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000769 }
caryclarkdac1d172014-06-17 05:15:38 -0700770 if (state.fSlowest.count()) {
771 SkTDArray<SortByTime*> slowest;
772 for (int index = 0; index < state.fSlowest.count(); ++index) {
773 *slowest.append() = &state.fSlowest[index];
774 }
775 if (slowest.count() > 0) {
776 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
777 for (int index = 0; index < slowest.count(); ++index) {
778 const TestResult& result = *slowest[index];
779 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
780 }
781 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000782 }
783 }
mtklein406654b2014-09-03 15:34:37 -0700784 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000785 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
786 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700787 SkString filename(result.fFilename);
788 if (!filename.endsWith(".skp")) {
789 filename.append(".skp");
790 }
791 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableEncode,
792 (&testSkpClipEncode, result.fDirNo, filename.c_str(), &testRunner));
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000793 }
caryclarkdac1d172014-06-17 05:15:38 -0700794 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000795}
796
caryclark19eb3b22014-07-18 05:08:14 -0700797class Test {
798public:
799 Test() {}
800 virtual ~Test() {}
801
802 const char* getName() { onGetName(&fName); return fName.c_str(); }
803 void run() { onRun(); }
804
805protected:
806 virtual void onGetName(SkString*) = 0;
807 virtual void onRun() = 0;
808
809private:
810 SkString fName;
811};
812
813typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
814
815#define DEF_TEST(name) \
816 static void test_##name(); \
817 class name##Class : public Test { \
818 public: \
819 static Test* Factory(void*) { return SkNEW(name##Class); } \
820 protected: \
821 virtual void onGetName(SkString* name) SK_OVERRIDE { \
822 name->set(#name); \
823 } \
824 virtual void onRun() SK_OVERRIDE { test_##name(); } \
825 }; \
826 static TestRegistry gReg_##name##Class(name##Class::Factory); \
827 static void test_##name()
828
829DEF_TEST(PathOpsSkpClip) {
830 gDirs.setDefault();
831 initTest();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000832 SkTArray<TestResult, true> errors;
833 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700834 state.init(0);
835 int dirNo;
836 gDirs.reset();
837 while ((dirNo = gDirs.next()) > 0) {
838 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000839 SkDebugf("dirNo=%d\n", dirNo);
840 }
841 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000842 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000843 break;
844 }
845 }
caryclark19eb3b22014-07-18 05:08:14 -0700846 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000847}
848
849static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000850 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000851}
852
caryclark19eb3b22014-07-18 05:08:14 -0700853DEF_TEST(PathOpsSkpClipThreaded) {
854 gDirs.setDefault();
855 initTest();
mtklein406654b2014-09-03 15:34:37 -0700856 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700857 int dirNo;
858 gDirs.reset();
859 while ((dirNo = gDirs.next()) > 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700860 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableDir,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000861 (&testSkpClipMain, dirNo, &testRunner));
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000862 }
863 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000864 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700865 state.init(0);
866 gDirs.reset();
867 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000868 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700869 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000870 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000871 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000872 }
caryclarkdac1d172014-06-17 05:15:38 -0700873 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
874 addError(&state, testState.fSlowest[inner]);
875 }
876 }
caryclark19eb3b22014-07-18 05:08:14 -0700877 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700878}
mtklein406654b2014-09-03 15:34:37 -0700879
caryclark19eb3b22014-07-18 05:08:14 -0700880static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
881 int firstDirNo = gDirs.first();
882 int dirNo;
883 while ((dirNo = gDirs.next()) > 0) {
884 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700885 return false;
886 }
caryclarkdac1d172014-06-17 05:15:38 -0700887 }
888 return true;
889}
890
caryclark19eb3b22014-07-18 05:08:14 -0700891DEF_TEST(PathOpsSkpClipUberThreaded) {
892 gDirs.setDefault();
893 const int firstDirNo = gDirs.next();
894 const int lastDirNo = gDirs.last();
895 initTest();
896 int dirCount = lastDirNo - firstDirNo + 1;
897 SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]);
898 SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]);
899 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700900 return;
901 }
mtklein406654b2014-09-03 15:34:37 -0700902 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700903 int dirNo;
904 gDirs.reset();
905 while ((dirNo = gDirs.next()) > 0) {
906 SkString dirName = get_in_path(dirNo, NULL);
caryclarkdac1d172014-06-17 05:15:38 -0700907 if (!dirName.size()) {
908 continue;
909 }
910 SkOSFile::Iter iter(dirName.c_str(), "skp");
911 SkString filename;
912 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700913 for (size_t index = 0; index < skipOverCount; ++index) {
914 if (skipOver[index].directory == dirNo
915 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700916 goto checkEarlyExit;
917 }
918 }
caryclark19eb3b22014-07-18 05:08:14 -0700919 {
920 SortByName name;
921 name.init(dirNo);
922 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
923 int count = sorted.get()[dirNo - firstDirNo].count();
924 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
925 count, &name, sizeof(&name)) < 0) {
926 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableFile,
927 (&testSkpClip, dirNo, filename.c_str(), &testRunner));
928 }
caryclarkdac1d172014-06-17 05:15:38 -0700929 }
930 checkEarlyExit:
931 ;
932 }
933
934 }
935 testRunner.render();
caryclark19eb3b22014-07-18 05:08:14 -0700936 SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]);
937 if (!buildTests(results.get(), NULL)) {
caryclarkdac1d172014-06-17 05:15:38 -0700938 return;
939 }
940 SkTDArray<TestResult> allResults;
941 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700942 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700943 allResults.append(array.count(), array.begin());
944 }
945 int allCount = allResults.count();
946 SkTDArray<SortByPixel*> pixels;
947 SkTDArray<SortByTime*> times;
948 for (int index = 0; index < allCount; ++index) {
949 *pixels.append() = (SortByPixel*) &allResults[index];
950 *times.append() = (SortByTime*) &allResults[index];
951 }
952 TestState state;
953 if (pixels.count()) {
954 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
955 for (int inner = 0; inner < kMaxFiles; ++inner) {
956 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
957 }
958 }
959 if (times.count()) {
960 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
961 for (int inner = 0; inner < kMaxFiles; ++inner) {
962 *state.fSlowest.append() = *times[allCount - inner - 1];
963 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000964 }
caryclark19eb3b22014-07-18 05:08:14 -0700965 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000966}
967
caryclark19eb3b22014-07-18 05:08:14 -0700968DEF_TEST(PathOpsSkpClipOneOff) {
969 const int testIndex = FLAGS_testIndex;
970 int dirNo = gDirs.next();
971 if (dirNo < 0) {
972 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000973 }
caryclark19eb3b22014-07-18 05:08:14 -0700974 const char* skp = gNames.next();
975 if (!skp) {
976 skp = skipOver[testIndex].filename;
977 }
978 initTest();
979 SkAssertResult(get_in_path(dirNo, skp).size());
980 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000981 TestResult state;
982 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700983 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000984 SkDebugf("%s", state.status().c_str());
985 }
986 state.fTestStep = kEncodeFiles;
987 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000988}
caryclark19eb3b22014-07-18 05:08:14 -0700989
990DEF_TEST(PathOpsTestSkipped) {
991 for (size_t index = 0; index < skipOverCount; ++index) {
992 const SkipOverTest& skip = skipOver[index];
993 if (!skip.blamePathOps) {
994 continue;
995 }
996 int dirNo = skip.directory;
997 const char* skp = skip.filename;
998 initTest();
999 SkAssertResult(get_in_path(dirNo, skp).size());
1000 SkString filename(skp);
1001 TestResult state;
1002 state.test(dirNo, filename);
1003 if (verbose()) {
1004 SkDebugf("%s", state.status().c_str());
1005 }
1006 state.fTestStep = kEncodeFiles;
1007 state.testOne();
1008 }
1009}
1010
1011DEF_TEST(PathOpsCopyFails) {
1012 FLAGS_verbose = true;
1013 for (size_t index = 0; index < skipOverCount; ++index) {
1014 int dirNo = skipOver[index].directory;
1015 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1016 }
1017 for (size_t index = 0; index < skipOverCount; ++index) {
1018 int dirNo = skipOver[index].directory;
1019 const char* filename = skipOver[index].filename;
1020 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1021 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1022 }
1023}
1024
1025template TestRegistry* TestRegistry::gHead;
1026
1027class Iter {
1028public:
1029 Iter() { this->reset(); }
1030 void reset() { fReg = TestRegistry::Head(); }
1031
1032 Test* next() {
1033 if (fReg) {
1034 TestRegistry::Factory fact = fReg->factory();
1035 fReg = fReg->next();
1036 Test* test = fact(NULL);
1037 return test;
1038 }
1039 return NULL;
1040 }
1041
1042private:
1043 const TestRegistry* fReg;
1044};
1045
1046int tool_main(int argc, char** argv);
1047int tool_main(int argc, char** argv) {
1048 SetupCrashHandler();
1049 SkCommandLineFlags::SetUsage("");
1050 SkCommandLineFlags::Parse(argc, argv);
1051 SkGraphics::Init();
1052 SkString header("PathOps SkpClip:");
1053 if (!FLAGS_match.isEmpty()) {
1054 header.appendf(" --match");
1055 for (int index = 0; index < FLAGS_match.count(); ++index) {
1056 header.appendf(" %s", FLAGS_match[index]);
1057 }
1058 }
1059 if (!FLAGS_dir.isEmpty()) {
1060 int count = FLAGS_dir.count();
1061 for (int i = 0; i < count; ++i) {
1062 const char* range = FLAGS_dir[i];
1063 const char* dash = strchr(range, '-');
1064 if (!dash) {
1065 dash = strchr(range, ',');
1066 }
1067 int first = atoi(range);
1068 int last = dash ? atoi(dash + 1) : first;
1069 if (!first || !last) {
1070 SkDebugf("couldn't parse --dir %s\n", range);
1071 return 1;
1072 }
1073 gDirs.set(first, last);
1074 }
1075 }
1076 if (!FLAGS_skp.isEmpty()) {
1077 gNames.set(FLAGS_skp);
1078 }
1079#ifdef SK_DEBUG
1080 header.append(" SK_DEBUG");
1081#else
1082 header.append(" SK_RELEASE");
1083#endif
1084 header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8);
1085 if (FLAGS_verbose) {
1086 header.appendf("\n");
1087 }
1088 SkDebugf(header.c_str());
1089 Iter iter;
1090 Test* test;
1091 while ((test = iter.next()) != NULL) {
1092 SkAutoTDelete<Test> owned(test);
1093 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1094 test->run();
1095 }
1096 }
1097 SkGraphics::Term();
1098 return 0;
1099}
1100
1101#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
1102int main(int argc, char * const argv[]) {
1103 return tool_main(argc, (char**) argv);
1104}
1105#endif