• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
test_read(skiatest::Reporter * reporter,SkStream * bufferedStream,const void * expectations,size_t bytesToRead)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 
test_rewind(skiatest::Reporter * reporter,SkStream * bufferedStream,bool shouldSucceed)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.
test_incremental_buffering(skiatest::Reporter * reporter,size_t bufferSize)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 
test_perfectly_sized_buffer(skiatest::Reporter * reporter,size_t bufferSize)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 
test_skipping(skiatest::Reporter * reporter,size_t bufferSize)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:
AndroidLikeMemoryStream(void * data,size_t size,bool ownMemory)109     AndroidLikeMemoryStream(void* data, size_t size, bool ownMemory)
110         : INHERITED(data, size, ownMemory)
111         , fIsAtEnd(false) {}
112 
read(void * dst,size_t requested)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 
isAtEnd() const121     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.
test_read_beyond_buffer(skiatest::Reporter * reporter,size_t bufferSize)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 
test_buffers(skiatest::Reporter * reporter,size_t bufferSize)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 
DEF_TEST(FrontBufferedStream,reporter)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