• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 namespace {
16 
17 #include "zlib.h"
18 
19 // Different zlib implementations use different T.
20 // We've seen size_t and unsigned.
skia_alloc_func(void *,T items,T size)21 template <typename T> void* skia_alloc_func(void*, T items, T size) {
22     return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
23 }
24 
skia_free_func(void *,void * address)25 void 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  */
stream_inflate(skiatest::Reporter * reporter,SkStream * src)31 std::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 
DEF_TEST(SkPDF_DeflateWStream,r)107 DEF_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