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