Home | History | Annotate | Download | only in tests
      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 
      8 #include "Test.h"
      9 
     10 #ifdef SK_SUPPORT_PDF
     11 
     12 #include "SkDeflate.h"
     13 #include "SkRandom.h"
     14 #include "SkTo.h"
     15 
     16 namespace {
     17 
     18 #include "zlib.h"
     19 
     20 // Different zlib implementations use different T.
     21 // We've seen size_t and unsigned.
     22 template <typename T> void* skia_alloc_func(void*, T items, T size) {
     23     return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
     24 }
     25 
     26 void skia_free_func(void*, void* address) { sk_free(address); }
     27 
     28 /**
     29  *  Use the un-deflate compression algorithm to decompress the data in src,
     30  *  returning the result.  Returns nullptr if an error occurs.
     31  */
     32 std::unique_ptr<SkStreamAsset> stream_inflate(skiatest::Reporter* reporter, SkStream* src) {
     33     SkDynamicMemoryWStream decompressedDynamicMemoryWStream;
     34     SkWStream* dst = &decompressedDynamicMemoryWStream;
     35 
     36     static const size_t kBufferSize = 1024;
     37     uint8_t inputBuffer[kBufferSize];
     38     uint8_t outputBuffer[kBufferSize];
     39     z_stream flateData;
     40     flateData.zalloc = &skia_alloc_func;
     41     flateData.zfree = &skia_free_func;
     42     flateData.opaque = nullptr;
     43     flateData.next_in = nullptr;
     44     flateData.avail_in = 0;
     45     flateData.next_out = outputBuffer;
     46     flateData.avail_out = kBufferSize;
     47     int rc;
     48     rc = inflateInit(&flateData);
     49     if (rc != Z_OK) {
     50         ERRORF(reporter, "Zlib: inflateInit failed");
     51         return nullptr;
     52     }
     53     uint8_t* input = (uint8_t*)src->getMemoryBase();
     54     size_t inputLength = src->getLength();
     55     if (input == nullptr || inputLength == 0) {
     56         input = nullptr;
     57         flateData.next_in = inputBuffer;
     58         flateData.avail_in = 0;
     59     } else {
     60         flateData.next_in = input;
     61         flateData.avail_in = SkToUInt(inputLength);
     62     }
     63 
     64     rc = Z_OK;
     65     while (true) {
     66         if (flateData.avail_out < kBufferSize) {
     67             if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
     68                 rc = Z_BUF_ERROR;
     69                 break;
     70             }
     71             flateData.next_out = outputBuffer;
     72             flateData.avail_out = kBufferSize;
     73         }
     74         if (rc != Z_OK)
     75             break;
     76         if (flateData.avail_in == 0) {
     77             if (input != nullptr)
     78                 break;
     79             size_t read = src->read(&inputBuffer, kBufferSize);
     80             if (read == 0)
     81                 break;
     82             flateData.next_in = inputBuffer;
     83             flateData.avail_in = SkToUInt(read);
     84         }
     85         rc = inflate(&flateData, Z_NO_FLUSH);
     86     }
     87     while (rc == Z_OK) {
     88         rc = inflate(&flateData, Z_FINISH);
     89         if (flateData.avail_out < kBufferSize) {
     90             if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
     91                 ERRORF(reporter, "write failed");
     92                 return nullptr;
     93             }
     94             flateData.next_out = outputBuffer;
     95             flateData.avail_out = kBufferSize;
     96         }
     97     }
     98 
     99     inflateEnd(&flateData);
    100     if (rc != Z_STREAM_END) {
    101         ERRORF(reporter, "Zlib: inflateEnd failed");
    102         return nullptr;
    103     }
    104     return decompressedDynamicMemoryWStream.detachAsStream();
    105 }
    106 }  // namespace
    107 
    108 DEF_TEST(SkPDF_DeflateWStream, r) {
    109     SkRandom random(123456);
    110     for (int i = 0; i < 50; ++i) {
    111         uint32_t size = random.nextULessThan(10000);
    112         SkAutoTMalloc<uint8_t> buffer(size);
    113         for (uint32_t j = 0; j < size; ++j) {
    114             buffer[j] = random.nextU() & 0xff;
    115         }
    116 
    117         SkDynamicMemoryWStream dynamicMemoryWStream;
    118         {
    119             SkDeflateWStream deflateWStream(&dynamicMemoryWStream);
    120             uint32_t j = 0;
    121             while (j < size) {
    122                 uint32_t writeSize =
    123                         SkTMin(size - j, random.nextRangeU(1, 400));
    124                 if (!deflateWStream.write(&buffer[j], writeSize)) {
    125                     ERRORF(r, "something went wrong.");
    126                     return;
    127                 }
    128                 j += writeSize;
    129             }
    130             REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
    131         }
    132         std::unique_ptr<SkStreamAsset> compressed(dynamicMemoryWStream.detachAsStream());
    133         std::unique_ptr<SkStreamAsset> decompressed(stream_inflate(r, compressed.get()));
    134 
    135         if (!decompressed) {
    136             ERRORF(r, "Decompression failed.");
    137             return;
    138         }
    139         if (decompressed->getLength() != size) {
    140             ERRORF(r, "Decompression failed to get right size [%d]."
    141                    " %u != %u", i,  (unsigned)(decompressed->getLength()),
    142                    (unsigned)size);
    143             SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", i);
    144             SkFILEWStream o(s.c_str());
    145             o.writeStream(compressed.get(), compressed->getLength());
    146             compressed->rewind();
    147 
    148             s = SkStringPrintf("/tmp/deftst_input_%d", i);
    149             SkFILEWStream o2(s.c_str());
    150             o2.write(&buffer[0], size);
    151 
    152             continue;
    153         }
    154         uint32_t minLength = SkTMin(size,
    155                                     (uint32_t)(decompressed->getLength()));
    156         for (uint32_t i = 0; i < minLength; ++i) {
    157             uint8_t c;
    158             SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t));
    159             SkASSERT(sizeof(uint8_t) == rb);
    160             if (buffer[i] != c) {
    161                 ERRORF(r, "Decompression failed at byte %u.", (unsigned)i);
    162                 break;
    163             }
    164         }
    165     }
    166     SkDeflateWStream emptyDeflateWStream(nullptr);
    167     REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
    168 }
    169 
    170 #endif
    171