// SkCodec's wbmp decoder was initially more restrictive than SkImageDecoder. // It required the second byte to be zero. But SkImageDecoder allowed a couple // of bits to be 1 (so long as they do not overlap with 0x9F). Test that // SkCodec now supports an image with these bits set. DEF_TEST(Codec_wbmp, r) { const char* path = "mandrill.wbmp"; SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { SkDebugf("Missing resource '%s'\n", path); return; } // Modify the stream to contain a second byte with some bits set. SkAutoTUnref<SkData> data(SkCopyStreamToData(stream)); uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); writeableData[1] = static_cast<uint8_t>(~0x9F); // SkImageDecoder supports this. SkBitmap bitmap; REPORTER_ASSERT(r, SkImageDecoder::DecodeMemory(data->data(), data->size(), &bitmap)); // So SkCodec should, too. SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); REPORTER_ASSERT(r, codec); if (!codec) { return; } test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); }
void test_ext_gcd() { const char *list[][3] = { {"2","3","1"}, {"2","4","2"}, {"20","40","20"}, {"-20","31","1"}, {"-20","-30","10"} }; int n = sizeof(list)/sizeof(list[0]); int correct = 0; test_info(stderr,"Start testing ext_gcd."); for(int i = 0; i < n; i++) { mpz_t a,b,c,d,e,f; mpz_init_set_str(a,list[i][0],10); mpz_init_set_str(b,list[i][1],10); mpz_init_set_str(c,list[i][2],10); mpz_init(d); mpz_init(e); mpz_init(f); cpt_ext_gcd(d,e,f,a,b); if(mpz_cmp(c,d)!=0) { test_unmatch(stderr,"test_ext_gcd",c,d); } else { mpz_mul(d,e,a); mpz_addmul(d,f,b); if(mpz_cmp(c,d)!=0) test_unmatch(stderr,"test_ext_gcd",c,d); else correct++; } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); } if(correct == n) test_info(stderr,"test_ext_gcd success."); else test_info(stderr,"test_ext_gcd failed."); }
static void siginfo(int unused __attribute__((__unused__))) { char buf[256]; test_info(buf, sizeof(buf)); atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); }
void test_inv_mod() { const char *list[][2] = { {"2","3"}, {"2","5"}, {"20","41"}, {"-20","31"}, {"-20","-29"} }; int n = sizeof(list)/sizeof(list[0]); int correct = 0; test_info(stderr,"Start testing inv_mod."); for(int i = 0; i < n; i++) { mpz_t a,b,c,d; mpz_init_set_str(a,list[i][0],10); mpz_init_set_str(b,list[i][1],10); mpz_init(c); mpz_init(d); cpt_inv_mod(d,a,b); mpz_mul(c,a,d); mpz_mod(c,c,b); if(mpz_cmp_si(c,1)!=0) { mpz_t tmp; mpz_init_set_si(tmp,1); test_unmatch(stderr,"test_inv_mod",c,tmp); mpz_clear(tmp); } else { correct++; } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); } if(correct == n) test_info(stderr,"test_inv_mod success."); else test_info(stderr,"test_inv_mod failed."); }
static void run_test (void) { guestfs_h *g; size_t i; printf ("Warming up the libguestfs cache ...\n"); for (i = 0; i < NR_WARMUP_PASSES; ++i) { g = create_handle (); add_drive (g); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); } printf ("Running the tests in %d passes ...\n", NR_TEST_PASSES); for (i = 0; i < NR_TEST_PASSES; ++i) { g = create_handle (); set_up_event_handlers (g, i); start_libvirt_thread (i); add_drive (g); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); stop_libvirt_thread (); printf (" pass %zu: %zu events collected in %" PRIi64 " ns\n", i+1, pass_data[i].nr_events, pass_data[i].elapsed_ns); } if (verbose) dump_pass_data (); printf ("Analyzing the results ...\n"); check_pass_data (); construct_timeline (); analyze_timeline (); if (verbose) dump_timeline (); printf ("\n"); g = create_handle (); test_info (g, NR_TEST_PASSES); guestfs_close (g); printf ("\n"); print_analysis (); printf ("\n"); printf ("Longest activities:\n"); printf ("\n"); print_longest_to_shortest (); free_pass_data (); free_final_timeline (); }
void test_gcd_list() { const char *list[][7] = { {"3","2","3","5","1"}, {"4","2","4","2","6","2"}, {"4","20","40","20","15","5"}, {"3","-20","31","1","1"}, {"5","-20","-30","10","8","16","2"} }; int n = sizeof(list)/sizeof(list[0]); int correct = 0; test_info(stderr,"Start testing gcd list."); for(int i = 0; i < n; i++) { mpz_t *l, c, d; int t = atoi(list[i][0]); l = (mpz_t *)malloc(sizeof(mpz_t)*t); for(int j = 0; j < t; j++) mpz_init_set_str(l[j],list[i][j+1],10); mpz_init_set_str(c,list[i][t+1],10); mpz_init(d); cpt_gcd_list(d,l,t); if(mpz_cmp(c,d)!=0) { test_unmatch(stderr,"test_gcd_list",c,d); } else { correct++; } for(int j = 0; j < t; j++) mpz_clear(l[j]); mpz_clear(c); mpz_clear(d); free(l); } if(correct == n) test_info(stderr,"test_gcd_list success."); else test_info(stderr,"test_gcd_list failed."); }
static void siginfo(int unused __unused) { char buf[256]; test_info(buf, sizeof(buf)); atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); if (last_fuzz != NULL) { fuzz_fmt(last_fuzz, buf, sizeof(buf)); atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); } }
// Test that even if webp_parse_header fails to peek enough, it will fall back to read() // + rewind() and succeed. DEF_TEST(Codec_webp_peek, r) { const char* path = "baby_tux.webp"; SkString fullPath(GetResourcePath(path)); SkAutoTUnref<SkData> data(SkData::NewFromFileName(fullPath.c_str())); if (!data) { SkDebugf("Missing resource '%s'\n", path); return; } // The limit is less than webp needs to peek or read. SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(new LimitedPeekingMemStream(data, 25))); REPORTER_ASSERT(r, codec); test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); // Similarly, a stream which does not peek should still succeed. codec.reset(SkCodec::NewFromStream(new LimitedPeekingMemStream(data, 0))); REPORTER_ASSERT(r, codec); test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); }
DEF_TEST(Codec_raw_notseekable, r) { const char* path = "dng_with_preview.dng"; SkString fullPath(GetResourcePath(path)); SkAutoTUnref<SkData> data(SkData::NewFromFileName(fullPath.c_str())); if (!data) { SkDebugf("Missing resource '%s'\n", path); return; } SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(new NotAssetMemStream(data))); REPORTER_ASSERT(r, codec); test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); }
static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* digest, const SkMD5::Digest* goodDigest) { REPORTER_ASSERT(r, info.dimensions() == size); bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); REPORTER_ASSERT(r, result == expectedResult); md5(bm, digest); if (goodDigest) { REPORTER_ASSERT(r, *digest == *goodDigest); } { // Test decoding to 565 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); SkCodec::Result expected565 = info.alphaType() == kOpaque_SkAlphaType ? expectedResult : SkCodec::kInvalidConversion; test_info(r, codec, info565, expected565, nullptr); } // Verify that re-decoding gives the same result. It is interesting to check this after // a decode to 565, since choosing to decode to 565 may result in some of the decode // options being modified. These options should return to their defaults on another // decode to kN32, so the new digest should match the old digest. test_info(r, codec, info, expectedResult, digest); { // Check alpha type conversions if (info.alphaType() == kOpaque_SkAlphaType) { test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), expectedResult, digest); test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), expectedResult, digest); } else { // Decoding to opaque should fail test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), SkCodec::kInvalidConversion, nullptr); SkAlphaType otherAt = info.alphaType(); if (kPremul_SkAlphaType == otherAt) { otherAt = kUnpremul_SkAlphaType; } else { otherAt = kPremul_SkAlphaType; } // The other non-opaque alpha type should always succeed, but not match. test_info(r, codec, info.makeAlphaType(otherAt), expectedResult, nullptr); } } }
int main() { while(1){ int number; printf("type in your test number: "); scanf("%d",&number); switch (number) { case 1: test_create(); break; case 2: test_close(); break; case 3: test_createwait();break; case 4: test_sig();break; case 5: test_info();break; case 6: test_chown();break; case 7: test_chmod();break; case 8: test_stat();break; default: printf("Wrong input test number"); } } }
void Analyze::results_json(Json::Value &root) { Json::Value tests; uint16_t total_evilness= 0; for (std::vector<Analyzer*>::iterator it = _analyzers.begin(); it != _analyzers.end(); ++it) { Analyzer *analyzer = *it; const std::string name = analyzer->name(); if (tests[name].isNull()) { Json::Value test_info(Json::objectValue); test_info["description"] = analyzer->description(); test_info["name"] = name; test_info["results"] = Json::Value(Json::arrayValue); tests[name] = test_info; } analyzer->results_json_results(tests[name]["results"]); tests[name]["status"] = analyzer->status_as_string(); tests[name]["severity-score"] = tests[name]["severity-score"].asLargestUInt() + analyzer->severity_score(); if (!pure_output()) { tests[name]["evilness"] = tests[name]["severity-score"]; tests[name]["evilness-is-deprecated"] = "Use severity-score"; } total_evilness += analyzer->severity_score(); } root["severity-score"] = total_evilness; if (!pure_output()) { root["evilness"] = root["severity-score"]; root["evilness-is-deprecated"] = "Use severity-score"; } root["tests"] = tests; results_json_add_version(root); results_json_add_statistics(root); }
void test_end(void) { gat_free(); int32 total = 0, failed = 0, success = 0; for (int i = 0; i < CASE_NUM; i++) { if (ginfo[i].used) { total++; if (ginfo[i].success) { success++; } else { failed++; } } } test_info(); printf("%s\n", failed > 0 ? "FAIL" : "PASS"); printf(" %d cases executed. S: %d. F: %d.\n", total, success, failed); if (failed > 0) { for (int i = 0; i < CASE_NUM; i++) { if (ginfo[i].used && !ginfo[i].success) { printf(" %s FAILED\n", ginfo[i].case_name); } } } for (int i = 0; i < CASE_NUM; i++) { ginfo[i].used = FALSE; } }
int main(int argc, char* argv[]) { int ch, conn_timeout = 10, rw_timeout = 10; acl::string addr("127.0.0.1:6379"), cmd, node; while ((ch = getopt(argc, argv, "hs:n:C:T:a:i:")) > 0) { switch (ch) { case 'h': usage(argv[0]); return 0; case 's': addr = optarg; break; case 'C': conn_timeout = atoi(optarg); break; case 'T': rw_timeout = atoi(optarg); break; case 'a': cmd = optarg; break; case 'i': node = optarg; break; default: break; } } acl::acl_cpp_init(); acl::redis_client client(addr.c_str(), conn_timeout, rw_timeout); acl::redis_cluster redis(&client); bool ret; if (cmd == "slots") ret = test_slots(redis); else if (cmd == "preset") ret = preset_all(addr.c_str()); else if (cmd == "nodes") ret = test_nodes(redis); else if (cmd == "slaves") { if (node.empty()) { printf("usage: %s -a slaves -i node\r\n", argv[0]); return 1; } ret = test_slaves(redis, node.c_str()); } else if (cmd == "info") ret = test_info(redis); else { ret = false; printf("unknown cmd: %s\r\n", cmd.c_str()); } if (ret == true) printf("test OK!\r\n"); else printf("test failed!\r\n"); #ifdef WIN32 printf("enter any key to exit\r\n"); getchar(); #endif return 0; }
void test_rat_approx() { const char *list[][7] = { {"3","8/3","2","3","8/3"}, {"3","11/4","2","3","11/4"}, {"4","4999/10000","0","1/2","2499/4999","4999/10000"}, {"4","4999/9997","0","1","1/2","4999/9997"}, {"5","523/311","1","2","5/3","37/22","523/311"} }; int n = sizeof(list)/sizeof(list[0]); int correct = 0; test_info(stderr,"Start testing rat_approx."); for(int i = 0; i < n; i++) { mpq_t *l, *res, c; unsigned int t = atoi(list[i][0]), tt; l = (mpq_t *)malloc(sizeof(mpq_t)*t); res = (mpq_t *)malloc(sizeof(mpq_t)*t); for(int j = 0; j < t; j++) { mpq_init(l[j]); mpq_set_str(l[j],list[i][j+2],10); mpq_init(res[j]); } mpq_init(c); mpq_set_str(c,list[i][1],10); tt = t; cpt_rat_approx(res,c,&tt); if(t != tt) { test_error(stderr,"test_rat_approx","number different"); test_unmatch_ui(stderr,"test_rat_approx",t,tt); } else { int nerr = 0; for(int j = 0; j < t; j++) { if(!mpq_equal(l[j],res[j])) { test_error(stderr,"test_rat_approx","result different"); test_unmatch_q(stderr,"test_rat_approx",l[j],res[j]); nerr++; } } if(!nerr) { correct++; } } for(int j = 0; j < t; j++) { mpq_clear(l[j]); mpq_clear(res[j]); } mpq_clear(c); free(l); free(res); } if(correct == n) test_info(stderr,"test_rat_approx success."); else test_info(stderr,"test_rat_approx failed."); }
int test_tick( wpan_dev_t *dev) { test_info( "wpan dev called tick...\n"); return 0; }
static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* digest, const SkMD5::Digest* goodDigest) { REPORTER_ASSERT(r, info.dimensions() == size); bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); REPORTER_ASSERT(r, result == expectedResult); md5(bm, digest); if (goodDigest) { REPORTER_ASSERT(r, *digest == *goodDigest); } { // Test decoding to 565 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); if (info.alphaType() == kOpaque_SkAlphaType) { // Decoding to 565 should succeed. SkBitmap bm565; bm565.allocPixels(info565); SkAutoLockPixels alp(bm565); // This will allow comparison even if the image is incomplete. bm565.eraseColor(SK_ColorBLACK); REPORTER_ASSERT(r, expectedResult == codec->getPixels(info565, bm565.getPixels(), bm565.rowBytes())); SkMD5::Digest digest565; md5(bm565, &digest565); // A dumb client's request for non-opaque should also succeed. for (auto alpha : { kPremul_SkAlphaType, kUnpremul_SkAlphaType }) { info565 = info565.makeAlphaType(alpha); test_info(r, codec, info565, expectedResult, &digest565); } } else { test_info(r, codec, info565, SkCodec::kInvalidConversion, nullptr); } } if (codec->getInfo().colorType() == kGray_8_SkColorType) { SkImageInfo grayInfo = codec->getInfo(); SkBitmap grayBm; grayBm.allocPixels(grayInfo); SkAutoLockPixels alp(grayBm); grayBm.eraseColor(SK_ColorBLACK); REPORTER_ASSERT(r, expectedResult == codec->getPixels(grayInfo, grayBm.getPixels(), grayBm.rowBytes())); SkMD5::Digest grayDigest; md5(grayBm, &grayDigest); for (auto alpha : { kPremul_SkAlphaType, kUnpremul_SkAlphaType }) { grayInfo = grayInfo.makeAlphaType(alpha); test_info(r, codec, grayInfo, expectedResult, &grayDigest); } } // Verify that re-decoding gives the same result. It is interesting to check this after // a decode to 565, since choosing to decode to 565 may result in some of the decode // options being modified. These options should return to their defaults on another // decode to kN32, so the new digest should match the old digest. test_info(r, codec, info, expectedResult, digest); { // Check alpha type conversions if (info.alphaType() == kOpaque_SkAlphaType) { test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), expectedResult, digest); test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), expectedResult, digest); } else { // Decoding to opaque should fail test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), SkCodec::kInvalidConversion, nullptr); SkAlphaType otherAt = info.alphaType(); if (kPremul_SkAlphaType == otherAt) { otherAt = kUnpremul_SkAlphaType; } else { otherAt = kPremul_SkAlphaType; } // The other non-opaque alpha type should always succeed, but not match. test_info(r, codec, info.makeAlphaType(otherAt), expectedResult, nullptr); } } }
static void check(skiatest::Reporter* r, const char path[], SkISize size, bool supportsScanlineDecoding, bool supportsSubsetDecoding, bool supportsIncomplete = true) { SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { SkDebugf("Missing resource '%s'\n", path); return; } SkAutoTDelete<SkCodec> codec(nullptr); bool isIncomplete = supportsIncomplete; if (isIncomplete) { size_t size = stream->getLength(); SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))); codec.reset(SkCodec::NewFromData(data)); } else { codec.reset(SkCodec::NewFromStream(stream.release())); } if (!codec) { ERRORF(r, "Unable to decode '%s'", path); return; } // Test full image decodes with SkCodec SkMD5::Digest codecDigest; const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); SkBitmap bm; SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nullptr); // Scanline decoding follows. // Need to call startScanlineDecode() first. REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); REPORTER_ASSERT(r, codec->skipScanlines(1) == 0); const SkCodec::Result startResult = codec->startScanlineDecode(info); if (supportsScanlineDecoding) { bm.eraseColor(SK_ColorYELLOW); REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); for (int y = 0; y < info.height(); y++) { const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); if (!isIncomplete) { REPORTER_ASSERT(r, 1 == lines); } } // verify that scanline decoding gives the same result. if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { compare_to_good_digest(r, codecDigest, bm); } // Cannot continue to decode scanlines beyond the end REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); // Interrupting a scanline decode with a full decode starts from // scratch REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess); const int lines = codec->getScanlines(bm.getAddr(0, 0), 1, 0); if (!isIncomplete) { REPORTER_ASSERT(r, lines == 1); } REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes()) == expectedResult); REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); REPORTER_ASSERT(r, codec->skipScanlines(1) == 0); // Test partial scanline decodes if (supports_partial_scanlines(path) && info.width() >= 3) { SkCodec::Options options; int width = info.width(); int height = info.height(); SkIRect subset = SkIRect::MakeXYWH(2 * (width / 3), 0, width / 3, height); options.fSubset = ⊂ const SkCodec::Result partialStartResult = codec->startScanlineDecode(info, &options, nullptr, nullptr); REPORTER_ASSERT(r, partialStartResult == SkCodec::kSuccess); for (int y = 0; y < height; y++) { const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); if (!isIncomplete) { REPORTER_ASSERT(r, 1 == lines); } } } } else { REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented); } // The rest of this function tests decoding subsets, and will decode an arbitrary number of // random subsets. // Do not attempt to decode subsets of an image of only once pixel, since there is no // meaningful subset. if (size.width() * size.height() == 1) { return; } SkRandom rand; SkIRect subset; SkCodec::Options opts; opts.fSubset = ⊂ for (int i = 0; i < 5; i++) { subset = generate_random_subset(&rand, size.width(), size.height()); SkASSERT(!subset.isEmpty()); const bool supported = codec->getValidSubset(&subset); REPORTER_ASSERT(r, supported == supportsSubsetDecoding); SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height()); SkBitmap bm; bm.allocPixels(subsetInfo); const SkCodec::Result result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &opts, nullptr, nullptr); if (supportsSubsetDecoding) { REPORTER_ASSERT(r, result == expectedResult); // Webp is the only codec that supports subsets, and it will have modified the subset // to have even left/top. REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop)); } else { // No subsets will work. REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); } } // SkAndroidCodec tests if (supportsScanlineDecoding || supportsSubsetDecoding) { SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { SkDebugf("Missing resource '%s'\n", path); return; } SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); if (isIncomplete) { size_t size = stream->getLength(); SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))); androidCodec.reset(SkAndroidCodec::NewFromData(data)); } else { androidCodec.reset(SkAndroidCodec::NewFromStream(stream.release())); } if (!androidCodec) { ERRORF(r, "Unable to decode '%s'", path); return; } SkBitmap bm; SkMD5::Digest androidCodecDigest; test_codec(r, androidCodec.get(), bm, info, size, expectedResult, &androidCodecDigest, &codecDigest); } if (!isIncomplete) { // Test SkCodecImageGenerator SkAutoTDelete<SkStream> stream(resource(path)); SkAutoTUnref<SkData> fullData(SkData::NewFromStream(stream, stream->getLength())); SkAutoTDelete<SkImageGenerator> gen(SkCodecImageGenerator::NewFromEncodedCodec(fullData)); SkBitmap bm; bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); compare_to_good_digest(r, codecDigest, bm); // Test using SkFrontBufferedStream, as Android does SkStream* bufferedStream = SkFrontBufferedStream::Create(new SkMemoryStream(fullData), SkCodec::MinBufferedBytesNeeded()); REPORTER_ASSERT(r, bufferedStream); codec.reset(SkCodec::NewFromStream(bufferedStream)); REPORTER_ASSERT(r, codec); if (codec) { test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest); } } // If we've just tested incomplete decodes, let's run the same test again on full decodes. if (isIncomplete) { check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, false); } }
static void check(skiatest::Reporter* r, const char path[], SkISize size, bool supportsScanlineDecoding, bool supportsSubsetDecoding, bool supports565 = true) { SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { SkDebugf("Missing resource '%s'\n", path); return; } SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); if (!codec) { ERRORF(r, "Unable to decode '%s'", path); return; } // This test is used primarily to verify rewinding works properly. Using kN32 allows // us to test this without the added overhead of creating different bitmaps depending // on the color type (ex: building a color table for kIndex8). DM is where we test // decodes to all possible destination color types. SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); REPORTER_ASSERT(r, info.dimensions() == size); { // Test decoding to 565 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); SkCodec::Result expected = (supports565 && info.alphaType() == kOpaque_SkAlphaType) ? SkCodec::kSuccess : SkCodec::kInvalidConversion; test_info(r, codec, info565, expected, NULL); } SkBitmap bm; bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes(), NULL, NULL, NULL); REPORTER_ASSERT(r, result == SkCodec::kSuccess); SkMD5::Digest digest; md5(bm, &digest); // verify that re-decoding gives the same result. test_info(r, codec, info, SkCodec::kSuccess, &digest); { // Check alpha type conversions if (info.alphaType() == kOpaque_SkAlphaType) { test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), SkCodec::kInvalidConversion, NULL); test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), SkCodec::kInvalidConversion, NULL); } else { // Decoding to opaque should fail test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), SkCodec::kInvalidConversion, NULL); SkAlphaType otherAt = info.alphaType(); if (kPremul_SkAlphaType == otherAt) { otherAt = kUnpremul_SkAlphaType; } else { otherAt = kPremul_SkAlphaType; } // The other non-opaque alpha type should always succeed, but not match. test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess, NULL); } } // Scanline decoding follows. stream.reset(resource(path)); SkAutoTDelete<SkScanlineDecoder> scanlineDecoder( SkScanlineDecoder::NewFromStream(stream.detach())); if (supportsScanlineDecoding) { bm.eraseColor(SK_ColorYELLOW); REPORTER_ASSERT(r, scanlineDecoder); REPORTER_ASSERT(r, scanlineDecoder->start(info) == SkCodec::kSuccess); for (int y = 0; y < info.height(); y++) { result = scanlineDecoder->getScanlines(bm.getAddr(0, y), 1, 0); REPORTER_ASSERT(r, result == SkCodec::kSuccess); } // verify that scanline decoding gives the same result. compare_to_good_digest(r, digest, bm); } else { REPORTER_ASSERT(r, !scanlineDecoder); } // The rest of this function tests decoding subsets, and will decode an arbitrary number of // random subsets. // Do not attempt to decode subsets of an image of only once pixel, since there is no // meaningful subset. if (size.width() * size.height() == 1) { return; } SkRandom rand; SkIRect subset; SkCodec::Options opts; opts.fSubset = ⊂ for (int i = 0; i < 5; i++) { subset = generate_random_subset(&rand, size.width(), size.height()); SkASSERT(!subset.isEmpty()); const bool supported = codec->getValidSubset(&subset); REPORTER_ASSERT(r, supported == supportsSubsetDecoding); SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height()); SkBitmap bm; bm.allocPixels(subsetInfo); const SkCodec::Result result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &opts, NULL, NULL); if (supportsSubsetDecoding) { REPORTER_ASSERT(r, result == SkCodec::kSuccess); // Webp is the only codec that supports subsets, and it will have modified the subset // to have even left/top. REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop)); } else { // No subsets will work. REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); } } }