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.
4
5#include "base/message_loop/message_loop.h"
6#include "components/gcm_driver/gcm_channel_status_request.h"
7#include "net/url_request/test_url_fetcher_factory.h"
8#include "net/url_request/url_request_test_util.h"
9#include "sync/protocol/experiment_status.pb.h"
10#include "sync/protocol/experiments_specifics.pb.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace gcm {
14
15class GCMChannelStatusRequestTest : public testing::Test {
16 public:
17  GCMChannelStatusRequestTest();
18  virtual ~GCMChannelStatusRequestTest();
19
20 protected:
21  enum GCMStatus {
22    NOT_SPECIFIED,
23    GCM_ENABLED,
24    GCM_DISABLED,
25  };
26
27  void StartRequest();
28  void SetResponseStatusAndString(net::HttpStatusCode status_code,
29                                  const std::string& response_body);
30  void SetResponseProtoData(GCMStatus status, int poll_interval_seconds);
31  void CompleteFetch();
32  void OnRequestCompleted(bool update_received,
33                          bool enabled,
34                          int poll_interval_seconds);
35
36  scoped_ptr<GCMChannelStatusRequest> request_;
37  base::MessageLoop message_loop_;
38  net::TestURLFetcherFactory url_fetcher_factory_;
39  scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
40  bool request_callback_invoked_;
41  bool update_received_;
42  bool enabled_;
43  int poll_interval_seconds_;
44};
45
46GCMChannelStatusRequestTest::GCMChannelStatusRequestTest()
47    : url_request_context_getter_(new net::TestURLRequestContextGetter(
48           message_loop_.message_loop_proxy())),
49      request_callback_invoked_(false),
50      update_received_(false),
51      enabled_(true),
52      poll_interval_seconds_(0) {
53}
54
55GCMChannelStatusRequestTest::~GCMChannelStatusRequestTest() {
56}
57
58void GCMChannelStatusRequestTest::StartRequest() {
59  request_.reset(new GCMChannelStatusRequest(
60      url_request_context_getter_.get(),
61      "http://channel.status.request.com/",
62      "user agent string",
63      base::Bind(&GCMChannelStatusRequestTest::OnRequestCompleted,
64                 base::Unretained(this))));
65  request_->Start();
66}
67
68void GCMChannelStatusRequestTest::SetResponseStatusAndString(
69    net::HttpStatusCode status_code,
70    const std::string& response_body) {
71  net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
72  ASSERT_TRUE(fetcher);
73  fetcher->set_response_code(status_code);
74  fetcher->SetResponseString(response_body);
75}
76
77void GCMChannelStatusRequestTest::SetResponseProtoData(
78    GCMStatus status, int poll_interval_seconds) {
79  sync_pb::ExperimentStatusResponse response_proto;
80  if (status != NOT_SPECIFIED) {
81    sync_pb::ExperimentsSpecifics* experiment_specifics =
82        response_proto.add_experiment();
83    experiment_specifics->mutable_gcm_channel()->set_enabled(status ==
84                                                             GCM_ENABLED);
85  }
86
87  // Zero |poll_interval_seconds| means the optional field is not set.
88  if (poll_interval_seconds)
89    response_proto.set_poll_interval_seconds(poll_interval_seconds);
90
91  std::string response_string;
92  response_proto.SerializeToString(&response_string);
93  SetResponseStatusAndString(net::HTTP_OK, response_string);
94}
95
96void GCMChannelStatusRequestTest::CompleteFetch() {
97  request_callback_invoked_ = false;
98  net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
99  ASSERT_TRUE(fetcher);
100  fetcher->delegate()->OnURLFetchComplete(fetcher);
101}
102
103void GCMChannelStatusRequestTest::OnRequestCompleted(
104    bool update_received, bool enabled, int poll_interval_seconds) {
105  request_callback_invoked_ = true;
106  update_received_ = update_received;
107  enabled_ = enabled;
108  poll_interval_seconds_ = poll_interval_seconds;
109}
110
111TEST_F(GCMChannelStatusRequestTest, RequestData) {
112  StartRequest();
113
114  net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
115  ASSERT_TRUE(fetcher);
116
117  EXPECT_EQ(GURL(request_->channel_status_request_url_),
118            fetcher->GetOriginalURL());
119
120  net::HttpRequestHeaders headers;
121  fetcher->GetExtraRequestHeaders(&headers);
122  std::string user_agent_header;
123  headers.GetHeader("User-Agent", &user_agent_header);
124  EXPECT_FALSE(user_agent_header.empty());
125  EXPECT_EQ(request_->user_agent_, user_agent_header);
126
127  std::string upload_data = fetcher->upload_data();
128  EXPECT_FALSE(upload_data.empty());
129  sync_pb::ExperimentStatusRequest proto_data;
130  proto_data.ParseFromString(upload_data);
131  EXPECT_EQ(1, proto_data.experiment_name_size());
132  EXPECT_EQ("gcm_channel", proto_data.experiment_name(0));
133}
134
135TEST_F(GCMChannelStatusRequestTest, ResponseHttpStatusNotOK) {
136  StartRequest();
137  SetResponseStatusAndString(net::HTTP_UNAUTHORIZED, "");
138  CompleteFetch();
139
140  EXPECT_FALSE(request_callback_invoked_);
141}
142
143TEST_F(GCMChannelStatusRequestTest, ResponseEmpty) {
144  StartRequest();
145  SetResponseStatusAndString(net::HTTP_OK, "");
146  CompleteFetch();
147
148  EXPECT_TRUE(request_callback_invoked_);
149  EXPECT_FALSE(update_received_);
150}
151
152TEST_F(GCMChannelStatusRequestTest, ResponseNotInProtoFormat) {
153  StartRequest();
154  SetResponseStatusAndString(net::HTTP_OK, "foo");
155  CompleteFetch();
156
157  EXPECT_FALSE(request_callback_invoked_);
158}
159
160TEST_F(GCMChannelStatusRequestTest, ResponseEmptyProtoData) {
161  StartRequest();
162  SetResponseProtoData(NOT_SPECIFIED, 0);
163  CompleteFetch();
164
165  EXPECT_TRUE(request_callback_invoked_);
166  EXPECT_FALSE(update_received_);
167}
168
169TEST_F(GCMChannelStatusRequestTest, ResponseWithDisabledStatus) {
170  StartRequest();
171  SetResponseProtoData(GCM_DISABLED, 0);
172  CompleteFetch();
173
174  EXPECT_TRUE(request_callback_invoked_);
175  EXPECT_TRUE(update_received_);
176  EXPECT_FALSE(enabled_);
177  EXPECT_EQ(
178      GCMChannelStatusRequest::default_poll_interval_seconds(),
179      poll_interval_seconds_);
180}
181
182TEST_F(GCMChannelStatusRequestTest, ResponseWithEnabledStatus) {
183  StartRequest();
184  SetResponseProtoData(GCM_ENABLED, 0);
185  CompleteFetch();
186
187  EXPECT_TRUE(request_callback_invoked_);
188  EXPECT_TRUE(update_received_);
189  EXPECT_TRUE(enabled_);
190  EXPECT_EQ(
191      GCMChannelStatusRequest::default_poll_interval_seconds(),
192      poll_interval_seconds_);
193}
194
195TEST_F(GCMChannelStatusRequestTest, ResponseWithPollInterval) {
196  // Setting a poll interval 15 minutes longer than the minimum interval we
197  // enforce.
198  int poll_interval_seconds =
199      GCMChannelStatusRequest::min_poll_interval_seconds() + 15 * 60;
200  StartRequest();
201  SetResponseProtoData(NOT_SPECIFIED, poll_interval_seconds);
202  CompleteFetch();
203
204  EXPECT_TRUE(request_callback_invoked_);
205  EXPECT_TRUE(update_received_);
206  EXPECT_TRUE(enabled_);
207  EXPECT_EQ(poll_interval_seconds, poll_interval_seconds_);
208}
209
210TEST_F(GCMChannelStatusRequestTest, ResponseWithShortPollInterval) {
211  // Setting a poll interval 15 minutes shorter than the minimum interval we
212  // enforce.
213  int poll_interval_seconds =
214      GCMChannelStatusRequest::min_poll_interval_seconds() - 15 * 60;
215  StartRequest();
216  SetResponseProtoData(NOT_SPECIFIED, poll_interval_seconds);
217  CompleteFetch();
218
219  EXPECT_TRUE(request_callback_invoked_);
220  EXPECT_TRUE(update_received_);
221  EXPECT_TRUE(enabled_);
222  EXPECT_EQ(GCMChannelStatusRequest::min_poll_interval_seconds(),
223            poll_interval_seconds_);
224}
225
226TEST_F(GCMChannelStatusRequestTest, ResponseWithDisabledStatusAndPollInterval) {
227  int poll_interval_seconds =
228      GCMChannelStatusRequest::min_poll_interval_seconds() + 15 * 60;
229  StartRequest();
230  SetResponseProtoData(GCM_DISABLED, poll_interval_seconds);
231  CompleteFetch();
232
233  EXPECT_TRUE(request_callback_invoked_);
234  EXPECT_TRUE(update_received_);
235  EXPECT_FALSE(enabled_);
236  EXPECT_EQ(poll_interval_seconds, poll_interval_seconds_);
237}
238
239}  // namespace gcm
240