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