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