Flutter Engine
The Flutter Engine
PDFDeflateWStreamTest.cpp
Go to the documentation of this file.
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
9
10#ifdef SK_SUPPORT_PDF
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
28using namespace skia_private;
29
30namespace {
31
32// Different zlib implementations use different T.
33// We've seen size_t and unsigned.
34template <typename T> void* skia_alloc_func(void*, T items, T size) {
35 return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
36}
37
38void 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 */
44std::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
120DEF_TEST(SkPDF_DeflateWStream, r) {
121 SkRandom random(123456);
122 for (int loop = 0; loop < 50; ++loop) {
123 uint32_t size = random.nextULessThan(10000);
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
reporter
Definition: FontMgrTest.cpp:39
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool read(SkStream *stream, void *buffer, size_t amount)
static void * sk_calloc_throw(size_t size)
Definition: SkMalloc.h:71
SK_API void sk_free(void *)
static const size_t kBufferSize
Definition: SkString.cpp:27
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
constexpr unsigned SkToUInt(S x)
Definition: SkTo.h:30
#define DEF_TEST(name, reporter)
Definition: Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition: SkStream.cpp:876
struct MyStruct s
if(end==-1)
static float min(float r, float g, float b)
Definition: hsl.cpp:48
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
#define T
Definition: precompiler.cc:65