11b5c604d9d344537941b11b136348edfc39f236chalcanary/* 21b5c604d9d344537941b11b136348edfc39f236chalcanary * Copyright 2015 Google Inc. 31b5c604d9d344537941b11b136348edfc39f236chalcanary * 41b5c604d9d344537941b11b136348edfc39f236chalcanary * Use of this source code is governed by a BSD-style license that can be 51b5c604d9d344537941b11b136348edfc39f236chalcanary * found in the LICENSE file. 61b5c604d9d344537941b11b136348edfc39f236chalcanary */ 71b5c604d9d344537941b11b136348edfc39f236chalcanary 843fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary#include "Test.h" 943fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary 1043fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary#ifdef SK_SUPPORT_PDF 1143fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary 12d9e57158ebd9b1f8317f0d76ef0402cfce0b0253halcanary#include "SkDeflate.h" 131b5c604d9d344537941b11b136348edfc39f236chalcanary#include "SkRandom.h" 141b5c604d9d344537941b11b136348edfc39f236chalcanary 1548305e835351291ef72a7084c6c1af7b185d89c0halcanarynamespace { 1648305e835351291ef72a7084c6c1af7b185d89c0halcanary 17650e20d705a39eaa861cfbc821e9e1f81cef5316halcanary#include "zlib.h" 1848305e835351291ef72a7084c6c1af7b185d89c0halcanary 1948305e835351291ef72a7084c6c1af7b185d89c0halcanary// Different zlib implementations use different T. 2048305e835351291ef72a7084c6c1af7b185d89c0halcanary// We've seen size_t and unsigned. 2148305e835351291ef72a7084c6c1af7b185d89c0halcanarytemplate <typename T> void* skia_alloc_func(void*, T items, T size) { 2248305e835351291ef72a7084c6c1af7b185d89c0halcanary return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size)); 2348305e835351291ef72a7084c6c1af7b185d89c0halcanary} 2448305e835351291ef72a7084c6c1af7b185d89c0halcanary 2548305e835351291ef72a7084c6c1af7b185d89c0halcanaryvoid skia_free_func(void*, void* address) { sk_free(address); } 2648305e835351291ef72a7084c6c1af7b185d89c0halcanary 2748305e835351291ef72a7084c6c1af7b185d89c0halcanary/** 2848305e835351291ef72a7084c6c1af7b185d89c0halcanary * Use the un-deflate compression algorithm to decompress the data in src, 2996fcdcc219d2a0d3579719b84b28bede76efba64halcanary * returning the result. Returns nullptr if an error occurs. 3048305e835351291ef72a7084c6c1af7b185d89c0halcanary */ 310b83319b7f301145b7fc89d7096ddcea91d4a56bHal Canarystd::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) { 3248305e835351291ef72a7084c6c1af7b185d89c0halcanary SkDynamicMemoryWStream decompressedDynamicMemoryWStream; 3348305e835351291ef72a7084c6c1af7b185d89c0halcanary SkWStream* dst = &decompressedDynamicMemoryWStream; 3448305e835351291ef72a7084c6c1af7b185d89c0halcanary 3548305e835351291ef72a7084c6c1af7b185d89c0halcanary static const size_t kBufferSize = 1024; 3648305e835351291ef72a7084c6c1af7b185d89c0halcanary uint8_t inputBuffer[kBufferSize]; 3748305e835351291ef72a7084c6c1af7b185d89c0halcanary uint8_t outputBuffer[kBufferSize]; 3848305e835351291ef72a7084c6c1af7b185d89c0halcanary z_stream flateData; 3948305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.zalloc = &skia_alloc_func; 4048305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.zfree = &skia_free_func; 4196fcdcc219d2a0d3579719b84b28bede76efba64halcanary flateData.opaque = nullptr; 4296fcdcc219d2a0d3579719b84b28bede76efba64halcanary flateData.next_in = nullptr; 4348305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_in = 0; 4448305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.next_out = outputBuffer; 4548305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_out = kBufferSize; 4648305e835351291ef72a7084c6c1af7b185d89c0halcanary int rc; 4748305e835351291ef72a7084c6c1af7b185d89c0halcanary rc = inflateInit(&flateData); 48d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary if (rc != Z_OK) { 49d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary ERRORF(reporter, "Zlib: inflateInit failed"); 5048305e835351291ef72a7084c6c1af7b185d89c0halcanary return nullptr; 51d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary } 5248305e835351291ef72a7084c6c1af7b185d89c0halcanary uint8_t* input = (uint8_t*)src->getMemoryBase(); 5348305e835351291ef72a7084c6c1af7b185d89c0halcanary size_t inputLength = src->getLength(); 5496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (input == nullptr || inputLength == 0) { 5596fcdcc219d2a0d3579719b84b28bede76efba64halcanary input = nullptr; 5648305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.next_in = inputBuffer; 5748305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_in = 0; 5848305e835351291ef72a7084c6c1af7b185d89c0halcanary } else { 5948305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.next_in = input; 6048305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_in = SkToUInt(inputLength); 6148305e835351291ef72a7084c6c1af7b185d89c0halcanary } 6248305e835351291ef72a7084c6c1af7b185d89c0halcanary 6348305e835351291ef72a7084c6c1af7b185d89c0halcanary rc = Z_OK; 6448305e835351291ef72a7084c6c1af7b185d89c0halcanary while (true) { 6548305e835351291ef72a7084c6c1af7b185d89c0halcanary if (flateData.avail_out < kBufferSize) { 6648305e835351291ef72a7084c6c1af7b185d89c0halcanary if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 6748305e835351291ef72a7084c6c1af7b185d89c0halcanary rc = Z_BUF_ERROR; 6848305e835351291ef72a7084c6c1af7b185d89c0halcanary break; 6948305e835351291ef72a7084c6c1af7b185d89c0halcanary } 7048305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.next_out = outputBuffer; 7148305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_out = kBufferSize; 7248305e835351291ef72a7084c6c1af7b185d89c0halcanary } 7348305e835351291ef72a7084c6c1af7b185d89c0halcanary if (rc != Z_OK) 7448305e835351291ef72a7084c6c1af7b185d89c0halcanary break; 7548305e835351291ef72a7084c6c1af7b185d89c0halcanary if (flateData.avail_in == 0) { 7696fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (input != nullptr) 7748305e835351291ef72a7084c6c1af7b185d89c0halcanary break; 7848305e835351291ef72a7084c6c1af7b185d89c0halcanary size_t read = src->read(&inputBuffer, kBufferSize); 7948305e835351291ef72a7084c6c1af7b185d89c0halcanary if (read == 0) 8048305e835351291ef72a7084c6c1af7b185d89c0halcanary break; 8148305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.next_in = inputBuffer; 8248305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_in = SkToUInt(read); 8348305e835351291ef72a7084c6c1af7b185d89c0halcanary } 8448305e835351291ef72a7084c6c1af7b185d89c0halcanary rc = inflate(&flateData, Z_NO_FLUSH); 8548305e835351291ef72a7084c6c1af7b185d89c0halcanary } 8648305e835351291ef72a7084c6c1af7b185d89c0halcanary while (rc == Z_OK) { 8748305e835351291ef72a7084c6c1af7b185d89c0halcanary rc = inflate(&flateData, Z_FINISH); 8848305e835351291ef72a7084c6c1af7b185d89c0halcanary if (flateData.avail_out < kBufferSize) { 89d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 90d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary ERRORF(reporter, "write failed"); 9148305e835351291ef72a7084c6c1af7b185d89c0halcanary return nullptr; 92d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary } 9348305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.next_out = outputBuffer; 9448305e835351291ef72a7084c6c1af7b185d89c0halcanary flateData.avail_out = kBufferSize; 9548305e835351291ef72a7084c6c1af7b185d89c0halcanary } 9648305e835351291ef72a7084c6c1af7b185d89c0halcanary } 9748305e835351291ef72a7084c6c1af7b185d89c0halcanary 9848305e835351291ef72a7084c6c1af7b185d89c0halcanary inflateEnd(&flateData); 9948305e835351291ef72a7084c6c1af7b185d89c0halcanary if (rc != Z_STREAM_END) { 100d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary ERRORF(reporter, "Zlib: inflateEnd failed"); 10148305e835351291ef72a7084c6c1af7b185d89c0halcanary return nullptr; 10248305e835351291ef72a7084c6c1af7b185d89c0halcanary } 10348305e835351291ef72a7084c6c1af7b185d89c0halcanary return decompressedDynamicMemoryWStream.detachAsStream(); 10448305e835351291ef72a7084c6c1af7b185d89c0halcanary} 10548305e835351291ef72a7084c6c1af7b185d89c0halcanary} // namespace 10648305e835351291ef72a7084c6c1af7b185d89c0halcanary 10757f744e3030fec4d1a2b3e9119011904b149a4dahalcanaryDEF_TEST(SkPDF_DeflateWStream, r) { 1081b5c604d9d344537941b11b136348edfc39f236chalcanary SkRandom random(123456); 1091b5c604d9d344537941b11b136348edfc39f236chalcanary for (int i = 0; i < 50; ++i) { 1101b5c604d9d344537941b11b136348edfc39f236chalcanary uint32_t size = random.nextULessThan(10000); 1111b5c604d9d344537941b11b136348edfc39f236chalcanary SkAutoTMalloc<uint8_t> buffer(size); 112e6cf9cb68511ff08156f834859db39232eb37be8mtklein for (uint32_t j = 0; j < size; ++j) { 113e6cf9cb68511ff08156f834859db39232eb37be8mtklein buffer[j] = random.nextU() & 0xff; 1141b5c604d9d344537941b11b136348edfc39f236chalcanary } 1151b5c604d9d344537941b11b136348edfc39f236chalcanary 1161b5c604d9d344537941b11b136348edfc39f236chalcanary SkDynamicMemoryWStream dynamicMemoryWStream; 1171b5c604d9d344537941b11b136348edfc39f236chalcanary { 1181b5c604d9d344537941b11b136348edfc39f236chalcanary SkDeflateWStream deflateWStream(&dynamicMemoryWStream); 1191b5c604d9d344537941b11b136348edfc39f236chalcanary uint32_t j = 0; 1201b5c604d9d344537941b11b136348edfc39f236chalcanary while (j < size) { 1211b5c604d9d344537941b11b136348edfc39f236chalcanary uint32_t writeSize = 1221b5c604d9d344537941b11b136348edfc39f236chalcanary SkTMin(size - j, random.nextRangeU(1, 400)); 1231b5c604d9d344537941b11b136348edfc39f236chalcanary if (!deflateWStream.write(&buffer[j], writeSize)) { 1241b5c604d9d344537941b11b136348edfc39f236chalcanary ERRORF(r, "something went wrong."); 1251b5c604d9d344537941b11b136348edfc39f236chalcanary return; 1261b5c604d9d344537941b11b136348edfc39f236chalcanary } 1271b5c604d9d344537941b11b136348edfc39f236chalcanary j += writeSize; 1281b5c604d9d344537941b11b136348edfc39f236chalcanary } 12957f744e3030fec4d1a2b3e9119011904b149a4dahalcanary REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size); 1301b5c604d9d344537941b11b136348edfc39f236chalcanary } 131145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream()); 132145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get())); 1331b5c604d9d344537941b11b136348edfc39f236chalcanary 134d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary if (!decompressed) { 135d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary ERRORF(r, "Decompression failed."); 136d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary return; 137d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary } 1381b5c604d9d344537941b11b136348edfc39f236chalcanary if (decompressed->getLength() != size) { 1391b5c604d9d344537941b11b136348edfc39f236chalcanary ERRORF(r, "Decompression failed to get right size [%d]." 1401b5c604d9d344537941b11b136348edfc39f236chalcanary " %u != %u", i, (unsigned)(decompressed->getLength()), 1411b5c604d9d344537941b11b136348edfc39f236chalcanary (unsigned)size); 1421b5c604d9d344537941b11b136348edfc39f236chalcanary SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", i); 1431b5c604d9d344537941b11b136348edfc39f236chalcanary SkFILEWStream o(s.c_str()); 1441b5c604d9d344537941b11b136348edfc39f236chalcanary o.writeStream(compressed.get(), compressed->getLength()); 1451b5c604d9d344537941b11b136348edfc39f236chalcanary compressed->rewind(); 1461b5c604d9d344537941b11b136348edfc39f236chalcanary 1471b5c604d9d344537941b11b136348edfc39f236chalcanary s = SkStringPrintf("/tmp/deftst_input_%d", i); 1481b5c604d9d344537941b11b136348edfc39f236chalcanary SkFILEWStream o2(s.c_str()); 1491b5c604d9d344537941b11b136348edfc39f236chalcanary o2.write(&buffer[0], size); 1501b5c604d9d344537941b11b136348edfc39f236chalcanary 1511b5c604d9d344537941b11b136348edfc39f236chalcanary continue; 1521b5c604d9d344537941b11b136348edfc39f236chalcanary } 1531b5c604d9d344537941b11b136348edfc39f236chalcanary uint32_t minLength = SkTMin(size, 1541b5c604d9d344537941b11b136348edfc39f236chalcanary (uint32_t)(decompressed->getLength())); 1551b5c604d9d344537941b11b136348edfc39f236chalcanary for (uint32_t i = 0; i < minLength; ++i) { 1561b5c604d9d344537941b11b136348edfc39f236chalcanary uint8_t c; 1571b5c604d9d344537941b11b136348edfc39f236chalcanary SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t)); 1581b5c604d9d344537941b11b136348edfc39f236chalcanary SkASSERT(sizeof(uint8_t) == rb); 1591b5c604d9d344537941b11b136348edfc39f236chalcanary if (buffer[i] != c) { 1601b5c604d9d344537941b11b136348edfc39f236chalcanary ERRORF(r, "Decompression failed at byte %u.", (unsigned)i); 1611b5c604d9d344537941b11b136348edfc39f236chalcanary break; 1621b5c604d9d344537941b11b136348edfc39f236chalcanary } 1631b5c604d9d344537941b11b136348edfc39f236chalcanary } 1641b5c604d9d344537941b11b136348edfc39f236chalcanary } 16557f744e3030fec4d1a2b3e9119011904b149a4dahalcanary SkDeflateWStream emptyDeflateWStream(nullptr); 16657f744e3030fec4d1a2b3e9119011904b149a4dahalcanary REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO")); 1671b5c604d9d344537941b11b136348edfc39f236chalcanary} 16843fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary 16943fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary#endif 170