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