1 /* 2 * Copyright 2013 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 #include "TestClassDef.h" 10 #include "SkFrontBufferedStream.h" 11 #include "SkRefCnt.h" 12 #include "SkStream.h" 13 #include "SkTypes.h" 14 15 static void test_read(skiatest::Reporter* reporter, SkStream* bufferedStream, 16 const void* expectations, size_t bytesToRead) { 17 // output for reading bufferedStream. 18 SkAutoMalloc storage(bytesToRead); 19 20 size_t bytesRead = bufferedStream->read(storage.get(), bytesToRead); 21 REPORTER_ASSERT(reporter, bytesRead == bytesToRead || bufferedStream->isAtEnd()); 22 REPORTER_ASSERT(reporter, memcmp(storage.get(), expectations, bytesRead) == 0); 23 } 24 25 static void test_rewind(skiatest::Reporter* reporter, 26 SkStream* bufferedStream, bool shouldSucceed) { 27 const bool success = bufferedStream->rewind(); 28 REPORTER_ASSERT(reporter, success == shouldSucceed); 29 } 30 31 // All tests will buffer this string, and compare output to the original. 32 // The string is long to ensure that all of our lengths being tested are 33 // smaller than the string length. 34 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx"; 35 36 // Tests reading the stream across boundaries of what has been buffered so far and what 37 // the total buffer size is. 38 static void test_incremental_buffering(skiatest::Reporter* reporter, size_t bufferSize) { 39 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); 40 41 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize)); 42 43 // First, test reading less than the max buffer size. 44 test_read(reporter, bufferedStream, gAbcs, bufferSize / 2); 45 46 // Now test rewinding back to the beginning and reading less than what was 47 // already buffered. 48 test_rewind(reporter, bufferedStream, true); 49 test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); 50 51 // Now test reading part of what was buffered, and buffering new data. 52 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 2); 53 54 // Now test reading what was buffered, buffering new data, and 55 // reading directly from the stream. 56 test_rewind(reporter, bufferedStream, true); 57 test_read(reporter, bufferedStream, gAbcs, bufferSize << 1); 58 59 // We have reached the end of the buffer, so rewinding will fail. 60 // This test assumes that the stream is larger than the buffer; otherwise the 61 // result of rewind should be true. 62 test_rewind(reporter, bufferedStream, false); 63 } 64 65 static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t bufferSize) { 66 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); 67 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize)); 68 69 // Read exactly the amount that fits in the buffer. 70 test_read(reporter, bufferedStream, gAbcs, bufferSize); 71 72 // Rewinding should succeed. 73 test_rewind(reporter, bufferedStream, true); 74 75 // Once again reading buffered info should succeed 76 test_read(reporter, bufferedStream, gAbcs, bufferSize); 77 78 // Read past the size of the buffer. At this point, we cannot return. 79 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1); 80 test_rewind(reporter, bufferedStream, false); 81 } 82 83 static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) { 84 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); 85 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize)); 86 87 // Skip half the buffer. 88 bufferedStream->skip(bufferSize / 2); 89 90 // Rewind, then read part of the buffer, which should have been read. 91 test_rewind(reporter, bufferedStream, true); 92 test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); 93 94 // Now skip beyond the buffered piece, but still within the total buffer. 95 bufferedStream->skip(bufferSize / 2); 96 97 // Test that reading will still work. 98 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 4); 99 100 test_rewind(reporter, bufferedStream, true); 101 test_read(reporter, bufferedStream, gAbcs, bufferSize); 102 } 103 104 // A custom class whose isAtEnd behaves the way Android's stream does - since it is an adaptor to a 105 // Java InputStream, it does not know that it is at the end until it has attempted to read beyond 106 // the end and failed. Used by test_read_beyond_buffer. 107 class AndroidLikeMemoryStream : public SkMemoryStream { 108 public: 109 AndroidLikeMemoryStream(void* data, size_t size, bool ownMemory) 110 : INHERITED(data, size, ownMemory) 111 , fIsAtEnd(false) {} 112 113 size_t read(void* dst, size_t requested) SK_OVERRIDE { 114 size_t bytesRead = this->INHERITED::read(dst, requested); 115 if (bytesRead < requested) { 116 fIsAtEnd = true; 117 } 118 return bytesRead; 119 } 120 121 bool isAtEnd() const SK_OVERRIDE { 122 return fIsAtEnd; 123 } 124 125 private: 126 bool fIsAtEnd; 127 typedef SkMemoryStream INHERITED; 128 }; 129 130 // This test ensures that buffering the exact length of the stream and attempting to read beyond it 131 // does not invalidate the buffer. 132 static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferSize) { 133 // Use a stream that behaves like Android's stream. 134 AndroidLikeMemoryStream memStream((void*)gAbcs, bufferSize, false); 135 136 // Create a buffer that matches the length of the stream. 137 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize)); 138 139 // Attempt to read one more than the bufferSize 140 test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1); 141 test_rewind(reporter, bufferedStream.get(), true); 142 143 // Ensure that the initial read did not invalidate the buffer. 144 test_read(reporter, bufferedStream, gAbcs, bufferSize); 145 } 146 147 static void test_buffers(skiatest::Reporter* reporter, size_t bufferSize) { 148 test_incremental_buffering(reporter, bufferSize); 149 test_perfectly_sized_buffer(reporter, bufferSize); 150 test_skipping(reporter, bufferSize); 151 test_read_beyond_buffer(reporter, bufferSize); 152 } 153 154 DEF_TEST(FrontBufferedStream, reporter) { 155 // Test 6 and 64, which are used by Android, as well as another arbitrary length. 156 test_buffers(reporter, 6); 157 test_buffers(reporter, 15); 158 test_buffers(reporter, 64); 159 } 160