1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/Test.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#ifdef SK_SUPPORT_PDF 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 13cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 14cb93a386Sopenharmony_ci#include "src/pdf/SkDeflate.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cinamespace { 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#include "zlib.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci// Different zlib implementations use different T. 21cb93a386Sopenharmony_ci// We've seen size_t and unsigned. 22cb93a386Sopenharmony_citemplate <typename T> void* skia_alloc_func(void*, T items, T size) { 23cb93a386Sopenharmony_ci return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size)); 24cb93a386Sopenharmony_ci} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_civoid skia_free_func(void*, void* address) { sk_free(address); } 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci/** 29cb93a386Sopenharmony_ci * Use the un-deflate compression algorithm to decompress the data in src, 30cb93a386Sopenharmony_ci * returning the result. Returns nullptr if an error occurs. 31cb93a386Sopenharmony_ci */ 32cb93a386Sopenharmony_cistd::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) { 33cb93a386Sopenharmony_ci SkDynamicMemoryWStream decompressedDynamicMemoryWStream; 34cb93a386Sopenharmony_ci SkWStream* dst = &decompressedDynamicMemoryWStream; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci static const size_t kBufferSize = 1024; 37cb93a386Sopenharmony_ci uint8_t inputBuffer[kBufferSize]; 38cb93a386Sopenharmony_ci uint8_t outputBuffer[kBufferSize]; 39cb93a386Sopenharmony_ci z_stream flateData; 40cb93a386Sopenharmony_ci flateData.zalloc = &skia_alloc_func; 41cb93a386Sopenharmony_ci flateData.zfree = &skia_free_func; 42cb93a386Sopenharmony_ci flateData.opaque = nullptr; 43cb93a386Sopenharmony_ci flateData.next_in = nullptr; 44cb93a386Sopenharmony_ci flateData.avail_in = 0; 45cb93a386Sopenharmony_ci flateData.next_out = outputBuffer; 46cb93a386Sopenharmony_ci flateData.avail_out = kBufferSize; 47cb93a386Sopenharmony_ci int rc; 48cb93a386Sopenharmony_ci rc = inflateInit(&flateData); 49cb93a386Sopenharmony_ci if (rc != Z_OK) { 50cb93a386Sopenharmony_ci ERRORF(reporter, "Zlib: inflateInit failed"); 51cb93a386Sopenharmony_ci return nullptr; 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci uint8_t* input = (uint8_t*)src->getMemoryBase(); 54cb93a386Sopenharmony_ci size_t inputLength = src->getLength(); 55cb93a386Sopenharmony_ci if (input == nullptr || inputLength == 0) { 56cb93a386Sopenharmony_ci input = nullptr; 57cb93a386Sopenharmony_ci flateData.next_in = inputBuffer; 58cb93a386Sopenharmony_ci flateData.avail_in = 0; 59cb93a386Sopenharmony_ci } else { 60cb93a386Sopenharmony_ci flateData.next_in = input; 61cb93a386Sopenharmony_ci flateData.avail_in = SkToUInt(inputLength); 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci rc = Z_OK; 65cb93a386Sopenharmony_ci while (true) { 66cb93a386Sopenharmony_ci if (flateData.avail_out < kBufferSize) { 67cb93a386Sopenharmony_ci if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 68cb93a386Sopenharmony_ci rc = Z_BUF_ERROR; 69cb93a386Sopenharmony_ci break; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci flateData.next_out = outputBuffer; 72cb93a386Sopenharmony_ci flateData.avail_out = kBufferSize; 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci if (rc != Z_OK) 75cb93a386Sopenharmony_ci break; 76cb93a386Sopenharmony_ci if (flateData.avail_in == 0) { 77cb93a386Sopenharmony_ci if (input != nullptr) 78cb93a386Sopenharmony_ci break; 79cb93a386Sopenharmony_ci size_t read = src->read(&inputBuffer, kBufferSize); 80cb93a386Sopenharmony_ci if (read == 0) 81cb93a386Sopenharmony_ci break; 82cb93a386Sopenharmony_ci flateData.next_in = inputBuffer; 83cb93a386Sopenharmony_ci flateData.avail_in = SkToUInt(read); 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci rc = inflate(&flateData, Z_NO_FLUSH); 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci while (rc == Z_OK) { 88cb93a386Sopenharmony_ci rc = inflate(&flateData, Z_FINISH); 89cb93a386Sopenharmony_ci if (flateData.avail_out < kBufferSize) { 90cb93a386Sopenharmony_ci if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 91cb93a386Sopenharmony_ci ERRORF(reporter, "write failed"); 92cb93a386Sopenharmony_ci return nullptr; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci flateData.next_out = outputBuffer; 95cb93a386Sopenharmony_ci flateData.avail_out = kBufferSize; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci inflateEnd(&flateData); 100cb93a386Sopenharmony_ci if (rc != Z_STREAM_END) { 101cb93a386Sopenharmony_ci ERRORF(reporter, "Zlib: inflateEnd failed"); 102cb93a386Sopenharmony_ci return nullptr; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci return decompressedDynamicMemoryWStream.detachAsStream(); 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci} // namespace 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ciDEF_TEST(SkPDF_DeflateWStream, r) { 109cb93a386Sopenharmony_ci SkRandom random(123456); 110cb93a386Sopenharmony_ci for (int loop = 0; loop < 50; ++loop) { 111cb93a386Sopenharmony_ci uint32_t size = random.nextULessThan(10000); 112cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> buffer(size); 113cb93a386Sopenharmony_ci for (uint32_t j = 0; j < size; ++j) { 114cb93a386Sopenharmony_ci buffer[j] = random.nextU() & 0xff; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci SkDynamicMemoryWStream dynamicMemoryWStream; 118cb93a386Sopenharmony_ci { 119cb93a386Sopenharmony_ci SkDeflateWStream deflateWStream(&dynamicMemoryWStream); 120cb93a386Sopenharmony_ci uint32_t j = 0; 121cb93a386Sopenharmony_ci while (j < size) { 122cb93a386Sopenharmony_ci uint32_t writeSize = 123cb93a386Sopenharmony_ci std::min(size - j, random.nextRangeU(1, 400)); 124cb93a386Sopenharmony_ci if (!deflateWStream.write(&buffer[j], writeSize)) { 125cb93a386Sopenharmony_ci ERRORF(r, "something went wrong."); 126cb93a386Sopenharmony_ci return; 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci j += writeSize; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size); 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream()); 133cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get())); 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci if (!decompressed) { 136cb93a386Sopenharmony_ci ERRORF(r, "Decompression failed."); 137cb93a386Sopenharmony_ci return; 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci if (decompressed->getLength() != size) { 140cb93a386Sopenharmony_ci ERRORF(r, "Decompression failed to get right size [%d]. %u != %u", 141cb93a386Sopenharmony_ci loop, (unsigned)(decompressed->getLength()), (unsigned)size); 142cb93a386Sopenharmony_ci SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", loop); 143cb93a386Sopenharmony_ci SkFILEWStream o(s.c_str()); 144cb93a386Sopenharmony_ci o.writeStream(compressed.get(), compressed->getLength()); 145cb93a386Sopenharmony_ci compressed->rewind(); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci s = SkStringPrintf("/tmp/deftst_input_%d", loop); 148cb93a386Sopenharmony_ci SkFILEWStream o2(s.c_str()); 149cb93a386Sopenharmony_ci o2.write(&buffer[0], size); 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci continue; 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci uint32_t minLength = std::min(size, (uint32_t)(decompressed->getLength())); 154cb93a386Sopenharmony_ci for (uint32_t i = 0; i < minLength; ++i) { 155cb93a386Sopenharmony_ci uint8_t c; 156cb93a386Sopenharmony_ci SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t)); 157cb93a386Sopenharmony_ci SkASSERT(sizeof(uint8_t) == rb); 158cb93a386Sopenharmony_ci if (buffer[i] != c) { 159cb93a386Sopenharmony_ci ERRORF(r, "Decompression failed at byte %u.", (unsigned)i); 160cb93a386Sopenharmony_ci break; 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci SkDeflateWStream emptyDeflateWStream(nullptr); 165cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO")); 166cb93a386Sopenharmony_ci} 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci#endif 169