1 /* 2 * Copyright 2011 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 "SkData.h" 9 #include "SkFlate.h" 10 #include "SkStream.h" 11 #include "Test.h" 12 13 // A memory stream that reports zero size with the standard call, like 14 // an unseekable file stream would. 15 class SkZeroSizeMemStream : public SkMemoryStream { 16 public: 17 virtual size_t read(void* buffer, size_t size) { 18 if (buffer == NULL && size == 0) 19 return 0; 20 if (buffer == NULL && size == kGetSizeKey) 21 size = 0; 22 return SkMemoryStream::read(buffer, size); 23 } 24 25 static const size_t kGetSizeKey = 0xDEADBEEF; 26 }; 27 28 // Returns a deterministic data of the given size that should be 29 // very compressible. 30 static SkData* new_test_data(size_t dataSize) { 31 SkAutoTMalloc<uint8_t> testBuffer(dataSize); 32 for (size_t i = 0; i < dataSize; ++i) { 33 testBuffer[i] = i % 64; 34 } 35 return SkData::NewFromMalloc(testBuffer.detach(), dataSize); 36 } 37 38 static void TestFlate(skiatest::Reporter* reporter, SkMemoryStream* testStream, 39 size_t dataSize) { 40 SkASSERT(testStream != NULL); 41 42 SkAutoDataUnref testData(new_test_data(dataSize)); 43 SkASSERT(testData->size() == dataSize); 44 45 testStream->setMemory(testData->data(), dataSize, /*copyData=*/ true); 46 SkDynamicMemoryWStream compressed; 47 bool deflateSuccess = SkFlate::Deflate(testStream, &compressed); 48 REPORTER_ASSERT(reporter, deflateSuccess); 49 50 // Check that the input data wasn't changed. 51 size_t inputSize = testStream->getLength(); 52 if (inputSize == 0) { 53 inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); 54 } 55 REPORTER_ASSERT(reporter, dataSize == inputSize); 56 if (dataSize == inputSize) { 57 REPORTER_ASSERT(reporter, memcmp(testData->data(), 58 testStream->getMemoryBase(), 59 dataSize) == 0); 60 } 61 62 size_t compressedSize = compressed.getOffset(); 63 64 SkAutoDataUnref compressedData(compressed.copyToData()); 65 testStream->setData(compressedData.get()); 66 67 SkDynamicMemoryWStream uncompressed; 68 bool inflateSuccess = SkFlate::Inflate(testStream, &uncompressed); 69 REPORTER_ASSERT(reporter, inflateSuccess); 70 71 // Check that the input data wasn't changed. 72 inputSize = testStream->getLength(); 73 if (inputSize == 0) { 74 inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); 75 } 76 REPORTER_ASSERT(reporter, compressedSize == inputSize); 77 if (compressedData->size() == inputSize) { 78 REPORTER_ASSERT(reporter, memcmp(testStream->getMemoryBase(), 79 compressedData->data(), 80 compressedData->size()) == 0); 81 } 82 83 // Check that the uncompressed data matches the source data. 84 SkAutoDataUnref uncompressedData(uncompressed.copyToData()); 85 REPORTER_ASSERT(reporter, dataSize == uncompressedData->size()); 86 if (dataSize == uncompressedData->size()) { 87 REPORTER_ASSERT(reporter, memcmp(testData->data(), 88 uncompressedData->data(), 89 dataSize) == 0); 90 } 91 92 if (compressedSize < 1) { return; } 93 94 double compressionRatio = static_cast<double>(dataSize) / compressedSize; 95 // Assert that some compression took place. 96 REPORTER_ASSERT(reporter, compressionRatio > 1.2); 97 98 if (reporter->verbose()) { 99 SkDebugf("Flate Test: \t input size: " SK_SIZE_T_SPECIFIER 100 "\tcompressed size: " SK_SIZE_T_SPECIFIER 101 "\tratio: %.4g\n", 102 dataSize, compressedSize, compressionRatio); 103 } 104 } 105 106 DEF_TEST(Flate, reporter) { 107 #ifdef SK_HAS_ZLIB 108 REPORTER_ASSERT(reporter, SkFlate::HaveFlate()); 109 #endif 110 if (SkFlate::HaveFlate()) { 111 SkMemoryStream memStream; 112 TestFlate(reporter, &memStream, 512); 113 TestFlate(reporter, &memStream, 10240); 114 115 SkZeroSizeMemStream fileStream; 116 TestFlate(reporter, &fileStream, 512); 117 TestFlate(reporter, &fileStream, 10240); 118 } 119 } 120