Chromium Code Reviews| Index: content/browser/android/url_request_content_job_unittest.cc |
| diff --git a/content/browser/android/url_request_content_job_unittest.cc b/content/browser/android/url_request_content_job_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5e0fbffea858b1eb5731af84f99f9f6b4a0e2796 |
| --- /dev/null |
| +++ b/content/browser/android/url_request_content_job_unittest.cc |
| @@ -0,0 +1,198 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/android/url_request_content_job.h" |
| + |
| +#include <algorithm> |
| + |
| +#include "base/files/file_util.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/run_loop.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "base/test/test_file_util.h" |
| +#include "net/url_request/url_request.h" |
| +#include "net/url_request/url_request_test_util.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +// A URLRequestJobFactory that will return URLRequestContentJobWithCallbacks |
| +// instances for content:// scheme URLs. |
| +class CallbacksJobFactory : public net::URLRequestJobFactory { |
| + public: |
| + class JobObserver { |
| + public: |
| + virtual void OnJobCreated(URLRequestContentJob* job) = 0; |
| + }; |
| + |
| + CallbacksJobFactory(const base::FilePath& path, JobObserver* observer) |
| + : path_(path), observer_(observer) { |
| + } |
| + |
| + ~CallbacksJobFactory() override {} |
| + |
| + net::URLRequestJob* MaybeCreateJobWithProtocolHandler( |
| + const std::string& scheme, |
| + net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate) const override { |
| + URLRequestContentJob* job = |
| + new URLRequestContentJob( |
| + request, |
| + network_delegate, |
| + path_, |
| + const_cast<base::MessageLoop*>(&message_loop_)->task_runner()); |
| + observer_->OnJobCreated(job); |
| + return job; |
| + } |
| + |
| + net::URLRequestJob* MaybeInterceptRedirect( |
| + net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate, |
| + const GURL& location) const override { |
| + return nullptr; |
| + } |
| + |
| + net::URLRequestJob* MaybeInterceptResponse( |
| + net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate) const override { |
| + return nullptr; |
| + } |
| + |
| + bool IsHandledProtocol(const std::string& scheme) const override { |
| + return scheme == "content"; |
| + } |
| + |
| + bool IsHandledURL(const GURL& url) const override { |
| + return IsHandledProtocol(url.scheme()); |
| + } |
| + |
| + bool IsSafeRedirectTarget(const GURL& location) const override { |
| + return false; |
| + } |
| + |
| + private: |
| + base::MessageLoop message_loop_; |
| + base::FilePath path_; |
| + JobObserver* observer_; |
| +}; |
| + |
| +class JobObserverImpl : public CallbacksJobFactory::JobObserver { |
| + public: |
| + void OnJobCreated(URLRequestContentJob* job) override { |
| + jobs_.push_back(job); |
| + } |
| + |
| + typedef std::vector<scoped_refptr<URLRequestContentJob> > JobList; |
| + |
| + const JobList& jobs() { return jobs_; } |
| + |
| + protected: |
| + JobList jobs_; |
| +}; |
| + |
| +// A simple holder for start/end used in http range requests. |
| +struct Range { |
| + int start; |
| + int end; |
| + |
| + Range() { |
|
no sievers
2014/11/25 20:50:18
nit: might as well remove this and explicitly run
qinmin
2014/11/25 23:37:02
Done.
|
| + start = 0; |
| + end = 0; |
| + } |
| + |
| + Range(int start, int end) { |
| + this->start = start; |
| + this->end = end; |
| + } |
| +}; |
| + |
| +// A superclass for tests of the OnSeekComplete / OnReadComplete functions of |
| +// URLRequestContentJob. |
| +class URLRequestContentJobTest : public testing::Test { |
| + public: |
| + URLRequestContentJobTest(); |
| + |
| + protected: |
| + // This inserts an image file into the android MediaStore and retrieves the |
| + // content URI. Then creates and runs a URLRequestContentJob to get the |
| + // contents out of it. If a Range is provided, this function will add the |
| + // appropriate Range http header to the request and verify the bytes |
| + // retrieved. |
| + void RunRequest(const Range* range); |
| + |
| + JobObserverImpl observer_; |
| + net::TestURLRequestContext context_; |
| + net::TestDelegate delegate_; |
| +}; |
| + |
| +URLRequestContentJobTest::URLRequestContentJobTest() {} |
| + |
| +void URLRequestContentJobTest::RunRequest(const Range* range) { |
| + base::FilePath test_dir; |
| + PathService::Get(base::DIR_SOURCE_ROOT, &test_dir); |
| + test_dir = test_dir.AppendASCII("content"); |
| + test_dir = test_dir.AppendASCII("test"); |
| + test_dir = test_dir.AppendASCII("data"); |
| + test_dir = test_dir.AppendASCII("android"); |
| + ASSERT_TRUE(base::PathExists(test_dir)); |
| + base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png")); |
| + |
| + // Insert the image into MediaStore. MediaStore will do some conversions, and |
| + // return the content URI. |
| + base::FilePath path = base::InsertImageIntoMediaStore(image_file); |
| + EXPECT_TRUE(path.IsContentUri()); |
| + EXPECT_TRUE(base::PathExists(path)); |
| + int64 file_size; |
| + EXPECT_TRUE(base::GetFileSize(path, &file_size)); |
| + EXPECT_LT(0, file_size); |
| + CallbacksJobFactory factory(path, &observer_); |
| + context_.set_job_factory(&factory); |
| + |
| + scoped_ptr<net::URLRequest> request(context_.CreateRequest( |
| + GURL(path.value()), net::DEFAULT_PRIORITY, &delegate_, NULL)); |
| + int expected_length = file_size; |
| + if (range) { |
| + ASSERT_GE(range->start, 0); |
| + ASSERT_GE(range->end, 0); |
| + ASSERT_LE(range->start, range->end); |
| + std::string range_value = |
| + base::StringPrintf("bytes=%d-%d", range->start, range->end); |
| + request->SetExtraRequestHeaderByName( |
| + net::HttpRequestHeaders::kRange, range_value, true /*overwrite*/); |
| + if (range->start <= file_size) |
| + expected_length = |
| + std::min(range->end, (int) file_size - 1) - range->start + 1; |
|
no sievers
2014/11/25 20:50:18
nit: bad-style cast, you can just do file_size - 1
qinmin
2014/11/25 23:37:02
range->end is an int, so need to cast file_size or
|
| + else |
| + expected_length = 0; |
| + } |
| + request->Start(); |
| + |
| + base::RunLoop loop; |
| + loop.Run(); |
| + |
| + EXPECT_FALSE(delegate_.request_failed()); |
| + ASSERT_EQ(observer_.jobs().size(), 1u); |
| + EXPECT_EQ(delegate_.bytes_received(), expected_length); |
| +} |
| + |
| +TEST_F(URLRequestContentJobTest, ContentURIWithoutRange) { |
| + RunRequest(NULL); |
| +} |
| + |
| +TEST_F(URLRequestContentJobTest, ContentURIWithSmallRange) { |
| + Range range(1, 10); |
| + RunRequest(&range); |
| +} |
| + |
| +TEST_F(URLRequestContentJobTest, ContentURIWithLargeRange) { |
| + Range range(1, 100000); |
| + RunRequest(&range); |
| +} |
| + |
| +} // namespace |
| + |
| +} // namespace content |