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