1// Copyright (c) 2012 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 <ostream>
6#include <vector>
7
8#include "base/bind.h"
9#include "base/message_loop/message_loop.h"
10#include "base/message_loop/message_loop_proxy.h"
11#include "base/run_loop.h"
12#include "base/strings/string_split.h"
13#include "components/policy/core/common/cloud/cloud_policy_constants.h"
14#include "components/policy/core/common/cloud/device_management_service.h"
15#include "components/policy/core/common/cloud/mock_device_management_service.h"
16#include "net/base/escape.h"
17#include "net/base/load_flags.h"
18#include "net/base/net_errors.h"
19#include "net/http/http_response_headers.h"
20#include "net/url_request/test_url_fetcher_factory.h"
21#include "net/url_request/url_request_status.h"
22#include "net/url_request/url_request_test_util.h"
23#include "testing/gmock/include/gmock/gmock.h"
24#include "testing/gtest/include/gtest/gtest.h"
25
26using testing::Mock;
27using testing::_;
28
29namespace em = enterprise_management;
30
31namespace policy {
32
33const char kServiceUrl[] = "https://example.com/management_service";
34
35// Encoded empty response messages for testing the error code paths.
36const char kResponseEmpty[] = "\x08\x00";
37
38#define PROTO_STRING(name) (std::string(name, arraysize(name) - 1))
39
40// Some helper constants.
41const char kGaiaAuthToken[] = "gaia-auth-token";
42const char kOAuthToken[] = "oauth-token";
43const char kDMToken[] = "device-management-token";
44const char kClientID[] = "device-id";
45const char kRobotAuthCode[] = "robot-oauth-auth-code";
46
47// Unit tests for the device management policy service. The tests are run
48// against a TestURLFetcherFactory that is used to short-circuit the request
49// without calling into the actual network stack.
50class DeviceManagementServiceTestBase : public testing::Test {
51 protected:
52  DeviceManagementServiceTestBase() {
53    request_context_ =
54        new net::TestURLRequestContextGetter(loop_.message_loop_proxy());
55    ResetService();
56    InitializeService();
57  }
58
59  ~DeviceManagementServiceTestBase() {
60    service_.reset();
61    base::RunLoop().RunUntilIdle();
62  }
63
64  void ResetService() {
65    scoped_ptr<DeviceManagementService::Configuration> configuration(
66        new MockDeviceManagementServiceConfiguration(kServiceUrl));
67    service_.reset(new DeviceManagementService(configuration.Pass()));
68  }
69
70  void InitializeService() {
71    service_->ScheduleInitialization(0);
72    base::RunLoop().RunUntilIdle();
73  }
74
75  net::TestURLFetcher* GetFetcher() {
76    return factory_.GetFetcherByID(DeviceManagementService::kURLFetcherID);
77  }
78
79  DeviceManagementRequestJob* StartRegistrationJob() {
80    DeviceManagementRequestJob* job =
81        service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION,
82                            request_context_);
83    job->SetGaiaToken(kGaiaAuthToken);
84    job->SetOAuthToken(kOAuthToken);
85    job->SetClientID(kClientID);
86    job->GetRequest()->mutable_register_request();
87    job->SetRetryCallback(base::Bind(
88        &DeviceManagementServiceTestBase::OnJobRetry, base::Unretained(this)));
89    job->Start(base::Bind(&DeviceManagementServiceTestBase::OnJobDone,
90                          base::Unretained(this)));
91    return job;
92  }
93
94  DeviceManagementRequestJob* StartApiAuthCodeFetchJob() {
95    DeviceManagementRequestJob* job = service_->CreateJob(
96        DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH,
97        request_context_);
98    job->SetGaiaToken(kGaiaAuthToken);
99    job->SetOAuthToken(kOAuthToken);
100    job->SetClientID(kClientID);
101    job->GetRequest()->mutable_service_api_access_request();
102    job->SetRetryCallback(base::Bind(
103        &DeviceManagementServiceTestBase::OnJobRetry, base::Unretained(this)));
104    job->Start(base::Bind(&DeviceManagementServiceTestBase::OnJobDone,
105                          base::Unretained(this)));
106    return job;
107  }
108
109  DeviceManagementRequestJob* StartUnregistrationJob() {
110    DeviceManagementRequestJob* job =
111        service_->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION,
112                            request_context_);
113    job->SetDMToken(kDMToken);
114    job->SetClientID(kClientID);
115    job->GetRequest()->mutable_unregister_request();
116    job->SetRetryCallback(base::Bind(
117        &DeviceManagementServiceTestBase::OnJobRetry, base::Unretained(this)));
118    job->Start(base::Bind(&DeviceManagementServiceTestBase::OnJobDone,
119                          base::Unretained(this)));
120    return job;
121  }
122
123  DeviceManagementRequestJob* StartPolicyFetchJob() {
124    DeviceManagementRequestJob* job =
125        service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH,
126                            request_context_);
127    job->SetGaiaToken(kGaiaAuthToken);
128    job->SetOAuthToken(kOAuthToken);
129    job->SetClientID(kClientID);
130    em::PolicyFetchRequest* fetch_request =
131        job->GetRequest()->mutable_policy_request()->add_request();
132    fetch_request->set_policy_type(dm_protocol::kChromeUserPolicyType);
133    job->SetRetryCallback(base::Bind(
134        &DeviceManagementServiceTestBase::OnJobRetry, base::Unretained(this)));
135    job->Start(base::Bind(&DeviceManagementServiceTestBase::OnJobDone,
136                          base::Unretained(this)));
137    return job;
138  }
139
140  DeviceManagementRequestJob* StartAutoEnrollmentJob() {
141    DeviceManagementRequestJob* job =
142        service_->CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT,
143                            request_context_);
144    job->SetClientID(kClientID);
145    em::DeviceAutoEnrollmentRequest* request =
146        job->GetRequest()->mutable_auto_enrollment_request();
147    request->set_modulus(1);
148    request->set_remainder(0);
149    job->SetRetryCallback(base::Bind(
150        &DeviceManagementServiceTestBase::OnJobRetry, base::Unretained(this)));
151    job->Start(base::Bind(&DeviceManagementServiceTestBase::OnJobDone,
152                          base::Unretained(this)));
153    return job;
154  }
155
156  void SendResponse(net::TestURLFetcher* fetcher,
157                    const net::URLRequestStatus request_status,
158                    int http_status,
159                    const std::string& response) {
160    fetcher->set_url(GURL(kServiceUrl));
161    fetcher->set_status(request_status);
162    fetcher->set_response_code(http_status);
163    fetcher->SetResponseString(response);
164    fetcher->delegate()->OnURLFetchComplete(fetcher);
165  }
166
167  MOCK_METHOD3(OnJobDone, void(DeviceManagementStatus, int,
168                               const em::DeviceManagementResponse&));
169
170  MOCK_METHOD1(OnJobRetry, void(DeviceManagementRequestJob*));
171
172  base::MessageLoop loop_;
173  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
174  net::TestURLFetcherFactory factory_;
175  scoped_ptr<DeviceManagementService> service_;
176};
177
178struct FailedRequestParams {
179  FailedRequestParams(DeviceManagementStatus expected_status,
180                      net::URLRequestStatus::Status request_status,
181                      int http_status,
182                      const std::string& response)
183      : expected_status_(expected_status),
184        request_status_(request_status, 0),
185        http_status_(http_status),
186        response_(response) {}
187
188  DeviceManagementStatus expected_status_;
189  net::URLRequestStatus request_status_;
190  int http_status_;
191  std::string response_;
192};
193
194void PrintTo(const FailedRequestParams& params, std::ostream* os) {
195  *os << "FailedRequestParams " << params.expected_status_
196      << " " << params.request_status_.status()
197      << " " << params.http_status_;
198}
199
200// A parameterized test case for erroneous response situations, they're mostly
201// the same for all kinds of requests.
202class DeviceManagementServiceFailedRequestTest
203    : public DeviceManagementServiceTestBase,
204      public testing::WithParamInterface<FailedRequestParams> {
205};
206
207TEST_P(DeviceManagementServiceFailedRequestTest, RegisterRequest) {
208  EXPECT_CALL(*this, OnJobDone(GetParam().expected_status_, _, _));
209  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
210  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
211  net::TestURLFetcher* fetcher = GetFetcher();
212  ASSERT_TRUE(fetcher);
213
214  SendResponse(fetcher, GetParam().request_status_, GetParam().http_status_,
215               GetParam().response_);
216}
217
218TEST_P(DeviceManagementServiceFailedRequestTest, ApiAuthCodeFetchRequest) {
219  EXPECT_CALL(*this, OnJobDone(GetParam().expected_status_, _, _));
220  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
221  scoped_ptr<DeviceManagementRequestJob> request_job(
222      StartApiAuthCodeFetchJob());
223  net::TestURLFetcher* fetcher = GetFetcher();
224  ASSERT_TRUE(fetcher);
225
226  SendResponse(fetcher, GetParam().request_status_, GetParam().http_status_,
227               GetParam().response_);
228}
229
230TEST_P(DeviceManagementServiceFailedRequestTest, UnregisterRequest) {
231  EXPECT_CALL(*this, OnJobDone(GetParam().expected_status_, _, _));
232  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
233  scoped_ptr<DeviceManagementRequestJob> request_job(StartUnregistrationJob());
234  net::TestURLFetcher* fetcher = GetFetcher();
235  ASSERT_TRUE(fetcher);
236
237  SendResponse(fetcher, GetParam().request_status_, GetParam().http_status_,
238               GetParam().response_);
239}
240
241TEST_P(DeviceManagementServiceFailedRequestTest, PolicyRequest) {
242  EXPECT_CALL(*this, OnJobDone(GetParam().expected_status_, _, _));
243  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
244  scoped_ptr<DeviceManagementRequestJob> request_job(StartPolicyFetchJob());
245  net::TestURLFetcher* fetcher = GetFetcher();
246  ASSERT_TRUE(fetcher);
247
248  SendResponse(fetcher, GetParam().request_status_, GetParam().http_status_,
249               GetParam().response_);
250}
251
252TEST_P(DeviceManagementServiceFailedRequestTest, AutoEnrollmentRequest) {
253  EXPECT_CALL(*this, OnJobDone(GetParam().expected_status_, _, _));
254  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
255  scoped_ptr<DeviceManagementRequestJob> request_job(StartAutoEnrollmentJob());
256  net::TestURLFetcher* fetcher = GetFetcher();
257  ASSERT_TRUE(fetcher);
258
259  SendResponse(fetcher, GetParam().request_status_, GetParam().http_status_,
260               GetParam().response_);
261}
262
263INSTANTIATE_TEST_CASE_P(
264    DeviceManagementServiceFailedRequestTestInstance,
265    DeviceManagementServiceFailedRequestTest,
266    testing::Values(
267        FailedRequestParams(
268            DM_STATUS_REQUEST_FAILED,
269            net::URLRequestStatus::FAILED,
270            200,
271            PROTO_STRING(kResponseEmpty)),
272        FailedRequestParams(
273            DM_STATUS_HTTP_STATUS_ERROR,
274            net::URLRequestStatus::SUCCESS,
275            666,
276            PROTO_STRING(kResponseEmpty)),
277        FailedRequestParams(
278            DM_STATUS_RESPONSE_DECODING_ERROR,
279            net::URLRequestStatus::SUCCESS,
280            200,
281            PROTO_STRING("Not a protobuf.")),
282        FailedRequestParams(
283            DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED,
284            net::URLRequestStatus::SUCCESS,
285            403,
286            PROTO_STRING(kResponseEmpty)),
287        FailedRequestParams(
288            DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER,
289            net::URLRequestStatus::SUCCESS,
290            405,
291            PROTO_STRING(kResponseEmpty)),
292        FailedRequestParams(
293            DM_STATUS_SERVICE_DEVICE_ID_CONFLICT,
294            net::URLRequestStatus::SUCCESS,
295            409,
296            PROTO_STRING(kResponseEmpty)),
297        FailedRequestParams(
298            DM_STATUS_SERVICE_DEVICE_NOT_FOUND,
299            net::URLRequestStatus::SUCCESS,
300            410,
301            PROTO_STRING(kResponseEmpty)),
302        FailedRequestParams(
303            DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID,
304            net::URLRequestStatus::SUCCESS,
305            401,
306            PROTO_STRING(kResponseEmpty)),
307        FailedRequestParams(
308            DM_STATUS_REQUEST_INVALID,
309            net::URLRequestStatus::SUCCESS,
310            400,
311            PROTO_STRING(kResponseEmpty)),
312        FailedRequestParams(
313            DM_STATUS_TEMPORARY_UNAVAILABLE,
314            net::URLRequestStatus::SUCCESS,
315            404,
316            PROTO_STRING(kResponseEmpty)),
317        FailedRequestParams(
318            DM_STATUS_SERVICE_ACTIVATION_PENDING,
319            net::URLRequestStatus::SUCCESS,
320            412,
321            PROTO_STRING(kResponseEmpty)),
322        FailedRequestParams(
323            DM_STATUS_SERVICE_MISSING_LICENSES,
324            net::URLRequestStatus::SUCCESS,
325            402,
326            PROTO_STRING(kResponseEmpty))));
327
328// Simple query parameter parser for testing.
329class QueryParams {
330 public:
331  explicit QueryParams(const std::string& query) {
332    base::SplitStringIntoKeyValuePairs(query, '=', '&', &params_);
333  }
334
335  bool Check(const std::string& name, const std::string& expected_value) {
336    bool found = false;
337    for (ParamMap::const_iterator i(params_.begin()); i != params_.end(); ++i) {
338      std::string unescaped_name(net::UnescapeURLComponent(
339          i->first,
340          net::UnescapeRule::NORMAL |
341          net::UnescapeRule::SPACES |
342          net::UnescapeRule::URL_SPECIAL_CHARS |
343          net::UnescapeRule::CONTROL_CHARS |
344          net::UnescapeRule::REPLACE_PLUS_WITH_SPACE));
345      if (unescaped_name == name) {
346        if (found)
347          return false;
348        found = true;
349        std::string unescaped_value(net::UnescapeURLComponent(
350            i->second,
351            net::UnescapeRule::NORMAL |
352            net::UnescapeRule::SPACES |
353            net::UnescapeRule::URL_SPECIAL_CHARS |
354            net::UnescapeRule::CONTROL_CHARS |
355            net::UnescapeRule::REPLACE_PLUS_WITH_SPACE));
356        if (unescaped_value != expected_value)
357          return false;
358      }
359    }
360    return found;
361  }
362
363 private:
364  typedef std::vector<std::pair<std::string, std::string> > ParamMap;
365  ParamMap params_;
366};
367
368class DeviceManagementServiceTest
369    : public DeviceManagementServiceTestBase {
370 protected:
371  void CheckURLAndQueryParams(const GURL& request_url,
372                              const std::string& request_type,
373                              const std::string& device_id) {
374    const GURL service_url(kServiceUrl);
375    EXPECT_EQ(service_url.scheme(), request_url.scheme());
376    EXPECT_EQ(service_url.host(), request_url.host());
377    EXPECT_EQ(service_url.port(), request_url.port());
378    EXPECT_EQ(service_url.path(), request_url.path());
379
380    QueryParams query_params(request_url.query());
381    EXPECT_TRUE(query_params.Check(dm_protocol::kParamRequest, request_type));
382    EXPECT_TRUE(query_params.Check(dm_protocol::kParamDeviceID, device_id));
383    EXPECT_TRUE(query_params.Check(dm_protocol::kParamDeviceType,
384                                   dm_protocol::kValueDeviceType));
385    EXPECT_TRUE(query_params.Check(dm_protocol::kParamAppType,
386                                   dm_protocol::kValueAppType));
387  }
388};
389
390MATCHER_P(MessageEquals, reference, "") {
391  std::string reference_data;
392  std::string arg_data;
393  return arg.SerializeToString(&arg_data) &&
394         reference.SerializeToString(&reference_data) &&
395         arg_data == reference_data;
396}
397
398TEST_F(DeviceManagementServiceTest, RegisterRequest) {
399  em::DeviceManagementResponse expected_response;
400  expected_response.mutable_register_response()->
401      set_device_management_token(kDMToken);
402  EXPECT_CALL(*this, OnJobDone(DM_STATUS_SUCCESS, _,
403                               MessageEquals(expected_response)));
404  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
405  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
406  net::TestURLFetcher* fetcher = GetFetcher();
407  ASSERT_TRUE(fetcher);
408
409  CheckURLAndQueryParams(fetcher->GetOriginalURL(),
410                         dm_protocol::kValueRequestRegister,
411                         kClientID);
412
413  std::string expected_data;
414  ASSERT_TRUE(request_job->GetRequest()->SerializeToString(&expected_data));
415  EXPECT_EQ(expected_data, fetcher->upload_data());
416
417  // Generate the response.
418  std::string response_data;
419  ASSERT_TRUE(expected_response.SerializeToString(&response_data));
420  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
421  SendResponse(fetcher, status, 200, response_data);
422}
423
424TEST_F(DeviceManagementServiceTest, ApiAuthCodeFetchRequest) {
425  em::DeviceManagementResponse expected_response;
426  expected_response.mutable_service_api_access_response()->set_auth_code(
427      kRobotAuthCode);
428  EXPECT_CALL(*this, OnJobDone(DM_STATUS_SUCCESS, _,
429                               MessageEquals(expected_response)));
430  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
431  scoped_ptr<DeviceManagementRequestJob> request_job(
432      StartApiAuthCodeFetchJob());
433  net::TestURLFetcher* fetcher = GetFetcher();
434  ASSERT_TRUE(fetcher);
435
436  CheckURLAndQueryParams(fetcher->GetOriginalURL(),
437                         dm_protocol::kValueRequestApiAuthorization,
438                         kClientID);
439
440  std::string expected_data;
441  ASSERT_TRUE(request_job->GetRequest()->SerializeToString(&expected_data));
442  EXPECT_EQ(expected_data, fetcher->upload_data());
443
444  // Generate the response.
445  std::string response_data;
446  ASSERT_TRUE(expected_response.SerializeToString(&response_data));
447  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
448  SendResponse(fetcher, status, 200, response_data);
449}
450
451TEST_F(DeviceManagementServiceTest, UnregisterRequest) {
452  em::DeviceManagementResponse expected_response;
453  expected_response.mutable_unregister_response();
454  EXPECT_CALL(*this, OnJobDone(DM_STATUS_SUCCESS, _,
455                               MessageEquals(expected_response)));
456  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
457  scoped_ptr<DeviceManagementRequestJob> request_job(StartUnregistrationJob());
458  net::TestURLFetcher* fetcher = GetFetcher();
459  ASSERT_TRUE(fetcher);
460
461  // Check the data the fetcher received.
462  const GURL& request_url(fetcher->GetOriginalURL());
463  const GURL service_url(kServiceUrl);
464  EXPECT_EQ(service_url.scheme(), request_url.scheme());
465  EXPECT_EQ(service_url.host(), request_url.host());
466  EXPECT_EQ(service_url.port(), request_url.port());
467  EXPECT_EQ(service_url.path(), request_url.path());
468
469  CheckURLAndQueryParams(fetcher->GetOriginalURL(),
470                         dm_protocol::kValueRequestUnregister,
471                         kClientID);
472
473  std::string expected_data;
474  ASSERT_TRUE(request_job->GetRequest()->SerializeToString(&expected_data));
475  EXPECT_EQ(expected_data, fetcher->upload_data());
476
477  // Generate the response.
478  std::string response_data;
479  ASSERT_TRUE(expected_response.SerializeToString(&response_data));
480  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
481  SendResponse(fetcher, status, 200, response_data);
482}
483
484TEST_F(DeviceManagementServiceTest, CancelRegisterRequest) {
485  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
486  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
487  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
488  net::TestURLFetcher* fetcher = GetFetcher();
489  ASSERT_TRUE(fetcher);
490
491  // There shouldn't be any callbacks.
492  request_job.reset();
493}
494
495TEST_F(DeviceManagementServiceTest, CancelApiAuthCodeFetch) {
496  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
497  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
498  scoped_ptr<DeviceManagementRequestJob> request_job(
499      StartApiAuthCodeFetchJob());
500  net::TestURLFetcher* fetcher = GetFetcher();
501  ASSERT_TRUE(fetcher);
502
503  // There shouldn't be any callbacks.
504  request_job.reset();
505}
506
507TEST_F(DeviceManagementServiceTest, CancelUnregisterRequest) {
508  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
509  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
510  scoped_ptr<DeviceManagementRequestJob> request_job(StartUnregistrationJob());
511  net::TestURLFetcher* fetcher = GetFetcher();
512  ASSERT_TRUE(fetcher);
513
514  // There shouldn't be any callbacks.
515  request_job.reset();
516}
517
518TEST_F(DeviceManagementServiceTest, CancelPolicyRequest) {
519  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
520  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
521  scoped_ptr<DeviceManagementRequestJob> request_job(StartPolicyFetchJob());
522  net::TestURLFetcher* fetcher = GetFetcher();
523  ASSERT_TRUE(fetcher);
524
525  // There shouldn't be any callbacks.
526  request_job.reset();
527}
528
529TEST_F(DeviceManagementServiceTest, JobQueueing) {
530  // Start with a non-initialized service.
531  ResetService();
532
533  em::DeviceManagementResponse expected_response;
534  expected_response.mutable_register_response()->
535      set_device_management_token(kDMToken);
536  EXPECT_CALL(*this, OnJobDone(DM_STATUS_SUCCESS, _,
537                               MessageEquals(expected_response)));
538  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
539
540  // Make a request. We should not see any fetchers being created.
541  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
542  net::TestURLFetcher* fetcher = GetFetcher();
543  ASSERT_FALSE(fetcher);
544
545  // Now initialize the service. That should start the job.
546  InitializeService();
547  fetcher = GetFetcher();
548  ASSERT_TRUE(fetcher);
549  factory_.RemoveFetcherFromMap(DeviceManagementService::kURLFetcherID);
550
551  // Check that the request is processed as expected.
552  std::string response_data;
553  ASSERT_TRUE(expected_response.SerializeToString(&response_data));
554  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
555  SendResponse(fetcher, status, 200, response_data);
556}
557
558TEST_F(DeviceManagementServiceTest, CancelRequestAfterShutdown) {
559  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
560  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
561  scoped_ptr<DeviceManagementRequestJob> request_job(StartPolicyFetchJob());
562  net::TestURLFetcher* fetcher = GetFetcher();
563  ASSERT_TRUE(fetcher);
564
565  // Shutdown the service and cancel the job afterwards.
566  service_->Shutdown();
567  request_job.reset();
568}
569
570ACTION_P(ResetPointer, pointer) {
571  pointer->reset();
572}
573
574TEST_F(DeviceManagementServiceTest, CancelDuringCallback) {
575  // Make a request.
576  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
577  net::TestURLFetcher* fetcher = GetFetcher();
578  ASSERT_TRUE(fetcher);
579
580  EXPECT_CALL(*this, OnJobDone(_, _, _))
581      .WillOnce(ResetPointer(&request_job));
582  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
583
584  // Generate a callback.
585  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
586  SendResponse(fetcher, status, 500, std::string());
587
588  // Job should have been reset.
589  EXPECT_FALSE(request_job.get());
590}
591
592TEST_F(DeviceManagementServiceTest, RetryOnProxyError) {
593  // Make a request.
594  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
595  EXPECT_CALL(*this, OnJobRetry(_));
596
597  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
598  net::TestURLFetcher* fetcher = GetFetcher();
599  ASSERT_TRUE(fetcher);
600  EXPECT_TRUE((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) == 0);
601  const GURL original_url(fetcher->GetOriginalURL());
602  const std::string upload_data(fetcher->upload_data());
603
604  // Generate a callback with a proxy failure.
605  net::URLRequestStatus status(net::URLRequestStatus::FAILED,
606                               net::ERR_PROXY_CONNECTION_FAILED);
607  SendResponse(fetcher, status, 200, std::string());
608
609  // Verify that a new URLFetcher was started that bypasses the proxy.
610  fetcher = GetFetcher();
611  ASSERT_TRUE(fetcher);
612  EXPECT_TRUE(fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY);
613  EXPECT_EQ(original_url, fetcher->GetOriginalURL());
614  EXPECT_EQ(upload_data, fetcher->upload_data());
615}
616
617TEST_F(DeviceManagementServiceTest, RetryOnBadResponseFromProxy) {
618  // Make a request.
619  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
620  EXPECT_CALL(*this, OnJobRetry(_));
621
622  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
623  net::TestURLFetcher* fetcher = GetFetcher();
624  ASSERT_TRUE(fetcher);
625  EXPECT_TRUE((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) == 0);
626  const GURL original_url(fetcher->GetOriginalURL());
627  const std::string upload_data(fetcher->upload_data());
628  fetcher->set_was_fetched_via_proxy(true);
629  scoped_refptr<net::HttpResponseHeaders> headers;
630  headers = new net::HttpResponseHeaders(
631      "HTTP/1.1 200 OK\0Content-type: bad/type\0\0");
632  fetcher->set_response_headers(headers);
633
634  // Generate a callback with a valid http response, that was generated by
635  // a bad/wrong proxy.
636  net::URLRequestStatus status;
637  SendResponse(fetcher, status, 200, std::string());
638
639  // Verify that a new URLFetcher was started that bypasses the proxy.
640  fetcher = GetFetcher();
641  ASSERT_TRUE(fetcher);
642  EXPECT_TRUE((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) != 0);
643  EXPECT_EQ(original_url, fetcher->GetOriginalURL());
644  EXPECT_EQ(upload_data, fetcher->upload_data());
645}
646
647TEST_F(DeviceManagementServiceTest, RetryOnNetworkChanges) {
648  // Make a request.
649  EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
650  EXPECT_CALL(*this, OnJobRetry(_));
651
652  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
653  net::TestURLFetcher* fetcher = GetFetcher();
654  ASSERT_TRUE(fetcher);
655  const GURL original_url(fetcher->GetOriginalURL());
656  const std::string original_upload_data(fetcher->upload_data());
657
658  // Make it fail with ERR_NETWORK_CHANGED.
659  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
660                                            net::ERR_NETWORK_CHANGED));
661  fetcher->set_url(GURL(kServiceUrl));
662  fetcher->delegate()->OnURLFetchComplete(fetcher);
663
664  // Verify that a new URLFetcher was started that retries this job, after
665  // having called OnJobRetry.
666  Mock::VerifyAndClearExpectations(this);
667  fetcher = GetFetcher();
668  ASSERT_TRUE(fetcher);
669  EXPECT_EQ(original_url, fetcher->GetOriginalURL());
670  EXPECT_EQ(original_upload_data, fetcher->upload_data());
671  EXPECT_EQ(net::URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
672}
673
674TEST_F(DeviceManagementServiceTest, RetryLimit) {
675  scoped_ptr<DeviceManagementRequestJob> request_job(StartRegistrationJob());
676
677  // Simulate 3 failed network requests.
678  for (int i = 0; i < 3; ++i) {
679    // Make the current fetcher fail with ERR_NETWORK_CHANGED.
680    net::TestURLFetcher* fetcher = GetFetcher();
681    ASSERT_TRUE(fetcher);
682    EXPECT_CALL(*this, OnJobDone(_, _, _)).Times(0);
683    EXPECT_CALL(*this, OnJobRetry(_));
684    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
685                                              net::ERR_NETWORK_CHANGED));
686    fetcher->set_url(GURL(kServiceUrl));
687    fetcher->delegate()->OnURLFetchComplete(fetcher);
688    Mock::VerifyAndClearExpectations(this);
689  }
690
691  // At the next failure the DeviceManagementService should give up retrying and
692  // pass the error code to the job's owner.
693  net::TestURLFetcher* fetcher = GetFetcher();
694  ASSERT_TRUE(fetcher);
695  EXPECT_CALL(*this, OnJobDone(DM_STATUS_REQUEST_FAILED, _, _));
696  EXPECT_CALL(*this, OnJobRetry(_)).Times(0);
697  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
698                                            net::ERR_NETWORK_CHANGED));
699  fetcher->set_url(GURL(kServiceUrl));
700  fetcher->delegate()->OnURLFetchComplete(fetcher);
701  Mock::VerifyAndClearExpectations(this);
702}
703
704}  // namespace policy
705