blob: 20ee2496c6978c19e7ab001dc872fd3216f64b72 [file] [log] [blame]
halcanary1b5c6042015-02-18 11:29:56 -08001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tests/Test.h"
Hal Canary43fb7a02016-12-30 13:09:03 -05009
10#ifdef SK_SUPPORT_PDF
11
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/private/SkTo.h"
13#include "include/utils/SkRandom.h"
14#include "src/pdf/SkDeflate.h"
halcanary1b5c6042015-02-18 11:29:56 -080015
halcanary48305e82015-08-18 13:30:25 -070016namespace {
17
halcanary650e20d2016-08-25 09:07:02 -070018#include "zlib.h"
halcanary48305e82015-08-18 13:30:25 -070019
20// Different zlib implementations use different T.
21// We've seen size_t and unsigned.
22template <typename T> void* skia_alloc_func(void*, T items, T size) {
23 return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
24}
25
26void skia_free_func(void*, void* address) { sk_free(address); }
27
28/**
29 * Use the un-deflate compression algorithm to decompress the data in src,
halcanary96fcdcc2015-08-27 07:41:13 -070030 * returning the result. Returns nullptr if an error occurs.
halcanary48305e82015-08-18 13:30:25 -070031 */
Hal Canary0b833192017-03-14 14:35:02 -040032std::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) {
halcanary48305e82015-08-18 13:30:25 -070033 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;
halcanary96fcdcc2015-08-27 07:41:13 -070042 flateData.opaque = nullptr;
43 flateData.next_in = nullptr;
halcanary48305e82015-08-18 13:30:25 -070044 flateData.avail_in = 0;
45 flateData.next_out = outputBuffer;
46 flateData.avail_out = kBufferSize;
47 int rc;
48 rc = inflateInit(&flateData);
halcanaryd5722a42016-02-26 08:29:25 -080049 if (rc != Z_OK) {
50 ERRORF(reporter, "Zlib: inflateInit failed");
halcanary48305e82015-08-18 13:30:25 -070051 return nullptr;
halcanaryd5722a42016-02-26 08:29:25 -080052 }
halcanary48305e82015-08-18 13:30:25 -070053 uint8_t* input = (uint8_t*)src->getMemoryBase();
54 size_t inputLength = src->getLength();
halcanary96fcdcc2015-08-27 07:41:13 -070055 if (input == nullptr || inputLength == 0) {
56 input = nullptr;
halcanary48305e82015-08-18 13:30:25 -070057 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) {
halcanary96fcdcc2015-08-27 07:41:13 -070077 if (input != nullptr)
halcanary48305e82015-08-18 13:30:25 -070078 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) {
halcanaryd5722a42016-02-26 08:29:25 -080090 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
91 ERRORF(reporter, "write failed");
halcanary48305e82015-08-18 13:30:25 -070092 return nullptr;
halcanaryd5722a42016-02-26 08:29:25 -080093 }
halcanary48305e82015-08-18 13:30:25 -070094 flateData.next_out = outputBuffer;
95 flateData.avail_out = kBufferSize;
96 }
97 }
98
99 inflateEnd(&flateData);
100 if (rc != Z_STREAM_END) {
halcanaryd5722a42016-02-26 08:29:25 -0800101 ERRORF(reporter, "Zlib: inflateEnd failed");
halcanary48305e82015-08-18 13:30:25 -0700102 return nullptr;
103 }
104 return decompressedDynamicMemoryWStream.detachAsStream();
105}
106} // namespace
107
halcanary57f744e2016-09-09 11:41:59 -0700108DEF_TEST(SkPDF_DeflateWStream, r) {
halcanary1b5c6042015-02-18 11:29:56 -0800109 SkRandom random(123456);
110 for (int i = 0; i < 50; ++i) {
111 uint32_t size = random.nextULessThan(10000);
112 SkAutoTMalloc<uint8_t> buffer(size);
mtkleine6cf9cb2015-02-26 13:25:05 -0800113 for (uint32_t j = 0; j < size; ++j) {
114 buffer[j] = random.nextU() & 0xff;
halcanary1b5c6042015-02-18 11:29:56 -0800115 }
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 }
halcanary57f744e2016-09-09 11:41:59 -0700130 REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
halcanary1b5c6042015-02-18 11:29:56 -0800131 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400132 std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream());
133 std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get()));
halcanary1b5c6042015-02-18 11:29:56 -0800134
halcanaryd5722a42016-02-26 08:29:25 -0800135 if (!decompressed) {
136 ERRORF(r, "Decompression failed.");
137 return;
138 }
halcanary1b5c6042015-02-18 11:29:56 -0800139 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 }
halcanary57f744e2016-09-09 11:41:59 -0700166 SkDeflateWStream emptyDeflateWStream(nullptr);
167 REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
halcanary1b5c6042015-02-18 11:29:56 -0800168}
Hal Canary43fb7a02016-12-30 13:09:03 -0500169
170#endif