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