1 // Copyright (c) 2011 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 <vector>
6
7 #include "base/message_loop.h"
8 #include "base/string_split.h"
9 #include "chrome/browser/policy/device_management_backend_impl.h"
10 #include "chrome/browser/policy/device_management_backend_mock.h"
11 #include "chrome/browser/policy/device_management_service.h"
12 #include "chrome/browser/policy/proto/device_management_constants.h"
13 #include "chrome/common/net/test_url_fetcher_factory.h"
14 #include "chrome/test/test_url_request_context_getter.h"
15 #include "content/browser/browser_thread.h"
16 #include "net/base/escape.h"
17 #include "net/url_request/url_request_status.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using testing::_;
23 using testing::IgnoreResult;
24 using testing::InvokeWithoutArgs;
25
26 namespace policy {
27
28 const char kServiceUrl[] = "https://example.com/management_service";
29
30 // Encoded empty response messages for testing the error code paths.
31 const char kResponseEmpty[] = "\x08\x00";
32
33 #define PROTO_STRING(name) (std::string(name, arraysize(name) - 1))
34
35 // Some helper constants.
36 const char kAuthToken[] = "auth-token";
37 const char kDMToken[] = "device-management-token";
38 const char kDeviceId[] = "device-id";
39
40 // Unit tests for the device management policy service. The tests are run
41 // against a TestURLFetcherFactory that is used to short-circuit the request
42 // without calling into the actual network stack.
43 template<typename TESTBASE>
44 class DeviceManagementServiceTestBase : public TESTBASE {
45 protected:
DeviceManagementServiceTestBase()46 DeviceManagementServiceTestBase()
47 : request_context_(new TestURLRequestContextGetter()),
48 io_thread_(BrowserThread::IO, &loop_) {
49 ResetService();
50 service_->Initialize(request_context_.get());
51 }
52
SetUp()53 virtual void SetUp() {
54 URLFetcher::set_factory(&factory_);
55 }
56
TearDown()57 virtual void TearDown() {
58 URLFetcher::set_factory(NULL);
59 backend_.reset();
60 service_.reset();
61 request_context_ = NULL;
62 loop_.RunAllPending();
63 }
64
ResetService()65 void ResetService() {
66 backend_.reset();
67 service_.reset(new DeviceManagementService(kServiceUrl));
68 backend_.reset(service_->CreateBackend());
69 }
70
71 TestURLFetcherFactory factory_;
72 scoped_refptr<TestURLRequestContextGetter> request_context_;
73 scoped_ptr<DeviceManagementService> service_;
74 scoped_ptr<DeviceManagementBackend> backend_;
75
76 private:
77 MessageLoopForUI loop_;
78 BrowserThread io_thread_;
79 };
80
81 struct FailedRequestParams {
FailedRequestParamspolicy::FailedRequestParams82 FailedRequestParams(DeviceManagementBackend::ErrorCode expected_error,
83 net::URLRequestStatus::Status request_status,
84 int http_status,
85 const std::string& response)
86 : expected_error_(expected_error),
87 request_status_(request_status, 0),
88 http_status_(http_status),
89 response_(response) {}
90
91 DeviceManagementBackend::ErrorCode expected_error_;
92 net::URLRequestStatus request_status_;
93 int http_status_;
94 std::string response_;
95 };
96
97 // A parameterized test case for erroneous response situations, they're mostly
98 // the same for all kinds of requests.
99 class DeviceManagementServiceFailedRequestTest
100 : public DeviceManagementServiceTestBase<
101 testing::TestWithParam<FailedRequestParams> > {
102 };
103
TEST_P(DeviceManagementServiceFailedRequestTest,RegisterRequest)104 TEST_P(DeviceManagementServiceFailedRequestTest, RegisterRequest) {
105 DeviceRegisterResponseDelegateMock mock;
106 EXPECT_CALL(mock, OnError(GetParam().expected_error_));
107 em::DeviceRegisterRequest request;
108 backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
109 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
110 ASSERT_TRUE(fetcher);
111
112 fetcher->delegate()->OnURLFetchComplete(fetcher,
113 GURL(kServiceUrl),
114 GetParam().request_status_,
115 GetParam().http_status_,
116 ResponseCookies(),
117 GetParam().response_);
118 }
119
TEST_P(DeviceManagementServiceFailedRequestTest,UnregisterRequest)120 TEST_P(DeviceManagementServiceFailedRequestTest, UnregisterRequest) {
121 DeviceUnregisterResponseDelegateMock mock;
122 EXPECT_CALL(mock, OnError(GetParam().expected_error_));
123 em::DeviceUnregisterRequest request;
124 backend_->ProcessUnregisterRequest(kDMToken, kDeviceId, request, &mock);
125 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
126 ASSERT_TRUE(fetcher);
127
128 fetcher->delegate()->OnURLFetchComplete(fetcher,
129 GURL(kServiceUrl),
130 GetParam().request_status_,
131 GetParam().http_status_,
132 ResponseCookies(),
133 GetParam().response_);
134 }
135
TEST_P(DeviceManagementServiceFailedRequestTest,PolicyRequest)136 TEST_P(DeviceManagementServiceFailedRequestTest, PolicyRequest) {
137 DevicePolicyResponseDelegateMock mock;
138 EXPECT_CALL(mock, OnError(GetParam().expected_error_));
139 em::DevicePolicyRequest request;
140 request.set_policy_scope(kChromePolicyScope);
141 em::DevicePolicySettingRequest* setting_request =
142 request.add_setting_request();
143 setting_request->set_key(kChromeDevicePolicySettingKey);
144 backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
145 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
146 ASSERT_TRUE(fetcher);
147
148 fetcher->delegate()->OnURLFetchComplete(fetcher,
149 GURL(kServiceUrl),
150 GetParam().request_status_,
151 GetParam().http_status_,
152 ResponseCookies(),
153 GetParam().response_);
154 }
155
156 INSTANTIATE_TEST_CASE_P(
157 DeviceManagementServiceFailedRequestTestInstance,
158 DeviceManagementServiceFailedRequestTest,
159 testing::Values(
160 FailedRequestParams(
161 DeviceManagementBackend::kErrorRequestFailed,
162 net::URLRequestStatus::FAILED,
163 200,
164 PROTO_STRING(kResponseEmpty)),
165 FailedRequestParams(
166 DeviceManagementBackend::kErrorHttpStatus,
167 net::URLRequestStatus::SUCCESS,
168 666,
169 PROTO_STRING(kResponseEmpty)),
170 FailedRequestParams(
171 DeviceManagementBackend::kErrorResponseDecoding,
172 net::URLRequestStatus::SUCCESS,
173 200,
174 PROTO_STRING("Not a protobuf.")),
175 FailedRequestParams(
176 DeviceManagementBackend::kErrorServiceManagementNotSupported,
177 net::URLRequestStatus::SUCCESS,
178 403,
179 PROTO_STRING(kResponseEmpty)),
180 FailedRequestParams(
181 DeviceManagementBackend::kErrorServiceDeviceNotFound,
182 net::URLRequestStatus::SUCCESS,
183 901,
184 PROTO_STRING(kResponseEmpty)),
185 FailedRequestParams(
186 DeviceManagementBackend::kErrorServiceManagementTokenInvalid,
187 net::URLRequestStatus::SUCCESS,
188 401,
189 PROTO_STRING(kResponseEmpty)),
190 FailedRequestParams(
191 DeviceManagementBackend::kErrorRequestInvalid,
192 net::URLRequestStatus::SUCCESS,
193 400,
194 PROTO_STRING(kResponseEmpty)),
195 FailedRequestParams(
196 DeviceManagementBackend::kErrorTemporaryUnavailable,
197 net::URLRequestStatus::SUCCESS,
198 404,
199 PROTO_STRING(kResponseEmpty)),
200 FailedRequestParams(
201 DeviceManagementBackend::kErrorServiceActivationPending,
202 net::URLRequestStatus::SUCCESS,
203 491,
204 PROTO_STRING(kResponseEmpty))));
205
206 // Simple query parameter parser for testing.
207 class QueryParams {
208 public:
QueryParams(const std::string & query)209 explicit QueryParams(const std::string& query) {
210 base::SplitStringIntoKeyValuePairs(query, '=', '&', ¶ms_);
211 }
212
Check(const std::string & name,const std::string & expected_value)213 bool Check(const std::string& name, const std::string& expected_value) {
214 bool found = false;
215 for (ParamMap::const_iterator i(params_.begin()); i != params_.end(); ++i) {
216 std::string unescaped_name(
217 UnescapeURLComponent(i->first,
218 UnescapeRule::NORMAL |
219 UnescapeRule::SPACES |
220 UnescapeRule::URL_SPECIAL_CHARS |
221 UnescapeRule::CONTROL_CHARS |
222 UnescapeRule::REPLACE_PLUS_WITH_SPACE));
223 if (unescaped_name == name) {
224 if (found)
225 return false;
226 found = true;
227 std::string unescaped_value(
228 UnescapeURLComponent(i->second,
229 UnescapeRule::NORMAL |
230 UnescapeRule::SPACES |
231 UnescapeRule::URL_SPECIAL_CHARS |
232 UnescapeRule::CONTROL_CHARS |
233 UnescapeRule::REPLACE_PLUS_WITH_SPACE));
234 if (unescaped_value != expected_value)
235 return false;
236 }
237 }
238 return found;
239 }
240
241 private:
242 typedef std::vector<std::pair<std::string, std::string> > ParamMap;
243 ParamMap params_;
244 };
245
246 class DeviceManagementServiceTest
247 : public DeviceManagementServiceTestBase<testing::Test> {
248 public:
ResetBackend()249 void ResetBackend() {
250 backend_.reset();
251 }
252
253 protected:
CheckURLAndQueryParams(const GURL & request_url,const std::string & request_type,const std::string & device_id)254 void CheckURLAndQueryParams(const GURL& request_url,
255 const std::string& request_type,
256 const std::string& device_id) {
257 const GURL service_url(kServiceUrl);
258 EXPECT_EQ(service_url.scheme(), request_url.scheme());
259 EXPECT_EQ(service_url.host(), request_url.host());
260 EXPECT_EQ(service_url.port(), request_url.port());
261 EXPECT_EQ(service_url.path(), request_url.path());
262
263 QueryParams query_params(request_url.query());
264 EXPECT_TRUE(query_params.Check(
265 DeviceManagementBackendImpl::kParamRequest, request_type));
266 EXPECT_TRUE(query_params.Check(
267 DeviceManagementBackendImpl::kParamDeviceID, device_id));
268 EXPECT_TRUE(query_params.Check(
269 DeviceManagementBackendImpl::kParamDeviceType,
270 DeviceManagementBackendImpl::kValueDeviceType));
271 EXPECT_TRUE(query_params.Check(
272 DeviceManagementBackendImpl::kParamAppType,
273 DeviceManagementBackendImpl::kValueAppType));
274 EXPECT_TRUE(query_params.Check(
275 DeviceManagementBackendImpl::kParamAgent,
276 DeviceManagementBackendImpl::GetAgentString()));
277 }
278 };
279
280 MATCHER_P(MessageEquals, reference, "") {
281 std::string reference_data;
282 std::string arg_data;
283 return arg.SerializeToString(&arg_data) &&
284 reference.SerializeToString(&reference_data) &&
285 arg_data == reference_data;
286 }
287
TEST_F(DeviceManagementServiceTest,RegisterRequest)288 TEST_F(DeviceManagementServiceTest, RegisterRequest) {
289 DeviceRegisterResponseDelegateMock mock;
290 em::DeviceRegisterResponse expected_response;
291 expected_response.set_device_management_token(kDMToken);
292 EXPECT_CALL(mock, HandleRegisterResponse(MessageEquals(expected_response)));
293 em::DeviceRegisterRequest request;
294 backend_->ProcessRegisterRequest(kDMToken, kDeviceId, request, &mock);
295 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
296 ASSERT_TRUE(fetcher);
297
298 CheckURLAndQueryParams(fetcher->original_url(),
299 DeviceManagementBackendImpl::kValueRequestRegister,
300 kDeviceId);
301
302 em::DeviceManagementRequest expected_request_wrapper;
303 expected_request_wrapper.mutable_register_request()->CopyFrom(request);
304 std::string expected_request_data;
305 ASSERT_TRUE(expected_request_wrapper.SerializeToString(
306 &expected_request_data));
307 EXPECT_EQ(expected_request_data, fetcher->upload_data());
308
309 // Generate the response.
310 std::string response_data;
311 em::DeviceManagementResponse response_wrapper;
312 response_wrapper.mutable_register_response()->CopyFrom(expected_response);
313 ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
314 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
315 fetcher->delegate()->OnURLFetchComplete(fetcher,
316 GURL(kServiceUrl),
317 status,
318 200,
319 ResponseCookies(),
320 response_data);
321 }
322
TEST_F(DeviceManagementServiceTest,UnregisterRequest)323 TEST_F(DeviceManagementServiceTest, UnregisterRequest) {
324 DeviceUnregisterResponseDelegateMock mock;
325 em::DeviceUnregisterResponse expected_response;
326 EXPECT_CALL(mock, HandleUnregisterResponse(MessageEquals(expected_response)));
327 em::DeviceUnregisterRequest request;
328 backend_->ProcessUnregisterRequest(kDMToken, kDeviceId, request, &mock);
329 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
330 ASSERT_TRUE(fetcher);
331
332 // Check the data the fetcher received.
333 const GURL& request_url(fetcher->original_url());
334 const GURL service_url(kServiceUrl);
335 EXPECT_EQ(service_url.scheme(), request_url.scheme());
336 EXPECT_EQ(service_url.host(), request_url.host());
337 EXPECT_EQ(service_url.port(), request_url.port());
338 EXPECT_EQ(service_url.path(), request_url.path());
339
340 CheckURLAndQueryParams(fetcher->original_url(),
341 DeviceManagementBackendImpl::kValueRequestUnregister,
342 kDeviceId);
343
344 em::DeviceManagementRequest expected_request_wrapper;
345 expected_request_wrapper.mutable_unregister_request()->CopyFrom(request);
346 std::string expected_request_data;
347 ASSERT_TRUE(expected_request_wrapper.SerializeToString(
348 &expected_request_data));
349 EXPECT_EQ(expected_request_data, fetcher->upload_data());
350
351 // Generate the response.
352 std::string response_data;
353 em::DeviceManagementResponse response_wrapper;
354 response_wrapper.mutable_unregister_response()->CopyFrom(expected_response);
355 ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
356 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
357 fetcher->delegate()->OnURLFetchComplete(fetcher,
358 GURL(kServiceUrl),
359 status,
360 200,
361 ResponseCookies(),
362 response_data);
363 }
364
TEST_F(DeviceManagementServiceTest,CancelRegisterRequest)365 TEST_F(DeviceManagementServiceTest, CancelRegisterRequest) {
366 DeviceRegisterResponseDelegateMock mock;
367 EXPECT_CALL(mock, HandleRegisterResponse(_)).Times(0);
368 em::DeviceRegisterRequest request;
369 backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
370 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
371 ASSERT_TRUE(fetcher);
372
373 // There shouldn't be any callbacks.
374 backend_.reset();
375 }
376
TEST_F(DeviceManagementServiceTest,CancelUnregisterRequest)377 TEST_F(DeviceManagementServiceTest, CancelUnregisterRequest) {
378 DeviceUnregisterResponseDelegateMock mock;
379 EXPECT_CALL(mock, HandleUnregisterResponse(_)).Times(0);
380 em::DeviceUnregisterRequest request;
381 backend_->ProcessUnregisterRequest(kDMToken, kDeviceId, request, &mock);
382 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
383 ASSERT_TRUE(fetcher);
384
385 // There shouldn't be any callbacks.
386 backend_.reset();
387 }
388
TEST_F(DeviceManagementServiceTest,CancelPolicyRequest)389 TEST_F(DeviceManagementServiceTest, CancelPolicyRequest) {
390 DevicePolicyResponseDelegateMock mock;
391 EXPECT_CALL(mock, HandlePolicyResponse(_)).Times(0);
392 em::DevicePolicyRequest request;
393 request.set_policy_scope(kChromePolicyScope);
394 em::DevicePolicySettingRequest* setting_request =
395 request.add_setting_request();
396 setting_request->set_key(kChromeDevicePolicySettingKey);
397 setting_request->set_watermark("stale");
398 backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
399 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
400 ASSERT_TRUE(fetcher);
401
402 // There shouldn't be any callbacks.
403 backend_.reset();
404 }
405
TEST_F(DeviceManagementServiceTest,JobQueueing)406 TEST_F(DeviceManagementServiceTest, JobQueueing) {
407 // Start with a non-initialized service.
408 ResetService();
409
410 // Make a request. We should not see any fetchers being created.
411 DeviceRegisterResponseDelegateMock mock;
412 em::DeviceRegisterResponse expected_response;
413 expected_response.set_device_management_token(kDMToken);
414 EXPECT_CALL(mock, HandleRegisterResponse(MessageEquals(expected_response)));
415 em::DeviceRegisterRequest request;
416 backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
417 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
418 ASSERT_FALSE(fetcher);
419
420 // Now initialize the service. That should start the job.
421 service_->Initialize(request_context_.get());
422 fetcher = factory_.GetFetcherByID(0);
423 ASSERT_TRUE(fetcher);
424 factory_.RemoveFetcherFromMap(0);
425
426 // Check that the request is processed as expected.
427 std::string response_data;
428 em::DeviceManagementResponse response_wrapper;
429 response_wrapper.mutable_register_response()->CopyFrom(expected_response);
430 ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
431 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
432 fetcher->delegate()->OnURLFetchComplete(fetcher,
433 GURL(kServiceUrl),
434 status,
435 200,
436 ResponseCookies(),
437 response_data);
438 }
439
TEST_F(DeviceManagementServiceTest,CancelRequestAfterShutdown)440 TEST_F(DeviceManagementServiceTest, CancelRequestAfterShutdown) {
441 DevicePolicyResponseDelegateMock mock;
442 EXPECT_CALL(mock, HandlePolicyResponse(_)).Times(0);
443 em::DevicePolicyRequest request;
444 request.set_policy_scope(kChromePolicyScope);
445 em::DevicePolicySettingRequest* setting_request =
446 request.add_setting_request();
447 setting_request->set_key(kChromeDevicePolicySettingKey);
448 setting_request->set_watermark("stale");
449 backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
450 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
451 ASSERT_TRUE(fetcher);
452
453 // Shutdown the service and cancel the job afterwards.
454 service_->Shutdown();
455 backend_.reset();
456 }
457
TEST_F(DeviceManagementServiceTest,CancelDuringCallback)458 TEST_F(DeviceManagementServiceTest, CancelDuringCallback) {
459 // Make a request.
460 DeviceRegisterResponseDelegateMock mock;
461 EXPECT_CALL(mock, OnError(_))
462 .WillOnce(InvokeWithoutArgs(this,
463 &DeviceManagementServiceTest::ResetBackend))
464 .RetiresOnSaturation();
465 em::DeviceRegisterRequest request;
466 backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
467 TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
468 ASSERT_TRUE(fetcher);
469
470 // Generate a callback.
471 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
472 fetcher->delegate()->OnURLFetchComplete(fetcher,
473 GURL(kServiceUrl),
474 status,
475 500,
476 ResponseCookies(),
477 "");
478
479 // Backend should have been reset.
480 EXPECT_FALSE(backend_.get());
481 }
482
483 } // namespace policy
484