blob: ad0a95f22b91f55895d554a70ce989d57d26169a [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"
reed89889b62014-10-29 12:36:45 -070018#include "SkRunnable.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000019#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000020#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000021#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000022#include "SkTArray.h"
23#include "SkTDArray.h"
mtklein406654b2014-09-03 15:34:37 -070024#include "SkTaskGroup.h"
caryclark19eb3b22014-07-18 05:08:14 -070025#include "SkTemplates.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000026#include "SkTime.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000027
caryclark19eb3b22014-07-18 05:08:14 -070028__SK_FORCE_IMAGE_DECODER_LINKING;
caryclark@google.com07e97fc2013-07-08 17:17:02 +000029
caryclark19eb3b22014-07-18 05:08:14 -070030/* add local exceptions here */
31/* TODO : add command flag interface */
32const struct SkipOverTest {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000033 int directory;
34 const char* filename;
caryclark19eb3b22014-07-18 05:08:14 -070035 bool blamePathOps;
36} skipOver[] = {
37 { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
38 { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
39 { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb)
40 {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
41 {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
caryclark5e27e0e2014-08-12 07:46:33 -070042 {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?)
caryclark19eb3b22014-07-18 05:08:14 -070043 {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection
44 {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic)
45 {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y));
46 {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0);
47 {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?)
48 {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple);
49 {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
50 {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2);
51 {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
52 {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex];
53 {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1);
54 {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
55 {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0);
56 {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000057};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000058
caryclark19eb3b22014-07-18 05:08:14 -070059size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]);
caryclarkdac1d172014-06-17 05:15:38 -070060
caryclark19eb3b22014-07-18 05:08:14 -070061
62/* customize file in/out here */
63/* TODO : add command flag interface */
64#define CHROME_VERSION "1e5dfa4-4a995df"
65#define SUMMARY_RUN 1
66
67#ifdef SK_BUILD_FOR_WIN
68 #define DRIVE_SPEC "D:"
69 #define PATH_SLASH "\\"
70#else
71 #define DRIVE_SPEC ""
72 #define PATH_SLASH "/"
73#endif
74
75#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave"
76#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave"
77#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary"
78#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION
79
80static const char outOpDir[] = "opClip";
81static const char outOldDir[] = "oldClip";
82static const char outStatusDir[] = "statusTest";
83
84static SkString get_in_path(int dirNo, const char* filename) {
85 SkString path;
86 SkASSERT(dirNo);
87 path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST);
88 if (!sk_exists(path.c_str())) {
89 SkDebugf("could not read %s\n", path.c_str());
90 return SkString();
91 }
92 if (filename) {
93 path.appendf("%s%s", PATH_SLASH, filename);
mtklein406654b2014-09-03 15:34:37 -070094 if (!sk_exists(path.c_str())) {
caryclark19eb3b22014-07-18 05:08:14 -070095 SkDebugf("could not read %s\n", path.c_str());
96 return SkString();
97 }
98 }
99 return path;
100}
mtklein406654b2014-09-03 15:34:37 -0700101
caryclark19eb3b22014-07-18 05:08:14 -0700102static void make_recursive_dir(const SkString& path) {
103 if (sk_exists(path.c_str())) {
104 return;
105 }
106 const char* pathStr = path.c_str();
107 int last = (int) path.size();
108 do {
109 while (last > 0 && pathStr[--last] != PATH_SLASH[0])
110 ;
111 SkASSERT(last > 0);
112 SkString shorter(pathStr, last);
113 if (sk_mkdir(shorter.c_str())) {
114 break;
115 }
116 } while (true);
117 do {
118 while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0])
119 ;
120 SkString shorter(pathStr, last);
121 SkAssertResult(sk_mkdir(shorter.c_str()));
122 } while (last < (int) path.size());
123}
124
125static SkString get_out_path(int dirNo, const char* dirName) {
126 SkString path;
127 SkASSERT(dirNo);
128 SkASSERT(dirName);
129 path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName);
130 make_recursive_dir(path);
131 return path;
132}
mtklein406654b2014-09-03 15:34:37 -0700133
caryclark19eb3b22014-07-18 05:08:14 -0700134static SkString get_sum_path(const char* dirName) {
135 SkString path;
136 SkASSERT(dirName);
137 path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName);
138 SkDebugf("%s\n", path.c_str());
139 make_recursive_dir(path);
140 return path;
141}
142
143static SkString make_png_name(const char* filename) {
144 SkString pngName = SkString(filename);
145 pngName.remove(pngName.size() - 3, 3);
146 pngName.append("png");
147 return pngName;
148}
149
150////////////////////////////////////////////////////////
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000151
152enum TestStep {
153 kCompareBits,
154 kEncodeFiles,
155};
156
157enum {
caryclarkdac1d172014-06-17 05:15:38 -0700158 kMaxLength = 256,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000159 kMaxFiles = 128,
160 kSmallLimit = 1000,
161};
162
163struct TestResult {
164 void init(int dirNo) {
165 fDirNo = dirNo;
166 sk_bzero(fFilename, sizeof(fFilename));
167 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000168 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000169 }
mtklein406654b2014-09-03 15:34:37 -0700170
caryclark19eb3b22014-07-18 05:08:14 -0700171 void init(int dirNo, const SkString& filename) {
172 fDirNo = dirNo;
173 strcpy(fFilename, filename.c_str());
174 fTestStep = kCompareBits;
mtklein406654b2014-09-03 15:34:37 -0700175 fScale = 1;
caryclark19eb3b22014-07-18 05:08:14 -0700176 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000177
178 SkString status() {
179 SkString outStr;
180 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
181 return outStr;
182 }
183
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000184 SkString progress() {
185 SkString outStr;
186 outStr.printf("dir=%d %s ", fDirNo, fFilename);
187 if (fPixelError) {
188 outStr.appendf(" err=%d", fPixelError);
189 }
190 if (fTime) {
191 outStr.appendf(" time=%d", fTime);
192 }
193 if (fScale != 1) {
194 outStr.appendf(" scale=%d", fScale);
195 }
196 outStr.appendf("\n");
197 return outStr;
198
199 }
200
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000201 void test(int dirNo, const SkString& filename) {
202 init(dirNo);
203 strcpy(fFilename, filename.c_str());
204 testOne();
205 }
206
207 void testOne();
mtklein406654b2014-09-03 15:34:37 -0700208
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000209 char fFilename[kMaxLength];
210 TestStep fTestStep;
211 int fDirNo;
212 int fPixelError;
213 int fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000214 int fScale;
215};
216
217class SortByPixel : public TestResult {
218public:
219 bool operator<(const SortByPixel& rh) const {
220 return fPixelError < rh.fPixelError;
221 }
222};
223
224class SortByTime : public TestResult {
225public:
226 bool operator<(const SortByTime& rh) const {
227 return fTime < rh.fTime;
228 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000229};
230
caryclarkdac1d172014-06-17 05:15:38 -0700231class SortByName : public TestResult {
232public:
233 bool operator<(const SortByName& rh) const {
234 return strcmp(fFilename, rh.fFilename) < 0;
235 }
236};
237
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000238struct TestState {
caryclark19eb3b22014-07-18 05:08:14 -0700239 void init(int dirNo) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000240 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000241 }
242
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000243 SkTDArray<SortByPixel> fPixelWorst;
244 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000245 TestResult fResult;
246};
247
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000248struct TestRunner {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000249 ~TestRunner();
250 void render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000251 SkTDArray<class TestRunnable*> fRunnables;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000252};
253
254class TestRunnable : public SkRunnable {
255public:
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000256 virtual void run() SK_OVERRIDE {
257 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
258 (*fTestFun)(&fState);
259 }
260
261 TestState fState;
262 void (*fTestFun)(TestState*);
263};
264
caryclarkdac1d172014-06-17 05:15:38 -0700265
266class TestRunnableDir : public TestRunnable {
267public:
268 TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700269 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700270 fTestFun = testFun;
271 }
272
273};
274
275class TestRunnableFile : public TestRunnable {
276public:
277 TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) {
caryclark19eb3b22014-07-18 05:08:14 -0700278 fState.init(dirNo);
caryclarkdac1d172014-06-17 05:15:38 -0700279 strcpy(fState.fResult.fFilename, name);
280 fTestFun = testFun;
281 }
282};
283
284class TestRunnableEncode : public TestRunnableFile {
285public:
286 TestRunnableEncode(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner)
287 : TestRunnableFile(testFun, dirNo, name, runner) {
288 fState.fResult.fTestStep = kEncodeFiles;
289 }
290};
291
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000292TestRunner::~TestRunner() {
293 for (int index = 0; index < fRunnables.count(); index++) {
294 SkDELETE(fRunnables[index]);
295 }
296}
297
298void TestRunner::render() {
mtklein406654b2014-09-03 15:34:37 -0700299 SkTaskGroup tg;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000300 for (int index = 0; index < fRunnables.count(); ++ index) {
mtklein406654b2014-09-03 15:34:37 -0700301 tg.add(fRunnables[index]);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000302 }
303}
304
305////////////////////////////////////////////////
306
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000307
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000308static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
309 const int kRowCount = 3;
310 const int kThreshold = 3;
311 int width = SkTMin(gr.width(), sk.width());
312 if (width < kRowCount) {
313 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000314 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000315 int height = SkTMin(gr.height(), sk.height());
316 if (height < kRowCount) {
317 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000318 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000319 int errorTotal = 0;
320 SkTArray<int, true> errorRows;
321 errorRows.push_back_n(width * kRowCount);
322 SkAutoLockPixels autoGr(gr);
323 SkAutoLockPixels autoSk(sk);
324 for (int y = 0; y < height; ++y) {
325 SkPMColor* grRow = gr.getAddr32(0, y);
326 SkPMColor* skRow = sk.getAddr32(0, y);
327 int* base = &errorRows[0];
328 int* cOut = &errorRows[y % kRowCount];
329 for (int x = 0; x < width; ++x) {
330 SkPMColor grColor = grRow[x];
331 SkPMColor skColor = skRow[x];
332 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
333 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
334 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
335 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
336 if (error < kThreshold || x < 2) {
337 continue;
338 }
339 if (base[x - 2] < kThreshold
340 || base[width + x - 2] < kThreshold
341 || base[width * 2 + x - 2] < kThreshold
342 || base[x - 1] < kThreshold
343 || base[width + x - 1] < kThreshold
344 || base[width * 2 + x - 1] < kThreshold
345 || base[x] < kThreshold
346 || base[width + x] < kThreshold
347 || base[width * 2 + x] < kThreshold) {
348 continue;
349 }
350 errorTotal += error;
351 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000352 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000353 return errorTotal;
354}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000355
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000356static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000357 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
358 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000359 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000360 int worstCount = data->fPixelWorst.count();
361 int pixelError = testResult.fPixelError;
362 if (pixelError > 0) {
363 for (int index = 0; index < worstCount; ++index) {
364 if (pixelError > data->fPixelWorst[index].fPixelError) {
365 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
366 return true;
367 }
368 }
369 }
370 int slowCount = data->fSlowest.count();
371 int time = testResult.fTime;
372 if (time > 0) {
373 for (int index = 0; index < slowCount; ++index) {
374 if (time > data->fSlowest[index].fTime) {
375 data->fSlowest[index] = *(SortByTime*) &testResult;
376 return true;
377 }
378 }
379 }
380 if (pixelError > 0 && worstCount < kMaxFiles) {
381 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
382 return true;
383 }
384 if (time > 0 && slowCount < kMaxFiles) {
385 *data->fSlowest.append() = *(SortByTime*) &testResult;
386 return true;
387 }
388 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000389}
390
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000391static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
392 canvas->save();
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700393 SkScalar pWidth = pic->cullRect().width();
394 SkScalar pHeight = pic->cullRect().height();
395 const SkScalar maxDimension = 1000.0f;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000396 const int slices = 3;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700397 SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
398 SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
399 SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000400 canvas->clipRect(rect);
401 SkMSec start = SkTime::GetMSecs();
402 for (int x = 0; x < slices; ++x) {
403 for (int y = 0; y < slices; ++y) {
robertphillipsc5ba71d2014-09-04 08:42:50 -0700404 pic->playback(canvas);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700405 canvas->translate(0, yInterval);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000406 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700407 canvas->translate(xInterval, -yInterval * slices);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000408 }
409 SkMSec end = SkTime::GetMSecs();
410 canvas->restore();
411 return end - start;
412}
413
414static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
415 canvas->clear(SK_ColorWHITE);
416 if (scale != 1) {
417 canvas->save();
418 canvas->scale(1.0f / scale, 1.0f / scale);
419 }
robertphillipsc5ba71d2014-09-04 08:42:50 -0700420 pic->playback(canvas);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000421 if (scale != 1) {
422 canvas->restore();
423 }
424}
425
426static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
caryclark19eb3b22014-07-18 05:08:14 -0700427 SkString outFile = get_sum_path(outDir);
428 outFile.appendf("%s%s", PATH_SLASH, pngName);
429 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000430 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
431 bitmap.width(), bitmap.height());
432 }
433}
434
435void TestResult::testOne() {
436 SkPicture* pic = NULL;
437 {
438 #if DEBUG_SHOW_TEST_NAME
439 if (fTestStep == kCompareBits) {
440 SkString testName(fFilename);
441 const char http[] = "http";
442 if (testName.startsWith(http)) {
443 testName.remove(0, sizeof(http) - 1);
444 }
445 while (testName.startsWith("_")) {
446 testName.remove(0, 1);
447 }
448 const char dotSkp[] = ".skp";
449 if (testName.endsWith(dotSkp)) {
450 size_t len = testName.size();
451 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
452 }
453 testName.prepend("skp");
454 testName.append("1");
455 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
456 } else if (fTestStep == kEncodeFiles) {
457 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
458 }
459 #endif
caryclark19eb3b22014-07-18 05:08:14 -0700460 SkString path = get_in_path(fDirNo, fFilename);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000461 SkFILEStream stream(path.c_str());
462 if (!stream.isValid()) {
463 SkDebugf("invalid stream %s\n", path.c_str());
464 goto finish;
465 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000466 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000467 if (!pic) {
468 SkDebugf("unable to decode %s\n", fFilename);
469 goto finish;
470 }
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700471 SkScalar width = pic->cullRect().width();
472 SkScalar height = pic->cullRect().height();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000473 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000474 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000475 while (width / fScale > 32767 || height / fScale > 32767) {
476 ++fScale;
477 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000478 do {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700479 int dimX = SkScalarCeilToInt(width / fScale);
480 int dimY = SkScalarCeilToInt(height / fScale);
reed84825042014-09-02 12:50:45 -0700481 if (oldBitmap.tryAllocN32Pixels(dimX, dimY) && opBitmap.tryAllocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000482 break;
483 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000484 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000485 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000486 if (fScale >= 256) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700487 SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000488 width, height);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000489 goto finish;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000490 }
491 oldBitmap.eraseColor(SK_ColorWHITE);
492 SkCanvas oldCanvas(oldBitmap);
493 oldCanvas.setAllowSimplifyClip(false);
494 opBitmap.eraseColor(SK_ColorWHITE);
495 SkCanvas opCanvas(opBitmap);
496 opCanvas.setAllowSimplifyClip(true);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000497 drawPict(pic, &oldCanvas, fScale);
498 drawPict(pic, &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000499 if (fTestStep == kCompareBits) {
500 fPixelError = similarBits(oldBitmap, opBitmap);
501 int oldTime = timePict(pic, &oldCanvas);
502 int opTime = timePict(pic, &opCanvas);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000503 fTime = SkTMax(0, oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000504 } else if (fTestStep == kEncodeFiles) {
505 SkString pngStr = make_png_name(fFilename);
506 const char* pngName = pngStr.c_str();
507 writePict(oldBitmap, outOldDir, pngName);
508 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000509 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000510 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000511finish:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000512 if (pic) {
513 pic->unref();
514 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000515}
516
caryclark19eb3b22014-07-18 05:08:14 -0700517DEFINE_string2(match, m, "PathOpsSkpClipThreaded",
518 "[~][^]substring[$] [...] of test name to run.\n"
519 "Multiple matches may be separated by spaces.\n"
520 "~ causes a matching test to always be skipped\n"
521 "^ requires the start of the test to match\n"
522 "$ requires the end of the test to match\n"
523 "^ and $ requires an exact match\n"
524 "If a test does not match any list entry,\n"
525 "it is skipped unless some list entry starts with ~");
526DEFINE_string2(dir, d, NULL, "range of directories (e.g., 1-100)");
527DEFINE_string2(skp, s, NULL, "skp to test");
528DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
529DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only).");
caryclark19eb3b22014-07-18 05:08:14 -0700530DEFINE_bool2(verbose, v, false, "enable verbose output.");
531
532static bool verbose() {
533 return FLAGS_verbose;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000534}
535
caryclark19eb3b22014-07-18 05:08:14 -0700536class Dirs {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000537public:
caryclark19eb3b22014-07-18 05:08:14 -0700538 Dirs() {
539 reset();
540 sk_bzero(fRun, sizeof(fRun));
541 fSet = false;
542 }
543
544 int first() const {
545 int index = 0;
546 while (++index < kMaxDir) {
547 if (fRun[index]) {
548 return index;
549 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000550 }
caryclark19eb3b22014-07-18 05:08:14 -0700551 SkASSERT(0);
552 return -1;
553 }
554
555 int last() const {
556 int index = kMaxDir;
557 while (--index > 0 && !fRun[index])
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000558 ;
caryclark19eb3b22014-07-18 05:08:14 -0700559 return index;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000560 }
561
caryclark19eb3b22014-07-18 05:08:14 -0700562 int next() {
563 while (++fIndex < kMaxDir) {
564 if (fRun[fIndex]) {
565 return fIndex;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000566 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000567 }
caryclark19eb3b22014-07-18 05:08:14 -0700568 return -1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000569 }
570
caryclark19eb3b22014-07-18 05:08:14 -0700571 void reset() {
572 fIndex = -1;
573 }
574
575 void set(int start, int end) {
576 while (start < end) {
577 fRun[start++] = 1;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000578 }
caryclark19eb3b22014-07-18 05:08:14 -0700579 fSet = true;
580 }
581
582 void setDefault() {
583 if (!fSet) {
584 set(1, 100);
585 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000586 }
587
588private:
caryclark19eb3b22014-07-18 05:08:14 -0700589 enum {
590 kMaxDir = 101
591 };
592 char fRun[kMaxDir];
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000593 int fIndex;
caryclark19eb3b22014-07-18 05:08:14 -0700594 bool fSet;
595} gDirs;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000596
caryclark19eb3b22014-07-18 05:08:14 -0700597class Filenames {
598public:
599 Filenames()
600 : fIndex(-1) {
601 }
602
603 const char* next() {
604 while (fNames && ++fIndex < fNames->count()) {
605 return (*fNames)[fIndex];
606 }
607 return NULL;
608 }
mtklein406654b2014-09-03 15:34:37 -0700609
caryclark19eb3b22014-07-18 05:08:14 -0700610 void set(const SkCommandLineFlags::StringArray& names) {
611 fNames = &names;
612 }
613
614private:
615 int fIndex;
616 const SkCommandLineFlags::StringArray* fNames;
617} gNames;
618
mtklein406654b2014-09-03 15:34:37 -0700619static bool buildTestDir(int dirNo, int firstDirNo,
caryclark19eb3b22014-07-18 05:08:14 -0700620 SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
621 SkString dirName = get_out_path(dirNo, outStatusDir);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000622 if (!dirName.size()) {
623 return false;
624 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000625 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000626 SkString filename;
627 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700628 TestResult test;
629 test.init(dirNo);
630 SkString spaceFile(filename);
631 char* spaces = spaceFile.writable_str();
632 int spaceSize = (int) spaceFile.size();
633 for (int index = 0; index < spaceSize; ++index) {
634 if (spaces[index] == '.') {
635 spaces[index] = ' ';
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000636 }
637 }
caryclark19eb3b22014-07-18 05:08:14 -0700638 int success = sscanf(spaces, "%s %d %d skp", test.fFilename,
639 &test.fPixelError, &test.fTime);
640 if (success < 3) {
641 SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success);
642 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000643 }
caryclark19eb3b22014-07-18 05:08:14 -0700644 *tests[dirNo - firstDirNo].append() = test;
645 }
646 if (!sorted) {
647 return true;
648 }
649 SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo];
650 int count = testSet.count();
651 for (int index = 0; index < count; ++index) {
652 *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index];
653 }
654 if (sorted[dirNo - firstDirNo].count()) {
655 SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(),
656 sorted[dirNo - firstDirNo].end() - 1);
657 if (verbose()) {
658 SkDebugf("+");
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000659 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000660 }
661 return true;
662}
663
caryclark19eb3b22014-07-18 05:08:14 -0700664static void testSkpClip(TestState* data) {
665 data->fResult.testOne();
666 SkString statName(data->fResult.fFilename);
667 SkASSERT(statName.endsWith(".skp"));
668 statName.remove(statName.size() - 4, 4);
669 statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime);
670 SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir);
671 if (!statusFile.size()) {
672 SkDebugf("failed to create %s", statusFile.c_str());
673 return;
674 }
675 statusFile.appendf("%s%s", PATH_SLASH, statName.c_str());
676 SkFILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag);
677 if (!file) {
678 SkDebugf("failed to create %s", statusFile.c_str());
679 return;
680 }
681 sk_fclose(file);
682 if (verbose()) {
683 if (data->fResult.fPixelError || data->fResult.fTime) {
684 SkDebugf("%s", data->fResult.progress().c_str());
685 } else {
686 SkDebugf(".");
687 }
688 }
689}
690
691bool Less(const SortByName& a, const SortByName& b);
692bool Less(const SortByName& a, const SortByName& b) {
693 return a < b;
694}
695
696static bool doOneDir(TestState* state, bool threaded) {
697 int dirNo = state->fResult.fDirNo;
698 SkString dirName = get_in_path(dirNo, NULL);
699 if (!dirName.size()) {
700 return false;
701 }
702 SkTDArray<TestResult> tests[1];
703 SkTDArray<SortByName*> sorted[1];
704 if (!buildTestDir(dirNo, dirNo, tests, sorted)) {
705 return false;
706 }
707 SkOSFile::Iter iter(dirName.c_str(), "skp");
708 SkString filename;
709 while (iter.next(&filename)) {
710 for (size_t index = 0; index < skipOverCount; ++index) {
711 if (skipOver[index].directory == dirNo
712 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
713 goto checkEarlyExit;
714 }
715 }
716 {
717 SortByName name;
718 name.init(dirNo);
719 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
720 int count = sorted[0].count();
721 int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name));
722 if (idx >= 0) {
723 SortByName* found = sorted[0][idx];
724 (void) addError(state, *found);
725 continue;
726 }
727 TestResult test;
728 test.init(dirNo, filename);
729 state->fResult = test;
730 testSkpClip(state);
731#if 0 // artificially limit to a few while debugging code
732 static int debugLimit = 0;
733 if (++debugLimit == 5) {
734 return true;
735 }
736#endif
737 }
738checkEarlyExit:
739 ;
740 }
741 return true;
742}
743
744static void initTest() {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000745#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC
746 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
747 SK_CONF_SET("images.png.suppressDecoderWarnings", true);
748#endif
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000749}
750
caryclarkdac1d172014-06-17 05:15:38 -0700751static void testSkpClipEncode(TestState* data) {
752 data->fResult.testOne();
caryclark19eb3b22014-07-18 05:08:14 -0700753 if (verbose()) {
754 SkDebugf("+");
caryclarkdac1d172014-06-17 05:15:38 -0700755 }
756}
757
caryclark19eb3b22014-07-18 05:08:14 -0700758static void encodeFound(TestState& state) {
759 if (verbose()) {
caryclarkdac1d172014-06-17 05:15:38 -0700760 if (state.fPixelWorst.count()) {
761 SkTDArray<SortByPixel*> worst;
762 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
763 *worst.append() = &state.fPixelWorst[index];
764 }
765 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
766 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
767 const TestResult& result = *worst[index];
768 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
769 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000770 }
caryclarkdac1d172014-06-17 05:15:38 -0700771 if (state.fSlowest.count()) {
772 SkTDArray<SortByTime*> slowest;
773 for (int index = 0; index < state.fSlowest.count(); ++index) {
774 *slowest.append() = &state.fSlowest[index];
775 }
776 if (slowest.count() > 0) {
777 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
778 for (int index = 0; index < slowest.count(); ++index) {
779 const TestResult& result = *slowest[index];
780 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
781 }
782 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000783 }
784 }
mtklein406654b2014-09-03 15:34:37 -0700785 TestRunner testRunner;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000786 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
787 const TestResult& result = state.fPixelWorst[index];
caryclarkdac1d172014-06-17 05:15:38 -0700788 SkString filename(result.fFilename);
789 if (!filename.endsWith(".skp")) {
790 filename.append(".skp");
791 }
792 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableEncode,
793 (&testSkpClipEncode, result.fDirNo, filename.c_str(), &testRunner));
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000794 }
caryclarkdac1d172014-06-17 05:15:38 -0700795 testRunner.render();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000796}
797
caryclark19eb3b22014-07-18 05:08:14 -0700798class Test {
799public:
800 Test() {}
801 virtual ~Test() {}
802
803 const char* getName() { onGetName(&fName); return fName.c_str(); }
804 void run() { onRun(); }
805
806protected:
807 virtual void onGetName(SkString*) = 0;
808 virtual void onRun() = 0;
809
810private:
811 SkString fName;
812};
813
814typedef SkTRegistry<Test*(*)(void*)> TestRegistry;
815
816#define DEF_TEST(name) \
817 static void test_##name(); \
818 class name##Class : public Test { \
819 public: \
820 static Test* Factory(void*) { return SkNEW(name##Class); } \
821 protected: \
822 virtual void onGetName(SkString* name) SK_OVERRIDE { \
823 name->set(#name); \
824 } \
825 virtual void onRun() SK_OVERRIDE { test_##name(); } \
826 }; \
827 static TestRegistry gReg_##name##Class(name##Class::Factory); \
828 static void test_##name()
829
830DEF_TEST(PathOpsSkpClip) {
831 gDirs.setDefault();
832 initTest();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000833 SkTArray<TestResult, true> errors;
834 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700835 state.init(0);
836 int dirNo;
837 gDirs.reset();
838 while ((dirNo = gDirs.next()) > 0) {
839 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000840 SkDebugf("dirNo=%d\n", dirNo);
841 }
842 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000843 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000844 break;
845 }
846 }
caryclark19eb3b22014-07-18 05:08:14 -0700847 encodeFound(state);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000848}
849
850static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000851 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000852}
853
caryclark19eb3b22014-07-18 05:08:14 -0700854DEF_TEST(PathOpsSkpClipThreaded) {
855 gDirs.setDefault();
856 initTest();
mtklein406654b2014-09-03 15:34:37 -0700857 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700858 int dirNo;
859 gDirs.reset();
860 while ((dirNo = gDirs.next()) > 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700861 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableDir,
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000862 (&testSkpClipMain, dirNo, &testRunner));
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000863 }
864 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000865 TestState state;
caryclark19eb3b22014-07-18 05:08:14 -0700866 state.init(0);
867 gDirs.reset();
868 while ((dirNo = gDirs.next()) > 0) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000869 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
caryclarkdac1d172014-06-17 05:15:38 -0700870 SkASSERT(testState.fResult.fDirNo == dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000871 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000872 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000873 }
caryclarkdac1d172014-06-17 05:15:38 -0700874 for (int inner = 0; inner < testState.fSlowest.count(); ++inner) {
875 addError(&state, testState.fSlowest[inner]);
876 }
877 }
caryclark19eb3b22014-07-18 05:08:14 -0700878 encodeFound(state);
caryclarkdac1d172014-06-17 05:15:38 -0700879}
mtklein406654b2014-09-03 15:34:37 -0700880
caryclark19eb3b22014-07-18 05:08:14 -0700881static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) {
882 int firstDirNo = gDirs.first();
883 int dirNo;
884 while ((dirNo = gDirs.next()) > 0) {
885 if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) {
caryclarkdac1d172014-06-17 05:15:38 -0700886 return false;
887 }
caryclarkdac1d172014-06-17 05:15:38 -0700888 }
889 return true;
890}
891
caryclark19eb3b22014-07-18 05:08:14 -0700892DEF_TEST(PathOpsSkpClipUberThreaded) {
893 gDirs.setDefault();
894 const int firstDirNo = gDirs.next();
895 const int lastDirNo = gDirs.last();
896 initTest();
897 int dirCount = lastDirNo - firstDirNo + 1;
898 SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]);
899 SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]);
900 if (!buildTests(tests.get(), sorted.get())) {
caryclarkdac1d172014-06-17 05:15:38 -0700901 return;
902 }
mtklein406654b2014-09-03 15:34:37 -0700903 TestRunner testRunner;
caryclark19eb3b22014-07-18 05:08:14 -0700904 int dirNo;
905 gDirs.reset();
906 while ((dirNo = gDirs.next()) > 0) {
907 SkString dirName = get_in_path(dirNo, NULL);
caryclarkdac1d172014-06-17 05:15:38 -0700908 if (!dirName.size()) {
909 continue;
910 }
911 SkOSFile::Iter iter(dirName.c_str(), "skp");
912 SkString filename;
913 while (iter.next(&filename)) {
caryclark19eb3b22014-07-18 05:08:14 -0700914 for (size_t index = 0; index < skipOverCount; ++index) {
915 if (skipOver[index].directory == dirNo
916 && strcmp(filename.c_str(), skipOver[index].filename) == 0) {
caryclarkdac1d172014-06-17 05:15:38 -0700917 goto checkEarlyExit;
918 }
919 }
caryclark19eb3b22014-07-18 05:08:14 -0700920 {
921 SortByName name;
922 name.init(dirNo);
923 strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp
924 int count = sorted.get()[dirNo - firstDirNo].count();
925 if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(),
926 count, &name, sizeof(&name)) < 0) {
927 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableFile,
928 (&testSkpClip, dirNo, filename.c_str(), &testRunner));
929 }
caryclarkdac1d172014-06-17 05:15:38 -0700930 }
931 checkEarlyExit:
932 ;
933 }
934
935 }
936 testRunner.render();
caryclark19eb3b22014-07-18 05:08:14 -0700937 SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]);
938 if (!buildTests(results.get(), NULL)) {
caryclarkdac1d172014-06-17 05:15:38 -0700939 return;
940 }
941 SkTDArray<TestResult> allResults;
942 for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) {
caryclark19eb3b22014-07-18 05:08:14 -0700943 SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo];
caryclarkdac1d172014-06-17 05:15:38 -0700944 allResults.append(array.count(), array.begin());
945 }
946 int allCount = allResults.count();
947 SkTDArray<SortByPixel*> pixels;
948 SkTDArray<SortByTime*> times;
949 for (int index = 0; index < allCount; ++index) {
950 *pixels.append() = (SortByPixel*) &allResults[index];
951 *times.append() = (SortByTime*) &allResults[index];
952 }
953 TestState state;
954 if (pixels.count()) {
955 SkTQSort<SortByPixel>(pixels.begin(), pixels.end() - 1);
956 for (int inner = 0; inner < kMaxFiles; ++inner) {
957 *state.fPixelWorst.append() = *pixels[allCount - inner - 1];
958 }
959 }
960 if (times.count()) {
961 SkTQSort<SortByTime>(times.begin(), times.end() - 1);
962 for (int inner = 0; inner < kMaxFiles; ++inner) {
963 *state.fSlowest.append() = *times[allCount - inner - 1];
964 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000965 }
caryclark19eb3b22014-07-18 05:08:14 -0700966 encodeFound(state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000967}
968
caryclark19eb3b22014-07-18 05:08:14 -0700969DEF_TEST(PathOpsSkpClipOneOff) {
970 const int testIndex = FLAGS_testIndex;
971 int dirNo = gDirs.next();
972 if (dirNo < 0) {
973 dirNo = skipOver[testIndex].directory;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000974 }
caryclark19eb3b22014-07-18 05:08:14 -0700975 const char* skp = gNames.next();
976 if (!skp) {
977 skp = skipOver[testIndex].filename;
978 }
979 initTest();
980 SkAssertResult(get_in_path(dirNo, skp).size());
981 SkString filename(skp);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000982 TestResult state;
983 state.test(dirNo, filename);
caryclark19eb3b22014-07-18 05:08:14 -0700984 if (verbose()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000985 SkDebugf("%s", state.status().c_str());
986 }
987 state.fTestStep = kEncodeFiles;
988 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000989}
caryclark19eb3b22014-07-18 05:08:14 -0700990
991DEF_TEST(PathOpsTestSkipped) {
992 for (size_t index = 0; index < skipOverCount; ++index) {
993 const SkipOverTest& skip = skipOver[index];
994 if (!skip.blamePathOps) {
995 continue;
996 }
997 int dirNo = skip.directory;
998 const char* skp = skip.filename;
999 initTest();
1000 SkAssertResult(get_in_path(dirNo, skp).size());
1001 SkString filename(skp);
1002 TestResult state;
1003 state.test(dirNo, filename);
1004 if (verbose()) {
1005 SkDebugf("%s", state.status().c_str());
1006 }
1007 state.fTestStep = kEncodeFiles;
1008 state.testOne();
1009 }
1010}
1011
1012DEF_TEST(PathOpsCopyFails) {
1013 FLAGS_verbose = true;
1014 for (size_t index = 0; index < skipOverCount; ++index) {
1015 int dirNo = skipOver[index].directory;
1016 SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo);
1017 }
1018 for (size_t index = 0; index < skipOverCount; ++index) {
1019 int dirNo = skipOver[index].directory;
1020 const char* filename = skipOver[index].filename;
1021 SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave"
1022 "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo);
1023 }
1024}
1025
1026template TestRegistry* TestRegistry::gHead;
1027
1028class Iter {
1029public:
1030 Iter() { this->reset(); }
1031 void reset() { fReg = TestRegistry::Head(); }
1032
1033 Test* next() {
1034 if (fReg) {
1035 TestRegistry::Factory fact = fReg->factory();
1036 fReg = fReg->next();
1037 Test* test = fact(NULL);
1038 return test;
1039 }
1040 return NULL;
1041 }
1042
1043private:
1044 const TestRegistry* fReg;
1045};
1046
1047int tool_main(int argc, char** argv);
1048int tool_main(int argc, char** argv) {
1049 SetupCrashHandler();
1050 SkCommandLineFlags::SetUsage("");
1051 SkCommandLineFlags::Parse(argc, argv);
1052 SkGraphics::Init();
1053 SkString header("PathOps SkpClip:");
1054 if (!FLAGS_match.isEmpty()) {
1055 header.appendf(" --match");
1056 for (int index = 0; index < FLAGS_match.count(); ++index) {
1057 header.appendf(" %s", FLAGS_match[index]);
1058 }
1059 }
1060 if (!FLAGS_dir.isEmpty()) {
1061 int count = FLAGS_dir.count();
1062 for (int i = 0; i < count; ++i) {
1063 const char* range = FLAGS_dir[i];
1064 const char* dash = strchr(range, '-');
1065 if (!dash) {
1066 dash = strchr(range, ',');
1067 }
1068 int first = atoi(range);
1069 int last = dash ? atoi(dash + 1) : first;
1070 if (!first || !last) {
1071 SkDebugf("couldn't parse --dir %s\n", range);
1072 return 1;
1073 }
1074 gDirs.set(first, last);
1075 }
1076 }
1077 if (!FLAGS_skp.isEmpty()) {
1078 gNames.set(FLAGS_skp);
1079 }
1080#ifdef SK_DEBUG
1081 header.append(" SK_DEBUG");
1082#else
1083 header.append(" SK_RELEASE");
1084#endif
1085 header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8);
1086 if (FLAGS_verbose) {
1087 header.appendf("\n");
1088 }
1089 SkDebugf(header.c_str());
1090 Iter iter;
1091 Test* test;
1092 while ((test = iter.next()) != NULL) {
1093 SkAutoTDelete<Test> owned(test);
1094 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
1095 test->run();
1096 }
1097 }
1098 SkGraphics::Term();
1099 return 0;
1100}
1101
1102#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
1103int main(int argc, char * const argv[]) {
1104 return tool_main(argc, (char**) argv);
1105}
1106#endif