blob: 3693fa5536a19117db699e5d5edde71f61c0da04 [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
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +00008#include "Test.h"
9#include "TestClassDef.h"
scroggo@google.com83fd2c72013-09-26 21:35:39 +000010#include "SkFrontBufferedStream.h"
11#include "SkRefCnt.h"
scroggo@google.com09a53832013-11-12 20:53:05 +000012#include "SkStream.h"
scroggo@google.com83fd2c72013-09-26 21:35:39 +000013#include "SkTypes.h"
scroggo@google.com83fd2c72013-09-26 21:35:39 +000014
15static 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
25static 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.
34const 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.
38static 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
65static 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
83static 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.
107class AndroidLikeMemoryStream : public SkMemoryStream {
108public:
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
125private:
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.
132static 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
147static 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
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000154DEF_TEST(FrontBufferedStream, reporter) {
scroggo@google.com83fd2c72013-09-26 21:35:39 +0000155 // 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}