OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkFrontBufferedStream.h" | 8 #include "SkFrontBufferedStream.h" |
9 #include "SkRefCnt.h" | 9 #include "SkRefCnt.h" |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
11 #include "SkTypes.h" | 11 #include "SkTypes.h" |
12 #include "Test.h" | 12 #include "Test.h" |
13 | 13 |
14 static void test_read(skiatest::Reporter* reporter, SkStream* bufferedStream, | 14 static void test_read(skiatest::Reporter* reporter, SkStream* bufferedStream, |
15 const void* expectations, size_t bytesToRead) { | 15 const void* expectations, size_t bytesToRead) { |
16 // output for reading bufferedStream. | 16 // output for reading bufferedStream. |
17 SkAutoMalloc storage(bytesToRead); | 17 SkAutoMalloc storage(bytesToRead); |
18 | 18 |
19 size_t bytesRead = bufferedStream->read(storage.get(), bytesToRead); | 19 const size_t bytesRead = bufferedStream->read(storage.get(), bytesToRead); |
20 REPORTER_ASSERT(reporter, bytesRead == bytesToRead || bufferedStream->isAtEn
d()); | 20 REPORTER_ASSERT(reporter, bytesRead == bytesToRead || bufferedStream->isAtEn
d()); |
21 REPORTER_ASSERT(reporter, memcmp(storage.get(), expectations, bytesRead) ==
0); | 21 REPORTER_ASSERT(reporter, memcmp(storage.get(), expectations, bytesRead) ==
0); |
22 } | 22 } |
23 | 23 |
24 static void test_rewind(skiatest::Reporter* reporter, | 24 static void test_rewind(skiatest::Reporter* reporter, |
25 SkStream* bufferedStream, bool shouldSucceed) { | 25 SkStream* bufferedStream, bool shouldSucceed) { |
26 const bool success = bufferedStream->rewind(); | 26 const bool success = bufferedStream->rewind(); |
27 REPORTER_ASSERT(reporter, success == shouldSucceed); | 27 REPORTER_ASSERT(reporter, success == shouldSucceed); |
28 } | 28 } |
29 | 29 |
| 30 // Test that hasLength() returns the correct value, based on the stream |
| 31 // being wrapped. A length can only be known if the wrapped stream has a |
| 32 // length and it has a position (so its initial position can be taken into |
| 33 // account when computing the length). |
| 34 static void test_hasLength(skiatest::Reporter* reporter, |
| 35 const SkStream& bufferedStream, |
| 36 const SkStream& streamBeingBuffered) { |
| 37 if (streamBeingBuffered.hasLength() && streamBeingBuffered.hasPosition()) { |
| 38 REPORTER_ASSERT(reporter, bufferedStream.hasLength()); |
| 39 } else { |
| 40 REPORTER_ASSERT(reporter, !bufferedStream.hasLength()); |
| 41 } |
| 42 } |
| 43 |
30 // All tests will buffer this string, and compare output to the original. | 44 // All tests will buffer this string, and compare output to the original. |
31 // The string is long to ensure that all of our lengths being tested are | 45 // The string is long to ensure that all of our lengths being tested are |
32 // smaller than the string length. | 46 // smaller than the string length. |
33 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
ghijklmnopqrstuvwx"; | 47 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef
ghijklmnopqrstuvwx"; |
34 | 48 |
35 // Tests reading the stream across boundaries of what has been buffered so far a
nd what | 49 // Tests reading the stream across boundaries of what has been buffered so far a
nd what |
36 // the total buffer size is. | 50 // the total buffer size is. |
37 static void test_incremental_buffering(skiatest::Reporter* reporter, size_t buff
erSize) { | 51 static void test_incremental_buffering(skiatest::Reporter* reporter, size_t buff
erSize) { |
38 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); | 52 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); |
39 | 53 |
40 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); | 54 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); |
| 55 test_hasLength(reporter, *bufferedStream.get(), memStream); |
41 | 56 |
42 // First, test reading less than the max buffer size. | 57 // First, test reading less than the max buffer size. |
43 test_read(reporter, bufferedStream, gAbcs, bufferSize / 2); | 58 test_read(reporter, bufferedStream, gAbcs, bufferSize / 2); |
44 | 59 |
45 // Now test rewinding back to the beginning and reading less than what was | 60 // Now test rewinding back to the beginning and reading less than what was |
46 // already buffered. | 61 // already buffered. |
47 test_rewind(reporter, bufferedStream, true); | 62 test_rewind(reporter, bufferedStream, true); |
48 test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); | 63 test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); |
49 | 64 |
50 // Now test reading part of what was buffered, and buffering new data. | 65 // Now test reading part of what was buffered, and buffering new data. |
51 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), b
ufferSize / 2); | 66 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), b
ufferSize / 2); |
52 | 67 |
53 // Now test reading what was buffered, buffering new data, and | 68 // Now test reading what was buffered, buffering new data, and |
54 // reading directly from the stream. | 69 // reading directly from the stream. |
55 test_rewind(reporter, bufferedStream, true); | 70 test_rewind(reporter, bufferedStream, true); |
56 test_read(reporter, bufferedStream, gAbcs, bufferSize << 1); | 71 test_read(reporter, bufferedStream, gAbcs, bufferSize << 1); |
57 | 72 |
58 // We have reached the end of the buffer, so rewinding will fail. | 73 // We have reached the end of the buffer, so rewinding will fail. |
59 // This test assumes that the stream is larger than the buffer; otherwise th
e | 74 // This test assumes that the stream is larger than the buffer; otherwise th
e |
60 // result of rewind should be true. | 75 // result of rewind should be true. |
61 test_rewind(reporter, bufferedStream, false); | 76 test_rewind(reporter, bufferedStream, false); |
62 } | 77 } |
63 | 78 |
64 static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t buf
ferSize) { | 79 static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t buf
ferSize) { |
65 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); | 80 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); |
66 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); | 81 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); |
| 82 test_hasLength(reporter, *bufferedStream.get(), memStream); |
67 | 83 |
68 // Read exactly the amount that fits in the buffer. | 84 // Read exactly the amount that fits in the buffer. |
69 test_read(reporter, bufferedStream, gAbcs, bufferSize); | 85 test_read(reporter, bufferedStream, gAbcs, bufferSize); |
70 | 86 |
71 // Rewinding should succeed. | 87 // Rewinding should succeed. |
72 test_rewind(reporter, bufferedStream, true); | 88 test_rewind(reporter, bufferedStream, true); |
73 | 89 |
74 // Once again reading buffered info should succeed | 90 // Once again reading buffered info should succeed |
75 test_read(reporter, bufferedStream, gAbcs, bufferSize); | 91 test_read(reporter, bufferedStream, gAbcs, bufferSize); |
76 | 92 |
77 // Read past the size of the buffer. At this point, we cannot return. | 93 // Read past the size of the buffer. At this point, we cannot return. |
78 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1
); | 94 test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1
); |
79 test_rewind(reporter, bufferedStream, false); | 95 test_rewind(reporter, bufferedStream, false); |
80 } | 96 } |
81 | 97 |
82 static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) { | 98 static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) { |
83 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); | 99 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); |
84 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); | 100 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); |
| 101 test_hasLength(reporter, *bufferedStream.get(), memStream); |
85 | 102 |
86 // Skip half the buffer. | 103 // Skip half the buffer. |
87 bufferedStream->skip(bufferSize / 2); | 104 bufferedStream->skip(bufferSize / 2); |
88 | 105 |
89 // Rewind, then read part of the buffer, which should have been read. | 106 // Rewind, then read part of the buffer, which should have been read. |
90 test_rewind(reporter, bufferedStream, true); | 107 test_rewind(reporter, bufferedStream, true); |
91 test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); | 108 test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); |
92 | 109 |
93 // Now skip beyond the buffered piece, but still within the total buffer. | 110 // Now skip beyond the buffered piece, but still within the total buffer. |
94 bufferedStream->skip(bufferSize / 2); | 111 bufferedStream->skip(bufferSize / 2); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 }; | 144 }; |
128 | 145 |
129 // This test ensures that buffering the exact length of the stream and attemptin
g to read beyond it | 146 // This test ensures that buffering the exact length of the stream and attemptin
g to read beyond it |
130 // does not invalidate the buffer. | 147 // does not invalidate the buffer. |
131 static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferS
ize) { | 148 static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferS
ize) { |
132 // Use a stream that behaves like Android's stream. | 149 // Use a stream that behaves like Android's stream. |
133 AndroidLikeMemoryStream memStream((void*)gAbcs, bufferSize, false); | 150 AndroidLikeMemoryStream memStream((void*)gAbcs, bufferSize, false); |
134 | 151 |
135 // Create a buffer that matches the length of the stream. | 152 // Create a buffer that matches the length of the stream. |
136 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); | 153 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); |
| 154 test_hasLength(reporter, *bufferedStream.get(), memStream); |
137 | 155 |
138 // Attempt to read one more than the bufferSize | 156 // Attempt to read one more than the bufferSize |
139 test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1); | 157 test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1); |
140 test_rewind(reporter, bufferedStream.get(), true); | 158 test_rewind(reporter, bufferedStream.get(), true); |
141 | 159 |
142 // Ensure that the initial read did not invalidate the buffer. | 160 // Ensure that the initial read did not invalidate the buffer. |
143 test_read(reporter, bufferedStream, gAbcs, bufferSize); | 161 test_read(reporter, bufferedStream, gAbcs, bufferSize); |
144 } | 162 } |
145 | 163 |
| 164 // Dummy stream that optionally has a length and/or position. Tests that FrontBu
fferedStream's |
| 165 // length depends on the stream it's buffering having a length and position. |
| 166 class LengthOptionalStream : public SkStream { |
| 167 public: |
| 168 LengthOptionalStream(bool hasLength, bool hasPosition) |
| 169 : fHasLength(hasLength) |
| 170 , fHasPosition(hasPosition) |
| 171 {} |
| 172 |
| 173 virtual bool hasLength() const SK_OVERRIDE { |
| 174 return fHasLength; |
| 175 } |
| 176 |
| 177 virtual bool hasPosition() const SK_OVERRIDE { |
| 178 return fHasPosition; |
| 179 } |
| 180 |
| 181 virtual size_t read(void*, size_t) SK_OVERRIDE { |
| 182 return 0; |
| 183 } |
| 184 |
| 185 virtual bool isAtEnd() const SK_OVERRIDE { |
| 186 return true; |
| 187 } |
| 188 |
| 189 private: |
| 190 const bool fHasLength; |
| 191 const bool fHasPosition; |
| 192 }; |
| 193 |
| 194 // Test all possible combinations of the wrapped stream having a length and a po
sition. |
| 195 static void test_length_combos(skiatest::Reporter* reporter, size_t bufferSize)
{ |
| 196 for (int hasLen = 0; hasLen <= 1; hasLen++) { |
| 197 for (int hasPos = 0; hasPos <= 1; hasPos++) { |
| 198 LengthOptionalStream stream((bool) hasLen, (bool) hasPos); |
| 199 SkAutoTUnref<SkStream> buffered(SkFrontBufferedStream::Create(&strea
m, bufferSize)); |
| 200 test_hasLength(reporter, *buffered.get(), stream); |
| 201 } |
| 202 } |
| 203 } |
| 204 |
| 205 // Test using a stream with an initial offset. |
| 206 static void test_initial_offset(skiatest::Reporter* reporter, size_t bufferSize)
{ |
| 207 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); |
| 208 |
| 209 // Skip a few characters into the memStream, so that bufferedStream represen
ts an offset into |
| 210 // the stream it wraps. |
| 211 const size_t arbitraryOffset = 17; |
| 212 memStream.skip(arbitraryOffset); |
| 213 SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStre
am, bufferSize)); |
| 214 |
| 215 // Since SkMemoryStream has a length and a position, bufferedStream must als
o. |
| 216 REPORTER_ASSERT(reporter, bufferedStream->hasLength()); |
| 217 |
| 218 const size_t amountToRead = 10; |
| 219 const size_t bufferedLength = bufferedStream->getLength(); |
| 220 size_t currentPosition = bufferedStream->getPosition(); |
| 221 REPORTER_ASSERT(reporter, 0 == currentPosition); |
| 222 |
| 223 // Read the stream in chunks. After each read, the position must match curre
ntPosition, |
| 224 // which sums the amount attempted to read, unless the end of the stream has
been reached. |
| 225 // Importantly, the end should not have been reached until currentPosition =
= bufferedLength. |
| 226 while (currentPosition < bufferedLength) { |
| 227 REPORTER_ASSERT(reporter, !bufferedStream->isAtEnd()); |
| 228 test_read(reporter, bufferedStream, gAbcs + arbitraryOffset + currentPos
ition, |
| 229 amountToRead); |
| 230 currentPosition = SkTMin(currentPosition + amountToRead, bufferedLength)
; |
| 231 REPORTER_ASSERT(reporter, bufferedStream->getPosition() == currentPositi
on); |
| 232 } |
| 233 REPORTER_ASSERT(reporter, bufferedStream->isAtEnd()); |
| 234 REPORTER_ASSERT(reporter, bufferedLength == currentPosition); |
| 235 } |
| 236 |
146 static void test_buffers(skiatest::Reporter* reporter, size_t bufferSize) { | 237 static void test_buffers(skiatest::Reporter* reporter, size_t bufferSize) { |
147 test_incremental_buffering(reporter, bufferSize); | 238 test_incremental_buffering(reporter, bufferSize); |
148 test_perfectly_sized_buffer(reporter, bufferSize); | 239 test_perfectly_sized_buffer(reporter, bufferSize); |
149 test_skipping(reporter, bufferSize); | 240 test_skipping(reporter, bufferSize); |
150 test_read_beyond_buffer(reporter, bufferSize); | 241 test_read_beyond_buffer(reporter, bufferSize); |
| 242 test_length_combos(reporter, bufferSize); |
| 243 test_initial_offset(reporter, bufferSize); |
151 } | 244 } |
152 | 245 |
153 DEF_TEST(FrontBufferedStream, reporter) { | 246 DEF_TEST(FrontBufferedStream, reporter) { |
154 // Test 6 and 64, which are used by Android, as well as another arbitrary le
ngth. | 247 // Test 6 and 64, which are used by Android, as well as another arbitrary le
ngth. |
155 test_buffers(reporter, 6); | 248 test_buffers(reporter, 6); |
156 test_buffers(reporter, 15); | 249 test_buffers(reporter, 15); |
157 test_buffers(reporter, 64); | 250 test_buffers(reporter, 64); |
158 } | 251 } |
OLD | NEW |