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/run_loop.h"
13#include "base/strings/stringprintf.h"
14#include "base/values.h"
15#include "chrome/browser/browser_process.h"
16#include "chrome/common/pref_names.h"
17#include "chrome/test/base/scoped_testing_local_state.h"
18#include "chrome/test/base/testing_browser_process.h"
19#include "components/policy/core/common/cloud/mock_device_management_service.h"
20#include "content/public/test/test_browser_thread_bundle.h"
21#include "crypto/sha2.h"
22#include "net/url_request/url_request_context_getter.h"
23#include "net/url_request/url_request_test_util.h"
24#include "testing/gmock/include/gmock/gmock.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27namespace em = enterprise_management;
28
29namespace policy {
30
31namespace {
32
33const char kStateKey[] = "state_key";
34const char kStateKeyHash[] =
35    "\xde\x74\xcd\xf0\x03\x36\x8c\x21\x79\xba\xb1\x5a\xc4\x32\xee\xd6"
36    "\xb3\x4a\x5e\xff\x73\x7e\x92\xd9\xf8\x6e\x72\x44\xd0\x97\xc3\xe6";
37
38using ::testing::InSequence;
39using ::testing::Mock;
40using ::testing::SaveArg;
41using ::testing::_;
42
43class AutoEnrollmentClientTest : public testing::Test {
44 protected:
45  AutoEnrollmentClientTest()
46      : scoped_testing_local_state_(
47            TestingBrowserProcess::GetGlobal()),
48        local_state_(scoped_testing_local_state_.Get()),
49        state_(AUTO_ENROLLMENT_STATE_PENDING) {}
50
51  virtual void SetUp() OVERRIDE {
52    CreateClient(kStateKey, true, 4, 8);
53    ASSERT_FALSE(local_state_->GetUserPref(prefs::kShouldAutoEnroll));
54    ASSERT_FALSE(local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit));
55  }
56
57  virtual void TearDown() OVERRIDE {
58    // Flush any deletion tasks.
59    base::RunLoop().RunUntilIdle();
60  }
61
62  void CreateClient(const std::string& state_key,
63                    bool retrieve_device_state,
64                    int power_initial,
65                    int power_limit) {
66    state_ = AUTO_ENROLLMENT_STATE_PENDING;
67    service_.reset(new MockDeviceManagementService());
68    EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _))
69        .WillRepeatedly(SaveArg<6>(&last_request_));
70    client_.reset(new AutoEnrollmentClient(
71        base::Bind(&AutoEnrollmentClientTest::ProgressCallback,
72                   base::Unretained(this)),
73        service_.get(),
74        local_state_,
75        new net::TestURLRequestContextGetter(
76            base::MessageLoop::current()->message_loop_proxy()),
77        state_key,
78        retrieve_device_state,
79        power_initial,
80        power_limit));
81  }
82
83  void ProgressCallback(AutoEnrollmentState state) {
84    state_ = state;
85  }
86
87  void ServerWillFail(DeviceManagementStatus error) {
88    em::DeviceManagementResponse dummy_response;
89    EXPECT_CALL(*service_,
90                CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _))
91        .WillOnce(service_->FailJob(error));
92  }
93
94  void ServerWillReply(int64 modulus, bool with_hashes, bool with_id_hash) {
95    em::DeviceManagementResponse response;
96    em::DeviceAutoEnrollmentResponse* enrollment_response =
97        response.mutable_auto_enrollment_response();
98    if (modulus >= 0)
99      enrollment_response->set_expected_modulus(modulus);
100    if (with_hashes) {
101      for (int i = 0; i < 10; ++i) {
102        std::string state_key = base::StringPrintf("state_key %d", i);
103        std::string hash = crypto::SHA256HashString(state_key);
104        enrollment_response->mutable_hash()->Add()->assign(hash);
105      }
106    }
107    if (with_id_hash) {
108      enrollment_response->mutable_hash()->Add()->assign(kStateKeyHash,
109                                                         crypto::kSHA256Length);
110    }
111    EXPECT_CALL(*service_,
112                CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _))
113        .WillOnce(service_->SucceedJob(response));
114  }
115
116  void ServerWillSendState(
117      const std::string& management_domain,
118      em::DeviceStateRetrievalResponse::RestoreMode restore_mode) {
119    em::DeviceManagementResponse response;
120    em::DeviceStateRetrievalResponse* state_response =
121        response.mutable_device_state_retrieval_response();
122    state_response->set_restore_mode(restore_mode);
123    state_response->set_management_domain(management_domain);
124    EXPECT_CALL(
125        *service_,
126        CreateJob(DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL, _))
127        .WillOnce(service_->SucceedJob(response));
128  }
129
130  void ServerWillReplyAsync(MockDeviceManagementJob** job) {
131    EXPECT_CALL(*service_,
132                CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _))
133        .WillOnce(service_->CreateAsyncJob(job));
134  }
135
136  bool HasCachedDecision() {
137    return local_state_->GetUserPref(prefs::kShouldAutoEnroll);
138  }
139
140  void VerifyCachedResult(bool should_enroll, int power_limit) {
141    base::FundamentalValue value_should_enroll(should_enroll);
142    base::FundamentalValue value_power_limit(power_limit);
143    EXPECT_TRUE(base::Value::Equals(
144        &value_should_enroll,
145        local_state_->GetUserPref(prefs::kShouldAutoEnroll)));
146    EXPECT_TRUE(base::Value::Equals(
147        &value_power_limit,
148        local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit)));
149  }
150
151  const em::DeviceAutoEnrollmentRequest& auto_enrollment_request() {
152    return last_request_.auto_enrollment_request();
153  }
154
155  content::TestBrowserThreadBundle browser_threads_;
156  ScopedTestingLocalState scoped_testing_local_state_;
157  TestingPrefServiceSimple* local_state_;
158  scoped_ptr<MockDeviceManagementService> service_;
159  scoped_ptr<AutoEnrollmentClient> client_;
160  em::DeviceManagementRequest last_request_;
161  AutoEnrollmentState state_;
162
163 private:
164  DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientTest);
165};
166
167TEST_F(AutoEnrollmentClientTest, NetworkFailure) {
168  ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
169  client_->Start();
170  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
171  EXPECT_FALSE(HasCachedDecision());
172}
173
174TEST_F(AutoEnrollmentClientTest, EmptyReply) {
175  ServerWillReply(-1, false, false);
176  client_->Start();
177  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
178  VerifyCachedResult(false, 8);
179}
180
181TEST_F(AutoEnrollmentClientTest, ClientUploadsRightBits) {
182  ServerWillReply(-1, false, false);
183  client_->Start();
184  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
185
186  EXPECT_TRUE(auto_enrollment_request().has_remainder());
187  EXPECT_TRUE(auto_enrollment_request().has_modulus());
188  EXPECT_EQ(16, auto_enrollment_request().modulus());
189  EXPECT_EQ(kStateKeyHash[31] & 0xf, auto_enrollment_request().remainder());
190  VerifyCachedResult(false, 8);
191}
192
193TEST_F(AutoEnrollmentClientTest, AskForMoreThenFail) {
194  InSequence sequence;
195  ServerWillReply(32, false, false);
196  ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
197  client_->Start();
198  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
199  EXPECT_FALSE(HasCachedDecision());
200}
201
202TEST_F(AutoEnrollmentClientTest, AskForMoreThenEvenMore) {
203  InSequence sequence;
204  ServerWillReply(32, false, false);
205  ServerWillReply(64, false, false);
206  client_->Start();
207  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
208  EXPECT_FALSE(HasCachedDecision());
209}
210
211TEST_F(AutoEnrollmentClientTest, AskForLess) {
212  InSequence sequence;
213  ServerWillReply(8, false, false);
214  ServerWillReply(-1, true, true);
215  ServerWillSendState(
216      "example.com",
217      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
218  client_->Start();
219  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
220  VerifyCachedResult(true, 8);
221}
222
223TEST_F(AutoEnrollmentClientTest, AskForSame) {
224  InSequence sequence;
225  ServerWillReply(16, false, false);
226  ServerWillReply(-1, true, true);
227  ServerWillSendState(
228      "example.com",
229      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
230  client_->Start();
231  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
232  VerifyCachedResult(true, 8);
233}
234
235TEST_F(AutoEnrollmentClientTest, AskForSameTwice) {
236  InSequence sequence;
237  ServerWillReply(16, false, false);
238  ServerWillReply(16, false, false);
239  client_->Start();
240  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
241  EXPECT_FALSE(HasCachedDecision());
242}
243
244TEST_F(AutoEnrollmentClientTest, AskForTooMuch) {
245  ServerWillReply(512, false, false);
246  client_->Start();
247  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
248  EXPECT_FALSE(HasCachedDecision());
249}
250
251TEST_F(AutoEnrollmentClientTest, AskNonPowerOf2) {
252  InSequence sequence;
253  ServerWillReply(100, false, false);
254  ServerWillReply(-1, false, false);
255  client_->Start();
256  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
257  EXPECT_TRUE(auto_enrollment_request().has_remainder());
258  EXPECT_TRUE(auto_enrollment_request().has_modulus());
259  EXPECT_EQ(128, auto_enrollment_request().modulus());
260  EXPECT_EQ(kStateKeyHash[31] & 0x7f, auto_enrollment_request().remainder());
261  VerifyCachedResult(false, 8);
262}
263
264TEST_F(AutoEnrollmentClientTest, ConsumerDevice) {
265  ServerWillReply(-1, true, false);
266  client_->Start();
267  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
268  VerifyCachedResult(false, 8);
269
270  // Network changes don't trigger retries after obtaining a response from
271  // the server.
272  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
273  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
274}
275
276TEST_F(AutoEnrollmentClientTest, EnterpriseDevice) {
277  ServerWillReply(-1, true, true);
278  ServerWillSendState(
279      "example.com",
280      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
281  client_->Start();
282  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
283  VerifyCachedResult(true, 8);
284
285  // Network changes don't trigger retries after obtaining a response from
286  // the server.
287  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
288  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
289}
290
291TEST_F(AutoEnrollmentClientTest, NoSerial) {
292  CreateClient("", true, 4, 8);
293  client_->Start();
294  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
295  EXPECT_FALSE(HasCachedDecision());
296}
297
298TEST_F(AutoEnrollmentClientTest, NoBitsUploaded) {
299  CreateClient(kStateKey, true, 0, 0);
300  ServerWillReply(-1, false, false);
301  client_->Start();
302  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
303  EXPECT_TRUE(auto_enrollment_request().has_remainder());
304  EXPECT_TRUE(auto_enrollment_request().has_modulus());
305  EXPECT_EQ(1, auto_enrollment_request().modulus());
306  EXPECT_EQ(0, auto_enrollment_request().remainder());
307  VerifyCachedResult(false, 0);
308}
309
310TEST_F(AutoEnrollmentClientTest, ManyBitsUploaded) {
311  int64 bottom62 = GG_INT64_C(0x386e7244d097c3e6);
312  for (int i = 0; i <= 62; ++i) {
313    CreateClient(kStateKey, true, i, i);
314    ServerWillReply(-1, false, false);
315    client_->Start();
316    EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
317    EXPECT_TRUE(auto_enrollment_request().has_remainder());
318    EXPECT_TRUE(auto_enrollment_request().has_modulus());
319    EXPECT_EQ(GG_INT64_C(1) << i, auto_enrollment_request().modulus());
320    EXPECT_EQ(bottom62 % (GG_INT64_C(1) << i),
321              auto_enrollment_request().remainder());
322    VerifyCachedResult(false, i);
323  }
324}
325
326TEST_F(AutoEnrollmentClientTest, MoreThan32BitsUploaded) {
327  CreateClient(kStateKey, true, 10, 37);
328  InSequence sequence;
329  ServerWillReply(GG_INT64_C(1) << 37, false, false);
330  ServerWillReply(-1, true, true);
331  ServerWillSendState(
332      "example.com",
333      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
334  client_->Start();
335  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
336  VerifyCachedResult(true, 37);
337}
338
339TEST_F(AutoEnrollmentClientTest, ReuseCachedDecision) {
340  EXPECT_CALL(*service_, CreateJob(_, _)).Times(0);
341  local_state_->SetUserPref(prefs::kShouldAutoEnroll,
342                            new base::FundamentalValue(true));
343  local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit,
344                            new base::FundamentalValue(8));
345  ServerWillSendState(
346      "example.com",
347      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
348  client_->Start();
349  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
350  AutoEnrollmentClient::CancelAutoEnrollment();
351  client_->Start();
352  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
353}
354
355TEST_F(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) {
356  local_state_->SetUserPref(prefs::kShouldAutoEnroll,
357                            new base::FundamentalValue(false));
358  local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit,
359                            new base::FundamentalValue(8));
360  CreateClient(kStateKey, true, 5, 10);
361  ServerWillReply(-1, true, true);
362  ServerWillSendState(
363      "example.com",
364      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
365  client_->Start();
366  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
367}
368
369TEST_F(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) {
370  ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
371  client_->Start();
372  // Don't invoke the callback if there was a network failure.
373  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
374  EXPECT_FALSE(HasCachedDecision());
375
376  // The client doesn't retry if no new connection became available.
377  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
378  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
379  EXPECT_FALSE(HasCachedDecision());
380
381  // Retry once the network is back.
382  ServerWillReply(-1, true, true);
383  ServerWillSendState(
384      "example.com",
385      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
386  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
387  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
388  EXPECT_TRUE(HasCachedDecision());
389
390  // Subsequent network changes don't trigger retries.
391  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
392  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
393  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
394  EXPECT_TRUE(HasCachedDecision());
395}
396
397TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonWithPendingRequest) {
398  MockDeviceManagementJob* job = NULL;
399  ServerWillReplyAsync(&job);
400  EXPECT_FALSE(job);
401  client_->Start();
402  ASSERT_TRUE(job);
403  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
404
405  // Cancel while a request is in flight.
406  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
407  client_.release()->CancelAndDeleteSoon();
408  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
409
410  // The client cleans itself up once a reply is received.
411  job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE,
412                    em::DeviceManagementResponse());
413  // The DeleteSoon task has been posted:
414  EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting());
415  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
416}
417
418TEST_F(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) {
419  MockDeviceManagementJob* job = NULL;
420  ServerWillReplyAsync(&job);
421  EXPECT_FALSE(job);
422  client_->Start();
423  ASSERT_TRUE(job);
424  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
425
426  // Cancel while a request is in flight.
427  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
428  AutoEnrollmentClient* client = client_.release();
429  client->CancelAndDeleteSoon();
430  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
431
432  // Network change events are ignored while a request is pending.
433  client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
434  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
435
436  // The client cleans itself up once a reply is received.
437  job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE,
438                    em::DeviceManagementResponse());
439  // The DeleteSoon task has been posted:
440  EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting());
441  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
442
443  // Network changes that have been posted before are also ignored:
444  client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
445  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
446}
447
448TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) {
449  ServerWillReply(-1, true, true);
450  ServerWillSendState(
451      "example.com",
452      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
453  client_->Start();
454  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
455
456  // The client will delete itself immediately if there are no pending
457  // requests.
458  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
459  client_.release()->CancelAndDeleteSoon();
460  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
461}
462
463TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) {
464  ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
465  client_->Start();
466  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
467
468  // The client will delete itself immediately if there are no pending
469  // requests.
470  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
471  client_.release()->CancelAndDeleteSoon();
472  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
473}
474
475TEST_F(AutoEnrollmentClientTest, NetworkFailureThenRequireUpdatedModulus) {
476  // This test verifies that if the first request fails due to a network
477  // problem then the second request will correctly handle an updated
478  // modulus request from the server.
479
480  ServerWillFail(DM_STATUS_REQUEST_FAILED);
481  client_->Start();
482  // Callback should signal the connection error.
483  EXPECT_EQ(AUTO_ENROLLMENT_STATE_CONNECTION_ERROR, state_);
484  EXPECT_FALSE(HasCachedDecision());
485  Mock::VerifyAndClearExpectations(service_.get());
486
487  InSequence sequence;
488  // The default client uploads 4 bits. Make the server ask for 5.
489  ServerWillReply(1 << 5, false, false);
490  EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _));
491  // Then reply with a valid response and include the hash.
492  ServerWillReply(-1, true, true);
493  EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _));
494  // State download triggers.
495  ServerWillSendState(
496      "example.com",
497      em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
498  EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _));
499
500  // Trigger a network change event.
501  client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
502  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
503  EXPECT_TRUE(HasCachedDecision());
504  Mock::VerifyAndClearExpectations(service_.get());
505}
506
507TEST_F(AutoEnrollmentClientTest, NoDeviceStateRetrieval) {
508  CreateClient(kStateKey, false, 4, 8);
509  ServerWillReply(-1, true, true);
510  EXPECT_CALL(*service_,
511              CreateJob(DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL,
512                        _)).Times(0);
513  client_->Start();
514  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
515  VerifyCachedResult(true, 8);
516}
517
518}  // namespace
519}  // namespace policy
520