Index: net/url_request/sdch_dictionary_fetcher_unittest.cc |
diff --git a/net/url_request/sdch_dictionary_fetcher_unittest.cc b/net/url_request/sdch_dictionary_fetcher_unittest.cc |
index eddc06076745003fdcfdb1debe92b123b1d1f582..fecc5adb2cc9089a777bd302e4f600132d569c58 100644 |
--- a/net/url_request/sdch_dictionary_fetcher_unittest.cc |
+++ b/net/url_request/sdch_dictionary_fetcher_unittest.cc |
@@ -21,6 +21,7 @@ |
#include "net/url_request/url_request_data_job.h" |
#include "net/url_request/url_request_filter.h" |
#include "net/url_request/url_request_interceptor.h" |
+#include "net/url_request/url_request_redirect_job.h" |
#include "net/url_request/url_request_test_util.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -29,7 +30,8 @@ namespace net { |
namespace { |
const char kSampleBufferContext[] = "This is a sample buffer."; |
-const char kTestDomain[] = "top.domain.test"; |
+const char kTestDomain1[] = "top.domain.test"; |
+const char kTestDomain2[] = "top2.domain.test"; |
class URLRequestSpecifiedResponseJob : public URLRequestSimpleJob { |
public: |
@@ -82,35 +84,66 @@ class URLRequestSpecifiedResponseJob : public URLRequestSimpleJob { |
DISALLOW_COPY_AND_ASSIGN(URLRequestSpecifiedResponseJob); |
}; |
-class SpecifiedResponseJobInterceptor : public URLRequestInterceptor { |
+// Wrap URLRequestRedirectJob in a destruction callback. |
+class TestURLRequestRedirectJob : public URLRequestRedirectJob { |
public: |
- // A callback to be called whenever a URLRequestSpecifiedResponseJob is |
- // created or destroyed. The first argument will be the change in number of |
- // jobs (i.e. +1 for created, -1 for destroyed). |
- // The second argument will be undefined if the job is being created, |
- // and will contain the load flags passed to the request the |
- // job was created for if the job is being destroyed. |
+ TestURLRequestRedirectJob(URLRequest* request, |
+ NetworkDelegate* network_delegate, |
+ const GURL& redirect_destination, |
+ ResponseCode response_code, |
+ const std::string& redirect_reason, |
+ base::Closure destruction_callback) |
+ : URLRequestRedirectJob(request, |
+ network_delegate, |
+ redirect_destination, |
+ response_code, |
+ redirect_reason), |
+ destruction_callback_(destruction_callback) {} |
+ ~TestURLRequestRedirectJob() override { destruction_callback_.Run(); } |
+ |
+ private: |
+ const base::Closure destruction_callback_; |
+}; |
+ |
+static const char* redirect_signal = "/redirect/"; |
+class SDCHTestRequestInterceptor : public URLRequestInterceptor { |
+ public: |
+ // A callback to be called whenever a URLRequestJob child of this |
+ // interceptor is created or destroyed. The first argument will be the |
+ // change in number of jobs (i.e. +1 for created, -1 for destroyed). |
+ // The second argument will be undefined if the job is being created |
+ // or a redirect job is being destroyed, and (for non-redirect job |
+ // destruction) will contain the load flags passed to the request the |
+ // job was created for. |
typedef base::Callback<void(int outstanding_job_delta, |
int destruction_load_flags)> LifecycleCallback; |
// |*info| will be returned from all child URLRequestSpecifiedResponseJobs. |
// Note that: a) this pointer is shared with the caller, and the caller must |
- // guarantee that |*info| outlives the SpecifiedResponseJobInterceptor, and |
+ // guarantee that |*info| outlives the SDCHTestRequestInterceptor, and |
// b) |*info| is mutable, and changes to should propagate to |
// URLRequestSpecifiedResponseJobs created after any change. |
- SpecifiedResponseJobInterceptor(HttpResponseInfo* http_response_info, |
- const LifecycleCallback& lifecycle_callback) |
+ SDCHTestRequestInterceptor(HttpResponseInfo* http_response_info, |
+ const LifecycleCallback& lifecycle_callback) |
: http_response_info_(http_response_info), |
lifecycle_callback_(lifecycle_callback) { |
DCHECK(!lifecycle_callback_.is_null()); |
} |
- ~SpecifiedResponseJobInterceptor() override {} |
+ ~SDCHTestRequestInterceptor() override {} |
URLRequestJob* MaybeInterceptRequest( |
URLRequest* request, |
NetworkDelegate* network_delegate) const override { |
lifecycle_callback_.Run(1, 0); |
+ std::string path = request->url().path(); |
+ if (path.substr(0, strlen(redirect_signal)) == redirect_signal) { |
+ return new TestURLRequestRedirectJob( |
+ request, network_delegate, GURL(path.substr(strlen(redirect_signal))), |
+ URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "testing", |
+ base::Bind(lifecycle_callback_, -1, 0)); |
+ } |
+ |
return new URLRequestSpecifiedResponseJob( |
request, network_delegate, *http_response_info_, |
base::Bind(lifecycle_callback_, -1)); |
@@ -118,25 +151,45 @@ class SpecifiedResponseJobInterceptor : public URLRequestInterceptor { |
// The caller must ensure that both |*http_response_info| and the |
// callback remain valid for the lifetime of the |
- // SpecifiedResponseJobInterceptor (i.e. until Unregister() is called). |
+ // SDCHTestRequestInterceptor (i.e. until Unregister() is called). |
static void RegisterWithFilter(HttpResponseInfo* http_response_info, |
const LifecycleCallback& lifecycle_callback) { |
- std::unique_ptr<SpecifiedResponseJobInterceptor> interceptor( |
- new SpecifiedResponseJobInterceptor(http_response_info, |
- lifecycle_callback)); |
+ URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
+ "http", kTestDomain1, |
+ std::unique_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
+ http_response_info, lifecycle_callback))); |
URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
- "http", kTestDomain, std::move(interceptor)); |
+ "https", kTestDomain1, |
+ std::unique_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
+ http_response_info, lifecycle_callback))); |
+ |
+ URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
+ "http", kTestDomain2, |
+ std::unique_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
+ http_response_info, lifecycle_callback))); |
+ |
+ URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
+ "https", kTestDomain2, |
+ std::unique_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
+ http_response_info, lifecycle_callback))); |
} |
static void Unregister() { |
- URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", kTestDomain); |
+ URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", |
+ kTestDomain1); |
+ URLRequestFilter::GetInstance()->RemoveHostnameHandler("https", |
+ kTestDomain1); |
+ URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", |
+ kTestDomain2); |
+ URLRequestFilter::GetInstance()->RemoveHostnameHandler("https", |
+ kTestDomain2); |
} |
private: |
HttpResponseInfo* http_response_info_; |
LifecycleCallback lifecycle_callback_; |
- DISALLOW_COPY_AND_ASSIGN(SpecifiedResponseJobInterceptor); |
+ DISALLOW_COPY_AND_ASSIGN(SDCHTestRequestInterceptor); |
}; |
// Local test infrastructure |
@@ -147,17 +200,19 @@ class SpecifiedResponseJobInterceptor : public URLRequestInterceptor { |
// that is called when the class is destroyed. That callback |
// takes as arguemnt the load flags used for the request the |
// job was created for. |
-// * SpecifiedResponseJobInterceptor: This class is a |
-// URLRequestInterceptor that generates the class above. It is constructed |
+// * SDCHTestRequestInterceptor: This class is a |
+// URLRequestInterceptor that generates either the class above or an |
+// instance of URLRequestRedirectJob (if the first component of the path |
+// is "redirect"). It is constructed |
// with a pointer to the (mutable) resposne info that should be |
-// returned from the URLRequestSpecifiedResponseJob children, as well as |
+// returned from constructed URLRequestSpecifiedResponseJobs, as well as |
// a callback that is run when URLRequestSpecifiedResponseJobs are |
// created or destroyed. |
// * SdchDictionaryFetcherTest: This class registers the above interceptor, |
// tracks the number of jobs requested and the subset of those |
// that are still outstanding. It exports an interface to wait until there |
// are no jobs outstanding. It shares an HttpResponseInfo structure |
-// with the SpecifiedResponseJobInterceptor to control the response |
+// with the SDCHTestRequestInterceptor to control the response |
// information returned by the jbos. |
// The standard pattern for tests is to schedule a dictionary fetch, wait |
// for no jobs outstanding, then test that the fetch results are as expected. |
@@ -182,14 +237,14 @@ class SdchDictionaryFetcherTest : public ::testing::Test { |
factory_(this) { |
response_info_to_return_.request_time = base::Time::Now(); |
response_info_to_return_.response_time = base::Time::Now(); |
- SpecifiedResponseJobInterceptor::RegisterWithFilter( |
+ SDCHTestRequestInterceptor::RegisterWithFilter( |
&response_info_to_return_, |
base::Bind(&SdchDictionaryFetcherTest::OnNumberJobsChanged, |
factory_.GetWeakPtr())); |
} |
~SdchDictionaryFetcherTest() override { |
- SpecifiedResponseJobInterceptor::Unregister(); |
+ SDCHTestRequestInterceptor::Unregister(); |
} |
void OnDictionaryFetched(const std::string& dictionary_text, |
@@ -214,7 +269,7 @@ class SdchDictionaryFetcherTest : public ::testing::Test { |
GURL PathToGurl(const char* path) const { |
std::string gurl_string("http://"); |
- gurl_string += kTestDomain; |
+ gurl_string += kTestDomain1; |
gurl_string += "/"; |
gurl_string += path; |
return GURL(gurl_string); |
@@ -434,6 +489,35 @@ TEST_F(SdchDictionaryFetcherTest, CancelAllowsFutureFetches) { |
EXPECT_EQ(2, jobs_requested()); |
} |
+TEST_F(SdchDictionaryFetcherTest, Redirect) { |
+ GURL dictionary_url(PathToGurl("dictionary")); |
+ GURL local_redirect_url(dictionary_url.GetWithEmptyPath().spec() + |
+ "redirect/" + dictionary_url.spec()); |
+ EXPECT_TRUE(fetcher()->Schedule(local_redirect_url, GetDefaultCallback())); |
+ WaitForNoJobs(); |
+ |
+ // The redirect should have been rejected with no dictionary added. |
+ EXPECT_EQ(1, jobs_requested()); |
+ std::vector<DictionaryAdditions> additions; |
+ GetDictionaryAdditions(&additions); |
+ EXPECT_EQ(0u, additions.size()); |
+ |
+ // Simple SDCH dictionary fetch test, to make sure the fetcher was left |
+ // in reasonable shape by the above. |
+ |
+ GURL dictionary2_url(PathToGurl("dictionary2")); |
+ fetcher()->Schedule(dictionary2_url, GetDefaultCallback()); |
+ WaitForNoJobs(); |
+ |
+ EXPECT_EQ(2, jobs_requested()); |
+ GetDictionaryAdditions(&additions); |
+ ASSERT_EQ(1u, additions.size()); |
+ EXPECT_EQ( |
+ URLRequestSpecifiedResponseJob::ExpectedResponseForURL(dictionary2_url), |
+ additions[0].dictionary_text); |
+ EXPECT_FALSE(last_load_flags_seen() & LOAD_ONLY_FROM_CACHE); |
+} |
+ |
} // namespace |
} // namespace net |