• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "tests/Test.h"
9  
10  #ifdef SK_SUPPORT_PDF
11  
12  #include "include/private/SkTo.h"
13  #include "include/utils/SkRandom.h"
14  #include "src/pdf/SkDeflate.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.
skia_alloc_func(void *,T items,T size)22  template <typename T> void* skia_alloc_func(void*, T items, T size) {
23      return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size));
24  }
25  
skia_free_func(void *,void * address)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   */
stream_inflate(skiatest::Reporter * reporter,SkStream * src)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  
DEF_TEST(SkPDF_DeflateWStream,r)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