1// Copyright (c) 2012 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_registry.h"
9#include "content/browser/streams/stream_url_request_job.h"
10#include "content/browser/streams/stream_write_observer.h"
11#include "net/base/request_priority.h"
12#include "net/http/http_byte_range.h"
13#include "net/http/http_response_headers.h"
14#include "net/url_request/url_request.h"
15#include "net/url_request/url_request_context.h"
16#include "net/url_request/url_request_job_factory_impl.h"
17#include "net/url_request/url_request_test_util.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20namespace content {
21
22namespace {
23
24const int kBufferSize = 1024;
25const char kTestData1[] = "Hello";
26const char kTestData2[] = "Here it is data.";
27
28const GURL kStreamURL("blob://stream");
29
30}  // namespace
31
32class StreamURLRequestJobTest : public testing::Test {
33 public:
34  // A simple ProtocolHandler implementation to create StreamURLRequestJob.
35  class MockProtocolHandler :
36      public net::URLRequestJobFactory::ProtocolHandler {
37   public:
38    MockProtocolHandler(StreamRegistry* registry) : registry_(registry) {}
39
40    // net::URLRequestJobFactory::ProtocolHandler override.
41    virtual net::URLRequestJob* MaybeCreateJob(
42        net::URLRequest* request,
43        net::NetworkDelegate* network_delegate) const OVERRIDE {
44      scoped_refptr<Stream> stream = registry_->GetStream(request->url());
45      if (stream.get())
46        return new StreamURLRequestJob(request, network_delegate, stream);
47      return NULL;
48    }
49
50   private:
51    StreamRegistry* registry_;
52  };
53
54  StreamURLRequestJobTest() {}
55
56  virtual void SetUp() {
57    registry_.reset(new StreamRegistry());
58
59    url_request_job_factory_.SetProtocolHandler(
60        "blob", new MockProtocolHandler(registry_.get()));
61    url_request_context_.set_job_factory(&url_request_job_factory_);
62  }
63
64  virtual void TearDown() {
65  }
66
67  void TestSuccessRequest(const GURL& url,
68                          const std::string& expected_response) {
69    TestRequest("GET", url, net::HttpRequestHeaders(), 200, expected_response);
70  }
71
72  void TestRequest(const std::string& method,
73                   const GURL& url,
74                   const net::HttpRequestHeaders& extra_headers,
75                   int expected_status_code,
76                   const std::string& expected_response) {
77    net::TestDelegate delegate;
78    request_ = url_request_context_.CreateRequest(
79        url, net::DEFAULT_PRIORITY, &delegate, NULL);
80    request_->set_method(method);
81    if (!extra_headers.IsEmpty())
82      request_->SetExtraRequestHeaders(extra_headers);
83    request_->Start();
84
85    base::MessageLoop::current()->RunUntilIdle();
86
87    // Verify response.
88    EXPECT_TRUE(request_->status().is_success());
89    ASSERT_TRUE(request_->response_headers());
90    EXPECT_EQ(expected_status_code,
91              request_->response_headers()->response_code());
92    EXPECT_EQ(expected_response, delegate.data_received());
93  }
94
95 protected:
96  base::MessageLoopForIO message_loop_;
97  scoped_ptr<StreamRegistry> registry_;
98
99  net::URLRequestContext url_request_context_;
100  net::URLRequestJobFactoryImpl url_request_job_factory_;
101  scoped_ptr<net::URLRequest> request_;
102};
103
104TEST_F(StreamURLRequestJobTest, TestGetSimpleDataRequest) {
105  scoped_refptr<Stream> stream(
106      new Stream(registry_.get(), NULL, kStreamURL));
107
108  scoped_refptr<net::StringIOBuffer> buffer(
109      new net::StringIOBuffer(kTestData1));
110
111  stream->AddData(buffer, buffer->size());
112  stream->Finalize();
113
114  TestSuccessRequest(kStreamURL, kTestData1);
115}
116
117TEST_F(StreamURLRequestJobTest, TestGetLargeStreamRequest) {
118  scoped_refptr<Stream> stream(
119      new Stream(registry_.get(), NULL, kStreamURL));
120
121  std::string large_data;
122  large_data.reserve(kBufferSize * 5);
123  for (int i = 0; i < kBufferSize * 5; ++i)
124    large_data.append(1, static_cast<char>(i % 256));
125
126  scoped_refptr<net::StringIOBuffer> buffer(
127      new net::StringIOBuffer(large_data));
128
129  stream->AddData(buffer, buffer->size());
130  stream->Finalize();
131  TestSuccessRequest(kStreamURL, large_data);
132}
133
134TEST_F(StreamURLRequestJobTest, TestGetNonExistentStreamRequest) {
135  net::TestDelegate delegate;
136  request_ = url_request_context_.CreateRequest(
137      kStreamURL, net::DEFAULT_PRIORITY, &delegate, NULL);
138  request_->set_method("GET");
139  request_->Start();
140
141  base::MessageLoop::current()->RunUntilIdle();
142
143  // Verify response.
144  EXPECT_FALSE(request_->status().is_success());
145}
146
147TEST_F(StreamURLRequestJobTest, TestRangeDataRequest) {
148  scoped_refptr<Stream> stream(
149      new Stream(registry_.get(), NULL, kStreamURL));
150
151  scoped_refptr<net::StringIOBuffer> buffer(
152      new net::StringIOBuffer(kTestData2));
153
154  stream->AddData(buffer, buffer->size());
155  stream->Finalize();
156
157  net::HttpRequestHeaders extra_headers;
158  extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
159                          net::HttpByteRange::Bounded(0, 3).GetHeaderValue());
160  TestRequest("GET", kStreamURL, extra_headers,
161              200, std::string(kTestData2, 4));
162}
163
164TEST_F(StreamURLRequestJobTest, TestInvalidRangeDataRequest) {
165  scoped_refptr<Stream> stream(
166      new Stream(registry_.get(), NULL, kStreamURL));
167
168  scoped_refptr<net::StringIOBuffer> buffer(
169      new net::StringIOBuffer(kTestData2));
170
171  stream->AddData(buffer, buffer->size());
172  stream->Finalize();
173
174  net::HttpRequestHeaders extra_headers;
175  extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
176                          net::HttpByteRange::Bounded(1, 3).GetHeaderValue());
177  TestRequest("GET", kStreamURL, extra_headers, 405, std::string());
178}
179
180}  // namespace content
181