Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / android / url_request_content_job_unittest.cc
blob028a864968a5541d55fc89da1704b632f6e2c209
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 "content/browser/android/url_request_content_job.h"
7 #include <algorithm>
9 #include "base/files/file_util.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/test/test_file_util.h"
14 #include "net/url_request/url_request.h"
15 #include "net/url_request/url_request_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
19 namespace content {
21 namespace {
23 // A URLRequestJobFactory that will return URLRequestContentJobWithCallbacks
24 // instances for content:// scheme URLs.
25 class CallbacksJobFactory : public net::URLRequestJobFactory {
26 public:
27 class JobObserver {
28 public:
29 virtual void OnJobCreated(URLRequestContentJob* job) = 0;
32 CallbacksJobFactory(const base::FilePath& path, JobObserver* observer)
33 : path_(path), observer_(observer) {
36 ~CallbacksJobFactory() override {}
38 net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
39 const std::string& scheme,
40 net::URLRequest* request,
41 net::NetworkDelegate* network_delegate) const override {
42 URLRequestContentJob* job =
43 new URLRequestContentJob(
44 request,
45 network_delegate,
46 path_,
47 const_cast<base::MessageLoop*>(&message_loop_)->task_runner());
48 observer_->OnJobCreated(job);
49 return job;
52 net::URLRequestJob* MaybeInterceptRedirect(
53 net::URLRequest* request,
54 net::NetworkDelegate* network_delegate,
55 const GURL& location) const override {
56 return nullptr;
59 net::URLRequestJob* MaybeInterceptResponse(
60 net::URLRequest* request,
61 net::NetworkDelegate* network_delegate) const override {
62 return nullptr;
65 bool IsHandledProtocol(const std::string& scheme) const override {
66 return scheme == "content";
69 bool IsHandledURL(const GURL& url) const override {
70 return IsHandledProtocol(url.scheme());
73 bool IsSafeRedirectTarget(const GURL& location) const override {
74 return false;
77 private:
78 base::MessageLoop message_loop_;
79 base::FilePath path_;
80 JobObserver* observer_;
83 class JobObserverImpl : public CallbacksJobFactory::JobObserver {
84 public:
85 void OnJobCreated(URLRequestContentJob* job) override {
86 jobs_.push_back(job);
89 typedef std::vector<scoped_refptr<URLRequestContentJob> > JobList;
91 const JobList& jobs() { return jobs_; }
93 protected:
94 JobList jobs_;
97 // A simple holder for start/end used in http range requests.
98 struct Range {
99 int start;
100 int end;
102 explicit Range(int start, int end) {
103 this->start = start;
104 this->end = end;
108 // A superclass for tests of the OnSeekComplete / OnReadComplete functions of
109 // URLRequestContentJob.
110 class URLRequestContentJobTest : public testing::Test {
111 public:
112 URLRequestContentJobTest();
114 protected:
115 // This inserts an image file into the android MediaStore and retrieves the
116 // content URI. Then creates and runs a URLRequestContentJob to get the
117 // contents out of it. If a Range is provided, this function will add the
118 // appropriate Range http header to the request and verify the bytes
119 // retrieved.
120 void RunRequest(const Range* range);
122 JobObserverImpl observer_;
123 net::TestURLRequestContext context_;
124 net::TestDelegate delegate_;
127 URLRequestContentJobTest::URLRequestContentJobTest() {}
129 void URLRequestContentJobTest::RunRequest(const Range* range) {
130 base::FilePath test_dir;
131 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
132 test_dir = test_dir.AppendASCII("content");
133 test_dir = test_dir.AppendASCII("test");
134 test_dir = test_dir.AppendASCII("data");
135 test_dir = test_dir.AppendASCII("android");
136 ASSERT_TRUE(base::PathExists(test_dir));
137 base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png"));
139 // Insert the image into MediaStore. MediaStore will do some conversions, and
140 // return the content URI.
141 base::FilePath path = base::InsertImageIntoMediaStore(image_file);
142 EXPECT_TRUE(path.IsContentUri());
143 EXPECT_TRUE(base::PathExists(path));
144 int64 file_size;
145 EXPECT_TRUE(base::GetFileSize(path, &file_size));
146 EXPECT_LT(0, file_size);
147 CallbacksJobFactory factory(path, &observer_);
148 context_.set_job_factory(&factory);
150 scoped_ptr<net::URLRequest> request(context_.CreateRequest(
151 GURL(path.value()), net::DEFAULT_PRIORITY, &delegate_));
152 int expected_length = file_size;
153 if (range) {
154 ASSERT_GE(range->start, 0);
155 ASSERT_GE(range->end, 0);
156 ASSERT_LE(range->start, range->end);
157 std::string range_value =
158 base::StringPrintf("bytes=%d-%d", range->start, range->end);
159 request->SetExtraRequestHeaderByName(
160 net::HttpRequestHeaders::kRange, range_value, true /*overwrite*/);
161 if (range->start <= file_size)
162 expected_length =
163 std::min(range->end, (int) (file_size - 1)) - range->start + 1;
164 else
165 expected_length = 0;
167 request->Start();
169 base::RunLoop loop;
170 loop.Run();
172 EXPECT_FALSE(delegate_.request_failed());
173 ASSERT_EQ(observer_.jobs().size(), 1u);
174 EXPECT_EQ(delegate_.bytes_received(), expected_length);
177 TEST_F(URLRequestContentJobTest, ContentURIWithoutRange) {
178 RunRequest(NULL);
181 TEST_F(URLRequestContentJobTest, ContentURIWithSmallRange) {
182 Range range(1, 10);
183 RunRequest(&range);
186 TEST_F(URLRequestContentJobTest, ContentURIWithLargeRange) {
187 Range range(1, 100000);
188 RunRequest(&range);
191 TEST_F(URLRequestContentJobTest, ContentURIWithZeroRange) {
192 Range range(0, 0);
193 RunRequest(&range);
196 } // namespace
198 } // namespace content