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