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.
4
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"
12
13namespace content {
14
15class StreamTest : public testing::Test {
16 public:
17  StreamTest() : producing_seed_key_(0) {}
18
19  virtual void SetUp() OVERRIDE {
20    registry_.reset(new StreamRegistry());
21  }
22
23  // Create a new IO buffer of the given |buffer_size| and fill it with random
24  // data.
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_;
31    return buffer;
32  }
33
34 protected:
35  base::MessageLoop message_loop_;
36  scoped_ptr<StreamRegistry> registry_;
37
38 private:
39  int producing_seed_key_;
40};
41
42class TestStreamReader : public StreamReadObserver {
43 public:
44  TestStreamReader() : buffer_(new net::GrowableIOBuffer()) {
45  }
46  virtual ~TestStreamReader() {}
47
48  void Read(Stream* stream) {
49    const size_t kBufferSize = 32768;
50    scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
51
52    int bytes_read = 0;
53    while (stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read) ==
54           Stream::STREAM_HAS_DATA) {
55      size_t old_capacity = buffer_->capacity();
56      buffer_->SetCapacity(old_capacity + bytes_read);
57      memcpy(buffer_->StartOfBuffer() + old_capacity,
58             buffer->data(), bytes_read);
59    }
60  }
61
62  virtual void OnDataAvailable(Stream* stream) OVERRIDE {
63    Read(stream);
64  }
65
66  scoped_refptr<net::GrowableIOBuffer> buffer() { return buffer_; }
67
68 private:
69  scoped_refptr<net::GrowableIOBuffer> buffer_;
70};
71
72class TestStreamWriter : public StreamWriteObserver {
73 public:
74  TestStreamWriter() {}
75  virtual ~TestStreamWriter() {}
76
77  void Write(Stream* stream,
78             scoped_refptr<net::IOBuffer> buffer,
79             size_t buffer_size) {
80    stream->AddData(buffer, buffer_size);
81  }
82
83  virtual void OnSpaceAvailable(Stream* stream) OVERRIDE {
84  }
85
86  virtual void OnClose(Stream* stream) OVERRIDE {
87  }
88};
89
90TEST_F(StreamTest, SetReadObserver) {
91  TestStreamReader reader;
92  TestStreamWriter writer;
93
94  GURL url("blob://stream");
95  scoped_refptr<Stream> stream(
96      new Stream(registry_.get(), &writer, url));
97  EXPECT_TRUE(stream->SetReadObserver(&reader));
98}
99
100TEST_F(StreamTest, SetReadObserver_SecondFails) {
101  TestStreamReader reader1;
102  TestStreamReader reader2;
103  TestStreamWriter writer;
104
105  GURL url("blob://stream");
106  scoped_refptr<Stream> stream(
107      new Stream(registry_.get(), &writer, url));
108  EXPECT_TRUE(stream->SetReadObserver(&reader1));
109  EXPECT_FALSE(stream->SetReadObserver(&reader2));
110}
111
112TEST_F(StreamTest, SetReadObserver_TwoReaders) {
113  TestStreamReader reader1;
114  TestStreamReader reader2;
115  TestStreamWriter writer;
116
117  GURL url("blob://stream");
118  scoped_refptr<Stream> stream(
119      new Stream(registry_.get(), &writer, url));
120  EXPECT_TRUE(stream->SetReadObserver(&reader1));
121
122  // Once the first read observer is removed, a new one can be added.
123  stream->RemoveReadObserver(&reader1);
124  EXPECT_TRUE(stream->SetReadObserver(&reader2));
125}
126
127TEST_F(StreamTest, Stream) {
128  TestStreamReader reader;
129  TestStreamWriter writer;
130
131  GURL url("blob://stream");
132  scoped_refptr<Stream> stream(
133      new Stream(registry_.get(), &writer, url));
134  EXPECT_TRUE(stream->SetReadObserver(&reader));
135
136  const int kBufferSize = 1000000;
137  scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
138  writer.Write(stream.get(), buffer, kBufferSize);
139  stream->Finalize();
140  reader.Read(stream.get());
141  base::MessageLoop::current()->RunUntilIdle();
142
143  ASSERT_EQ(reader.buffer()->capacity(), kBufferSize);
144  for (int i = 0; i < kBufferSize; i++)
145    EXPECT_EQ(buffer->data()[i], reader.buffer()->data()[i]);
146}
147
148TEST_F(StreamTest, GetStream) {
149  TestStreamWriter writer;
150
151  GURL url("blob://stream");
152  scoped_refptr<Stream> stream1(
153      new Stream(registry_.get(), &writer, url));
154
155  scoped_refptr<Stream> stream2 = registry_->GetStream(url);
156  ASSERT_EQ(stream1, stream2);
157}
158
159TEST_F(StreamTest, GetStream_Missing) {
160  TestStreamWriter writer;
161
162  GURL url1("blob://stream");
163  scoped_refptr<Stream> stream1(
164      new Stream(registry_.get(), &writer, url1));
165
166  GURL url2("blob://stream2");
167  scoped_refptr<Stream> stream2 = registry_->GetStream(url2);
168  ASSERT_FALSE(stream2.get());
169}
170
171TEST_F(StreamTest, CloneStream) {
172  TestStreamWriter writer;
173
174  GURL url1("blob://stream");
175  scoped_refptr<Stream> stream1(
176      new Stream(registry_.get(), &writer, url1));
177
178  GURL url2("blob://stream2");
179  ASSERT_TRUE(registry_->CloneStream(url2, url1));
180  scoped_refptr<Stream> stream2 = registry_->GetStream(url2);
181  ASSERT_EQ(stream1, stream2);
182}
183
184TEST_F(StreamTest, CloneStream_Missing) {
185  TestStreamWriter writer;
186
187  GURL url1("blob://stream");
188  scoped_refptr<Stream> stream1(
189      new Stream(registry_.get(), &writer, url1));
190
191  GURL url2("blob://stream2");
192  GURL url3("blob://stream3");
193  ASSERT_FALSE(registry_->CloneStream(url2, url3));
194  scoped_refptr<Stream> stream2 = registry_->GetStream(url2);
195  ASSERT_FALSE(stream2.get());
196}
197
198TEST_F(StreamTest, UnregisterStream) {
199  TestStreamWriter writer;
200
201  GURL url("blob://stream");
202  scoped_refptr<Stream> stream1(
203      new Stream(registry_.get(), &writer, url));
204
205  registry_->UnregisterStream(url);
206  scoped_refptr<Stream> stream2 = registry_->GetStream(url);
207  ASSERT_FALSE(stream2.get());
208}
209
210}  // namespace content
211