Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "gm_expectations.h" | 8 #include "gm_expectations.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 static bool expect_to_fail(const char* filename) { | 177 static bool expect_to_fail(const char* filename) { |
| 178 if (NULL == gJsonExpectations.get()) { | 178 if (NULL == gJsonExpectations.get()) { |
| 179 return false; | 179 return false; |
| 180 } | 180 } |
| 181 skiagm::Expectations jsExpectations = gJsonExpectations->get(filename); | 181 skiagm::Expectations jsExpectations = gJsonExpectations->get(filename); |
| 182 return jsExpectations.ignoreFailure(); | 182 return jsExpectations.ignoreFailure(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 /** | 185 /** |
| 186 * Compare against an expectation for this filename, if there is one. | 186 * Compare against an expectation for this filename, if there is one. |
| 187 * @param bitmap SkBitmap to compare to the expected value. | 187 * @param digest GmResultDigest, computed from the decoded bitmap, to compare t o the |
| 188 * expectation. | |
| 188 * @param filename String used to find the expected value. | 189 * @param filename String used to find the expected value. |
| 189 * @param failureArray Array to add a failure message to on failure. | 190 * @param failureArray Array to add a failure message to on failure. |
| 190 * @param missingArray Array to add missing expectation to on failure. | 191 * @param missingArray Array to add missing expectation to on failure. |
| 191 * @return bool True in any of these cases: | 192 * @return bool True in any of these cases: |
| 192 * - the bitmap matches the expectation. | 193 * - the bitmap matches the expectation. |
| 193 * False in any of these cases: | 194 * False in any of these cases: |
| 194 * - there is no expectations file. | 195 * - there is no expectations file. |
| 195 * - there is an expectations file, but no expectation for this bitmap. | 196 * - there is an expectations file, but no expectation for this bitmap. |
| 196 * - there is an expectation for this bitmap, but it did not ma tch. | 197 * - there is an expectation for this bitmap, but it did not ma tch. |
| 197 * - expectation could not be computed from the bitmap. | 198 * - expectation could not be computed from the bitmap. |
| 198 */ | 199 */ |
| 199 static bool compare_to_expectations_if_necessary(const SkBitmap& bitmap, const c har* filename, | 200 static bool compare_to_expectations_if_necessary(const skiagm::GmResultDigest& d igest, |
| 201 const char* filename, | |
| 200 SkTArray<SkString, false>* fail ureArray, | 202 SkTArray<SkString, false>* fail ureArray, |
| 201 SkTArray<SkString, false>* miss ingArray) { | 203 SkTArray<SkString, false>* miss ingArray) { |
| 202 skiagm::GmResultDigest resultDigest(bitmap); | 204 if (!digest.isValid()) { |
| 203 if (!resultDigest.isValid()) { | |
| 204 if (failureArray != NULL) { | 205 if (failureArray != NULL) { |
| 205 failureArray->push_back().printf("decoded %s, but could not create a GmResultDigest.", | 206 failureArray->push_back().printf("decoded %s, but could not create a GmResultDigest.", |
| 206 filename); | 207 filename); |
| 207 } | 208 } |
| 208 return false; | 209 return false; |
| 209 } | 210 } |
| 210 | 211 |
| 211 if (NULL == gJsonExpectations.get()) { | 212 if (NULL == gJsonExpectations.get()) { |
| 212 return false; | 213 return false; |
| 213 } | 214 } |
| 214 | 215 |
| 215 skiagm::Expectations jsExpectation = gJsonExpectations->get(filename); | 216 skiagm::Expectations jsExpectation = gJsonExpectations->get(filename); |
| 216 if (jsExpectation.empty()) { | 217 if (jsExpectation.empty()) { |
| 217 if (missingArray != NULL) { | 218 if (missingArray != NULL) { |
| 218 missingArray->push_back().printf("decoded %s, but could not find exp ectation.", | 219 missingArray->push_back().printf("decoded %s, but could not find exp ectation.", |
| 219 filename); | 220 filename); |
| 220 } | 221 } |
| 221 return false; | 222 return false; |
| 222 } | 223 } |
| 223 | 224 |
| 224 if (jsExpectation.match(resultDigest)) { | 225 if (jsExpectation.match(digest)) { |
| 225 return true; | 226 return true; |
| 226 } | 227 } |
| 227 | 228 |
| 228 if (failureArray != NULL) { | 229 if (failureArray != NULL) { |
| 229 failureArray->push_back().printf("decoded %s, but the result does not ma tch " | 230 failureArray->push_back().printf("decoded %s, but the result does not ma tch " |
| 230 "expectations.", | 231 "expectations.", |
| 231 filename); | 232 filename); |
| 232 } | 233 } |
| 233 return false; | 234 return false; |
| 234 } | 235 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 "create a directory for extractS ubset comparison.", | 298 "create a directory for extractS ubset comparison.", |
| 298 subsetDim, filename); | 299 subsetDim, filename); |
| 299 return false; | 300 return false; |
| 300 } | 301 } |
| 301 | 302 |
| 302 make_outname(&outPath, dirExtracted.c_str(), filename, suffix.c_str()); | 303 make_outname(&outPath, dirExtracted.c_str(), filename, suffix.c_str()); |
| 303 SkAssertResult(write_bitmap(outPath.c_str(), extractedSubset)); | 304 SkAssertResult(write_bitmap(outPath.c_str(), extractedSubset)); |
| 304 return true; | 305 return true; |
| 305 } | 306 } |
| 306 | 307 |
| 308 // FIXME: This test could be run on windows/mac once we remove their dependence on | |
| 309 // getLength. | |
|
epoger
2013/08/28 14:47:56
Can we leave the code in place, but only CALL it o
scroggo
2013/08/28 17:54:38
Won't our warnings complain that there is a static
| |
| 310 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) | |
| 311 | |
| 312 /** | |
| 313 * Dummy class for testing to ensure that a stream without a length decodes the same | |
| 314 * as a stream with a length. | |
| 315 */ | |
| 316 class FILEStreamWithoutLength : public SkFILEStream { | |
| 317 public: | |
| 318 FILEStreamWithoutLength(const char path[]) | |
| 319 : INHERITED(path) {} | |
| 320 | |
| 321 virtual bool hasLength() const SK_OVERRIDE { | |
| 322 return false; | |
| 323 } | |
| 324 | |
| 325 private: | |
| 326 typedef SkFILEStream INHERITED; | |
| 327 }; | |
| 328 | |
| 329 /** | |
| 330 * Test that decoding a stream which reports to not have a length still results in the | |
| 331 * same image as if it did report to have a length. Assumes that codec was used to | |
| 332 * successfully decode the file using SkFILEStream. | |
| 333 * @param srcPath The path to the file, for recreating the length-less stream. | |
| 334 * @param codec The SkImageDecoder originally used to decode srcPath, which wil l be used | |
| 335 * again to decode the length-less stream. | |
| 336 * @param digest GmResultDigest computed from decoding the stream the first tim e. | |
| 337 * Decoding the length-less stream is expected to result in a matching dige st. | |
| 338 */ | |
| 339 static void test_stream_without_length(const char srcPath[], SkImageDecoder* cod ec, | |
| 340 const skiagm::GmResultDigest& digest) { | |
| 341 if (!digest.isValid()) { | |
| 342 // An error was already reported. | |
| 343 return; | |
| 344 } | |
| 345 SkASSERT(srcPath); | |
| 346 SkASSERT(codec); | |
| 347 FILEStreamWithoutLength stream(srcPath); | |
| 348 // This will only be called after a successful decode. Creating a stream fro m the same | |
| 349 // path should never fail. | |
| 350 SkASSERT(stream.isValid()); | |
| 351 SkBitmap bm; | |
| 352 if (!codec->decode(&stream, &bm, gPrefConfig, SkImageDecoder::kDecodePixels_ Mode)) { | |
| 353 gDecodeFailures.push_back().appendf("Without using getLength, %s failed to decode\n", | |
| 354 srcPath); | |
| 355 return; | |
| 356 } | |
| 357 skiagm::GmResultDigest lengthLessDigest(bm); | |
| 358 if (!lengthLessDigest.isValid()) { | |
| 359 gDecodeFailures.push_back().appendf("Without using getLength, %s failed to build " | |
| 360 "a digest\n", srcPath); | |
| 361 return; | |
| 362 } | |
| 363 if (!lengthLessDigest.equals(digest)) { | |
| 364 gDecodeFailures.push_back().appendf("Without using getLength, %s did not match digest " | |
| 365 "that uses getLength\n", srcPath); | |
| 366 } | |
| 367 } | |
| 368 #endif // defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) | |
| 369 | |
| 307 static void decodeFileAndWrite(const char srcPath[], const SkString* writePath) { | 370 static void decodeFileAndWrite(const char srcPath[], const SkString* writePath) { |
| 308 SkBitmap bitmap; | 371 SkBitmap bitmap; |
| 309 SkFILEStream stream(srcPath); | 372 SkFILEStream stream(srcPath); |
| 310 if (!stream.isValid()) { | 373 if (!stream.isValid()) { |
| 311 gInvalidStreams.push_back().set(srcPath); | 374 gInvalidStreams.push_back().set(srcPath); |
| 312 return; | 375 return; |
| 313 } | 376 } |
| 314 | 377 |
| 315 SkImageDecoder* codec = SkImageDecoder::Factory(&stream); | 378 SkImageDecoder* codec = SkImageDecoder::Factory(&stream); |
| 316 if (NULL == codec) { | 379 if (NULL == codec) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 346 gDecodeFailures.push_back() = failure; | 409 gDecodeFailures.push_back() = failure; |
| 347 } else { | 410 } else { |
| 348 // Now check that the bounds match: | 411 // Now check that the bounds match: |
| 349 if (dim.width() != bitmap.width() || dim.height() != bitmap.height() ) { | 412 if (dim.width() != bitmap.width() || dim.height() != bitmap.height() ) { |
| 350 SkString failure = SkStringPrintf("bounds do not match for %s", srcPath); | 413 SkString failure = SkStringPrintf("bounds do not match for %s", srcPath); |
| 351 gDecodeFailures.push_back() = failure; | 414 gDecodeFailures.push_back() = failure; |
| 352 } | 415 } |
| 353 } | 416 } |
| 354 } | 417 } |
| 355 | 418 |
| 356 if (compare_to_expectations_if_necessary(bitmap, filename, | 419 skiagm::BitmapAndDigest bandd(bitmap); |
|
epoger
2013/08/28 14:47:56
Minor suggestion: maybe "bitmapAndDigest" instead
scroggo
2013/08/28 17:54:38
Done.
| |
| 420 if (compare_to_expectations_if_necessary(bandd.fDigest, filename, | |
| 357 &gDecodeFailures, | 421 &gDecodeFailures, |
| 358 &gMissingExpectations)) { | 422 &gMissingExpectations)) { |
| 359 gSuccessfulDecodes.push_back().printf("%s [%d %d]", srcPath, bitmap.widt h(), | 423 gSuccessfulDecodes.push_back().printf("%s [%d %d]", srcPath, bitmap.widt h(), |
| 360 bitmap.height()); | 424 bitmap.height()); |
| 361 } else if (!FLAGS_mismatchPath.isEmpty()) { | 425 } else if (!FLAGS_mismatchPath.isEmpty()) { |
| 362 SkString outPath; | 426 SkString outPath; |
| 363 make_outname(&outPath, FLAGS_mismatchPath[0], srcPath, ".png"); | 427 make_outname(&outPath, FLAGS_mismatchPath[0], srcPath, ".png"); |
| 364 if (write_bitmap(outPath.c_str(), bitmap)) { | 428 if (write_bitmap(outPath.c_str(), bitmap)) { |
| 365 gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str() ); | 429 gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str() ); |
| 366 } else { | 430 } else { |
| 367 gEncodeFailures.push_back().set(outPath); | 431 gEncodeFailures.push_back().set(outPath); |
| 368 } | 432 } |
| 369 } | 433 } |
| 370 | 434 |
| 435 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) | |
| 436 test_stream_without_length(srcPath, codec, bandd.fDigest); | |
| 437 #endif | |
| 438 | |
| 371 if (writePath != NULL) { | 439 if (writePath != NULL) { |
| 372 SkString outPath; | 440 SkString outPath; |
| 373 make_outname(&outPath, writePath->c_str(), srcPath, ".png"); | 441 make_outname(&outPath, writePath->c_str(), srcPath, ".png"); |
| 374 if (write_bitmap(outPath.c_str(), bitmap)) { | 442 if (write_bitmap(outPath.c_str(), bitmap)) { |
| 375 gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str() ); | 443 gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str() ); |
| 376 } else { | 444 } else { |
| 377 gEncodeFailures.push_back().set(outPath); | 445 gEncodeFailures.push_back().set(outPath); |
| 378 } | 446 } |
| 379 } | 447 } |
| 380 | 448 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 391 // Call decodeSubset multiple times: | 459 // Call decodeSubset multiple times: |
| 392 SkRandom rand(0); | 460 SkRandom rand(0); |
| 393 for (int i = 0; i < 5; i++) { | 461 for (int i = 0; i < 5; i++) { |
| 394 SkBitmap bitmapFromDecodeSubset; | 462 SkBitmap bitmapFromDecodeSubset; |
| 395 // FIXME: Come up with a more representative set of rectangles. | 463 // FIXME: Come up with a more representative set of rectangles. |
| 396 SkIRect rect = generate_random_rect(&rand, width, height); | 464 SkIRect rect = generate_random_rect(&rand, width, height); |
| 397 SkString subsetDim = SkStringPrintf("[%d,%d,%d,%d]", rect.fLeft, rect.fTop, | 465 SkString subsetDim = SkStringPrintf("[%d,%d,%d,%d]", rect.fLeft, rect.fTop, |
| 398 rect.fRight, rect.fBottom); | 466 rect.fRight, rect.fBottom); |
| 399 if (codec->decodeSubset(&bitmapFromDecodeSubset, rect, gPrefConf ig)) { | 467 if (codec->decodeSubset(&bitmapFromDecodeSubset, rect, gPrefConf ig)) { |
| 400 SkString subsetName = SkStringPrintf("%s_%s", filename, subs etDim.c_str()); | 468 SkString subsetName = SkStringPrintf("%s_%s", filename, subs etDim.c_str()); |
| 401 if (compare_to_expectations_if_necessary(bitmapFromDecodeSub set, | 469 skiagm::BitmapAndDigest subsetWithDigest(bitmapFromDecodeSub set); |
| 470 if (compare_to_expectations_if_necessary(subsetWithDigest.fD igest, | |
|
scroggo
2013/08/27 22:13:11
I could have left this as bitmapFromDecodeSubset,
epoger
2013/08/28 14:47:56
I don't know what the guidelines are for using the
scroggo
2013/08/28 17:54:38
Oh right, I do not need a BitmapAndDigest. (In fac
| |
| 402 subsetName.c_str(), | 471 subsetName.c_str(), |
| 403 &gFailedSubsetDecod es, | 472 &gFailedSubsetDecod es, |
| 404 &gMissingSubsetExpe ctations)) { | 473 &gMissingSubsetExpe ctations)) { |
| 405 gSuccessfulSubsetDecodes.push_back().printf("Decoded sub set %s from %s", | 474 gSuccessfulSubsetDecodes.push_back().printf("Decoded sub set %s from %s", |
| 406 subsetDim.c_str(), srcPath); | 475 subsetDim.c_str(), srcPath); |
| 407 } else if (!FLAGS_mismatchPath.isEmpty()) { | 476 } else if (!FLAGS_mismatchPath.isEmpty()) { |
| 408 write_subset(FLAGS_mismatchPath[0], filename, subsetDim. c_str(), | 477 write_subset(FLAGS_mismatchPath[0], filename, subsetDim. c_str(), |
| 409 &bitmapFromDecodeSubset, rect, bitmap); | 478 &bitmapFromDecodeSubset, rect, bitmap); |
| 410 } | 479 } |
| 411 | 480 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 } | 695 } |
| 627 | 696 |
| 628 return failed ? -1 : 0; | 697 return failed ? -1 : 0; |
| 629 } | 698 } |
| 630 | 699 |
| 631 #if !defined SK_BUILD_FOR_IOS | 700 #if !defined SK_BUILD_FOR_IOS |
| 632 int main(int argc, char * const argv[]) { | 701 int main(int argc, char * const argv[]) { |
| 633 return tool_main(argc, (char**) argv); | 702 return tool_main(argc, (char**) argv); |
| 634 } | 703 } |
| 635 #endif | 704 #endif |
| OLD | NEW |