blob: a93baa8ae936baaf1169f4e4c2e5988bd8783659 [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 "chrome/browser/enterprise/reporting/report_scheduler.h"
#include <utility>
#include "base/bind_helpers.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/enterprise/reporting/prefs.h"
#include "chrome/browser/policy/fake_browser_dm_token_storage.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/upgrade_detector/build_state.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/version_info/version_info.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::base::test::RunOnceCallback;
using ::testing::_;
using ::testing::ByMove;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::WithArgs;
namespace em = enterprise_management;
namespace enterprise_reporting {
namespace {
constexpr char kDMToken[] = "dm_token";
constexpr char kClientId[] = "client_id";
constexpr char kStaleProfileCountMetricsName[] =
"Enterprise.CloudReportingStaleProfileCount";
constexpr base::TimeDelta kDefaultUploadInterval =
base::TimeDelta::FromHours(24);
#if !defined(OS_CHROMEOS)
constexpr char kUploadTriggerMetricName[] =
"Enterprise.CloudReportingUploadTrigger";
#endif
} // namespace
ACTION_P(ScheduleGeneratorCallback, request_number) {
ReportGenerator::ReportRequests requests;
for (int i = 0; i < request_number; i++)
requests.push(std::make_unique<ReportGenerator::ReportRequest>());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(arg0), std::move(requests)));
}
class MockReportGenerator : public ReportGenerator {
public:
void Generate(bool with_profiles, ReportCallback callback) override {
OnGenerate(with_profiles, callback);
}
MOCK_METHOD2(OnGenerate, void(bool with_profiles, ReportCallback& callback));
MOCK_METHOD0(GenerateBasic, ReportRequests());
};
class MockReportUploader : public ReportUploader {
public:
MockReportUploader() : ReportUploader(nullptr, 0) {}
~MockReportUploader() override = default;
MOCK_METHOD2(SetRequestAndUpload, void(ReportRequests, ReportCallback));
private:
DISALLOW_COPY_AND_ASSIGN(MockReportUploader);
};
class ReportSchedulerTest : public ::testing::Test {
public:
ReportSchedulerTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
local_state_(TestingBrowserProcess::GetGlobal()),
profile_manager_(TestingBrowserProcess::GetGlobal(), &local_state_) {}
~ReportSchedulerTest() override = default;
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
client_ptr_ = std::make_unique<policy::MockCloudPolicyClient>();
client_ = client_ptr_.get();
generator_ptr_ = std::make_unique<MockReportGenerator>();
generator_ = generator_ptr_.get();
uploader_ptr_ = std::make_unique<MockReportUploader>();
uploader_ = uploader_ptr_.get();
#if !defined(OS_CHROMEOS)
SetLastUploadVersion(chrome::kChromeVersion);
#endif
Init(true, kDMToken, kClientId);
}
void Init(bool policy_enabled,
const std::string& dm_token,
const std::string& client_id) {
ToggleCloudReport(policy_enabled);
storage_.SetDMToken(dm_token);
storage_.SetClientId(client_id);
}
void CreateScheduler() {
scheduler_ =
std::make_unique<ReportScheduler>(client_, std::move(generator_ptr_));
scheduler_->SetReportUploaderForTesting(std::move(uploader_ptr_));
}
void SetLastUploadInHour(base::TimeDelta gap) {
previous_set_last_upload_timestamp_ = base::Time::Now() - gap;
local_state_.Get()->SetTime(kLastUploadTimestamp,
previous_set_last_upload_timestamp_);
}
void ToggleCloudReport(bool enabled) {
local_state_.Get()->SetManagedPref(prefs::kCloudReportingEnabled,
std::make_unique<base::Value>(enabled));
}
#if !defined(OS_CHROMEOS)
void SetLastUploadVersion(const std::string& version) {
local_state_.Get()->SetString(kLastUploadVersion, version);
}
void ExpectLastUploadVersion(const std::string& version) {
EXPECT_EQ(local_state_.Get()->GetString(kLastUploadVersion), version);
}
#endif // !defined(OS_CHROMEOS)
// If lastUploadTimestamp is updated recently, it should be updated as Now().
// Otherwise, it should be same as previous set timestamp.
void ExpectLastUploadTimestampUpdated(bool is_updated) {
auto current_last_upload_timestamp =
local_state_.Get()->GetTime(kLastUploadTimestamp);
if (is_updated) {
EXPECT_EQ(base::Time::Now(), current_last_upload_timestamp);
} else {
EXPECT_EQ(previous_set_last_upload_timestamp_,
current_last_upload_timestamp);
}
}
ReportGenerator::ReportRequests CreateRequests(int number) {
ReportGenerator::ReportRequests requests;
for (int i = 0; i < number; i++)
requests.push(std::make_unique<ReportGenerator::ReportRequest>());
return requests;
}
// Chrome OS needn't setup registration.
void EXPECT_CALL_SetupRegistration() {
#if defined(OS_CHROMEOS)
EXPECT_CALL(*client_, SetupRegistration(_, _, _)).Times(0);
#else
EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _));
#endif
}
void EXPECT_CALL_SetupRegistrationWithSetDMToken() {
#if defined(OS_CHROMEOS)
EXPECT_CALL(*client_, SetupRegistration(_, _, _)).Times(0);
#else
EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _))
.WillOnce(WithArgs<0>(
Invoke(client_, &policy::MockCloudPolicyClient::SetDMToken)));
#endif
}
base::test::ScopedFeatureList scoped_feature_list_;
content::BrowserTaskEnvironment task_environment_;
ScopedTestingLocalState local_state_;
TestingProfileManager profile_manager_;
std::unique_ptr<ReportScheduler> scheduler_;
policy::MockCloudPolicyClient* client_;
MockReportGenerator* generator_;
MockReportUploader* uploader_;
policy::FakeBrowserDMTokenStorage storage_;
base::Time previous_set_last_upload_timestamp_;
base::HistogramTester histogram_tester_;
private:
std::unique_ptr<policy::MockCloudPolicyClient> client_ptr_;
std::unique_ptr<MockReportGenerator> generator_ptr_;
std::unique_ptr<MockReportUploader> uploader_ptr_;
DISALLOW_COPY_AND_ASSIGN(ReportSchedulerTest);
};
TEST_F(ReportSchedulerTest, NoReportWithoutPolicy) {
Init(false, kDMToken, kClientId);
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
// Chrome OS needn't set dm token and client id in the report scheduler.
#if !defined(OS_CHROMEOS)
TEST_F(ReportSchedulerTest, NoReportWithoutDMToken) {
Init(true, "", kClientId);
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
TEST_F(ReportSchedulerTest, NoReportWithoutClientId) {
Init(true, kDMToken, "");
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
#endif
TEST_F(ReportSchedulerTest, UploadReportSucceeded) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is scheduled.
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, UploadReportTransientError) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kTransientError));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is scheduled.
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, UploadReportPersistentError) {
EXPECT_CALL_SetupRegistrationWithSetDMToken();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kPersistentError));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
// Turn off and on reporting to resume.
ToggleCloudReport(false);
ToggleCloudReport(true);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, NoReportGenerate) {
EXPECT_CALL_SetupRegistrationWithSetDMToken();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(0)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)).Times(0);
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
// Turn off and on reporting to resume.
ToggleCloudReport(false);
ToggleCloudReport(true);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, TimerDelayWithLastUploadTimestamp) {
const base::TimeDelta gap = base::TimeDelta::FromHours(10);
SetLastUploadInHour(gap);
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
base::TimeDelta next_report_delay = kDefaultUploadInterval - gap;
task_environment_.FastForwardBy(next_report_delay -
base::TimeDelta::FromSeconds(1));
ExpectLastUploadTimestampUpdated(false);
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, TimerDelayWithoutLastUploadTimestamp) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
task_environment_.FastForwardBy(base::TimeDelta());
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
}
TEST_F(ReportSchedulerTest,
ReportingIsDisabledWhileNewReportIsScheduledButNotPosted) {
EXPECT_CALL_SetupRegistration();
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
ToggleCloudReport(false);
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, ReportingIsDisabledWhileNewReportIsPosted) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
ToggleCloudReport(false);
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
ExpectLastUploadTimestampUpdated(true);
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, NoStaleProfileMetricsForSystemAndGuestProfile) {
EXPECT_CALL_SetupRegistration();
CreateScheduler();
// Does not record for system or guest profile.
profile_manager_.CreateSystemProfile();
profile_manager_.CreateGuestProfile();
scheduler_.reset();
histogram_tester_.ExpectTotalCount(kStaleProfileCountMetricsName, 0);
}
TEST_F(ReportSchedulerTest, NoStaleProfileMetricsBeforeFirstReport) {
EXPECT_CALL_SetupRegistration();
CreateScheduler();
profile_manager_.CreateTestingProfile("profile1");
scheduler_.reset();
histogram_tester_.ExpectTotalCount(kStaleProfileCountMetricsName, 0);
}
TEST_F(ReportSchedulerTest, StaleProfileMetricsForProfileAdded) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
task_environment_.FastForwardBy(base::TimeDelta());
profile_manager_.CreateTestingProfile("profile1");
scheduler_.reset();
histogram_tester_.ExpectUniqueSample(kStaleProfileCountMetricsName, 1, 1);
}
TEST_F(ReportSchedulerTest, StaleProfileMetricsForProfileRemoved) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
// Create a profile a head of time to prevent default profile creation during
// profile deleting.
profile_manager_.CreateTestingProfile("profile0");
CreateScheduler();
task_environment_.FastForwardBy(base::TimeDelta());
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile1");
profile_manager_.profile_manager()->ScheduleProfileForDeletion(
profile->GetPath(), base::DoNothing());
task_environment_.FastForwardBy(base::TimeDelta());
scheduler_.reset();
histogram_tester_.ExpectUniqueSample(kStaleProfileCountMetricsName, 0, 1);
}
TEST_F(ReportSchedulerTest, StaleProfileMetricsResetAfterNewUpload) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillRepeatedly(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
task_environment_.FastForwardBy(base::TimeDelta());
// Re-assign uploader for the second upload
auto new_uploader = std::make_unique<MockReportUploader>();
uploader_ = new_uploader.get();
scheduler_->SetReportUploaderForTesting(std::move(new_uploader));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
profile_manager_.CreateTestingProfile("profile1");
task_environment_.FastForwardBy(kDefaultUploadInterval);
scheduler_.reset();
histogram_tester_.ExpectUniqueSample(kStaleProfileCountMetricsName, 0, 1);
}
#if !defined(OS_CHROMEOS)
// Tests that a basic report is generated and uploaded when a browser update is
// detected.
TEST_F(ReportSchedulerTest, OnUpdate) {
// Pretend that a periodic report was generated recently so that one isn't
// kicked off during startup.
SetLastUploadInHour(base::TimeDelta::FromHours(1));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/false, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
g_browser_process->GetBuildState()->SetUpdate(
BuildState::UpdateType::kNormalUpdate,
base::Version("1" + version_info::GetVersionNumber()), base::nullopt);
task_environment_.RunUntilIdle();
// The timestamp should not have been updated, since a periodic report was not
// generated/uploaded.
ExpectLastUploadTimestampUpdated(false);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 2, 1);
}
// Tests that a full report is generated and uploaded following a basic report
// if the timer fires while the basic report is being uploaded.
TEST_F(ReportSchedulerTest, DeferredTimer) {
EXPECT_CALL_SetupRegistration();
CreateScheduler();
// An update arrives, triggering report generation and upload (sans profiles).
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/false, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
// Hang on to the uploader's ReportCallback.
ReportUploader::ReportCallback saved_callback;
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce([&saved_callback](ReportUploader::ReportRequests requests,
ReportUploader::ReportCallback callback) {
saved_callback = std::move(callback);
});
g_browser_process->GetBuildState()->SetUpdate(
BuildState::UpdateType::kNormalUpdate,
base::Version("1" + version_info::GetVersionNumber()), base::nullopt);
task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(generator_);
::testing::Mock::VerifyAndClearExpectations(uploader_);
// Now the timer fires before the upload completes. No new report should be
// generated yet.
task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(generator_);
// Once the previous upload completes, a new report should be generated
// forthwith.
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
auto new_uploader = std::make_unique<MockReportUploader>();
EXPECT_CALL(*new_uploader, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
std::move(saved_callback).Run(ReportUploader::kSuccess);
ExpectLastUploadTimestampUpdated(false);
::testing::Mock::VerifyAndClearExpectations(generator_);
this->uploader_ = new_uploader.get();
this->scheduler_->SetReportUploaderForTesting(std::move(new_uploader));
task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(uploader_);
ExpectLastUploadTimestampUpdated(true);
histogram_tester_.ExpectBucketCount(kUploadTriggerMetricName, 1, 1);
histogram_tester_.ExpectBucketCount(kUploadTriggerMetricName, 2, 1);
}
// Tests that a basic report is generated and uploaded during startup when a
// new version is being run and the last periodic upload was less than a day
// ago.
TEST_F(ReportSchedulerTest, OnNewVersion) {
// Pretend that the last upload was from a different browser version.
SetLastUploadVersion(chrome::kChromeVersion + std::string("1"));
// Pretend that a periodic report was generated recently.
SetLastUploadInHour(base::TimeDelta::FromHours(1));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/false, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
task_environment_.RunUntilIdle();
// The timestamp should not have been updated, since a periodic report was not
// generated/uploaded.
ExpectLastUploadTimestampUpdated(false);
// The last upload is now from this version.
ExpectLastUploadVersion(chrome::kChromeVersion);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 3, 1);
}
// Tests that a full report is generated and uploaded during startup when a
// new version is being run and the last periodic upload was more than a day
// ago.
TEST_F(ReportSchedulerTest, OnNewVersionRegularReport) {
// Pretend that the last upload was from a different browser version.
SetLastUploadVersion(chrome::kChromeVersion + std::string("1"));
// Pretend that a periodic report was last generated over a day ago.
SetLastUploadInHour(base::TimeDelta::FromHours(25));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(/*with_profiles=*/true, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _))
.WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
CreateScheduler();
task_environment_.RunUntilIdle();
// The timestamp should have been updated, since a periodic report was
// generated/uploaded.
ExpectLastUploadTimestampUpdated(true);
// The last upload is now from this version.
ExpectLastUploadVersion(chrome::kChromeVersion);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 1, 1);
}
#endif // !defined(OS_CHROMEOS)
} // namespace enterprise_reporting