| // Copyright 2018 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/chromeos/policy/app_install_event_log_manager.h" |
| |
| #include <iterator> |
| #include <map> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/sequenced_task_runner.h" |
| #include "base/stl_util.h" |
| #include "base/test/scoped_mock_time_message_loop_task_runner.h" |
| #include "base/test/test_mock_time_task_runner.h" |
| #include "base/test/test_simple_task_runner.h" |
| #include "base/time/tick_clock.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "chrome/browser/chromeos/policy/app_install_event_log.h" |
| #include "chrome/browser/chromeos/policy/app_install_event_log_uploader.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/arc/arc_prefs.h" |
| #include "components/policy/core/common/cloud/cloud_policy_client.h" |
| #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" |
| #include "components/policy/proto/device_management_backend.pb.h" |
| #include "components/prefs/pref_service.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "extensions/browser/quota_service.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::AnyNumber; |
| using testing::Invoke; |
| using testing::Mock; |
| using testing::Pointee; |
| using testing::SaveArg; |
| using testing::_; |
| |
| namespace em = enterprise_management; |
| |
| namespace policy { |
| |
| namespace { |
| |
| constexpr base::FilePath::CharType kLogFileName[] = |
| FILE_PATH_LITERAL("app_push_install_log"); |
| constexpr base::TimeDelta kStoreDelay = base::TimeDelta::FromSeconds(5); |
| constexpr base::TimeDelta kUploadInterval = base::TimeDelta::FromHours(3); |
| constexpr base::TimeDelta kExpeditedUploadDelay = |
| base::TimeDelta::FromMinutes(15); |
| constexpr base::TimeDelta kOneMs = base::TimeDelta::FromMilliseconds(1); |
| |
| constexpr int kTotalSizeExpeditedUploadThreshold = 2048; |
| constexpr int kMaxSizeExpeditedUploadThreshold = 512; |
| |
| constexpr char kDMToken[] = "token"; |
| constexpr const char* kPackageNames[] = {"com.example.app1", "com.example.app2", |
| "com.example.app3", "com.example.app4", |
| "com.example.app5"}; |
| |
| using Events = std::map<std::string, std::vector<em::AppInstallReportLogEvent>>; |
| |
| bool ContainsSameEvents(const Events& expected, |
| const em::AppInstallReportRequest& actual) { |
| if (actual.app_install_report_size() != static_cast<int>(expected.size())) { |
| return false; |
| } |
| for (const auto& expected_app_log : expected) { |
| bool app_found = false; |
| for (int i = 0; i < actual.app_install_report_size(); ++i) { |
| const auto& actual_app_log = actual.app_install_report(i); |
| if (actual_app_log.package() == expected_app_log.first) { |
| if (actual_app_log.log_size() != |
| static_cast<int>(expected_app_log.second.size())) { |
| return false; |
| } |
| for (int j = 0; j < static_cast<int>(expected_app_log.second.size()); |
| ++j) { |
| if (actual_app_log.log(j).SerializePartialAsString() != |
| expected_app_log.second[j].SerializePartialAsString()) { |
| return false; |
| } |
| } |
| app_found = true; |
| break; |
| } |
| } |
| if (!app_found) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| MATCHER_P(MatchEvents, expected, "contains events") { |
| return ContainsSameEvents(expected, arg); |
| } |
| |
| class TestLogTaskRunnerWrapper |
| : public AppInstallEventLogManager::LogTaskRunnerWrapper { |
| public: |
| TestLogTaskRunnerWrapper() { |
| test_task_runner_ = new base::TestSimpleTaskRunner; |
| } |
| |
| scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() override { |
| return test_task_runner_; |
| } |
| |
| base::TestSimpleTaskRunner* test_task_runner() const { |
| return test_task_runner_.get(); |
| } |
| |
| private: |
| scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestLogTaskRunnerWrapper); |
| }; |
| |
| } // namespace |
| |
| class AppInstallEventLogManagerTest : public testing::Test { |
| protected: |
| AppInstallEventLogManagerTest() |
| : uploader_(&cloud_policy_client_), |
| log_task_runner_(log_task_runner_wrapper_.test_task_runner()), |
| log_file_path_(profile_.GetPath().Append(kLogFileName)), |
| packages_{std::begin(kPackageNames), std::end(kPackageNames)} {} |
| |
| // testing::Test: |
| void SetUp() override { |
| cloud_policy_client_.SetDMToken(kDMToken); |
| |
| event_.set_timestamp(0); |
| event_.set_event_type(em::AppInstallReportLogEvent::SUCCESS); |
| |
| scoped_main_task_runner_ = |
| std::make_unique<base::ScopedMockTimeMessageLoopTaskRunner>(); |
| main_task_runner_ = scoped_main_task_runner_->task_runner(); |
| } |
| |
| // testing::Test: |
| void TearDown() override { |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_CALL(cloud_policy_client_, CancelAppInstallReportUpload()) |
| .Times(AnyNumber()); |
| manager_.reset(); |
| FastForwardUntilNoTasksRemain(); |
| |
| main_task_runner_ = nullptr; |
| scoped_main_task_runner_.reset(); |
| } |
| |
| void CreateManager() { |
| manager_ = std::make_unique<AppInstallEventLogManager>( |
| &log_task_runner_wrapper_, &uploader_, &profile_); |
| FlushNonDelayedTasks(); |
| } |
| |
| void AddLogEntry(int app_index) { |
| ASSERT_GE(app_index, 0); |
| ASSERT_LT(app_index, static_cast<int>(base::size(kPackageNames))); |
| const std::string package_name = kPackageNames[app_index]; |
| events_[package_name].push_back(event_); |
| manager_->Add({kPackageNames[app_index]}, event_); |
| FlushNonDelayedTasks(); |
| event_.set_timestamp(event_.timestamp() + 1); |
| } |
| |
| void AddLogEntryForsetOfApps(const std::set<std::string>& packages) { |
| for (const auto& package_name : packages) { |
| events_[package_name].push_back(event_); |
| } |
| manager_->Add(packages, event_); |
| FlushNonDelayedTasks(); |
| event_.set_timestamp(event_.timestamp() + 1); |
| } |
| |
| void AddLogEntryForAllApps() { AddLogEntryForsetOfApps(packages_); } |
| |
| void ExpectUploadAndCaptureCallback( |
| CloudPolicyClient::StatusCallback* callback) { |
| EXPECT_CALL(cloud_policy_client_, |
| UploadAppInstallReport(Pointee(MatchEvents(events_)), _)) |
| .WillOnce(SaveArg<1>(callback)); |
| } |
| |
| void ReportUploadSuccess(const CloudPolicyClient::StatusCallback& callback) { |
| callback.Run(true /* success */); |
| FlushNonDelayedTasks(); |
| } |
| |
| void ExpectAndCompleteUpload() { |
| EXPECT_CALL(cloud_policy_client_, |
| UploadAppInstallReport(Pointee(MatchEvents(events_)), _)) |
| .WillOnce(Invoke([](const em::AppInstallReportRequest*, |
| const CloudPolicyClient::StatusCallback& callback) { |
| callback.Run(true /* success */); |
| })); |
| } |
| |
| void FlushNonDelayedTasks() { |
| main_task_runner_->RunUntilIdle(); |
| while (log_task_runner_->HasPendingTask()) { |
| log_task_runner_->RunUntilIdle(); |
| main_task_runner_->RunUntilIdle(); |
| } |
| } |
| |
| void FastForwardTo(const base::TimeDelta& offset) { |
| main_task_runner_->FastForwardBy( |
| offset - (main_task_runner_->NowTicks() - base::TimeTicks())); |
| FlushNonDelayedTasks(); |
| } |
| |
| void FastForwardUntilNoTasksRemain() { |
| main_task_runner_->FastForwardUntilNoTasksRemain(); |
| while (log_task_runner_->HasPendingTask()) { |
| log_task_runner_->RunUntilIdle(); |
| main_task_runner_->FastForwardUntilNoTasksRemain(); |
| } |
| } |
| |
| void VerifyLogFile() { |
| EXPECT_TRUE(base::PathExists(log_file_path_)); |
| AppInstallEventLog log(log_file_path_); |
| em::AppInstallReportRequest log_events; |
| log.Serialize(&log_events); |
| EXPECT_TRUE(ContainsSameEvents(events_, log_events)); |
| } |
| |
| void VerifyAndDeleteLogFile() { |
| VerifyLogFile(); |
| base::DeleteFile(log_file_path_, false /* recursive */); |
| } |
| |
| TestLogTaskRunnerWrapper log_task_runner_wrapper_; |
| content::TestBrowserThreadBundle browser_thread_bundle_; |
| extensions::QuotaService::ScopedDisablePurgeForTesting |
| disable_purge_for_testing_; |
| TestingProfile profile_; |
| MockCloudPolicyClient cloud_policy_client_; |
| AppInstallEventLogUploader uploader_; |
| std::unique_ptr<base::ScopedMockTimeMessageLoopTaskRunner> |
| scoped_main_task_runner_; |
| |
| base::TestSimpleTaskRunner* log_task_runner_ = nullptr; |
| base::TestMockTimeTaskRunner* main_task_runner_ = nullptr; |
| |
| const base::FilePath log_file_path_; |
| const std::set<std::string> packages_; |
| |
| em::AppInstallReportLogEvent event_; |
| Events events_; |
| |
| std::unique_ptr<AppInstallEventLogManager> manager_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(AppInstallEventLogManagerTest); |
| }; |
| |
| // Create a manager with an empty log. Verify that no store is scheduled and no |
| // upload occurs. |
| TEST_F(AppInstallEventLogManagerTest, CreateEmpty) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Store a populated log. Create a manager that loads the non-empty log. Delete |
| // the log. Verify that no store is scheduled and an expedited initial upload |
| // occurs after fifteen minutes. |
| TEST_F(AppInstallEventLogManagerTest, CreateNonEmpty) { |
| AppInstallEventLog log(log_file_path_); |
| events_[kPackageNames[0]].push_back(event_); |
| log.Add(kPackageNames[0], event_); |
| log.Store(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| base::DeleteFile(log_file_path_, false /* recursive */); |
| |
| FastForwardTo(kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Add a log entry after two minutes. Verify that a store is scheduled after |
| // five seconds and an expedited initial upload occurs after a total of fifteen |
| // minutes. |
| TEST_F(AppInstallEventLogManagerTest, AddBeforeInitialUpload) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(2); |
| FastForwardTo(offset); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Add four log entries at two second cadence. Verify that |
| // stores are scheduled after five and eleven seconds and an upload occurs |
| // after three hours. |
| TEST_F(AppInstallEventLogManagerTest, Add) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(offset + base::TimeDelta::FromSeconds(2)); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(offset + base::TimeDelta::FromSeconds(4)); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + base::TimeDelta::FromSeconds(6)); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(offset + base::TimeDelta::FromSeconds(6) + kStoreDelay - |
| kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + base::TimeDelta::FromSeconds(6) + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + kUploadInterval - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(offset + kUploadInterval); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Add an identical log entry for multiple apps. Verify |
| // that a store is scheduled after five seconds and an upload occurs after three |
| // hours. |
| TEST_F(AppInstallEventLogManagerTest, AddForMultipleApps) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| AddLogEntryForAllApps(); |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + kUploadInterval - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(offset + kUploadInterval); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Add an identical log entry for an empty set of apps. |
| // Verify that no store is scheduled and no upload occurs. |
| TEST_F(AppInstallEventLogManagerTest, AddForZeroApps) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| AddLogEntryForsetOfApps({}); |
| |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Fill the log for one app until its size exceeds the |
| // threshold for expedited upload. Verify that a store is scheduled after five |
| // seconds and an upload occurs after fifteen minutes. |
| TEST_F(AppInstallEventLogManagerTest, AddToTriggerMaxSizeExpedited) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| for (int i = 0; i <= kMaxSizeExpeditedUploadThreshold; ++i) { |
| AddLogEntry(0 /* app_index */); |
| } |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(offset + kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Fill the logs for five apps until their total size |
| // exceeds the threshold for expedited upload. Verify that a store is scheduled |
| // after five seconds and an upload occurs after fifteen minutes. |
| TEST_F(AppInstallEventLogManagerTest, AddToTriggerTotalSizeExpedited) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| int i = 0; |
| while (i <= kTotalSizeExpeditedUploadThreshold) { |
| for (int j = 0; j < static_cast<int>(base::size(kPackageNames)); ++i, ++j) { |
| AddLogEntry(j /* app_index */); |
| } |
| } |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(offset + kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Add an identical log entry for multiple apps repeatedly, |
| // until the log size exceeds the threshold for expedited upload. Verify that a |
| // store is scheduled after five seconds and an upload occurs after fifteen |
| // minutes. |
| TEST_F(AppInstallEventLogManagerTest, |
| AddForMultipleAppsToTriggerTotalSizeExpedited) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| for (int i = 0; i <= kTotalSizeExpeditedUploadThreshold; |
| i += base::size(kPackageNames)) { |
| AddLogEntryForAllApps(); |
| } |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(offset + kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Add a log entry. Verify that a store is scheduled after five seconds and an |
| // expedited initial upload starts after fifteen minutes. Then, add another log |
| // entry. Complete the upload. Verify that the pending log entry is stored. |
| // Then, verify that a regular upload occurs three hours later. |
| TEST_F(AppInstallEventLogManagerTest, RequestUploadAddUpload) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| |
| CloudPolicyClient::StatusCallback upload_callback; |
| ExpectUploadAndCaptureCallback(&upload_callback); |
| FastForwardTo(kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| AddLogEntry(0 /* app_index */); |
| ReportUploadSuccess(upload_callback); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardTo(kExpeditedUploadDelay + kUploadInterval - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(kExpeditedUploadDelay + kUploadInterval); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Add a log entry. Verify that a store is scheduled after five seconds and an |
| // expedited initial upload starts after fifteen minutes. Then, fill the log for |
| // one app until its size exceeds the threshold for expedited upload. Complete |
| // the upload. Verify that the pending log entries are stored. Then, verify that |
| // an expedited upload occurs fifteen minutes later. |
| TEST_F(AppInstallEventLogManagerTest, RequestUploadAddExpeditedUpload) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| AddLogEntry(0 /* app_index */); |
| |
| FastForwardTo(kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| |
| CloudPolicyClient::StatusCallback upload_callback; |
| ExpectUploadAndCaptureCallback(&upload_callback); |
| FastForwardTo(kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| for (int i = 0; i <= kMaxSizeExpeditedUploadThreshold; ++i) { |
| AddLogEntry(0 /* app_index */); |
| } |
| ReportUploadSuccess(upload_callback); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardTo(kExpeditedUploadDelay + kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(kExpeditedUploadDelay + kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Wait twenty minutes. Fill the log for one app until its size exceeds the |
| // threshold for expedited upload. Verify that a store is scheduled after five |
| // seconds and an upload starts after fifteen minutes. Then, add another log |
| // entry. Complete the upload. Verify that the pending log entry is stored. |
| // Then, verify that a regular upload occurs three hours later. |
| TEST_F(AppInstallEventLogManagerTest, RequestExpeditedUploadAddUpload) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| const base::TimeDelta offset = base::TimeDelta::FromMinutes(20); |
| FastForwardTo(offset); |
| for (int i = 0; i <= kMaxSizeExpeditedUploadThreshold; ++i) { |
| AddLogEntry(0 /* app_index */); |
| } |
| |
| FastForwardTo(offset + kStoreDelay - kOneMs); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardTo(offset + kStoreDelay); |
| VerifyAndDeleteLogFile(); |
| |
| FastForwardTo(offset + kExpeditedUploadDelay - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| CloudPolicyClient::StatusCallback upload_callback; |
| ExpectUploadAndCaptureCallback(&upload_callback); |
| FastForwardTo(offset + kExpeditedUploadDelay); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| AddLogEntry(0 /* app_index */); |
| ReportUploadSuccess(upload_callback); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardTo(offset + kExpeditedUploadDelay + kUploadInterval - kOneMs); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| ExpectAndCompleteUpload(); |
| FastForwardTo(offset + kExpeditedUploadDelay + kUploadInterval); |
| Mock::VerifyAndClearExpectations(&cloud_policy_client_); |
| events_.clear(); |
| VerifyAndDeleteLogFile(); |
| |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Add a log entry. Destroy the manager. Verify that an immediate store is |
| // scheduled during destruction. |
| TEST_F(AppInstallEventLogManagerTest, StoreOnShutdown) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| AddLogEntry(0 /* app_index */); |
| |
| EXPECT_CALL(cloud_policy_client_, CancelAppInstallReportUpload()); |
| manager_.reset(); |
| FlushNonDelayedTasks(); |
| VerifyAndDeleteLogFile(); |
| } |
| |
| // Store a populated log. Populate the prefs holding the lists of apps for which |
| // push-install has been requested and is still pending. Clear all data related |
| // to the app-install event log. Verify that the prefs are cleared and an |
| // immediate deletion of the log file is scheduled. |
| TEST_F(AppInstallEventLogManagerTest, Clear) { |
| AppInstallEventLog log(log_file_path_); |
| events_[kPackageNames[0]].push_back(event_); |
| log.Add(kPackageNames[0], event_); |
| log.Store(); |
| |
| base::ListValue list; |
| list.AppendString("test"); |
| profile_.GetPrefs()->Set(arc::prefs::kArcPushInstallAppsRequested, list); |
| profile_.GetPrefs()->Set(arc::prefs::kArcPushInstallAppsPending, list); |
| |
| AppInstallEventLogManager::Clear(&log_task_runner_wrapper_, &profile_); |
| EXPECT_TRUE(profile_.GetPrefs() |
| ->FindPreference(arc::prefs::kArcPushInstallAppsRequested) |
| ->IsDefaultValue()); |
| EXPECT_TRUE(profile_.GetPrefs() |
| ->FindPreference(arc::prefs::kArcPushInstallAppsPending) |
| ->IsDefaultValue()); |
| VerifyLogFile(); |
| |
| FlushNonDelayedTasks(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| // Add a log entry. Destroy the manager. Verify that an immediate store is |
| // scheduled during destruction. Then, populate the prefs holding the lists of |
| // apps for which push-install has been requested and is still pending. Clear |
| // all data related to the app-install event log. Verify that the prefs are |
| // cleared. Create a manager. Verify that the log file is deleted before the |
| // manager attempts to load it. |
| TEST_F(AppInstallEventLogManagerTest, RunClearRun) { |
| EXPECT_CALL(cloud_policy_client_, UploadAppInstallReport(_, _)).Times(0); |
| CreateManager(); |
| |
| AddLogEntry(0 /* app_index */); |
| |
| EXPECT_CALL(cloud_policy_client_, CancelAppInstallReportUpload()); |
| manager_.reset(); |
| FlushNonDelayedTasks(); |
| VerifyLogFile(); |
| |
| base::ListValue list; |
| list.AppendString("test"); |
| profile_.GetPrefs()->Set(arc::prefs::kArcPushInstallAppsRequested, list); |
| profile_.GetPrefs()->Set(arc::prefs::kArcPushInstallAppsPending, list); |
| |
| AppInstallEventLogManager::Clear(&log_task_runner_wrapper_, &profile_); |
| EXPECT_TRUE(profile_.GetPrefs() |
| ->FindPreference(arc::prefs::kArcPushInstallAppsRequested) |
| ->IsDefaultValue()); |
| EXPECT_TRUE(profile_.GetPrefs() |
| ->FindPreference(arc::prefs::kArcPushInstallAppsPending) |
| ->IsDefaultValue()); |
| |
| CreateManager(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| |
| FastForwardUntilNoTasksRemain(); |
| EXPECT_FALSE(base::PathExists(log_file_path_)); |
| } |
| |
| } // namespace policy |