Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / url_request / url_request_simple_job_unittest.cc
blob1286977b9cd6037b0b9857eb3620b2f4ee8f591a
1 // Copyright 2014 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/bind_helpers.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/threading/sequenced_worker_pool.h"
10 #include "base/threading/worker_pool.h"
11 #include "net/base/request_priority.h"
12 #include "net/url_request/url_request_job.h"
13 #include "net/url_request/url_request_job_factory.h"
14 #include "net/url_request/url_request_job_factory_impl.h"
15 #include "net/url_request/url_request_simple_job.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace net {
21 namespace {
23 const char kTestData[] = "Huge data array";
24 const int kRangeFirstPosition = 5;
25 const int kRangeLastPosition = 8;
26 static_assert(kRangeFirstPosition > 0 &&
27 kRangeFirstPosition < kRangeLastPosition &&
28 kRangeLastPosition <
29 static_cast<int>(arraysize(kTestData) - 1),
30 "invalid range");
32 class MockSimpleJob : public URLRequestSimpleJob {
33 public:
34 MockSimpleJob(URLRequest* request,
35 NetworkDelegate* network_delegate,
36 scoped_refptr<base::TaskRunner> task_runner,
37 std::string data)
38 : URLRequestSimpleJob(request, network_delegate),
39 data_(data),
40 task_runner_(task_runner) {}
42 protected:
43 // URLRequestSimpleJob implementation:
44 int GetData(std::string* mime_type,
45 std::string* charset,
46 std::string* data,
47 const CompletionCallback& callback) const override {
48 mime_type->assign("text/plain");
49 charset->assign("US-ASCII");
50 data->assign(data_);
51 return OK;
54 base::TaskRunner* GetTaskRunner() const override {
55 return task_runner_.get();
58 private:
59 ~MockSimpleJob() override {}
61 const std::string data_;
63 scoped_refptr<base::TaskRunner> task_runner_;
65 DISALLOW_COPY_AND_ASSIGN(MockSimpleJob);
68 class CancelAfterFirstReadURLRequestDelegate : public TestDelegate {
69 public:
70 CancelAfterFirstReadURLRequestDelegate() : run_loop_(new base::RunLoop) {}
72 ~CancelAfterFirstReadURLRequestDelegate() override {}
74 void OnResponseStarted(URLRequest* request) override {
75 // net::TestDelegate will start the first read.
76 TestDelegate::OnResponseStarted(request);
77 request->Cancel();
78 run_loop_->Quit();
81 void OnReadCompleted(URLRequest* request, int bytes_read) override {
82 // Read should have been cancelled.
83 EXPECT_EQ(-1, bytes_read);
86 void WaitUntilHeadersReceived() const { run_loop_->Run(); }
88 private:
89 scoped_ptr<base::RunLoop> run_loop_;
91 DISALLOW_COPY_AND_ASSIGN(CancelAfterFirstReadURLRequestDelegate);
94 class SimpleJobProtocolHandler :
95 public URLRequestJobFactory::ProtocolHandler {
96 public:
97 SimpleJobProtocolHandler(scoped_refptr<base::TaskRunner> task_runner)
98 : task_runner_(task_runner) {}
99 URLRequestJob* MaybeCreateJob(
100 URLRequest* request,
101 NetworkDelegate* network_delegate) const override {
102 if (request->url().spec() == "data:empty")
103 return new MockSimpleJob(request, network_delegate, task_runner_, "");
104 return new MockSimpleJob(request, network_delegate, task_runner_,
105 kTestData);
108 ~SimpleJobProtocolHandler() override {}
110 private:
111 scoped_refptr<base::TaskRunner> task_runner_;
114 class URLRequestSimpleJobTest : public ::testing::Test {
115 public:
116 URLRequestSimpleJobTest()
117 : worker_pool_(
118 new base::SequencedWorkerPool(1, "URLRequestSimpleJobTest")),
119 task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
120 worker_pool_->GetSequenceToken(),
121 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
122 context_(true) {
123 job_factory_.SetProtocolHandler(
124 "data", make_scoped_ptr(new SimpleJobProtocolHandler(task_runner_)));
125 context_.set_job_factory(&job_factory_);
126 context_.Init();
128 request_ =
129 context_.CreateRequest(GURL("data:test"), DEFAULT_PRIORITY, &delegate_);
132 ~URLRequestSimpleJobTest() override { worker_pool_->Shutdown(); }
134 void StartRequest(const HttpRequestHeaders* headers) {
135 if (headers)
136 request_->SetExtraRequestHeaders(*headers);
137 request_->Start();
139 EXPECT_TRUE(request_->is_pending());
140 base::RunLoop().Run();
141 EXPECT_FALSE(request_->is_pending());
144 void TearDown() override { worker_pool_->Shutdown(); }
146 protected:
147 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
148 scoped_refptr<base::SequencedTaskRunner> task_runner_;
149 TestURLRequestContext context_;
150 URLRequestJobFactoryImpl job_factory_;
151 TestDelegate delegate_;
152 scoped_ptr<URLRequest> request_;
155 } // namespace
157 TEST_F(URLRequestSimpleJobTest, SimpleRequest) {
158 StartRequest(NULL);
159 ASSERT_TRUE(request_->status().is_success());
160 EXPECT_EQ(kTestData, delegate_.data_received());
163 TEST_F(URLRequestSimpleJobTest, RangeRequest) {
164 const std::string kExpectedBody = std::string(
165 kTestData + kRangeFirstPosition, kTestData + kRangeLastPosition + 1);
166 HttpRequestHeaders headers;
167 headers.SetHeader(
168 HttpRequestHeaders::kRange,
169 HttpByteRange::Bounded(kRangeFirstPosition, kRangeLastPosition)
170 .GetHeaderValue());
172 StartRequest(&headers);
174 ASSERT_TRUE(request_->status().is_success());
175 EXPECT_EQ(kExpectedBody, delegate_.data_received());
178 TEST_F(URLRequestSimpleJobTest, MultipleRangeRequest) {
179 HttpRequestHeaders headers;
180 int middle_pos = (kRangeFirstPosition + kRangeLastPosition)/2;
181 std::string range = base::StringPrintf("bytes=%d-%d,%d-%d",
182 kRangeFirstPosition,
183 middle_pos,
184 middle_pos + 1,
185 kRangeLastPosition);
186 headers.SetHeader(HttpRequestHeaders::kRange, range);
188 StartRequest(&headers);
190 EXPECT_TRUE(delegate_.request_failed());
191 EXPECT_EQ(ERR_REQUEST_RANGE_NOT_SATISFIABLE, request_->status().error());
194 TEST_F(URLRequestSimpleJobTest, InvalidRangeRequest) {
195 HttpRequestHeaders headers;
196 std::string range = base::StringPrintf(
197 "bytes=%d-%d", kRangeLastPosition, kRangeFirstPosition);
198 headers.SetHeader(HttpRequestHeaders::kRange, range);
200 StartRequest(&headers);
202 ASSERT_TRUE(request_->status().is_success());
203 EXPECT_EQ(kTestData, delegate_.data_received());
206 TEST_F(URLRequestSimpleJobTest, EmptyDataRequest) {
207 request_ =
208 context_.CreateRequest(GURL("data:empty"), DEFAULT_PRIORITY, &delegate_);
209 StartRequest(nullptr);
210 ASSERT_TRUE(request_->status().is_success());
211 EXPECT_EQ("", delegate_.data_received());
214 TEST_F(URLRequestSimpleJobTest, CancelBeforeResponseStarts) {
215 request_ =
216 context_.CreateRequest(GURL("data:cancel"), DEFAULT_PRIORITY, &delegate_);
217 request_->Start();
218 request_->Cancel();
220 base::RunLoop().RunUntilIdle();
221 EXPECT_EQ(URLRequestStatus::CANCELED, request_->status().status());
222 EXPECT_EQ(1, delegate_.response_started_count());
225 TEST_F(URLRequestSimpleJobTest, CancelAfterFirstReadStarted) {
226 CancelAfterFirstReadURLRequestDelegate cancel_delegate;
227 request_ = context_.CreateRequest(GURL("data:cancel"), DEFAULT_PRIORITY,
228 &cancel_delegate);
229 request_->Start();
230 cancel_delegate.WaitUntilHeadersReceived();
232 // Feed a dummy task to the SequencedTaskRunner to make sure that the
233 // callbacks which are invoked in ReadRawData have completed safely.
234 base::RunLoop run_loop;
235 EXPECT_TRUE(task_runner_->PostTaskAndReply(
236 FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure()));
237 run_loop.Run();
239 EXPECT_EQ(URLRequestStatus::CANCELED, request_->status().status());
240 EXPECT_EQ(1, cancel_delegate.response_started_count());
241 EXPECT_EQ("", cancel_delegate.data_received());
242 // Destroy the request so it doesn't outlive its delegate.
243 request_.reset();
246 } // namespace net