2015-02-18 19:29:56 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2015 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "tests/Test.h"
|
2016-12-30 18:09:03 +00:00
|
|
|
|
|
|
|
#ifdef SK_SUPPORT_PDF
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/private/SkTo.h"
|
|
|
|
#include "include/utils/SkRandom.h"
|
|
|
|
#include "src/pdf/SkDeflate.h"
|
2015-02-18 19:29:56 +00:00
|
|
|
|
2015-08-18 20:30:25 +00:00
|
|
|
namespace {
|
|
|
|
|
2016-08-25 16:07:02 +00:00
|
|
|
#include "zlib.h"
|
2015-08-18 20:30:25 +00:00
|
|
|
|
|
|
|
// Different zlib implementations use different T.
|
|
|
|
// We've seen size_t and unsigned.
|
|
|
|
template <typename T> void* skia_alloc_func(void*, T items, T size) {
|
|
|
|
return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
|
|
|
|
}
|
|
|
|
|
|
|
|
void skia_free_func(void*, void* address) { sk_free(address); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Use the un-deflate compression algorithm to decompress the data in src,
|
2015-08-27 14:41:13 +00:00
|
|
|
* returning the result. Returns nullptr if an error occurs.
|
2015-08-18 20:30:25 +00:00
|
|
|
*/
|
2017-03-14 18:35:02 +00:00
|
|
|
std::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) {
|
2015-08-18 20:30:25 +00:00
|
|
|
SkDynamicMemoryWStream decompressedDynamicMemoryWStream;
|
|
|
|
SkWStream* dst = &decompressedDynamicMemoryWStream;
|
|
|
|
|
|
|
|
static const size_t kBufferSize = 1024;
|
|
|
|
uint8_t inputBuffer[kBufferSize];
|
|
|
|
uint8_t outputBuffer[kBufferSize];
|
|
|
|
z_stream flateData;
|
|
|
|
flateData.zalloc = &skia_alloc_func;
|
|
|
|
flateData.zfree = &skia_free_func;
|
2015-08-27 14:41:13 +00:00
|
|
|
flateData.opaque = nullptr;
|
|
|
|
flateData.next_in = nullptr;
|
2015-08-18 20:30:25 +00:00
|
|
|
flateData.avail_in = 0;
|
|
|
|
flateData.next_out = outputBuffer;
|
|
|
|
flateData.avail_out = kBufferSize;
|
|
|
|
int rc;
|
|
|
|
rc = inflateInit(&flateData);
|
2016-02-26 16:29:25 +00:00
|
|
|
if (rc != Z_OK) {
|
|
|
|
ERRORF(reporter, "Zlib: inflateInit failed");
|
2015-08-18 20:30:25 +00:00
|
|
|
return nullptr;
|
2016-02-26 16:29:25 +00:00
|
|
|
}
|
2015-08-18 20:30:25 +00:00
|
|
|
uint8_t* input = (uint8_t*)src->getMemoryBase();
|
|
|
|
size_t inputLength = src->getLength();
|
2015-08-27 14:41:13 +00:00
|
|
|
if (input == nullptr || inputLength == 0) {
|
|
|
|
input = nullptr;
|
2015-08-18 20:30:25 +00:00
|
|
|
flateData.next_in = inputBuffer;
|
|
|
|
flateData.avail_in = 0;
|
|
|
|
} else {
|
|
|
|
flateData.next_in = input;
|
|
|
|
flateData.avail_in = SkToUInt(inputLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = Z_OK;
|
|
|
|
while (true) {
|
|
|
|
if (flateData.avail_out < kBufferSize) {
|
|
|
|
if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
|
|
|
|
rc = Z_BUF_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
flateData.next_out = outputBuffer;
|
|
|
|
flateData.avail_out = kBufferSize;
|
|
|
|
}
|
|
|
|
if (rc != Z_OK)
|
|
|
|
break;
|
|
|
|
if (flateData.avail_in == 0) {
|
2015-08-27 14:41:13 +00:00
|
|
|
if (input != nullptr)
|
2015-08-18 20:30:25 +00:00
|
|
|
break;
|
|
|
|
size_t read = src->read(&inputBuffer, kBufferSize);
|
|
|
|
if (read == 0)
|
|
|
|
break;
|
|
|
|
flateData.next_in = inputBuffer;
|
|
|
|
flateData.avail_in = SkToUInt(read);
|
|
|
|
}
|
|
|
|
rc = inflate(&flateData, Z_NO_FLUSH);
|
|
|
|
}
|
|
|
|
while (rc == Z_OK) {
|
|
|
|
rc = inflate(&flateData, Z_FINISH);
|
|
|
|
if (flateData.avail_out < kBufferSize) {
|
2016-02-26 16:29:25 +00:00
|
|
|
if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
|
|
|
|
ERRORF(reporter, "write failed");
|
2015-08-18 20:30:25 +00:00
|
|
|
return nullptr;
|
2016-02-26 16:29:25 +00:00
|
|
|
}
|
2015-08-18 20:30:25 +00:00
|
|
|
flateData.next_out = outputBuffer;
|
|
|
|
flateData.avail_out = kBufferSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inflateEnd(&flateData);
|
|
|
|
if (rc != Z_STREAM_END) {
|
2016-02-26 16:29:25 +00:00
|
|
|
ERRORF(reporter, "Zlib: inflateEnd failed");
|
2015-08-18 20:30:25 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return decompressedDynamicMemoryWStream.detachAsStream();
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
2016-09-09 18:41:59 +00:00
|
|
|
DEF_TEST(SkPDF_DeflateWStream, r) {
|
2015-02-18 19:29:56 +00:00
|
|
|
SkRandom random(123456);
|
2021-08-12 14:48:09 +00:00
|
|
|
for (int loop = 0; loop < 50; ++loop) {
|
2015-02-18 19:29:56 +00:00
|
|
|
uint32_t size = random.nextULessThan(10000);
|
|
|
|
SkAutoTMalloc<uint8_t> buffer(size);
|
2015-02-26 21:25:05 +00:00
|
|
|
for (uint32_t j = 0; j < size; ++j) {
|
|
|
|
buffer[j] = random.nextU() & 0xff;
|
2015-02-18 19:29:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SkDynamicMemoryWStream dynamicMemoryWStream;
|
|
|
|
{
|
|
|
|
SkDeflateWStream deflateWStream(&dynamicMemoryWStream);
|
|
|
|
uint32_t j = 0;
|
|
|
|
while (j < size) {
|
|
|
|
uint32_t writeSize =
|
2020-02-07 15:36:46 +00:00
|
|
|
std::min(size - j, random.nextRangeU(1, 400));
|
2015-02-18 19:29:56 +00:00
|
|
|
if (!deflateWStream.write(&buffer[j], writeSize)) {
|
|
|
|
ERRORF(r, "something went wrong.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
j += writeSize;
|
|
|
|
}
|
2016-09-09 18:41:59 +00:00
|
|
|
REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
|
2015-02-18 19:29:56 +00:00
|
|
|
}
|
2016-11-03 18:40:50 +00:00
|
|
|
std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream());
|
|
|
|
std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get()));
|
2015-02-18 19:29:56 +00:00
|
|
|
|
2016-02-26 16:29:25 +00:00
|
|
|
if (!decompressed) {
|
|
|
|
ERRORF(r, "Decompression failed.");
|
|
|
|
return;
|
|
|
|
}
|
2015-02-18 19:29:56 +00:00
|
|
|
if (decompressed->getLength() != size) {
|
2021-08-12 14:48:09 +00:00
|
|
|
ERRORF(r, "Decompression failed to get right size [%d]. %u != %u",
|
|
|
|
loop, (unsigned)(decompressed->getLength()), (unsigned)size);
|
|
|
|
SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", loop);
|
2015-02-18 19:29:56 +00:00
|
|
|
SkFILEWStream o(s.c_str());
|
|
|
|
o.writeStream(compressed.get(), compressed->getLength());
|
|
|
|
compressed->rewind();
|
|
|
|
|
2021-08-12 14:48:09 +00:00
|
|
|
s = SkStringPrintf("/tmp/deftst_input_%d", loop);
|
2015-02-18 19:29:56 +00:00
|
|
|
SkFILEWStream o2(s.c_str());
|
|
|
|
o2.write(&buffer[0], size);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2021-08-12 14:48:09 +00:00
|
|
|
uint32_t minLength = std::min(size, (uint32_t)(decompressed->getLength()));
|
2015-02-18 19:29:56 +00:00
|
|
|
for (uint32_t i = 0; i < minLength; ++i) {
|
|
|
|
uint8_t c;
|
|
|
|
SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t));
|
|
|
|
SkASSERT(sizeof(uint8_t) == rb);
|
|
|
|
if (buffer[i] != c) {
|
|
|
|
ERRORF(r, "Decompression failed at byte %u.", (unsigned)i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-09 18:41:59 +00:00
|
|
|
SkDeflateWStream emptyDeflateWStream(nullptr);
|
|
|
|
REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
|
2015-02-18 19:29:56 +00:00
|
|
|
}
|
2016-12-30 18:09:03 +00:00
|
|
|
|
|
|
|
#endif
|