auto_enrollment_client_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "chrome/browser/chromeos/policy/auto_enrollment_client.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/message_loop/message_loop.h" 10#include "base/prefs/pref_service.h" 11#include "base/prefs/testing_pref_service.h" 12#include "base/values.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/common/pref_names.h" 15#include "chrome/test/base/scoped_testing_local_state.h" 16#include "chrome/test/base/testing_browser_process.h" 17#include "components/policy/core/common/cloud/mock_device_management_service.h" 18#include "content/public/test/test_browser_thread_bundle.h" 19#include "crypto/sha2.h" 20#include "net/url_request/url_request_context_getter.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 25namespace em = enterprise_management; 26 27namespace policy { 28 29namespace { 30 31const char* kSerial = "serial"; 32const char* kSerialHash = 33 "\x01\x44\xb1\xde\xfc\xf7\x56\x10\x87\x01\x5f\x8d\x83\x0d\x65\xb1" 34 "\x6f\x02\x4a\xd7\xeb\x92\x45\xfc\xd4\xe4\x37\xa1\x55\x2b\x13\x8a"; 35 36using ::testing::InSequence; 37using ::testing::SaveArg; 38using ::testing::_; 39 40class AutoEnrollmentClientTest : public testing::Test { 41 protected: 42 AutoEnrollmentClientTest() 43 : scoped_testing_local_state_( 44 TestingBrowserProcess::GetGlobal()), 45 local_state_(scoped_testing_local_state_.Get()), 46 completion_callback_count_(0) {} 47 48 virtual void SetUp() OVERRIDE { 49 CreateClient(kSerial, 4, 8); 50 ASSERT_FALSE(local_state_->GetUserPref(prefs::kShouldAutoEnroll)); 51 ASSERT_FALSE(local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit)); 52 } 53 54 void CreateClient(const std::string& serial, 55 int power_initial, 56 int power_limit) { 57 service_.reset(new MockDeviceManagementService()); 58 EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _)) 59 .WillRepeatedly(SaveArg<6>(&last_request_)); 60 base::Closure callback = 61 base::Bind(&AutoEnrollmentClientTest::CompletionCallback, 62 base::Unretained(this)); 63 client_.reset(new AutoEnrollmentClient( 64 callback, 65 service_.get(), 66 local_state_, 67 new net::TestURLRequestContextGetter( 68 base::MessageLoop::current()->message_loop_proxy()), 69 serial, 70 power_initial, 71 power_limit)); 72 } 73 74 void CompletionCallback() { 75 completion_callback_count_++; 76 } 77 78 void ServerWillFail(DeviceManagementStatus error) { 79 em::DeviceManagementResponse dummy_response; 80 EXPECT_CALL(*service_, 81 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _)) 82 .WillOnce(service_->FailJob(error)); 83 } 84 85 void ServerWillReply(int64 modulus, bool with_hashes, bool with_serial_hash) { 86 em::DeviceManagementResponse response; 87 em::DeviceAutoEnrollmentResponse* enrollment_response = 88 response.mutable_auto_enrollment_response(); 89 if (modulus >= 0) 90 enrollment_response->set_expected_modulus(modulus); 91 if (with_hashes) { 92 for (size_t i = 0; i < 10; ++i) { 93 std::string serial = "serial X"; 94 serial[7] = '0' + i; 95 std::string hash = crypto::SHA256HashString(serial); 96 enrollment_response->mutable_hash()->Add()->assign(hash); 97 } 98 } 99 if (with_serial_hash) { 100 enrollment_response->mutable_hash()->Add()->assign(kSerialHash, 101 crypto::kSHA256Length); 102 } 103 EXPECT_CALL(*service_, 104 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _)) 105 .WillOnce(service_->SucceedJob(response)); 106 } 107 108 void ServerWillReplyAsync(MockDeviceManagementJob** job) { 109 EXPECT_CALL(*service_, 110 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _)) 111 .WillOnce(service_->CreateAsyncJob(job)); 112 } 113 114 bool HasCachedDecision() { 115 return local_state_->GetUserPref(prefs::kShouldAutoEnroll); 116 } 117 118 void VerifyCachedResult(bool should_enroll, int power_limit) { 119 base::FundamentalValue value_should_enroll(should_enroll); 120 base::FundamentalValue value_power_limit(power_limit); 121 EXPECT_TRUE(base::Value::Equals( 122 &value_should_enroll, 123 local_state_->GetUserPref(prefs::kShouldAutoEnroll))); 124 EXPECT_TRUE(base::Value::Equals( 125 &value_power_limit, 126 local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit))); 127 } 128 129 const em::DeviceAutoEnrollmentRequest& auto_enrollment_request() { 130 return last_request_.auto_enrollment_request(); 131 } 132 133 content::TestBrowserThreadBundle browser_threads_; 134 ScopedTestingLocalState scoped_testing_local_state_; 135 TestingPrefServiceSimple* local_state_; 136 scoped_ptr<MockDeviceManagementService> service_; 137 scoped_ptr<AutoEnrollmentClient> client_; 138 em::DeviceManagementRequest last_request_; 139 int completion_callback_count_; 140 141 private: 142 DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientTest); 143}; 144 145TEST_F(AutoEnrollmentClientTest, NetworkFailure) { 146 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 147 client_->Start(); 148 EXPECT_FALSE(client_->should_auto_enroll()); 149 EXPECT_EQ(0, completion_callback_count_); 150 EXPECT_FALSE(HasCachedDecision()); 151} 152 153TEST_F(AutoEnrollmentClientTest, EmptyReply) { 154 ServerWillReply(-1, false, false); 155 client_->Start(); 156 EXPECT_FALSE(client_->should_auto_enroll()); 157 EXPECT_EQ(1, completion_callback_count_); 158 VerifyCachedResult(false, 8); 159} 160 161TEST_F(AutoEnrollmentClientTest, ClientUploadsRightBits) { 162 ServerWillReply(-1, false, false); 163 client_->Start(); 164 EXPECT_FALSE(client_->should_auto_enroll()); 165 EXPECT_EQ(1, completion_callback_count_); 166 167 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 168 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 169 EXPECT_EQ(16, auto_enrollment_request().modulus()); 170 EXPECT_EQ(kSerialHash[31] & 0xf, auto_enrollment_request().remainder()); 171 VerifyCachedResult(false, 8); 172} 173 174TEST_F(AutoEnrollmentClientTest, AskForMoreThenFail) { 175 InSequence sequence; 176 ServerWillReply(32, false, false); 177 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 178 client_->Start(); 179 EXPECT_FALSE(client_->should_auto_enroll()); 180 EXPECT_EQ(0, completion_callback_count_); 181 EXPECT_FALSE(HasCachedDecision()); 182} 183 184TEST_F(AutoEnrollmentClientTest, AskForMoreThenEvenMore) { 185 InSequence sequence; 186 ServerWillReply(32, false, false); 187 ServerWillReply(64, false, false); 188 client_->Start(); 189 EXPECT_FALSE(client_->should_auto_enroll()); 190 EXPECT_EQ(1, completion_callback_count_); 191 EXPECT_FALSE(HasCachedDecision()); 192} 193 194TEST_F(AutoEnrollmentClientTest, AskForLess) { 195 InSequence sequence; 196 ServerWillReply(8, false, false); 197 ServerWillReply(-1, true, true); 198 client_->Start(); 199 EXPECT_TRUE(client_->should_auto_enroll()); 200 EXPECT_EQ(1, completion_callback_count_); 201 VerifyCachedResult(true, 8); 202} 203 204TEST_F(AutoEnrollmentClientTest, AskForSame) { 205 InSequence sequence; 206 ServerWillReply(16, false, false); 207 ServerWillReply(-1, true, true); 208 client_->Start(); 209 EXPECT_TRUE(client_->should_auto_enroll()); 210 EXPECT_EQ(1, completion_callback_count_); 211 VerifyCachedResult(true, 8); 212} 213 214TEST_F(AutoEnrollmentClientTest, AskForSameTwice) { 215 InSequence sequence; 216 ServerWillReply(16, false, false); 217 ServerWillReply(16, false, false); 218 client_->Start(); 219 EXPECT_FALSE(client_->should_auto_enroll()); 220 EXPECT_EQ(1, completion_callback_count_); 221 EXPECT_FALSE(HasCachedDecision()); 222} 223 224TEST_F(AutoEnrollmentClientTest, AskForTooMuch) { 225 ServerWillReply(512, false, false); 226 client_->Start(); 227 EXPECT_FALSE(client_->should_auto_enroll()); 228 EXPECT_EQ(1, completion_callback_count_); 229 EXPECT_FALSE(HasCachedDecision()); 230} 231 232TEST_F(AutoEnrollmentClientTest, AskNonPowerOf2) { 233 InSequence sequence; 234 ServerWillReply(100, false, false); 235 ServerWillReply(-1, false, false); 236 client_->Start(); 237 EXPECT_FALSE(client_->should_auto_enroll()); 238 EXPECT_EQ(1, completion_callback_count_); 239 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 240 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 241 EXPECT_EQ(128, auto_enrollment_request().modulus()); 242 EXPECT_EQ(kSerialHash[31] & 0x7f, auto_enrollment_request().remainder()); 243 VerifyCachedResult(false, 8); 244} 245 246TEST_F(AutoEnrollmentClientTest, ConsumerDevice) { 247 ServerWillReply(-1, true, false); 248 client_->Start(); 249 EXPECT_FALSE(client_->should_auto_enroll()); 250 EXPECT_EQ(1, completion_callback_count_); 251 VerifyCachedResult(false, 8); 252 253 // Network changes don't trigger retries after obtaining a response from 254 // the server. 255 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 256 EXPECT_EQ(1, completion_callback_count_); 257} 258 259TEST_F(AutoEnrollmentClientTest, EnterpriseDevice) { 260 ServerWillReply(-1, true, true); 261 client_->Start(); 262 EXPECT_TRUE(client_->should_auto_enroll()); 263 EXPECT_EQ(1, completion_callback_count_); 264 VerifyCachedResult(true, 8); 265 266 // Network changes don't trigger retries after obtaining a response from 267 // the server. 268 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 269 EXPECT_EQ(1, completion_callback_count_); 270} 271 272TEST_F(AutoEnrollmentClientTest, NoSerial) { 273 CreateClient("", 4, 8); 274 client_->Start(); 275 EXPECT_FALSE(client_->should_auto_enroll()); 276 EXPECT_EQ(1, completion_callback_count_); 277 EXPECT_FALSE(HasCachedDecision()); 278} 279 280TEST_F(AutoEnrollmentClientTest, NoBitsUploaded) { 281 CreateClient(kSerial, 0, 0); 282 ServerWillReply(-1, false, false); 283 client_->Start(); 284 EXPECT_FALSE(client_->should_auto_enroll()); 285 EXPECT_EQ(1, completion_callback_count_); 286 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 287 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 288 EXPECT_EQ(1, auto_enrollment_request().modulus()); 289 EXPECT_EQ(0, auto_enrollment_request().remainder()); 290 VerifyCachedResult(false, 0); 291} 292 293TEST_F(AutoEnrollmentClientTest, ManyBitsUploaded) { 294 int64 bottom62 = GG_INT64_C(0x14e437a1552b138a); 295 for (int i = 0; i <= 62; ++i) { 296 completion_callback_count_ = 0; 297 CreateClient(kSerial, i, i); 298 ServerWillReply(-1, false, false); 299 client_->Start(); 300 EXPECT_FALSE(client_->should_auto_enroll()); 301 EXPECT_EQ(1, completion_callback_count_); 302 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 303 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 304 EXPECT_EQ(GG_INT64_C(1) << i, auto_enrollment_request().modulus()); 305 EXPECT_EQ(bottom62 % (GG_INT64_C(1) << i), 306 auto_enrollment_request().remainder()); 307 VerifyCachedResult(false, i); 308 } 309} 310 311TEST_F(AutoEnrollmentClientTest, MoreThan32BitsUploaded) { 312 CreateClient(kSerial, 10, 37); 313 InSequence sequence; 314 ServerWillReply(GG_INT64_C(1) << 37, false, false); 315 ServerWillReply(-1, true, true); 316 client_->Start(); 317 EXPECT_TRUE(client_->should_auto_enroll()); 318 EXPECT_EQ(1, completion_callback_count_); 319 VerifyCachedResult(true, 37); 320} 321 322TEST_F(AutoEnrollmentClientTest, ReuseCachedDecision) { 323 EXPECT_CALL(*service_, CreateJob(_, _)).Times(0); 324 local_state_->SetUserPref(prefs::kShouldAutoEnroll, 325 base::Value::CreateBooleanValue(true)); 326 local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit, 327 base::Value::CreateIntegerValue(8)); 328 client_->Start(); 329 EXPECT_TRUE(client_->should_auto_enroll()); 330 EXPECT_EQ(1, completion_callback_count_); 331 AutoEnrollmentClient::CancelAutoEnrollment(); 332 client_->Start(); 333 EXPECT_FALSE(client_->should_auto_enroll()); 334 EXPECT_EQ(2, completion_callback_count_); 335} 336 337TEST_F(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) { 338 local_state_->SetUserPref(prefs::kShouldAutoEnroll, 339 base::Value::CreateBooleanValue(false)); 340 local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit, 341 base::Value::CreateIntegerValue(8)); 342 CreateClient(kSerial, 5, 10); 343 ServerWillReply(-1, true, true); 344 client_->Start(); 345 EXPECT_TRUE(client_->should_auto_enroll()); 346 EXPECT_EQ(1, completion_callback_count_); 347} 348 349TEST_F(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) { 350 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 351 client_->Start(); 352 EXPECT_FALSE(client_->should_auto_enroll()); 353 // Don't invoke the callback if there was a network failure. 354 EXPECT_EQ(0, completion_callback_count_); 355 EXPECT_FALSE(HasCachedDecision()); 356 357 // The client doesn't retry if no new connection became available. 358 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE); 359 EXPECT_FALSE(client_->should_auto_enroll()); 360 EXPECT_EQ(0, completion_callback_count_); 361 EXPECT_FALSE(HasCachedDecision()); 362 363 // Retry once the network is back. 364 ServerWillReply(-1, true, true); 365 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 366 EXPECT_TRUE(client_->should_auto_enroll()); 367 EXPECT_EQ(1, completion_callback_count_); 368 EXPECT_TRUE(HasCachedDecision()); 369 370 // Subsequent network changes don't trigger retries. 371 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE); 372 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 373 EXPECT_TRUE(client_->should_auto_enroll()); 374 EXPECT_EQ(1, completion_callback_count_); 375 EXPECT_TRUE(HasCachedDecision()); 376} 377 378TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonWithPendingRequest) { 379 MockDeviceManagementJob* job = NULL; 380 ServerWillReplyAsync(&job); 381 EXPECT_FALSE(job); 382 client_->Start(); 383 ASSERT_TRUE(job); 384 EXPECT_EQ(0, completion_callback_count_); 385 386 // Cancel while a request is in flight. 387 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 388 client_.release()->CancelAndDeleteSoon(); 389 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 390 391 // The client cleans itself up once a reply is received. 392 job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE, 393 em::DeviceManagementResponse()); 394 // The DeleteSoon task has been posted: 395 EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting()); 396 EXPECT_EQ(0, completion_callback_count_); 397} 398 399TEST_F(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) { 400 MockDeviceManagementJob* job = NULL; 401 ServerWillReplyAsync(&job); 402 EXPECT_FALSE(job); 403 client_->Start(); 404 ASSERT_TRUE(job); 405 EXPECT_EQ(0, completion_callback_count_); 406 407 // Cancel while a request is in flight. 408 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 409 AutoEnrollmentClient* client = client_.release(); 410 client->CancelAndDeleteSoon(); 411 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 412 413 // Network change events are ignored while a request is pending. 414 client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 415 EXPECT_EQ(0, completion_callback_count_); 416 417 // The client cleans itself up once a reply is received. 418 job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE, 419 em::DeviceManagementResponse()); 420 // The DeleteSoon task has been posted: 421 EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting()); 422 EXPECT_EQ(0, completion_callback_count_); 423 424 // Network changes that have been posted before are also ignored: 425 client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 426 EXPECT_EQ(0, completion_callback_count_); 427} 428 429TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) { 430 ServerWillReply(-1, true, true); 431 client_->Start(); 432 EXPECT_EQ(1, completion_callback_count_); 433 EXPECT_TRUE(client_->should_auto_enroll()); 434 435 // The client will delete itself immediately if there are no pending 436 // requests. 437 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 438 client_.release()->CancelAndDeleteSoon(); 439 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 440} 441 442TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) { 443 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 444 client_->Start(); 445 EXPECT_EQ(0, completion_callback_count_); 446 EXPECT_FALSE(client_->should_auto_enroll()); 447 448 // The client will delete itself immediately if there are no pending 449 // requests. 450 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 451 client_.release()->CancelAndDeleteSoon(); 452 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 453} 454 455} // namespace 456 457} // namespace policy 458