11b5c604d9d344537941b11b136348edfc39f236chalcanary/*
21b5c604d9d344537941b11b136348edfc39f236chalcanary * Copyright 2015 Google Inc.
31b5c604d9d344537941b11b136348edfc39f236chalcanary *
41b5c604d9d344537941b11b136348edfc39f236chalcanary * Use of this source code is governed by a BSD-style license that can be
51b5c604d9d344537941b11b136348edfc39f236chalcanary * found in the LICENSE file.
61b5c604d9d344537941b11b136348edfc39f236chalcanary */
71b5c604d9d344537941b11b136348edfc39f236chalcanary
843fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary#include "Test.h"
943fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary
1043fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary#ifdef SK_SUPPORT_PDF
1143fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary
12d9e57158ebd9b1f8317f0d76ef0402cfce0b0253halcanary#include "SkDeflate.h"
131b5c604d9d344537941b11b136348edfc39f236chalcanary#include "SkRandom.h"
141b5c604d9d344537941b11b136348edfc39f236chalcanary
1548305e835351291ef72a7084c6c1af7b185d89c0halcanarynamespace {
1648305e835351291ef72a7084c6c1af7b185d89c0halcanary
17650e20d705a39eaa861cfbc821e9e1f81cef5316halcanary#include "zlib.h"
1848305e835351291ef72a7084c6c1af7b185d89c0halcanary
1948305e835351291ef72a7084c6c1af7b185d89c0halcanary// Different zlib implementations use different T.
2048305e835351291ef72a7084c6c1af7b185d89c0halcanary// We've seen size_t and unsigned.
2148305e835351291ef72a7084c6c1af7b185d89c0halcanarytemplate <typename T> void* skia_alloc_func(void*, T items, T size) {
2248305e835351291ef72a7084c6c1af7b185d89c0halcanary    return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
2348305e835351291ef72a7084c6c1af7b185d89c0halcanary}
2448305e835351291ef72a7084c6c1af7b185d89c0halcanary
2548305e835351291ef72a7084c6c1af7b185d89c0halcanaryvoid skia_free_func(void*, void* address) { sk_free(address); }
2648305e835351291ef72a7084c6c1af7b185d89c0halcanary
2748305e835351291ef72a7084c6c1af7b185d89c0halcanary/**
2848305e835351291ef72a7084c6c1af7b185d89c0halcanary *  Use the un-deflate compression algorithm to decompress the data in src,
2996fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  returning the result.  Returns nullptr if an error occurs.
3048305e835351291ef72a7084c6c1af7b185d89c0halcanary */
310b83319b7f301145b7fc89d7096ddcea91d4a56bHal Canarystd::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) {
3248305e835351291ef72a7084c6c1af7b185d89c0halcanary    SkDynamicMemoryWStream decompressedDynamicMemoryWStream;
3348305e835351291ef72a7084c6c1af7b185d89c0halcanary    SkWStream* dst = &decompressedDynamicMemoryWStream;
3448305e835351291ef72a7084c6c1af7b185d89c0halcanary
3548305e835351291ef72a7084c6c1af7b185d89c0halcanary    static const size_t kBufferSize = 1024;
3648305e835351291ef72a7084c6c1af7b185d89c0halcanary    uint8_t inputBuffer[kBufferSize];
3748305e835351291ef72a7084c6c1af7b185d89c0halcanary    uint8_t outputBuffer[kBufferSize];
3848305e835351291ef72a7084c6c1af7b185d89c0halcanary    z_stream flateData;
3948305e835351291ef72a7084c6c1af7b185d89c0halcanary    flateData.zalloc = &skia_alloc_func;
4048305e835351291ef72a7084c6c1af7b185d89c0halcanary    flateData.zfree = &skia_free_func;
4196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    flateData.opaque = nullptr;
4296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    flateData.next_in = nullptr;
4348305e835351291ef72a7084c6c1af7b185d89c0halcanary    flateData.avail_in = 0;
4448305e835351291ef72a7084c6c1af7b185d89c0halcanary    flateData.next_out = outputBuffer;
4548305e835351291ef72a7084c6c1af7b185d89c0halcanary    flateData.avail_out = kBufferSize;
4648305e835351291ef72a7084c6c1af7b185d89c0halcanary    int rc;
4748305e835351291ef72a7084c6c1af7b185d89c0halcanary    rc = inflateInit(&flateData);
48d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary    if (rc != Z_OK) {
49d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary        ERRORF(reporter, "Zlib: inflateInit failed");
5048305e835351291ef72a7084c6c1af7b185d89c0halcanary        return nullptr;
51d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary    }
5248305e835351291ef72a7084c6c1af7b185d89c0halcanary    uint8_t* input = (uint8_t*)src->getMemoryBase();
5348305e835351291ef72a7084c6c1af7b185d89c0halcanary    size_t inputLength = src->getLength();
5496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (input == nullptr || inputLength == 0) {
5596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        input = nullptr;
5648305e835351291ef72a7084c6c1af7b185d89c0halcanary        flateData.next_in = inputBuffer;
5748305e835351291ef72a7084c6c1af7b185d89c0halcanary        flateData.avail_in = 0;
5848305e835351291ef72a7084c6c1af7b185d89c0halcanary    } else {
5948305e835351291ef72a7084c6c1af7b185d89c0halcanary        flateData.next_in = input;
6048305e835351291ef72a7084c6c1af7b185d89c0halcanary        flateData.avail_in = SkToUInt(inputLength);
6148305e835351291ef72a7084c6c1af7b185d89c0halcanary    }
6248305e835351291ef72a7084c6c1af7b185d89c0halcanary
6348305e835351291ef72a7084c6c1af7b185d89c0halcanary    rc = Z_OK;
6448305e835351291ef72a7084c6c1af7b185d89c0halcanary    while (true) {
6548305e835351291ef72a7084c6c1af7b185d89c0halcanary        if (flateData.avail_out < kBufferSize) {
6648305e835351291ef72a7084c6c1af7b185d89c0halcanary            if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
6748305e835351291ef72a7084c6c1af7b185d89c0halcanary                rc = Z_BUF_ERROR;
6848305e835351291ef72a7084c6c1af7b185d89c0halcanary                break;
6948305e835351291ef72a7084c6c1af7b185d89c0halcanary            }
7048305e835351291ef72a7084c6c1af7b185d89c0halcanary            flateData.next_out = outputBuffer;
7148305e835351291ef72a7084c6c1af7b185d89c0halcanary            flateData.avail_out = kBufferSize;
7248305e835351291ef72a7084c6c1af7b185d89c0halcanary        }
7348305e835351291ef72a7084c6c1af7b185d89c0halcanary        if (rc != Z_OK)
7448305e835351291ef72a7084c6c1af7b185d89c0halcanary            break;
7548305e835351291ef72a7084c6c1af7b185d89c0halcanary        if (flateData.avail_in == 0) {
7696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (input != nullptr)
7748305e835351291ef72a7084c6c1af7b185d89c0halcanary                break;
7848305e835351291ef72a7084c6c1af7b185d89c0halcanary            size_t read = src->read(&inputBuffer, kBufferSize);
7948305e835351291ef72a7084c6c1af7b185d89c0halcanary            if (read == 0)
8048305e835351291ef72a7084c6c1af7b185d89c0halcanary                break;
8148305e835351291ef72a7084c6c1af7b185d89c0halcanary            flateData.next_in = inputBuffer;
8248305e835351291ef72a7084c6c1af7b185d89c0halcanary            flateData.avail_in = SkToUInt(read);
8348305e835351291ef72a7084c6c1af7b185d89c0halcanary        }
8448305e835351291ef72a7084c6c1af7b185d89c0halcanary        rc = inflate(&flateData, Z_NO_FLUSH);
8548305e835351291ef72a7084c6c1af7b185d89c0halcanary    }
8648305e835351291ef72a7084c6c1af7b185d89c0halcanary    while (rc == Z_OK) {
8748305e835351291ef72a7084c6c1af7b185d89c0halcanary        rc = inflate(&flateData, Z_FINISH);
8848305e835351291ef72a7084c6c1af7b185d89c0halcanary        if (flateData.avail_out < kBufferSize) {
89d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary            if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
90d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary                ERRORF(reporter, "write failed");
9148305e835351291ef72a7084c6c1af7b185d89c0halcanary                return nullptr;
92d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary            }
9348305e835351291ef72a7084c6c1af7b185d89c0halcanary            flateData.next_out = outputBuffer;
9448305e835351291ef72a7084c6c1af7b185d89c0halcanary            flateData.avail_out = kBufferSize;
9548305e835351291ef72a7084c6c1af7b185d89c0halcanary        }
9648305e835351291ef72a7084c6c1af7b185d89c0halcanary    }
9748305e835351291ef72a7084c6c1af7b185d89c0halcanary
9848305e835351291ef72a7084c6c1af7b185d89c0halcanary    inflateEnd(&flateData);
9948305e835351291ef72a7084c6c1af7b185d89c0halcanary    if (rc != Z_STREAM_END) {
100d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary        ERRORF(reporter, "Zlib: inflateEnd failed");
10148305e835351291ef72a7084c6c1af7b185d89c0halcanary        return nullptr;
10248305e835351291ef72a7084c6c1af7b185d89c0halcanary    }
10348305e835351291ef72a7084c6c1af7b185d89c0halcanary    return decompressedDynamicMemoryWStream.detachAsStream();
10448305e835351291ef72a7084c6c1af7b185d89c0halcanary}
10548305e835351291ef72a7084c6c1af7b185d89c0halcanary}  // namespace
10648305e835351291ef72a7084c6c1af7b185d89c0halcanary
10757f744e3030fec4d1a2b3e9119011904b149a4dahalcanaryDEF_TEST(SkPDF_DeflateWStream, r) {
1081b5c604d9d344537941b11b136348edfc39f236chalcanary    SkRandom random(123456);
1091b5c604d9d344537941b11b136348edfc39f236chalcanary    for (int i = 0; i < 50; ++i) {
1101b5c604d9d344537941b11b136348edfc39f236chalcanary        uint32_t size = random.nextULessThan(10000);
1111b5c604d9d344537941b11b136348edfc39f236chalcanary        SkAutoTMalloc<uint8_t> buffer(size);
112e6cf9cb68511ff08156f834859db39232eb37be8mtklein        for (uint32_t j = 0; j < size; ++j) {
113e6cf9cb68511ff08156f834859db39232eb37be8mtklein            buffer[j] = random.nextU() & 0xff;
1141b5c604d9d344537941b11b136348edfc39f236chalcanary        }
1151b5c604d9d344537941b11b136348edfc39f236chalcanary
1161b5c604d9d344537941b11b136348edfc39f236chalcanary        SkDynamicMemoryWStream dynamicMemoryWStream;
1171b5c604d9d344537941b11b136348edfc39f236chalcanary        {
1181b5c604d9d344537941b11b136348edfc39f236chalcanary            SkDeflateWStream deflateWStream(&dynamicMemoryWStream);
1191b5c604d9d344537941b11b136348edfc39f236chalcanary            uint32_t j = 0;
1201b5c604d9d344537941b11b136348edfc39f236chalcanary            while (j < size) {
1211b5c604d9d344537941b11b136348edfc39f236chalcanary                uint32_t writeSize =
1221b5c604d9d344537941b11b136348edfc39f236chalcanary                        SkTMin(size - j, random.nextRangeU(1, 400));
1231b5c604d9d344537941b11b136348edfc39f236chalcanary                if (!deflateWStream.write(&buffer[j], writeSize)) {
1241b5c604d9d344537941b11b136348edfc39f236chalcanary                    ERRORF(r, "something went wrong.");
1251b5c604d9d344537941b11b136348edfc39f236chalcanary                    return;
1261b5c604d9d344537941b11b136348edfc39f236chalcanary                }
1271b5c604d9d344537941b11b136348edfc39f236chalcanary                j += writeSize;
1281b5c604d9d344537941b11b136348edfc39f236chalcanary            }
12957f744e3030fec4d1a2b3e9119011904b149a4dahalcanary            REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
1301b5c604d9d344537941b11b136348edfc39f236chalcanary        }
131145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner        std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream());
132145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner        std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get()));
1331b5c604d9d344537941b11b136348edfc39f236chalcanary
134d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary        if (!decompressed) {
135d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary            ERRORF(r, "Decompression failed.");
136d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary            return;
137d5722a4a1bab889fec835a7abc6b2c62b57827f7halcanary        }
1381b5c604d9d344537941b11b136348edfc39f236chalcanary        if (decompressed->getLength() != size) {
1391b5c604d9d344537941b11b136348edfc39f236chalcanary            ERRORF(r, "Decompression failed to get right size [%d]."
1401b5c604d9d344537941b11b136348edfc39f236chalcanary                   " %u != %u", i,  (unsigned)(decompressed->getLength()),
1411b5c604d9d344537941b11b136348edfc39f236chalcanary                   (unsigned)size);
1421b5c604d9d344537941b11b136348edfc39f236chalcanary            SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", i);
1431b5c604d9d344537941b11b136348edfc39f236chalcanary            SkFILEWStream o(s.c_str());
1441b5c604d9d344537941b11b136348edfc39f236chalcanary            o.writeStream(compressed.get(), compressed->getLength());
1451b5c604d9d344537941b11b136348edfc39f236chalcanary            compressed->rewind();
1461b5c604d9d344537941b11b136348edfc39f236chalcanary
1471b5c604d9d344537941b11b136348edfc39f236chalcanary            s = SkStringPrintf("/tmp/deftst_input_%d", i);
1481b5c604d9d344537941b11b136348edfc39f236chalcanary            SkFILEWStream o2(s.c_str());
1491b5c604d9d344537941b11b136348edfc39f236chalcanary            o2.write(&buffer[0], size);
1501b5c604d9d344537941b11b136348edfc39f236chalcanary
1511b5c604d9d344537941b11b136348edfc39f236chalcanary            continue;
1521b5c604d9d344537941b11b136348edfc39f236chalcanary        }
1531b5c604d9d344537941b11b136348edfc39f236chalcanary        uint32_t minLength = SkTMin(size,
1541b5c604d9d344537941b11b136348edfc39f236chalcanary                                    (uint32_t)(decompressed->getLength()));
1551b5c604d9d344537941b11b136348edfc39f236chalcanary        for (uint32_t i = 0; i < minLength; ++i) {
1561b5c604d9d344537941b11b136348edfc39f236chalcanary            uint8_t c;
1571b5c604d9d344537941b11b136348edfc39f236chalcanary            SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t));
1581b5c604d9d344537941b11b136348edfc39f236chalcanary            SkASSERT(sizeof(uint8_t) == rb);
1591b5c604d9d344537941b11b136348edfc39f236chalcanary            if (buffer[i] != c) {
1601b5c604d9d344537941b11b136348edfc39f236chalcanary                ERRORF(r, "Decompression failed at byte %u.", (unsigned)i);
1611b5c604d9d344537941b11b136348edfc39f236chalcanary                break;
1621b5c604d9d344537941b11b136348edfc39f236chalcanary            }
1631b5c604d9d344537941b11b136348edfc39f236chalcanary        }
1641b5c604d9d344537941b11b136348edfc39f236chalcanary    }
16557f744e3030fec4d1a2b3e9119011904b149a4dahalcanary    SkDeflateWStream emptyDeflateWStream(nullptr);
16657f744e3030fec4d1a2b3e9119011904b149a4dahalcanary    REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
1671b5c604d9d344537941b11b136348edfc39f236chalcanary}
16843fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary
16943fb7a014b785960e5892cadd0bd30c10328ae8aHal Canary#endif
170