blob: aa6e112e8b50cf4d55929d37635e6e223a4284b6 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/device_sync/cryptauth_scheduler_impl.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/base64.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/timer/mock_timer.h"
#include "chromeos/network/network_state_test_helper.h"
#include "chromeos/services/device_sync/fake_cryptauth_scheduler.h"
#include "chromeos/services/device_sync/pref_names.h"
#include "chromeos/services/device_sync/proto/cryptauth_v2_test_util.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
namespace chromeos {
namespace device_sync {
namespace {
enum class NetworkConnectionStatus { kDisconnected, kConnecting, kConnected };
constexpr base::TimeDelta kZeroTimeDelta = base::TimeDelta::FromSeconds(0);
constexpr base::TimeDelta kImmediateRetryDelay =
base::TimeDelta::FromMinutes(5);
const char kWifiServiceGuid[] = "wifiGuid";
const char kSessionId[] = "sessionId";
// Serializes and base64 encodes the input ClientDirective.
// Copied from cryptauth_enrollment_scheduler_impl.cc.
// TODO(https://crbug.com/964563): Replace when utility functions are added.
std::string ClientDirectiveToPrefString(
const cryptauthv2::ClientDirective& client_directive) {
std::string encoded_serialized_client_directive;
base::Base64Encode(client_directive.SerializeAsString(),
&encoded_serialized_client_directive);
return encoded_serialized_client_directive;
}
// TODO(https://crbug.com/964563): Replace when utility functions are added.
std::string ClientMetadataToPrefString(
const cryptauthv2::ClientMetadata& client_metadata) {
std::string encoded_serialized_client_metadata;
base::Base64Encode(client_metadata.SerializeAsString(),
&encoded_serialized_client_metadata);
return encoded_serialized_client_metadata;
}
} // namespace
class DeviceSyncCryptAuthSchedulerImplTest : public testing::Test {
protected:
DeviceSyncCryptAuthSchedulerImplTest() = default;
~DeviceSyncCryptAuthSchedulerImplTest() override = default;
void SetUp() override {
CryptAuthSchedulerImpl::RegisterPrefs(pref_service_.registry());
}
void CreateScheduler(
const base::Optional<cryptauthv2::ClientDirective>&
persisted_client_directive,
const base::Optional<cryptauthv2::ClientMetadata>&
persisted_client_metadata,
const base::Optional<base::Time>& persisted_last_enrollment_attempt_time,
const base::Optional<base::Time>&
persisted_last_successful_enrollment_time) {
if (persisted_client_directive) {
pref_service_.SetString(
prefs::kCryptAuthSchedulerClientDirective,
ClientDirectiveToPrefString(*persisted_client_directive));
}
if (persisted_client_metadata) {
pref_service_.SetString(
prefs::kCryptAuthSchedulerNextEnrollmentRequestClientMetadata,
ClientMetadataToPrefString(*persisted_client_metadata));
}
if (persisted_last_enrollment_attempt_time) {
pref_service_.SetTime(prefs::kCryptAuthSchedulerLastEnrollmentAttemptTime,
*persisted_last_enrollment_attempt_time);
}
if (persisted_last_successful_enrollment_time) {
pref_service_.SetTime(
prefs::kCryptAuthSchedulerLastSuccessfulEnrollmentTime,
*persisted_last_successful_enrollment_time);
}
EXPECT_TRUE(!scheduler_);
auto mock_enrollment_timer = std::make_unique<base::MockOneShotTimer>();
mock_enrollment_timer_ = mock_enrollment_timer.get();
scheduler_ = CryptAuthSchedulerImpl::Factory::Get()->BuildInstance(
&pref_service_, network_helper_.network_state_handler(), &test_clock_,
std::move(mock_enrollment_timer));
VerifyLastEnrollmentAttemptTime(persisted_last_enrollment_attempt_time);
VerifyLastSuccessfulEnrollmentTime(
persisted_last_successful_enrollment_time);
}
void AddDisconnectedWifiNetwork() {
EXPECT_TRUE(wifi_network_service_path_.empty());
std::stringstream ss;
ss << "{"
<< " \"GUID\": \"" << kWifiServiceGuid << "\","
<< " \"Type\": \"" << shill::kTypeWifi << "\","
<< " \"State\": \"" << shill::kStateIdle << "\""
<< "}";
wifi_network_service_path_ = network_helper_.ConfigureService(ss.str());
}
void SetWifiNetworkStatus(NetworkConnectionStatus connection_status) {
std::string shill_connection_status;
switch (connection_status) {
case NetworkConnectionStatus::kDisconnected:
shill_connection_status = shill::kStateIdle;
break;
case NetworkConnectionStatus::kConnecting:
shill_connection_status = shill::kStateAssociation;
break;
case NetworkConnectionStatus::kConnected:
shill_connection_status = shill::kStateReady;
break;
}
network_helper_.SetServiceProperty(wifi_network_service_path_,
shill::kStateProperty,
base::Value(shill_connection_status));
base::RunLoop().RunUntilIdle();
}
void RemoveWifiNetwork() {
EXPECT_TRUE(!wifi_network_service_path_.empty());
network_helper_.service_test()->RemoveService(wifi_network_service_path_);
base::RunLoop().RunUntilIdle();
wifi_network_service_path_.clear();
}
void VerifyLastClientMetadataReceivedByEnrollmentDelegate(
size_t total_received,
const base::Optional<cryptauthv2::ClientMetadata>& last_received =
base::nullopt) {
EXPECT_EQ(total_received, fake_enrollment_delegate_
.client_metadata_from_enrollment_requests()
.size());
if (fake_enrollment_delegate_.client_metadata_from_enrollment_requests()
.empty())
return;
EXPECT_TRUE(last_received);
EXPECT_EQ(
last_received->SerializeAsString(),
fake_enrollment_delegate_.client_metadata_from_enrollment_requests()
.back()
.SerializeAsString());
}
void VerifyLastPolicyReferenceReceivedByEnrollmentDelegate(
size_t total_received,
const base::Optional<cryptauthv2::PolicyReference>& last_received =
base::nullopt) {
EXPECT_EQ(total_received, fake_enrollment_delegate_
.policy_references_from_enrollment_requests()
.size());
if (fake_enrollment_delegate_.policy_references_from_enrollment_requests()
.empty())
return;
EXPECT_EQ(
last_received.has_value(),
fake_enrollment_delegate_.policy_references_from_enrollment_requests()
.back()
.has_value());
if (fake_enrollment_delegate_.policy_references_from_enrollment_requests()
.back()
.has_value() &&
last_received.has_value()) {
EXPECT_EQ(
last_received->SerializeAsString(),
fake_enrollment_delegate_.policy_references_from_enrollment_requests()
.back()
->SerializeAsString());
}
}
void VerifyLastSuccessfulEnrollmentTime(
const base::Optional<base::Time>& expected_time) {
EXPECT_EQ(expected_time, scheduler_->GetLastSuccessfulEnrollmentTime());
EXPECT_EQ(pref_service_.GetTime(
prefs::kCryptAuthSchedulerLastSuccessfulEnrollmentTime),
expected_time.value_or(base::Time()));
}
void VerifyLastEnrollmentAttemptTime(
const base::Optional<base::Time>& expected_time) {
EXPECT_EQ(pref_service_.GetTime(
prefs::kCryptAuthSchedulerLastEnrollmentAttemptTime),
expected_time.value_or(base::Time()));
}
void VerifyClientDirective(
const cryptauthv2::ClientDirective& expected_client_directive) {
EXPECT_EQ(
ClientDirectiveToPrefString(expected_client_directive),
pref_service_.GetString(prefs::kCryptAuthSchedulerClientDirective));
EXPECT_EQ(base::TimeDelta::FromMilliseconds(
expected_client_directive.checkin_delay_millis()),
scheduler()->GetRefreshPeriod());
}
void VerifyScheduledEnrollment(
const cryptauthv2::ClientMetadata& expected_scheduled_enrollment_request,
const base::TimeDelta& expected_delay) {
VerifyNextEnrollmentRequest(expected_scheduled_enrollment_request);
EXPECT_TRUE(mock_enrollment_timer_->IsRunning());
EXPECT_EQ(expected_delay, mock_enrollment_timer_->GetCurrentDelay());
EXPECT_EQ(expected_delay, scheduler_->GetTimeToNextEnrollmentRequest());
EXPECT_FALSE(scheduler()->IsWaitingForEnrollmentResult());
}
void VerifyNoEnrollmentsTriggeredButRequestQueued(
const cryptauthv2::ClientMetadata& expected_enrollment_request) {
VerifyNextEnrollmentRequest(expected_enrollment_request);
EXPECT_FALSE(enrollment_timer()->IsRunning());
EXPECT_FALSE(scheduler()->IsWaitingForEnrollmentResult());
VerifyLastPolicyReferenceReceivedByEnrollmentDelegate(
0 /* total_received */);
VerifyLastClientMetadataReceivedByEnrollmentDelegate(
0 /* total_received */);
}
base::WeakPtr<FakeCryptAuthSchedulerEnrollmentDelegate>
fake_enrollment_delegate() {
return fake_enrollment_delegate_.GetWeakPtr();
}
base::SimpleTestClock* clock() { return &test_clock_; }
base::MockOneShotTimer* enrollment_timer() { return mock_enrollment_timer_; }
CryptAuthScheduler* scheduler() { return scheduler_.get(); }
private:
void VerifyNextEnrollmentRequest(
const cryptauthv2::ClientMetadata& expected_enrollment_request) {
EXPECT_EQ(
ClientMetadataToPrefString(expected_enrollment_request),
pref_service_.GetString(
prefs::kCryptAuthSchedulerNextEnrollmentRequestClientMetadata));
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
FakeCryptAuthSchedulerEnrollmentDelegate fake_enrollment_delegate_;
TestingPrefServiceSimple pref_service_;
base::SimpleTestClock test_clock_;
base::MockOneShotTimer* mock_enrollment_timer_;
NetworkStateTestHelper network_helper_{
false /* use_default_devices_and_services */};
std::string wifi_network_service_path_;
std::unique_ptr<CryptAuthScheduler> scheduler_;
DISALLOW_COPY_AND_ASSIGN(DeviceSyncCryptAuthSchedulerImplTest);
};
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
SuccessfulInitializationAndPeriodicEnrollments) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
const base::Time kStartTime = base::Time::FromDoubleT(1600600000);
const base::Time kInitializationFinishTime =
kStartTime + base::TimeDelta::FromSeconds(5);
clock()->SetNow(kStartTime);
CreateScheduler(base::nullopt /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
// No enrollment has been scheduled yet.
EXPECT_FALSE(enrollment_timer()->IsRunning());
EXPECT_EQ(base::TimeDelta::Max(),
scheduler()->GetTimeToNextEnrollmentRequest());
EXPECT_FALSE(scheduler()->HasEnrollmentSchedulingStarted());
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
EXPECT_TRUE(scheduler()->HasEnrollmentSchedulingStarted());
// No successful enrollment has ever occurred; attempt immediately.
cryptauthv2::ClientMetadata expected_scheduled_enrollment_request =
cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::INITIALIZATION,
base::nullopt /* session_id */);
VerifyScheduledEnrollment(expected_scheduled_enrollment_request,
kZeroTimeDelta /* expected_delay */);
enrollment_timer()->Fire();
EXPECT_TRUE(scheduler()->IsWaitingForEnrollmentResult());
// There is no policy reference until CryptAuth sends one with a
// ClientDirective.
VerifyLastPolicyReferenceReceivedByEnrollmentDelegate(
1 /* total_received */, base::nullopt /* last_received*/);
VerifyLastClientMetadataReceivedByEnrollmentDelegate(
1 /* total_received */, expected_scheduled_enrollment_request);
clock()->SetNow(kInitializationFinishTime);
scheduler()->HandleEnrollmentResult(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::kSuccessNewKeysEnrolled,
cryptauthv2::GetClientDirectiveForTest()));
VerifyLastEnrollmentAttemptTime(kInitializationFinishTime);
VerifyLastSuccessfulEnrollmentTime(kInitializationFinishTime);
VerifyClientDirective(cryptauthv2::GetClientDirectiveForTest());
// A periodic enrollment attempt is now scheduled.
expected_scheduled_enrollment_request = cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::PERIODIC,
base::nullopt /* session_id */);
VerifyScheduledEnrollment(
expected_scheduled_enrollment_request,
scheduler()->GetRefreshPeriod() /* expected_delay */);
base::Time periodic_fired_time =
kInitializationFinishTime + scheduler()->GetRefreshPeriod();
clock()->SetNow(periodic_fired_time);
enrollment_timer()->Fire();
VerifyLastPolicyReferenceReceivedByEnrollmentDelegate(
2 /* total_received */,
cryptauthv2::GetClientDirectiveForTest().policy_reference());
VerifyLastClientMetadataReceivedByEnrollmentDelegate(
2 /* total_received */, expected_scheduled_enrollment_request);
// Assume no new ClientDirective was received from CryptAuth this time;
// scheduler continues to use last-known ClientDirective.
scheduler()->HandleEnrollmentResult(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::kSuccessNoNewKeysNeeded,
base::nullopt /* client_directive */));
VerifyLastEnrollmentAttemptTime(periodic_fired_time);
VerifyLastSuccessfulEnrollmentTime(periodic_fired_time);
VerifyClientDirective(cryptauthv2::GetClientDirectiveForTest());
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest, FailedEnrollments) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
CreateScheduler(
cryptauthv2::GetClientDirectiveForTest() /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
cryptauthv2::ClientMetadata expected_enrollment_request =
cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::INITIALIZATION,
base::nullopt /* session_id */);
VerifyScheduledEnrollment(expected_enrollment_request,
kZeroTimeDelta /* expected_delay */);
// After using all immediate failure retry attempts allotted by the client
// directive, schedule retries using client directive's retry_period_millis.
for (int attempt = 1;
attempt <= cryptauthv2::GetClientDirectiveForTest().retry_attempts() + 3;
++attempt) {
enrollment_timer()->Fire();
VerifyLastPolicyReferenceReceivedByEnrollmentDelegate(
attempt /* total_received */,
cryptauthv2::GetClientDirectiveForTest().policy_reference());
VerifyLastClientMetadataReceivedByEnrollmentDelegate(
attempt /* total_received */, expected_enrollment_request);
scheduler()->HandleEnrollmentResult(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::kErrorCryptAuthServerOverloaded,
base::nullopt /* client_directive */));
expected_enrollment_request.set_retry_count(attempt);
base::TimeDelta expected_delay =
attempt <= cryptauthv2::GetClientDirectiveForTest().retry_attempts()
? kImmediateRetryDelay
: base::TimeDelta::FromMilliseconds(
cryptauthv2::GetClientDirectiveForTest()
.retry_period_millis());
VerifyScheduledEnrollment(expected_enrollment_request, expected_delay);
}
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
EnrollmentRequestNotScheduledUntilSchedulerStarted) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
CreateScheduler(base::nullopt /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
scheduler()->RequestEnrollment(cryptauthv2::ClientMetadata::MANUAL,
kSessionId);
cryptauthv2::ClientMetadata expected_enrollment_request =
cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::MANUAL, kSessionId);
VerifyNoEnrollmentsTriggeredButRequestQueued(expected_enrollment_request);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
VerifyScheduledEnrollment(expected_enrollment_request,
kZeroTimeDelta /* expected_delay */);
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
EnrollmentRequestScheduledAfterCurrentEnrollmentFinishes) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
CreateScheduler(base::nullopt /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
// Start a server-initiated enrollment attempt.
scheduler()->RequestEnrollment(cryptauthv2::ClientMetadata::SERVER_INITIATED,
kSessionId);
enrollment_timer()->Fire();
// Request an enrollment while an enrollment attempt is in progress.
scheduler()->RequestEnrollment(cryptauthv2::ClientMetadata::MANUAL,
base::nullopt /* session_id */);
EXPECT_FALSE(enrollment_timer()->IsRunning());
scheduler()->HandleEnrollmentResult(CryptAuthEnrollmentResult(
CryptAuthEnrollmentResult::ResultCode::kErrorCryptAuthServerOverloaded,
cryptauthv2::GetClientDirectiveForTest()));
// Pending request scheduled after current enrollment attempt finishes, even
// if it fails.
VerifyScheduledEnrollment(
cryptauthv2::BuildClientMetadata(0 /* retry_count */,
cryptauthv2::ClientMetadata::MANUAL,
base::nullopt /* session_id */),
kZeroTimeDelta /* expected_delay */);
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
ScheduledEnrollmentRequestOverwritten) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
CreateScheduler(base::nullopt /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
scheduler()->RequestEnrollment(cryptauthv2::ClientMetadata::SERVER_INITIATED,
kSessionId);
VerifyScheduledEnrollment(
cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::SERVER_INITIATED,
kSessionId),
kZeroTimeDelta /* expected_delay */);
scheduler()->RequestEnrollment(cryptauthv2::ClientMetadata::MANUAL,
base::nullopt /* session_id */);
VerifyScheduledEnrollment(
cryptauthv2::BuildClientMetadata(0 /* retry_count */,
cryptauthv2::ClientMetadata::MANUAL,
base::nullopt /* session_id */),
kZeroTimeDelta /* expected_delay */);
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
ScheduleFailureRecoveryEnrollmentRequestOnStartUp) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
const base::Time kLastEnrollmentTime = base::Time::FromDoubleT(1600600000);
const base::Time kLastEnrollmentAttemptTime =
kLastEnrollmentTime + base::TimeDelta::FromDays(30);
const base::Time kStartTime =
kLastEnrollmentAttemptTime + (kImmediateRetryDelay / 2);
clock()->SetNow(kStartTime);
cryptauthv2::ClientMetadata persisted_enrollment_request =
cryptauthv2::BuildClientMetadata(5 /* retry_count */,
cryptauthv2::ClientMetadata::PERIODIC,
base::nullopt /* session_id */);
CreateScheduler(
cryptauthv2::GetClientDirectiveForTest() /* persisted_client_directive */,
persisted_enrollment_request /* persisted_client_metadata */,
kLastEnrollmentAttemptTime /* persisted_last_enrollment_attempt_time */,
kLastEnrollmentTime /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
// Retry count is reset to 1 on start-up so quick retry is triggered.
EXPECT_GT(cryptauthv2::GetClientDirectiveForTest().retry_attempts(), 0);
persisted_enrollment_request.set_retry_count(1);
VerifyScheduledEnrollment(persisted_enrollment_request,
kImmediateRetryDelay / 2 /* expected_delay */);
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest, EnrollmentRequestedWhileOffline) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kDisconnected);
CreateScheduler(base::nullopt /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
cryptauthv2::ClientMetadata expected_enrollment_request =
cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::INITIALIZATION,
base::nullopt /* session_id */);
VerifyScheduledEnrollment(expected_enrollment_request,
kZeroTimeDelta /* expected_delay */);
enrollment_timer()->Fire();
VerifyNoEnrollmentsTriggeredButRequestQueued(expected_enrollment_request);
SetWifiNetworkStatus(NetworkConnectionStatus::kConnecting);
VerifyNoEnrollmentsTriggeredButRequestQueued(expected_enrollment_request);
// Once Wifi network connected, reschedule enrollment.
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
VerifyScheduledEnrollment(expected_enrollment_request,
kZeroTimeDelta /* expected_delay */);
enrollment_timer()->Fire();
EXPECT_TRUE(scheduler()->IsWaitingForEnrollmentResult());
VerifyLastPolicyReferenceReceivedByEnrollmentDelegate(
1 /* total_received */, base::nullopt /* last_received*/);
VerifyLastClientMetadataReceivedByEnrollmentDelegate(
1 /* total_received */, expected_enrollment_request);
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
EnrollmentRequestedWithNoWifiNetwork) {
const base::Time kNow = base::Time::FromDoubleT(1600600000);
clock()->SetNow(kNow);
cryptauthv2::ClientMetadata expected_enrollment_request =
cryptauthv2::BuildClientMetadata(0 /* retry_count */,
cryptauthv2::ClientMetadata::PERIODIC,
base::nullopt /* session_id */);
CreateScheduler(
cryptauthv2::GetClientDirectiveForTest() /* persisted_client_directive */,
expected_enrollment_request /* persisted_client_metadata */,
kNow /* persisted_last_enrollment_attempt_time */,
kNow /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
VerifyScheduledEnrollment(expected_enrollment_request,
scheduler()->GetRefreshPeriod());
enrollment_timer()->Fire();
VerifyNoEnrollmentsTriggeredButRequestQueued(expected_enrollment_request);
// Once Wifi network connected, reschedule enrollment.
const base::TimeDelta kTimeElapsed = base::TimeDelta::FromHours(10);
clock()->SetNow(kNow + kTimeElapsed);
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
VerifyScheduledEnrollment(expected_enrollment_request,
scheduler()->GetRefreshPeriod() - kTimeElapsed);
}
TEST_F(DeviceSyncCryptAuthSchedulerImplTest,
EnrollmentScheduledAndWifiNetworkRemoved) {
AddDisconnectedWifiNetwork();
SetWifiNetworkStatus(NetworkConnectionStatus::kConnected);
CreateScheduler(base::nullopt /* persisted_client_directive */,
base::nullopt /* persisted_client_metadata */,
base::nullopt /* persisted_last_enrollment_attempt_time */,
base::nullopt /* persisted_last_successful_enrollment_time */
);
scheduler()->StartEnrollmentScheduling(fake_enrollment_delegate());
cryptauthv2::ClientMetadata expected_enrollment_request =
cryptauthv2::BuildClientMetadata(
0 /* retry_count */, cryptauthv2::ClientMetadata::INITIALIZATION,
base::nullopt /* session_id */);
VerifyScheduledEnrollment(expected_enrollment_request,
kZeroTimeDelta /* expected_delay */);
RemoveWifiNetwork();
enrollment_timer()->Fire();
VerifyNoEnrollmentsTriggeredButRequestQueued(expected_enrollment_request);
}
} // namespace device_sync
} // namespace chromeos