blob: 3d734c81a13a3fe1e95af6d2e3b44a23652112e9 [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
Hal Canary43fb7a02016-12-30 13:09:03 -05008#include "Test.h"
9
10#ifdef SK_SUPPORT_PDF
11
halcanaryd9e57152015-08-12 11:24:40 -070012#include "SkDeflate.h"
halcanary1b5c6042015-02-18 11:29:56 -080013#include "SkRandom.h"
halcanary1b5c6042015-02-18 11:29:56 -080014
halcanary48305e82015-08-18 13:30:25 -070015namespace {
16
halcanary650e20d2016-08-25 09:07:02 -070017#include "zlib.h"
halcanary48305e82015-08-18 13:30:25 -070018
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,
halcanary96fcdcc2015-08-27 07:41:13 -070029 * returning the result. Returns nullptr if an error occurs.
halcanary48305e82015-08-18 13:30:25 -070030 */
Hal Canary0b833192017-03-14 14:35:02 -040031std::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) {
halcanary48305e82015-08-18 13:30:25 -070032 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;
halcanary96fcdcc2015-08-27 07:41:13 -070041 flateData.opaque = nullptr;
42 flateData.next_in = nullptr;
halcanary48305e82015-08-18 13:30:25 -070043 flateData.avail_in = 0;
44 flateData.next_out = outputBuffer;
45 flateData.avail_out = kBufferSize;
46 int rc;
47 rc = inflateInit(&flateData);
halcanaryd5722a42016-02-26 08:29:25 -080048 if (rc != Z_OK) {
49 ERRORF(reporter, "Zlib: inflateInit failed");
halcanary48305e82015-08-18 13:30:25 -070050 return nullptr;
halcanaryd5722a42016-02-26 08:29:25 -080051 }
halcanary48305e82015-08-18 13:30:25 -070052 uint8_t* input = (uint8_t*)src->getMemoryBase();
53 size_t inputLength = src->getLength();
halcanary96fcdcc2015-08-27 07:41:13 -070054 if (input == nullptr || inputLength == 0) {
55 input = nullptr;
halcanary48305e82015-08-18 13:30:25 -070056 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) {
halcanary96fcdcc2015-08-27 07:41:13 -070076 if (input != nullptr)
halcanary48305e82015-08-18 13:30:25 -070077 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) {
halcanaryd5722a42016-02-26 08:29:25 -080089 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
90 ERRORF(reporter, "write failed");
halcanary48305e82015-08-18 13:30:25 -070091 return nullptr;
halcanaryd5722a42016-02-26 08:29:25 -080092 }
halcanary48305e82015-08-18 13:30:25 -070093 flateData.next_out = outputBuffer;
94 flateData.avail_out = kBufferSize;
95 }
96 }
97
98 inflateEnd(&flateData);
99 if (rc != Z_STREAM_END) {
halcanaryd5722a42016-02-26 08:29:25 -0800100 ERRORF(reporter, "Zlib: inflateEnd failed");
halcanary48305e82015-08-18 13:30:25 -0700101 return nullptr;
102 }
103 return decompressedDynamicMemoryWStream.detachAsStream();
104}
105} // namespace
106
halcanary57f744e2016-09-09 11:41:59 -0700107DEF_TEST(SkPDF_DeflateWStream, r) {
halcanary1b5c6042015-02-18 11:29:56 -0800108 SkRandom random(123456);
109 for (int i = 0; i < 50; ++i) {
110 uint32_t size = random.nextULessThan(10000);
111 SkAutoTMalloc<uint8_t> buffer(size);
mtkleine6cf9cb2015-02-26 13:25:05 -0800112 for (uint32_t j = 0; j < size; ++j) {
113 buffer[j] = random.nextU() & 0xff;
halcanary1b5c6042015-02-18 11:29:56 -0800114 }
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 }
halcanary57f744e2016-09-09 11:41:59 -0700129 REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
halcanary1b5c6042015-02-18 11:29:56 -0800130 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400131 std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream());
132 std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get()));
halcanary1b5c6042015-02-18 11:29:56 -0800133
halcanaryd5722a42016-02-26 08:29:25 -0800134 if (!decompressed) {
135 ERRORF(r, "Decompression failed.");
136 return;
137 }
halcanary1b5c6042015-02-18 11:29:56 -0800138 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 }
halcanary57f744e2016-09-09 11:41:59 -0700165 SkDeflateWStream emptyDeflateWStream(nullptr);
166 REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
halcanary1b5c6042015-02-18 11:29:56 -0800167}
Hal Canary43fb7a02016-12-30 13:09:03 -0500168
169#endif