Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
26using namespace skia_private;
27
28namespace {
29
30#include "zlib.h"
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
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
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 static SkString SkStringPrintf()
Definition SkString.h:287
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
static const uint8_t buffer[]
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