1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/message_loop/message_loop.h"
6 #include "base/test/test_simple_task_runner.h"
7 #include "content/browser/streams/stream.h"
8 #include "content/browser/streams/stream_read_observer.h"
9 #include "content/browser/streams/stream_registry.h"
10 #include "content/browser/streams/stream_write_observer.h"
11 #include "testing/gtest/include/gtest/gtest.h"
15 class StreamTest
: public testing::Test
{
17 StreamTest() : producing_seed_key_(0) {}
19 virtual void SetUp() OVERRIDE
{
20 registry_
.reset(new StreamRegistry());
23 // Create a new IO buffer of the given |buffer_size| and fill it with random
25 scoped_refptr
<net::IOBuffer
> NewIOBuffer(size_t buffer_size
) {
26 scoped_refptr
<net::IOBuffer
> buffer(new net::IOBuffer(buffer_size
));
27 char *bufferp
= buffer
->data();
28 for (size_t i
= 0; i
< buffer_size
; i
++)
29 bufferp
[i
] = (i
+ producing_seed_key_
) % (1 << sizeof(char));
30 ++producing_seed_key_
;
35 base::MessageLoop message_loop_
;
36 scoped_ptr
<StreamRegistry
> registry_
;
39 int producing_seed_key_
;
42 class TestStreamReader
: public StreamReadObserver
{
44 TestStreamReader() : buffer_(new net::GrowableIOBuffer()), completed_(false) {
46 virtual ~TestStreamReader() {}
48 void Read(Stream
* stream
) {
49 const size_t kBufferSize
= 32768;
50 scoped_refptr
<net::IOBuffer
> buffer(new net::IOBuffer(kBufferSize
));
54 Stream::StreamState state
=
55 stream
->ReadRawData(buffer
.get(), kBufferSize
, &bytes_read
);
57 case Stream::STREAM_HAS_DATA
:
58 // TODO(tyoshino): Move these expectations to the beginning of Read()
59 // method once Stream::Finalize() is fixed.
60 EXPECT_FALSE(completed_
);
62 case Stream::STREAM_COMPLETE
:
65 case Stream::STREAM_EMPTY
:
66 EXPECT_FALSE(completed_
);
68 case Stream::STREAM_ABORTED
:
69 EXPECT_FALSE(completed_
);
72 size_t old_capacity
= buffer_
->capacity();
73 buffer_
->SetCapacity(old_capacity
+ bytes_read
);
74 memcpy(buffer_
->StartOfBuffer() + old_capacity
,
75 buffer
->data(), bytes_read
);
79 virtual void OnDataAvailable(Stream
* stream
) OVERRIDE
{
83 scoped_refptr
<net::GrowableIOBuffer
> buffer() { return buffer_
; }
85 bool completed() const {
90 scoped_refptr
<net::GrowableIOBuffer
> buffer_
;
94 class TestStreamWriter
: public StreamWriteObserver
{
97 virtual ~TestStreamWriter() {}
99 void Write(Stream
* stream
,
100 scoped_refptr
<net::IOBuffer
> buffer
,
101 size_t buffer_size
) {
102 stream
->AddData(buffer
, buffer_size
);
105 virtual void OnSpaceAvailable(Stream
* stream
) OVERRIDE
{
108 virtual void OnClose(Stream
* stream
) OVERRIDE
{
112 TEST_F(StreamTest
, SetReadObserver
) {
113 TestStreamReader reader
;
114 TestStreamWriter writer
;
116 GURL
url("blob://stream");
117 scoped_refptr
<Stream
> stream(
118 new Stream(registry_
.get(), &writer
, url
));
119 EXPECT_TRUE(stream
->SetReadObserver(&reader
));
122 TEST_F(StreamTest
, SetReadObserver_SecondFails
) {
123 TestStreamReader reader1
;
124 TestStreamReader reader2
;
125 TestStreamWriter writer
;
127 GURL
url("blob://stream");
128 scoped_refptr
<Stream
> stream(
129 new Stream(registry_
.get(), &writer
, url
));
130 EXPECT_TRUE(stream
->SetReadObserver(&reader1
));
131 EXPECT_FALSE(stream
->SetReadObserver(&reader2
));
134 TEST_F(StreamTest
, SetReadObserver_TwoReaders
) {
135 TestStreamReader reader1
;
136 TestStreamReader reader2
;
137 TestStreamWriter writer
;
139 GURL
url("blob://stream");
140 scoped_refptr
<Stream
> stream(
141 new Stream(registry_
.get(), &writer
, url
));
142 EXPECT_TRUE(stream
->SetReadObserver(&reader1
));
144 // Once the first read observer is removed, a new one can be added.
145 stream
->RemoveReadObserver(&reader1
);
146 EXPECT_TRUE(stream
->SetReadObserver(&reader2
));
149 TEST_F(StreamTest
, Stream
) {
150 TestStreamReader reader
;
151 TestStreamWriter writer
;
153 GURL
url("blob://stream");
154 scoped_refptr
<Stream
> stream(
155 new Stream(registry_
.get(), &writer
, url
));
156 EXPECT_TRUE(stream
->SetReadObserver(&reader
));
158 const int kBufferSize
= 1000000;
159 scoped_refptr
<net::IOBuffer
> buffer(NewIOBuffer(kBufferSize
));
160 writer
.Write(stream
.get(), buffer
, kBufferSize
);
162 base::MessageLoop::current()->RunUntilIdle();
163 EXPECT_TRUE(reader
.completed());
165 ASSERT_EQ(reader
.buffer()->capacity(), kBufferSize
);
166 for (int i
= 0; i
< kBufferSize
; i
++)
167 EXPECT_EQ(buffer
->data()[i
], reader
.buffer()->data()[i
]);
170 // Test that even if a reader receives an empty buffer, once TransferData()
171 // method is called on it with |source_complete| = true, following Read() calls
172 // on it never returns STREAM_EMPTY. Together with StreamTest.Stream above, this
173 // guarantees that Reader::Read() call returns only STREAM_HAS_DATA
174 // or STREAM_COMPLETE in |data_available_callback_| call corresponding to
176 TEST_F(StreamTest
, ClosedReaderDoesNotReturnStreamEmpty
) {
177 TestStreamReader reader
;
178 TestStreamWriter writer
;
180 GURL
url("blob://stream");
181 scoped_refptr
<Stream
> stream(
182 new Stream(registry_
.get(), &writer
, url
));
183 EXPECT_TRUE(stream
->SetReadObserver(&reader
));
185 const int kBufferSize
= 0;
186 scoped_refptr
<net::IOBuffer
> buffer(NewIOBuffer(kBufferSize
));
187 stream
->AddData(buffer
, kBufferSize
);
189 base::MessageLoop::current()->RunUntilIdle();
190 EXPECT_TRUE(reader
.completed());
191 EXPECT_EQ(0, reader
.buffer()->capacity());
194 TEST_F(StreamTest
, GetStream
) {
195 TestStreamWriter writer
;
197 GURL
url("blob://stream");
198 scoped_refptr
<Stream
> stream1(
199 new Stream(registry_
.get(), &writer
, url
));
201 scoped_refptr
<Stream
> stream2
= registry_
->GetStream(url
);
202 ASSERT_EQ(stream1
, stream2
);
205 TEST_F(StreamTest
, GetStream_Missing
) {
206 TestStreamWriter writer
;
208 GURL
url1("blob://stream");
209 scoped_refptr
<Stream
> stream1(
210 new Stream(registry_
.get(), &writer
, url1
));
212 GURL
url2("blob://stream2");
213 scoped_refptr
<Stream
> stream2
= registry_
->GetStream(url2
);
214 ASSERT_FALSE(stream2
.get());
217 TEST_F(StreamTest
, CloneStream
) {
218 TestStreamWriter writer
;
220 GURL
url1("blob://stream");
221 scoped_refptr
<Stream
> stream1(
222 new Stream(registry_
.get(), &writer
, url1
));
224 GURL
url2("blob://stream2");
225 ASSERT_TRUE(registry_
->CloneStream(url2
, url1
));
226 scoped_refptr
<Stream
> stream2
= registry_
->GetStream(url2
);
227 ASSERT_EQ(stream1
, stream2
);
230 TEST_F(StreamTest
, CloneStream_Missing
) {
231 TestStreamWriter writer
;
233 GURL
url1("blob://stream");
234 scoped_refptr
<Stream
> stream1(
235 new Stream(registry_
.get(), &writer
, url1
));
237 GURL
url2("blob://stream2");
238 GURL
url3("blob://stream3");
239 ASSERT_FALSE(registry_
->CloneStream(url2
, url3
));
240 scoped_refptr
<Stream
> stream2
= registry_
->GetStream(url2
);
241 ASSERT_FALSE(stream2
.get());
244 TEST_F(StreamTest
, UnregisterStream
) {
245 TestStreamWriter writer
;
247 GURL
url("blob://stream");
248 scoped_refptr
<Stream
> stream1(
249 new Stream(registry_
.get(), &writer
, url
));
251 registry_
->UnregisterStream(url
);
252 scoped_refptr
<Stream
> stream2
= registry_
->GetStream(url
);
253 ASSERT_FALSE(stream2
.get());
256 TEST_F(StreamTest
, MemoryExceedMemoryUsageLimit
) {
257 TestStreamWriter writer1
;
258 TestStreamWriter writer2
;
260 GURL
url1("blob://stream");
261 scoped_refptr
<Stream
> stream1(
262 new Stream(registry_
.get(), &writer1
, url1
));
264 GURL
url2("blob://stream2");
265 scoped_refptr
<Stream
> stream2(
266 new Stream(registry_
.get(), &writer2
, url2
));
268 const int kMaxMemoryUsage
= 1500000;
269 registry_
->set_max_memory_usage_for_testing(kMaxMemoryUsage
);
271 const int kBufferSize
= 1000000;
272 scoped_refptr
<net::IOBuffer
> buffer(NewIOBuffer(kBufferSize
));
273 writer1
.Write(stream1
.get(), buffer
, kBufferSize
);
274 // Make transfer happen.
275 base::MessageLoop::current()->RunUntilIdle();
277 writer2
.Write(stream2
.get(), buffer
, kBufferSize
);
279 // Written data (1000000 * 2) exceeded limit (1500000). |stream2| should be
280 // unregistered with |registry_|.
281 EXPECT_EQ(NULL
, registry_
->GetStream(url2
).get());
283 writer1
.Write(stream1
.get(), buffer
, kMaxMemoryUsage
- kBufferSize
);
284 // Should be accepted since stream2 is unregistered and the new data is not
285 // so big to exceed the limit.
286 EXPECT_FALSE(registry_
->GetStream(url1
).get() == NULL
);
289 TEST_F(StreamTest
, UnderMemoryUsageLimit
) {
290 TestStreamWriter writer
;
291 TestStreamReader reader
;
293 GURL
url("blob://stream");
294 scoped_refptr
<Stream
> stream(new Stream(registry_
.get(), &writer
, url
));
295 EXPECT_TRUE(stream
->SetReadObserver(&reader
));
297 registry_
->set_max_memory_usage_for_testing(1500000);
299 const int kBufferSize
= 1000000;
300 scoped_refptr
<net::IOBuffer
> buffer(NewIOBuffer(kBufferSize
));
301 writer
.Write(stream
.get(), buffer
, kBufferSize
);
303 // Run loop to make |reader| consume the data.
304 base::MessageLoop::current()->RunUntilIdle();
306 writer
.Write(stream
.get(), buffer
, kBufferSize
);
308 EXPECT_EQ(stream
.get(), registry_
->GetStream(url
).get());
311 } // namespace content