blob: eedcaaf0c5a6f288bdd320e0c67ad33afc0ee5be [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
halcanaryd9e57152015-08-12 11:24:40 -07008#include "SkDeflate.h"
halcanary1b5c6042015-02-18 11:29:56 -08009#include "SkRandom.h"
10#include "Test.h"
11
halcanary48305e82015-08-18 13:30:25 -070012namespace {
13
halcanary650e20d2016-08-25 09:07:02 -070014#include "zlib.h"
halcanary48305e82015-08-18 13:30:25 -070015
16// Different zlib implementations use different T.
17// We've seen size_t and unsigned.
18template <typename T> void* skia_alloc_func(void*, T items, T size) {
19 return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
20}
21
22void skia_free_func(void*, void* address) { sk_free(address); }
23
24/**
25 * Use the un-deflate compression algorithm to decompress the data in src,
halcanary96fcdcc2015-08-27 07:41:13 -070026 * returning the result. Returns nullptr if an error occurs.
halcanary48305e82015-08-18 13:30:25 -070027 */
halcanaryd5722a42016-02-26 08:29:25 -080028SkStreamAsset* stream_inflate(skiatest::Reporter* reporter, SkStream* src) {
halcanary48305e82015-08-18 13:30:25 -070029 SkDynamicMemoryWStream decompressedDynamicMemoryWStream;
30 SkWStream* dst = &decompressedDynamicMemoryWStream;
31
32 static const size_t kBufferSize = 1024;
33 uint8_t inputBuffer[kBufferSize];
34 uint8_t outputBuffer[kBufferSize];
35 z_stream flateData;
36 flateData.zalloc = &skia_alloc_func;
37 flateData.zfree = &skia_free_func;
halcanary96fcdcc2015-08-27 07:41:13 -070038 flateData.opaque = nullptr;
39 flateData.next_in = nullptr;
halcanary48305e82015-08-18 13:30:25 -070040 flateData.avail_in = 0;
41 flateData.next_out = outputBuffer;
42 flateData.avail_out = kBufferSize;
43 int rc;
44 rc = inflateInit(&flateData);
halcanaryd5722a42016-02-26 08:29:25 -080045 if (rc != Z_OK) {
46 ERRORF(reporter, "Zlib: inflateInit failed");
halcanary48305e82015-08-18 13:30:25 -070047 return nullptr;
halcanaryd5722a42016-02-26 08:29:25 -080048 }
halcanary48305e82015-08-18 13:30:25 -070049 uint8_t* input = (uint8_t*)src->getMemoryBase();
50 size_t inputLength = src->getLength();
halcanary96fcdcc2015-08-27 07:41:13 -070051 if (input == nullptr || inputLength == 0) {
52 input = nullptr;
halcanary48305e82015-08-18 13:30:25 -070053 flateData.next_in = inputBuffer;
54 flateData.avail_in = 0;
55 } else {
56 flateData.next_in = input;
57 flateData.avail_in = SkToUInt(inputLength);
58 }
59
60 rc = Z_OK;
61 while (true) {
62 if (flateData.avail_out < kBufferSize) {
63 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
64 rc = Z_BUF_ERROR;
65 break;
66 }
67 flateData.next_out = outputBuffer;
68 flateData.avail_out = kBufferSize;
69 }
70 if (rc != Z_OK)
71 break;
72 if (flateData.avail_in == 0) {
halcanary96fcdcc2015-08-27 07:41:13 -070073 if (input != nullptr)
halcanary48305e82015-08-18 13:30:25 -070074 break;
75 size_t read = src->read(&inputBuffer, kBufferSize);
76 if (read == 0)
77 break;
78 flateData.next_in = inputBuffer;
79 flateData.avail_in = SkToUInt(read);
80 }
81 rc = inflate(&flateData, Z_NO_FLUSH);
82 }
83 while (rc == Z_OK) {
84 rc = inflate(&flateData, Z_FINISH);
85 if (flateData.avail_out < kBufferSize) {
halcanaryd5722a42016-02-26 08:29:25 -080086 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
87 ERRORF(reporter, "write failed");
halcanary48305e82015-08-18 13:30:25 -070088 return nullptr;
halcanaryd5722a42016-02-26 08:29:25 -080089 }
halcanary48305e82015-08-18 13:30:25 -070090 flateData.next_out = outputBuffer;
91 flateData.avail_out = kBufferSize;
92 }
93 }
94
95 inflateEnd(&flateData);
96 if (rc != Z_STREAM_END) {
halcanaryd5722a42016-02-26 08:29:25 -080097 ERRORF(reporter, "Zlib: inflateEnd failed");
halcanary48305e82015-08-18 13:30:25 -070098 return nullptr;
99 }
100 return decompressedDynamicMemoryWStream.detachAsStream();
101}
102} // namespace
103
halcanary57f744e2016-09-09 11:41:59 -0700104DEF_TEST(SkPDF_DeflateWStream, r) {
halcanary1b5c6042015-02-18 11:29:56 -0800105 SkRandom random(123456);
106 for (int i = 0; i < 50; ++i) {
107 uint32_t size = random.nextULessThan(10000);
108 SkAutoTMalloc<uint8_t> buffer(size);
mtkleine6cf9cb2015-02-26 13:25:05 -0800109 for (uint32_t j = 0; j < size; ++j) {
110 buffer[j] = random.nextU() & 0xff;
halcanary1b5c6042015-02-18 11:29:56 -0800111 }
112
113 SkDynamicMemoryWStream dynamicMemoryWStream;
114 {
115 SkDeflateWStream deflateWStream(&dynamicMemoryWStream);
116 uint32_t j = 0;
117 while (j < size) {
118 uint32_t writeSize =
119 SkTMin(size - j, random.nextRangeU(1, 400));
120 if (!deflateWStream.write(&buffer[j], writeSize)) {
121 ERRORF(r, "something went wrong.");
122 return;
123 }
124 j += writeSize;
125 }
halcanary57f744e2016-09-09 11:41:59 -0700126 REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
halcanary1b5c6042015-02-18 11:29:56 -0800127 }
128 SkAutoTDelete<SkStreamAsset> compressed(
129 dynamicMemoryWStream.detachAsStream());
halcanaryd5722a42016-02-26 08:29:25 -0800130 SkAutoTDelete<SkStreamAsset> decompressed(stream_inflate(r, compressed));
halcanary1b5c6042015-02-18 11:29:56 -0800131
halcanaryd5722a42016-02-26 08:29:25 -0800132 if (!decompressed) {
133 ERRORF(r, "Decompression failed.");
134 return;
135 }
halcanary1b5c6042015-02-18 11:29:56 -0800136 if (decompressed->getLength() != size) {
137 ERRORF(r, "Decompression failed to get right size [%d]."
138 " %u != %u", i, (unsigned)(decompressed->getLength()),
139 (unsigned)size);
140 SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", i);
141 SkFILEWStream o(s.c_str());
142 o.writeStream(compressed.get(), compressed->getLength());
143 compressed->rewind();
144
145 s = SkStringPrintf("/tmp/deftst_input_%d", i);
146 SkFILEWStream o2(s.c_str());
147 o2.write(&buffer[0], size);
148
149 continue;
150 }
151 uint32_t minLength = SkTMin(size,
152 (uint32_t)(decompressed->getLength()));
153 for (uint32_t i = 0; i < minLength; ++i) {
154 uint8_t c;
155 SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t));
156 SkASSERT(sizeof(uint8_t) == rb);
157 if (buffer[i] != c) {
158 ERRORF(r, "Decompression failed at byte %u.", (unsigned)i);
159 break;
160 }
161 }
162 }
halcanary57f744e2016-09-09 11:41:59 -0700163 SkDeflateWStream emptyDeflateWStream(nullptr);
164 REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
halcanary1b5c6042015-02-18 11:29:56 -0800165}