| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkData.h" |
| #include "SkFlate.h" |
| #include "SkStream.h" |
| #include "Test.h" |
| |
| // A memory stream that reports zero size with the standard call, like |
| // an unseekable file stream would. |
| class SkZeroSizeMemStream : public SkMemoryStream { |
| public: |
| virtual size_t read(void* buffer, size_t size) { |
| if (buffer == NULL && size == 0) |
| return 0; |
| if (buffer == NULL && size == kGetSizeKey) |
| size = 0; |
| return SkMemoryStream::read(buffer, size); |
| } |
| |
| static const size_t kGetSizeKey = 0xDEADBEEF; |
| }; |
| |
| // Returns a deterministic data of the given size that should be |
| // very compressible. |
| static SkData* new_test_data(size_t dataSize) { |
| SkAutoTMalloc<uint8_t> testBuffer(dataSize); |
| for (size_t i = 0; i < dataSize; ++i) { |
| testBuffer[SkToInt(i)] = i % 64; |
| } |
| return SkData::NewFromMalloc(testBuffer.detach(), dataSize); |
| } |
| |
| static void TestFlate(skiatest::Reporter* reporter, SkMemoryStream* testStream, |
| size_t dataSize) { |
| SkASSERT(testStream != NULL); |
| |
| SkAutoDataUnref testData(new_test_data(dataSize)); |
| SkASSERT(testData->size() == dataSize); |
| |
| testStream->setMemory(testData->data(), dataSize, /*copyData=*/ true); |
| SkDynamicMemoryWStream compressed; |
| bool deflateSuccess = SkFlate::Deflate(testStream, &compressed); |
| REPORTER_ASSERT(reporter, deflateSuccess); |
| |
| // Check that the input data wasn't changed. |
| size_t inputSize = testStream->getLength(); |
| if (inputSize == 0) { |
| inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); |
| } |
| REPORTER_ASSERT(reporter, dataSize == inputSize); |
| if (dataSize == inputSize) { |
| REPORTER_ASSERT(reporter, memcmp(testData->data(), |
| testStream->getMemoryBase(), |
| dataSize) == 0); |
| } |
| |
| size_t compressedSize = compressed.getOffset(); |
| |
| SkAutoDataUnref compressedData(compressed.copyToData()); |
| testStream->setData(compressedData.get()); |
| |
| SkDynamicMemoryWStream uncompressed; |
| bool inflateSuccess = SkFlate::Inflate(testStream, &uncompressed); |
| REPORTER_ASSERT(reporter, inflateSuccess); |
| |
| // Check that the input data wasn't changed. |
| inputSize = testStream->getLength(); |
| if (inputSize == 0) { |
| inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); |
| } |
| REPORTER_ASSERT(reporter, compressedSize == inputSize); |
| if (compressedData->size() == inputSize) { |
| REPORTER_ASSERT(reporter, memcmp(testStream->getMemoryBase(), |
| compressedData->data(), |
| compressedData->size()) == 0); |
| } |
| |
| // Check that the uncompressed data matches the source data. |
| SkAutoDataUnref uncompressedData(uncompressed.copyToData()); |
| REPORTER_ASSERT(reporter, dataSize == uncompressedData->size()); |
| if (dataSize == uncompressedData->size()) { |
| REPORTER_ASSERT(reporter, memcmp(testData->data(), |
| uncompressedData->data(), |
| dataSize) == 0); |
| } |
| |
| if (compressedSize < 1) { return; } |
| |
| double compressionRatio = static_cast<double>(dataSize) / compressedSize; |
| // Assert that some compression took place. |
| REPORTER_ASSERT(reporter, compressionRatio > 1.2); |
| |
| if (reporter->verbose()) { |
| SkDebugf("Flate Test: \t input size: " SK_SIZE_T_SPECIFIER |
| "\tcompressed size: " SK_SIZE_T_SPECIFIER |
| "\tratio: %.4g\n", |
| dataSize, compressedSize, compressionRatio); |
| } |
| } |
| |
| DEF_TEST(Flate, reporter) { |
| #ifdef SK_HAS_ZLIB |
| REPORTER_ASSERT(reporter, SkFlate::HaveFlate()); |
| #endif |
| if (SkFlate::HaveFlate()) { |
| SkMemoryStream memStream; |
| TestFlate(reporter, &memStream, 512); |
| TestFlate(reporter, &memStream, 10240); |
| |
| SkZeroSizeMemStream fileStream; |
| TestFlate(reporter, &fileStream, 512); |
| TestFlate(reporter, &fileStream, 10240); |
| } |
| } |