1 // Copyright 2015 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 "google_apis/gcm/engine/gcm_request_test_base.h"
6
7 #include <cmath>
8
9 #include "base/strings/string_tokenizer.h"
10 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
11 #include "services/network/test/test_url_loader_factory.h"
12 #include "services/network/test/test_utils.h"
13
14 namespace {
15
16 // Backoff policy for testing registration request.
17 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
18 // Number of initial errors (in sequence) to ignore before applying
19 // exponential back-off rules.
20 0,
21
22 // Initial delay for exponential back-off in ms.
23 15000, // 15 seconds.
24
25 // Factor by which the waiting time will be multiplied.
26 2,
27
28 // Fuzzing percentage. ex: 10% will spread requests randomly
29 // between 90%-100% of the calculated time.
30 0.5, // 50%.
31
32 // Maximum amount of time we are willing to delay our request in ms.
33 1000 * 60 * 5, // 5 minutes.
34
35 // Time to keep an entry from being discarded even when it
36 // has no significant state, -1 to never discard.
37 -1,
38
39 // Don't use initial delay unless the last request was an error.
40 false,
41 };
42
PendingForURL(network::TestURLLoaderFactory * factory,const std::string & url)43 const network::TestURLLoaderFactory::PendingRequest* PendingForURL(
44 network::TestURLLoaderFactory* factory,
45 const std::string& url) {
46 GURL gurl(url);
47 std::vector<network::TestURLLoaderFactory::PendingRequest>* pending =
48 factory->pending_requests();
49 for (const auto& pending_request : *pending) {
50 if (pending_request.request.url == gurl)
51 return &pending_request;
52 }
53 return nullptr;
54 }
55
56 } // namespace
57
58 namespace gcm {
59
GCMRequestTestBase()60 GCMRequestTestBase::GCMRequestTestBase()
61 : shared_factory_(
62 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
63 &test_url_loader_factory_)),
64 retry_count_(0) {}
65
~GCMRequestTestBase()66 GCMRequestTestBase::~GCMRequestTestBase() {
67 }
68
GetBackoffPolicy() const69 const net::BackoffEntry::Policy& GCMRequestTestBase::GetBackoffPolicy() const {
70 return kDefaultBackoffPolicy;
71 }
72
OnAboutToCompleteFetch()73 void GCMRequestTestBase::OnAboutToCompleteFetch() {}
74
SetResponseForURLAndComplete(const std::string & url,net::HttpStatusCode status_code,const std::string & response_body,int net_error_code)75 void GCMRequestTestBase::SetResponseForURLAndComplete(
76 const std::string& url,
77 net::HttpStatusCode status_code,
78 const std::string& response_body,
79 int net_error_code) {
80 if (retry_count_++)
81 FastForwardToTriggerNextRetry();
82
83 OnAboutToCompleteFetch();
84 EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest(
85 GURL(url), network::URLLoaderCompletionStatus(net_error_code),
86 network::CreateURLResponseHead(status_code), response_body));
87 }
88
GetExtraHeadersForURL(const std::string & url)89 const net::HttpRequestHeaders* GCMRequestTestBase::GetExtraHeadersForURL(
90 const std::string& url) {
91 const network::TestURLLoaderFactory::PendingRequest* pending_request =
92 PendingForURL(&test_url_loader_factory_, url);
93 return pending_request ? &pending_request->request.headers : nullptr;
94 }
95
GetUploadDataForURL(const std::string & url,std::string * data_out)96 bool GCMRequestTestBase::GetUploadDataForURL(const std::string& url,
97 std::string* data_out) {
98 const network::TestURLLoaderFactory::PendingRequest* pending_request =
99 PendingForURL(&test_url_loader_factory_, url);
100 if (!pending_request)
101 return false;
102 *data_out = network::GetUploadData(pending_request->request);
103 return true;
104 }
105
VerifyFetcherUploadDataForURL(const std::string & url,std::map<std::string,std::string> * expected_pairs)106 void GCMRequestTestBase::VerifyFetcherUploadDataForURL(
107 const std::string& url,
108 std::map<std::string, std::string>* expected_pairs) {
109 std::string upload_data;
110 ASSERT_TRUE(GetUploadDataForURL(url, &upload_data));
111
112 // Verify data was formatted properly.
113 base::StringTokenizer data_tokenizer(upload_data, "&=");
114 while (data_tokenizer.GetNext()) {
115 auto iter = expected_pairs->find(data_tokenizer.token());
116 ASSERT_TRUE(iter != expected_pairs->end()) << data_tokenizer.token();
117 ASSERT_TRUE(data_tokenizer.GetNext()) << data_tokenizer.token();
118 ASSERT_EQ(iter->second, data_tokenizer.token());
119 // Ensure that none of the keys appears twice.
120 expected_pairs->erase(iter);
121 }
122
123 ASSERT_EQ(0UL, expected_pairs->size());
124 }
125
FastForwardToTriggerNextRetry()126 void GCMRequestTestBase::FastForwardToTriggerNextRetry() {
127 // Here we compute the maximum delay time by skipping the jitter fluctuation
128 // that only affects in the negative way.
129 int next_retry_delay_ms = kDefaultBackoffPolicy.initial_delay_ms;
130 next_retry_delay_ms *=
131 pow(kDefaultBackoffPolicy.multiply_factor, retry_count_);
132 task_environment_.FastForwardBy(
133 base::TimeDelta::FromMilliseconds(next_retry_delay_ms));
134 }
135
136 } // namespace gcm
137