PDFDeflateWStreamTest.cpp revision 2880df2609eba09b555ca37be04b6ad89290c765
12880df2609eba09b555ca37be04b6ad89290c765Tom Hudson/*
22880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * Copyright 2015 Google Inc.
32880df2609eba09b555ca37be04b6ad89290c765Tom Hudson *
42880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * Use of this source code is governed by a BSD-style license that can be
52880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * found in the LICENSE file.
62880df2609eba09b555ca37be04b6ad89290c765Tom Hudson */
72880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
82880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkDeflate.h"
92880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkRandom.h"
102880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "Test.h"
112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
122880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonnamespace {
132880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
142880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#ifdef ZLIB_INCLUDE
152880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    #include ZLIB_INCLUDE
162880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#else
172880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    #include "zlib.h"
182880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#endif
192880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
202880df2609eba09b555ca37be04b6ad89290c765Tom Hudson// Different zlib implementations use different T.
212880df2609eba09b555ca37be04b6ad89290c765Tom Hudson// We've seen size_t and unsigned.
222880df2609eba09b555ca37be04b6ad89290c765Tom Hudsontemplate <typename T> void* skia_alloc_func(void*, T items, T size) {
232880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
252880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
262880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonvoid skia_free_func(void*, void* address) { sk_free(address); }
272880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
282880df2609eba09b555ca37be04b6ad89290c765Tom Hudson/**
292880df2609eba09b555ca37be04b6ad89290c765Tom Hudson *  Use the un-deflate compression algorithm to decompress the data in src,
302880df2609eba09b555ca37be04b6ad89290c765Tom Hudson *  returning the result.  Returns nullptr if an error occurs.
312880df2609eba09b555ca37be04b6ad89290c765Tom Hudson */
322880df2609eba09b555ca37be04b6ad89290c765Tom HudsonSkStreamAsset* stream_inflate(SkStream* src) {
332880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkDynamicMemoryWStream decompressedDynamicMemoryWStream;
342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkWStream* dst = &decompressedDynamicMemoryWStream;
352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
362880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    static const size_t kBufferSize = 1024;
372880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    uint8_t inputBuffer[kBufferSize];
382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    uint8_t outputBuffer[kBufferSize];
392880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    z_stream flateData;
402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.zalloc = &skia_alloc_func;
412880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.zfree = &skia_free_func;
422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.opaque = nullptr;
432880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.next_in = nullptr;
442880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.avail_in = 0;
452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.next_out = outputBuffer;
462880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    flateData.avail_out = kBufferSize;
472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    int rc;
482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    rc = inflateInit(&flateData);
492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (rc != Z_OK)
502880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        return nullptr;
512880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
522880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    uint8_t* input = (uint8_t*)src->getMemoryBase();
532880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    size_t inputLength = src->getLength();
542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (input == nullptr || inputLength == 0) {
552880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        input = nullptr;
562880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        flateData.next_in = inputBuffer;
572880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        flateData.avail_in = 0;
582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    } else {
592880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        flateData.next_in = input;
602880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        flateData.avail_in = SkToUInt(inputLength);
612880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
622880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
632880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    rc = Z_OK;
642880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    while (true) {
652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (flateData.avail_out < kBufferSize) {
662880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
672880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                rc = Z_BUF_ERROR;
682880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                break;
692880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            }
702880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            flateData.next_out = outputBuffer;
712880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            flateData.avail_out = kBufferSize;
722880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
732880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (rc != Z_OK)
742880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            break;
752880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (flateData.avail_in == 0) {
762880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (input != nullptr)
772880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                break;
782880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            size_t read = src->read(&inputBuffer, kBufferSize);
792880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (read == 0)
802880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                break;
812880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            flateData.next_in = inputBuffer;
822880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            flateData.avail_in = SkToUInt(read);
832880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
842880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        rc = inflate(&flateData, Z_NO_FLUSH);
852880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
862880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    while (rc == Z_OK) {
872880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        rc = inflate(&flateData, Z_FINISH);
882880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (flateData.avail_out < kBufferSize) {
892880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out))
902880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                return nullptr;
912880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            flateData.next_out = outputBuffer;
922880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            flateData.avail_out = kBufferSize;
932880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
942880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
962880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    inflateEnd(&flateData);
972880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (rc != Z_STREAM_END) {
982880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        return nullptr;
992880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1002880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    return decompressedDynamicMemoryWStream.detachAsStream();
1012880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
1022880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}  // namespace
1032880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1042880df2609eba09b555ca37be04b6ad89290c765Tom HudsonDEF_TEST(SkDeflateWStream, r) {
1052880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkRandom random(123456);
1062880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    for (int i = 0; i < 50; ++i) {
1072880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        uint32_t size = random.nextULessThan(10000);
1082880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkAutoTMalloc<uint8_t> buffer(size);
1092880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        for (uint32_t j = 0; j < size; ++j) {
1102880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            buffer[j] = random.nextU() & 0xff;
1112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
1122880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1132880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkDynamicMemoryWStream dynamicMemoryWStream;
1142880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        {
1152880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkDeflateWStream deflateWStream(&dynamicMemoryWStream);
1162880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            uint32_t j = 0;
1172880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            while (j < size) {
1182880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                uint32_t writeSize =
1192880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                        SkTMin(size - j, random.nextRangeU(1, 400));
1202880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                if (!deflateWStream.write(&buffer[j], writeSize)) {
1212880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                    ERRORF(r, "something went wrong.");
1222880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                    return;
1232880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                }
1242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                j += writeSize;
1252880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            }
1262880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
1272880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkAutoTDelete<SkStreamAsset> compressed(
1282880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                dynamicMemoryWStream.detachAsStream());
1292880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkAutoTDelete<SkStreamAsset> decompressed(stream_inflate(compressed));
1302880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1312880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (decompressed->getLength() != size) {
1322880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            ERRORF(r, "Decompression failed to get right size [%d]."
1332880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                   " %u != %u", i,  (unsigned)(decompressed->getLength()),
1342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                   (unsigned)size);
1352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", i);
1362880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkFILEWStream o(s.c_str());
1372880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            o.writeStream(compressed.get(), compressed->getLength());
1382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            compressed->rewind();
1392880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            s = SkStringPrintf("/tmp/deftst_input_%d", i);
1412880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkFILEWStream o2(s.c_str());
1422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            o2.write(&buffer[0], size);
1432880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1442880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            continue;
1452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
1462880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        uint32_t minLength = SkTMin(size,
1472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                                    (uint32_t)(decompressed->getLength()));
1482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        for (uint32_t i = 0; i < minLength; ++i) {
1492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            uint8_t c;
1502880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t));
1512880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkASSERT(sizeof(uint8_t) == rb);
1522880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (buffer[i] != c) {
1532880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                ERRORF(r, "Decompression failed at byte %u.", (unsigned)i);
1542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                break;
1552880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            }
1562880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
1572880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
159