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