PathOpsSkpClipTest.cpp revision e02c5dabbbfefca3e086b3653d71a7a4a9713277
1 2#include "SkBitmap.h" 3#include "SkCanvas.h" 4#include "SkColor.h" 5#include "SkColorPriv.h" 6#include "SkDevice.h" 7#include "SkGraphics.h" 8#include "SkImageDecoder.h" 9#include "SkImageEncoder.h" 10#include "SkOSFile.h" 11#include "SkPathOpsDebug.h" 12#include "SkPicture.h" 13#include "SkRTConf.h" 14#include "SkTSort.h" 15#include "SkStream.h" 16#include "SkString.h" 17#include "SkTArray.h" 18#include "SkTDArray.h" 19#include "SkThreadPool.h" 20#include "SkTime.h" 21#include "Test.h" 22 23#ifdef SK_BUILD_FOR_WIN 24 #define PATH_SLASH "\\" 25 #define IN_DIR "D:\\skp\\slave" 26 #define OUT_DIR "D:\\skpOut\\1\\" 27#else 28 #define PATH_SLASH "/" 29 #define IN_DIR "/skp/2311328-7fc2228/slave" 30 #define OUT_DIR "/skpOut/2/" 31#endif 32 33const struct { 34 int directory; 35 const char* filename; 36} skipOverSept[] = { 37 { 9, "http___www_catingueiraonline_com_.skp"}, // infinite loop 38 {13, "http___www_galaxystwo_com_.skp"}, // infinite loop 39 {15, "http___www_giffingtool_com_.skp"}, // joinCoincidence / findT / assert 40 {15, "http___www_thaienews_blogspot_com_.skp"}, // infinite loop 41 {17, "http___www_gruposejaumdivulgador_com_br_.skp"}, // calcCoincidentWinding asserts zeroSpan 42 {18, "http___www_argus_presse_fr_.skp"}, // can't find winding of remaining vertical edge 43 {21, "http___www_fashionscandal_com_.skp"}, // infinite loop 44 {21, "http___www_kenlevine_blogspot_com_.skp"}, // infinite loop 45 {25, "http___www_defense_studies_blogspot_com_.skp"}, // infinite loop 46 {27, "http___www_brokeroutpost_com_.skp"}, // suspect infinite loop 47 {28, "http___www_jaimebatistadasilva_blogspot_com_br_.skp"}, // suspect infinite loop 48 {28, "http___www_odia_com_br_.skp"}, // !simple->isClosed() 49 {29, "http___www_hubbyscook_com_.skp"}, // joinCoincidence / findT / assert 50 {30, "http___www_spankystokes_com_.skp"}, // suspect infinite loop 51 {32, "http___www_adalbertoday_blogspot_com_br_.skp"}, // suspect infinite loop 52 {32, "http___www_galery_annisa_com_.skp"}, // suspect infinite loop 53 {33, "http___www_pindosiya_com_.skp"}, // line quad intersection SkIntersections::assert 54 {36, "http___www_educationalcraft_com_.skp"}, // cubic / cubic near end / assert in SkIntersections::insert (missing skp test) 55 {36, "http___www_shaam_org_.skp"}, // suspect infinite loop 56 {36, "http___www_my_pillow_book_blogspot_gr_.skp"}, // suspect infinite loop 57 {39, "http___www_opbeat_com_.skp"}, // suspect infinite loop 58 {40, "http___www_phototransferapp_com_.skp"}, // !simple->isClosed() 59 {41, "http___www_freeismylife_com_.skp"}, // suspect infinite loop 60 {41, "http___www_accordidelmomento_com_.skp"}, // suspect infinite loop 61 {41, "http___www_evolvehq_com_.skp"}, // joinCoincidence / findT / assert 62 {44, "http___www_contextualnewsfeeds_com_.skp"}, // !simple->isClosed() 63 {44, "http___www_cooksnaps_com_.skp"}, // !simple->isClosed() 64 {44, "http___www_helha_be_.skp"}, // !simple->isClosed() 65 {45, "http___www_blondesmakemoney_blogspot_com_.skp"}, // suspect infinite loop 66 {46, "http___www_cheaphealthygood_blogspot_com_.skp"}, // suspect infinite loop 67 {47, "http___www_ajitvadakayil_blogspot_in_.skp"}, // suspect infinite loop 68 {49, "http___www_karnivool_com_au_.skp"}, // SkOpAngle::setSector SkASSERT(fSectorStart >= 0); 69 {49, "http___www_tunero_de_.skp"}, // computeonesumreverse calls markwinding with 0 winding 70 {49, "http___www_thaienews_blogspot_sg_.skp"}, // suspect infinite loop 71 {50, "http___www_docgelo_com_.skp"}, // rightAngleWinding (probably same as argus_presse) 72 {53, "http___www_lojaanabotafogo_com_br_.skp"}, // rrect validate assert 73 {54, "http___www_odecktestanswer2013_blogspot_in_.skp"}, // suspect infinite loop 74 {54, "http___www_cleristonsilva_com_br_.skp"}, // suspect infinite loop 75 {56, "http___www_simplysaru_com_.skp"}, // joinCoincidence / findT / assert 76 {57, "http___www_koukfamily_blogspot_gr_.skp"}, // suspect infinite loop 77 {57, "http___www_dinar2010_blogspot_com_.skp"}, // suspect infinite loop 78 {58, "http___www_artblart_com_.skp"}, // rightAngleWinding 79 {59, "http___www_accrispin_blogspot_com_.skp"}, // suspect infinite loop 80 {59, "http___www_vicisitudysordidez_blogspot_com_es_.skp"}, // suspect infinite loop 81 {60, "http___www_thehousingbubbleblog_com_.skp"}, // suspect infinite loop 82 {61, "http___www_jessicaslens_wordpress_com_.skp"}, // joinCoincidence / findT / assert 83 {61, "http___www_partsdata_de_.skp"}, // cubic-cubic intersection reduce checkLinear assert 84 {62, "http___www_blondesmakemoney_blogspot_com_au_.skp"}, // suspect infinite loop 85 {62, "http___www_intellibriefs_blogspot_in_.skp"}, // suspect infinite loop 86 {63, "http___www_tankerenemy_com_.skp"}, // suspect infinite loop 87 {65, "http___www_kpopexplorer_net_.skp"}, // joinCoincidence / findT / assert 88 {65, "http___www_bestthingsinbeauty_blogspot_com_.skp"}, // suspect infinite loop 89 {65, "http___www_wartepop_blogspot_com_br_.skp"}, // !simple->isClosed() 90 {65, "http___www_eolake_blogspot_com_.skp"}, // suspect infinite loop 91 {67, "http___www_cacadordemisterio_blogspot_com_br_.skp"}, // suspect infinite loop 92 {69, "http___www_misnotasyapuntes_blogspot_mx_.skp"}, // suspect infinite loop 93 {69, "http___www_awalkintheparknyc_blogspot_com_.skp"}, // suspect infinite loop 94 {71, "http___www_lokado_de_.skp"}, // joinCoincidence / findT / assert 95 {72, "http___www_karlosdesanjuan_blogspot_com_.skp"}, // suspect infinite loop 96 {73, "http___www_cyberlawsinindia_blogspot_in_.skp"}, // suspect infinite loop 97 {73, "http___www_taxiemmovimento_blogspot_com_br_.skp"}, // suspect infinite loop 98 {74, "http___www_giveusliberty1776_blogspot_com_.skp"}, // suspect infinite loop 99 {75, "http___www_e_cynical_blogspot_gr_.skp"}, // suspect infinite loop 100 {76, "http___www_seopack_blogspot_com_.skp"}, // SkOpAngle::setSector SkASSERT(fSectorStart >= 0); 101 {77, "http___www_sunsky_russia_com_.skp"}, // joinCoincidence / findT / assert (no op test, already fixed hopefully) 102 {78, "http___www_bisnisonlineinfo_com_.skp"}, // suspect infinite loop 103 {79, "http___www_danielsgroupcpa_com_.skp"}, // joinCoincidence / findT / assert (no op test, already fixed hopefully) 104 {80, "http___www_clinique_portugal_com_.skp"}, // suspect infinite loop 105 {81, "http___www_europebusines_blogspot_com_.skp"}, // suspect infinite loop 106 {82, "http___www_apopsignomi_blogspot_gr_.skp"}, // suspect infinite loop 107 {85, "http___www_ajitvadakayil_blogspot_com_.skp"}, // suspect infinite loop 108 {86, "http___www_madhousefamilyreviews_blogspot_co_uk_.skp"}, // suspect infinite loop 109}; 110 111size_t skipOverSeptCount = sizeof(skipOverSept) / sizeof(skipOverSept[0]); 112 113enum TestStep { 114 kCompareBits, 115 kEncodeFiles, 116}; 117 118enum { 119 kMaxLength = 128, 120 kMaxFiles = 128, 121 kSmallLimit = 1000, 122}; 123 124struct TestResult { 125 void init(int dirNo) { 126 fDirNo = dirNo; 127 sk_bzero(fFilename, sizeof(fFilename)); 128 fTestStep = kCompareBits; 129 fScale = 1; 130 } 131 132 SkString status() { 133 SkString outStr; 134 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime); 135 return outStr; 136 } 137 138 SkString progress() { 139 SkString outStr; 140 outStr.printf("dir=%d %s ", fDirNo, fFilename); 141 if (fPixelError) { 142 outStr.appendf(" err=%d", fPixelError); 143 } 144 if (fTime) { 145 outStr.appendf(" time=%d", fTime); 146 } 147 if (fScale != 1) { 148 outStr.appendf(" scale=%d", fScale); 149 } 150 outStr.appendf("\n"); 151 return outStr; 152 153 } 154 155 static void Test(int dirNo, const char* filename, TestStep testStep) { 156 TestResult test; 157 test.init(dirNo); 158 test.fTestStep = testStep; 159 strcpy(test.fFilename, filename); 160 test.testOne(); 161 } 162 163 void test(int dirNo, const SkString& filename) { 164 init(dirNo); 165 strcpy(fFilename, filename.c_str()); 166 testOne(); 167 } 168 169 void testOne(); 170 171 char fFilename[kMaxLength]; 172 TestStep fTestStep; 173 int fDirNo; 174 int fPixelError; 175 int fTime; 176 int fScale; 177}; 178 179class SortByPixel : public TestResult { 180public: 181 bool operator<(const SortByPixel& rh) const { 182 return fPixelError < rh.fPixelError; 183 } 184}; 185 186class SortByTime : public TestResult { 187public: 188 bool operator<(const SortByTime& rh) const { 189 return fTime < rh.fTime; 190 } 191}; 192 193struct TestState { 194 void init(int dirNo, skiatest::Reporter* reporter) { 195 fReporter = reporter; 196 fResult.init(dirNo); 197 } 198 199 SkTDArray<SortByPixel> fPixelWorst; 200 SkTDArray<SortByTime> fSlowest; 201 skiatest::Reporter* fReporter; 202 TestResult fResult; 203}; 204 205struct TestRunner { 206 TestRunner(skiatest::Reporter* reporter, int threadCount) 207 : fNumThreads(threadCount) 208 , fReporter(reporter) { 209 } 210 211 ~TestRunner(); 212 void render(); 213 int fNumThreads; 214 SkTDArray<class TestRunnable*> fRunnables; 215 skiatest::Reporter* fReporter; 216}; 217 218class TestRunnable : public SkRunnable { 219public: 220 TestRunnable(void (*testFun)(TestState*), int dirNo, TestRunner* runner) { 221 fState.init(dirNo, runner->fReporter); 222 fTestFun = testFun; 223 } 224 225 virtual void run() SK_OVERRIDE { 226 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024); 227 (*fTestFun)(&fState); 228 } 229 230 TestState fState; 231 void (*fTestFun)(TestState*); 232}; 233 234TestRunner::~TestRunner() { 235 for (int index = 0; index < fRunnables.count(); index++) { 236 SkDELETE(fRunnables[index]); 237 } 238} 239 240void TestRunner::render() { 241 SkThreadPool pool(fNumThreads); 242 for (int index = 0; index < fRunnables.count(); ++ index) { 243 pool.add(fRunnables[index]); 244 } 245} 246 247//////////////////////////////////////////////// 248 249static const char outOpDir[] = OUT_DIR "opClip"; 250static const char outOldDir[] = OUT_DIR "oldClip"; 251static const char outSkpDir[] = OUT_DIR "skpTest"; 252static const char outDiffDir[] = OUT_DIR "outTest"; 253static const char outStatusDir[] = OUT_DIR "statusTest"; 254 255static SkString make_filepath(int dirNo, const char* dir, const char* name) { 256 SkString path(dir); 257 if (dirNo) { 258 path.appendf("%d", dirNo); 259 } 260 path.append(PATH_SLASH); 261 path.append(name); 262 return path; 263} 264 265static SkString make_in_dir_name(int dirNo) { 266 SkString dirName(IN_DIR); 267 dirName.appendf("%d", dirNo); 268 if (!sk_exists(dirName.c_str())) { 269 SkDebugf("could not read dir %s\n", dirName.c_str()); 270 return SkString(); 271 } 272 return dirName; 273} 274 275static bool make_one_out_dir(const char* outDirStr) { 276 SkString outDir = make_filepath(0, outDirStr, ""); 277 if (!sk_exists(outDir.c_str())) { 278 if (!sk_mkdir(outDir.c_str())) { 279 SkDebugf("could not create dir %s\n", outDir.c_str()); 280 return false; 281 } 282 } 283 return true; 284} 285 286static bool make_out_dirs() { 287 SkString outDir = make_filepath(0, OUT_DIR, ""); 288 if (!sk_exists(outDir.c_str())) { 289 if (!sk_mkdir(outDir.c_str())) { 290 SkDebugf("could not create dir %s\n", outDir.c_str()); 291 return false; 292 } 293 } 294 return make_one_out_dir(outOldDir) 295 && make_one_out_dir(outOpDir) 296 && make_one_out_dir(outSkpDir) 297 && make_one_out_dir(outDiffDir) 298 && make_one_out_dir(outStatusDir); 299} 300 301static SkString make_png_name(const char* filename) { 302 SkString pngName = SkString(filename); 303 pngName.remove(pngName.size() - 3, 3); 304 pngName.append("png"); 305 return pngName; 306} 307 308static 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; 314 } 315 int height = SkTMin(gr.height(), sk.height()); 316 if (height < kRowCount) { 317 return true; 318 } 319 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 } 352 } 353 return errorTotal; 354} 355 356static bool addError(TestState* data, const TestResult& testResult) { 357 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) { 358 return false; 359 } 360 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; 389} 390 391static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) { 392 canvas->save(); 393 int pWidth = pic->width(); 394 int pHeight = pic->height(); 395 const int maxDimension = 1000; 396 const int slices = 3; 397 int xInterval = SkTMax(pWidth - maxDimension, 0) / (slices - 1); 398 int yInterval = SkTMax(pHeight - maxDimension, 0) / (slices - 1); 399 SkRect rect = {0, 0, SkIntToScalar(SkTMin(maxDimension, pWidth)), 400 SkIntToScalar(SkTMin(maxDimension, pHeight))}; 401 canvas->clipRect(rect); 402 SkMSec start = SkTime::GetMSecs(); 403 for (int x = 0; x < slices; ++x) { 404 for (int y = 0; y < slices; ++y) { 405 pic->draw(canvas); 406 canvas->translate(0, SkIntToScalar(yInterval)); 407 } 408 canvas->translate(SkIntToScalar(xInterval), SkIntToScalar(-yInterval * slices)); 409 } 410 SkMSec end = SkTime::GetMSecs(); 411 canvas->restore(); 412 return end - start; 413} 414 415static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) { 416 canvas->clear(SK_ColorWHITE); 417 if (scale != 1) { 418 canvas->save(); 419 canvas->scale(1.0f / scale, 1.0f / scale); 420 } 421 pic->draw(canvas); 422 if (scale != 1) { 423 canvas->restore(); 424 } 425} 426 427static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) { 428 SkString outFile = make_filepath(0, outDir, pngName); 429 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, 430 SkImageEncoder::kPNG_Type, 100)) { 431 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName, 432 bitmap.width(), bitmap.height()); 433 } 434} 435 436void TestResult::testOne() { 437 SkPicture* pic = NULL; 438 { 439 #if DEBUG_SHOW_TEST_NAME 440 if (fTestStep == kCompareBits) { 441 SkString testName(fFilename); 442 const char http[] = "http"; 443 if (testName.startsWith(http)) { 444 testName.remove(0, sizeof(http) - 1); 445 } 446 while (testName.startsWith("_")) { 447 testName.remove(0, 1); 448 } 449 const char dotSkp[] = ".skp"; 450 if (testName.endsWith(dotSkp)) { 451 size_t len = testName.size(); 452 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1); 453 } 454 testName.prepend("skp"); 455 testName.append("1"); 456 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH); 457 } else if (fTestStep == kEncodeFiles) { 458 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH); 459 } 460 #endif 461 SkString path = make_filepath(fDirNo, IN_DIR, fFilename); 462 SkFILEStream stream(path.c_str()); 463 if (!stream.isValid()) { 464 SkDebugf("invalid stream %s\n", path.c_str()); 465 goto finish; 466 } 467 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory); 468 if (!pic) { 469 SkDebugf("unable to decode %s\n", fFilename); 470 goto finish; 471 } 472 int width = pic->width(); 473 int height = pic->height(); 474 SkBitmap oldBitmap, opBitmap; 475 fScale = 1; 476 while (width / fScale > 32767 || height / fScale > 32767) { 477 ++fScale; 478 } 479 do { 480 int dimX = (width + fScale - 1) / fScale; 481 int dimY = (height + fScale - 1) / fScale; 482 if (oldBitmap.allocN32Pixels(dimX, dimY) && 483 opBitmap.allocN32Pixels(dimX, dimY)) { 484 break; 485 } 486 SkDebugf("-%d-", fScale); 487 } while (++fScale < 256); 488 if (fScale >= 256) { 489 SkDebugf("unable to allocate bitmap for %s (w=%d h=%d)\n", fFilename, 490 width, height); 491 goto finish; 492 } 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); 499 drawPict(pic, &oldCanvas, fScale); 500 drawPict(pic, &opCanvas, fScale); 501 if (fTestStep == kCompareBits) { 502 fPixelError = similarBits(oldBitmap, opBitmap); 503 int oldTime = timePict(pic, &oldCanvas); 504 int opTime = timePict(pic, &opCanvas); 505 fTime = SkTMax(0, oldTime - opTime); 506 } 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); 511 } 512 } 513finish: 514 if (pic) { 515 pic->unref(); 516 } 517} 518 519static SkString makeStatusString(int dirNo) { 520 SkString statName; 521 statName.printf("stats%d.txt", dirNo); 522 SkString statusFile = make_filepath(0, outStatusDir, statName.c_str()); 523 return statusFile; 524} 525 526class PreParser { 527public: 528 PreParser(int dirNo, bool threaded) 529 : fDirNo(dirNo) 530 , fIndex(0) 531 , fThreaded(threaded) { 532 SkString statusPath = makeStatusString(dirNo); 533 if (!sk_exists(statusPath.c_str())) { 534 return; 535 } 536 SkFILEStream reader; 537 reader.setPath(statusPath.c_str()); 538 while (fetch(reader, &fResults.push_back())) 539 ; 540 fResults.pop_back(); 541 } 542 543 bool fetch(SkFILEStream& reader, TestResult* result) { 544 char c; 545 int i = 0; 546 result->init(fDirNo); 547 result->fPixelError = 0; 548 result->fTime = 0; 549 do { 550 bool readOne = reader.read(&c, 1) != 0; 551 if (!readOne) { 552// SkASSERT(i == 0); // the current text may be incomplete -- if so, ignore it 553 return false; 554 } 555 if (c == ' ') { 556 result->fFilename[i++] = '\0'; 557 break; 558 } 559 result->fFilename[i++] = c; 560 SkASSERT(i < kMaxLength); 561 } while (true); 562 do { 563 if (!reader.read(&c, 1)) { 564 return false; 565 } 566 if (c == ' ') { 567 break; 568 } 569 SkASSERT(c >= '0' && c <= '9'); 570 result->fPixelError = result->fPixelError * 10 + (c - '0'); 571 } while (true); 572 bool minus = false; 573 do { 574 if (!reader.read(&c, 1)) { 575 return false; 576 } 577 if (c == '\n') { 578 break; 579 } 580 if (c == '-') { 581 minus = true; 582 continue; 583 } 584 SkASSERT(c >= '0' && c <= '9'); 585 result->fTime = result->fTime * 10 + (c - '0'); 586 } while (true); 587 if (minus) { 588 result->fTime = -result->fTime; 589 } 590 return true; 591 } 592 593 bool match(const SkString& filename, SkFILEWStream* stream, TestResult* result) { 594 if (fThreaded) { 595 for (int index = 0; index < fResults.count(); ++index) { 596 const TestResult& test = fResults[index]; 597 if (filename.equals(test.fFilename)) { 598 *result = test; 599 SkString outStr(result->status()); 600 stream->write(outStr.c_str(), outStr.size()); 601 return true; 602 } 603 } 604 } else if (fIndex < fResults.count()) { 605 *result = fResults[fIndex++]; 606 SkASSERT(filename.equals(result->fFilename)); 607 SkString outStr(result->status()); 608 stream->write(outStr.c_str(), outStr.size()); 609 return true; 610 } 611 return false; 612 } 613 614private: 615 int fDirNo; 616 int fIndex; 617 SkTArray<TestResult, true> fResults; 618 bool fThreaded; 619}; 620 621static bool doOneDir(TestState* state, bool threaded) { 622 int dirNo = state->fResult.fDirNo; 623 skiatest::Reporter* reporter = state->fReporter; 624 SkString dirName = make_in_dir_name(dirNo); 625 if (!dirName.size()) { 626 return false; 627 } 628 SkOSFile::Iter iter(dirName.c_str(), "skp"); 629 SkString filename; 630 int testCount = 0; 631 PreParser preParser(dirNo, threaded); 632 SkFILEWStream statusStream(makeStatusString(dirNo).c_str()); 633 while (iter.next(&filename)) { 634 for (size_t index = 0; index < skipOverSeptCount; ++index) { 635 if (skipOverSept[index].directory == dirNo 636 && strcmp(filename.c_str(), skipOverSept[index].filename) == 0) { 637 goto checkEarlyExit; 638 } 639 } 640 if (preParser.match(filename, &statusStream, &state->fResult)) { 641 (void) addError(state, state->fResult); 642 ++testCount; 643 goto checkEarlyExit; 644 } 645 { 646 TestResult& result = state->fResult; 647 result.test(dirNo, filename); 648 SkString outStr(result.status()); 649 statusStream.write(outStr.c_str(), outStr.size()); 650 statusStream.flush(); 651 if (addError(state, result)) { 652 SkDebugf("%s", result.progress().c_str()); 653 } 654 } 655 ++testCount; 656 if (reporter->verbose()) { 657 SkDebugf("."); 658 if (++testCount % 100 == 0) { 659 SkDebugf("%d\n", testCount); 660 } 661 } 662checkEarlyExit: 663 if (0 && testCount >= 1) { 664 return true; 665 } 666 } 667 return true; 668} 669 670static bool initTest() { 671#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC 672 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); 673 SK_CONF_SET("images.png.suppressDecoderWarnings", true); 674#endif 675 return make_out_dirs(); 676} 677 678static void encodeFound(skiatest::Reporter* reporter, TestState& state) { 679 if (reporter->verbose()) { 680 SkTDArray<SortByPixel*> worst; 681 for (int index = 0; index < state.fPixelWorst.count(); ++index) { 682 *worst.append() = &state.fPixelWorst[index]; 683 } 684 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1); 685 for (int index = 0; index < state.fPixelWorst.count(); ++index) { 686 const TestResult& result = *worst[index]; 687 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError); 688 } 689 SkTDArray<SortByTime*> slowest; 690 for (int index = 0; index < state.fSlowest.count(); ++index) { 691 *slowest.append() = &state.fSlowest[index]; 692 } 693 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1); 694 for (int index = 0; index < slowest.count(); ++index) { 695 const TestResult& result = *slowest[index]; 696 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime); 697 } 698 } 699 for (int index = 0; index < state.fPixelWorst.count(); ++index) { 700 const TestResult& result = state.fPixelWorst[index]; 701 TestResult::Test(result.fDirNo, result.fFilename, kEncodeFiles); 702 if (state.fReporter->verbose()) SkDebugf("+"); 703 } 704} 705 706DEF_TEST(PathOpsSkpClip, reporter) { 707 if (!initTest()) { 708 return; 709 } 710 SkTArray<TestResult, true> errors; 711 TestState state; 712 state.init(0, reporter); 713 for (int dirNo = 1; dirNo <= 100; ++dirNo) { 714 if (reporter->verbose()) { 715 SkDebugf("dirNo=%d\n", dirNo); 716 } 717 state.fResult.fDirNo = dirNo; 718 if (!doOneDir(&state, false)) { 719 break; 720 } 721 } 722 encodeFound(reporter, state); 723} 724 725static void testSkpClipMain(TestState* data) { 726 (void) doOneDir(data, true); 727} 728 729DEF_TEST(PathOpsSkpClipThreaded, reporter) { 730 if (!initTest()) { 731 return; 732 } 733 int threadCount = reporter->allowThreaded() ? SkThreadPool::kThreadPerCore : 1; 734 TestRunner testRunner(reporter, threadCount); 735 for (int dirNo = 1; dirNo <= 100; ++dirNo) { 736 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnable, 737 (&testSkpClipMain, dirNo, &testRunner)); 738 } 739 testRunner.render(); 740 TestState state; 741 state.init(0, reporter); 742 for (int dirNo = 1; dirNo <= 100; ++dirNo) { 743 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState; 744 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) { 745 SkASSERT(testState.fResult.fDirNo == dirNo); 746 addError(&state, testState.fPixelWorst[inner]); 747 } 748 } 749 encodeFound(reporter, state); 750} 751 752DEF_TEST(PathOpsSkpClipOneOff, reporter) { 753 if (!initTest()) { 754 return; 755 } 756 const int testIndex = 43 - 37; 757 int dirNo = skipOverSept[testIndex].directory; 758 SkAssertResult(make_in_dir_name(dirNo).size()); 759 SkString filename(skipOverSept[testIndex].filename); 760 TestResult state; 761 state.test(dirNo, filename); 762 if (reporter->verbose()) { 763 SkDebugf("%s", state.status().c_str()); 764 } 765 state.fTestStep = kEncodeFiles; 766 state.testOne(); 767} 768