blob: ddcfeb1a82e07bd144a18b98fe1fc1cf8be7f9cb [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 <utility>
#include <vector>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/optional.h>
#include <base/run_loop.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop_utils.h>
#include <dbus/dlcservice/dbus-constants.h>
#include <dlcservice/proto_bindings/dlcservice.pb.h>
#include <update_engine/proto_bindings/update_engine.pb.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <imageloader/dbus-proxy-mocks.h>
#include <update_engine/dbus-constants.h>
#include <update_engine/dbus-proxy-mocks.h>
#include "dlcservice/boot/boot_slot.h"
#include "dlcservice/boot/mock_boot_device.h"
#include "dlcservice/dlc_service.h"
#include "dlcservice/utils.h"
using brillo::ErrorPtr;
using std::move;
using std::string;
using std::vector;
using testing::_;
using testing::Return;
using testing::SetArgPointee;
using testing::StrictMock;
using update_engine::Operation;
using update_engine::StatusResult;
namespace dlcservice {
namespace {
constexpr char kFirstDlc[] = "First-Dlc";
constexpr char kSecondDlc[] = "Second-Dlc";
constexpr char kThirdDlc[] = "Third-Dlc";
constexpr char kPackage[] = "Package";
constexpr char kManifestWithPreloadAllowedName[] =
"imageloader-preload-allowed.json";
MATCHER_P(ProtoHasUrl,
url,
string("The protobuf provided does not have url: ") + url) {
return url == arg.omaha_url();
}
DlcModuleList CreateDlcModuleList(const vector<DlcId>& ids,
const string& omaha_url = "") {
DlcModuleList dlc_module_list;
dlc_module_list.set_omaha_url(omaha_url);
for (const string& id : ids) {
DlcModuleInfo* dlc_info = dlc_module_list.add_dlc_module_infos();
dlc_info->set_dlc_id(id);
}
return dlc_module_list;
}
class DlcServiceTestObserver : public DlcService::Observer {
public:
void SendInstallStatus(const InstallStatus& install_status) override {
install_status_.emplace(install_status);
}
bool IsSendInstallStatusCalled() { return install_status_.has_value(); }
InstallStatus GetInstallStatus() {
EXPECT_TRUE(install_status_.has_value())
<< "SendInstallStatus() was not called.";
base::Optional<InstallStatus> tmp;
tmp.swap(install_status_);
return *tmp;
}
private:
base::Optional<InstallStatus> install_status_;
};
} // namespace
class DlcServiceTest : public testing::Test {
public:
DlcServiceTest() {
loop_.SetAsCurrent();
// Initialize DLC path.
CHECK(scoped_temp_dir_.CreateUniqueTempDir());
manifest_path_ = JoinPaths(scoped_temp_dir_.GetPath(), "rootfs");
preloaded_content_path_ =
JoinPaths(scoped_temp_dir_.GetPath(), "preloaded_stateful");
content_path_ = JoinPaths(scoped_temp_dir_.GetPath(), "stateful");
mount_path_ = JoinPaths(scoped_temp_dir_.GetPath(), "mount");
base::FilePath mount_root_path = JoinPaths(mount_path_, "root");
base::CreateDirectory(manifest_path_);
base::CreateDirectory(preloaded_content_path_);
base::CreateDirectory(content_path_);
base::CreateDirectory(mount_root_path);
testdata_path_ = JoinPaths(getenv("SRC"), "testdata");
// Create DLC manifest sub-directories.
for (auto&& id : {kFirstDlc, kSecondDlc, kThirdDlc}) {
base::CreateDirectory(JoinPaths(manifest_path_, id, kPackage));
base::CopyFile(JoinPaths(testdata_path_, id, kPackage, kManifestName),
JoinPaths(manifest_path_, id, kPackage, kManifestName));
}
// Create mocks with default behaviors.
mock_boot_device_ = std::make_unique<MockBootDevice>();
EXPECT_CALL(*(mock_boot_device_.get()), GetBootDevice())
.WillOnce(Return("/dev/sdb5"));
EXPECT_CALL(*(mock_boot_device_.get()), IsRemovableDevice(_))
.WillOnce(Return(false));
current_slot_ = dlcservice::BootSlot::Slot::B;
mock_image_loader_proxy_ =
std::make_unique<StrictMock<ImageLoaderProxyMock>>();
mock_image_loader_proxy_ptr_ = mock_image_loader_proxy_.get();
mock_update_engine_proxy_ =
std::make_unique<StrictMock<UpdateEngineProxyMock>>();
mock_update_engine_proxy_ptr_ = mock_update_engine_proxy_.get();
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
DoRegisterStatusUpdateAdvancedSignalHandler(_, _))
.Times(1);
}
int64_t GetFileSize(const base::FilePath& path) {
int64_t file_size;
EXPECT_TRUE(base::GetFileSize(path, &file_size));
return file_size;
}
void ResizeImageFile(const base::FilePath& image_path, int64_t image_size) {
constexpr uint32_t file_flags =
base::File::FLAG_WRITE | base::File::FLAG_OPEN;
base::File file(image_path, file_flags);
EXPECT_TRUE(file.SetLength(image_size));
}
void CreateImageFileWithRightSize(const base::FilePath& image_path,
const base::FilePath& manifest_path,
const string& id,
const string& package) {
imageloader::Manifest manifest;
dlcservice::GetDlcManifest(manifest_path, id, package, &manifest);
int64_t image_size = manifest.preallocated_size();
constexpr uint32_t file_flags = base::File::FLAG_WRITE |
base::File::FLAG_READ |
base::File::FLAG_CREATE;
base::File file(image_path, file_flags);
EXPECT_TRUE(file.SetLength(image_size));
}
// Will modify DLC with |id| and |package| manifest file to allow preloading.
void SetUpDlcPreloadAllowed(const string& id, const string& package) {
auto from = JoinPaths(testdata_path_, id, kPackage,
kManifestWithPreloadAllowedName);
auto to = JoinPaths(manifest_path_, id, kPackage, kManifestName);
EXPECT_TRUE(base::PathExists(from));
EXPECT_TRUE(base::PathExists(to));
EXPECT_TRUE(base::CopyFile(from, to));
}
// Will create |path|/|id|/|package|/dlc.img file.
void SetUpDlcWithoutSlots(const base::FilePath& path,
const string& id,
const string& package) {
base::FilePath image_path = JoinPaths(path, id, package, kDlcImageFileName);
base::CreateDirectory(image_path.DirName());
CreateImageFileWithRightSize(image_path, manifest_path_, id, package);
}
// Will create |path/|id|/|package|/dlc_[a|b]/dlc.img files.
void SetUpDlcWithSlots(const base::FilePath& path,
const string& id,
const string& package) {
// Create DLC content sub-directories and empty images.
for (const auto& slot : {BootSlot::Slot::A, BootSlot::Slot::B}) {
base::FilePath image_path = GetDlcImagePath(path, id, package, slot);
base::CreateDirectory(image_path.DirName());
CreateImageFileWithRightSize(image_path, manifest_path_, id, package);
}
}
void ConstructDlcService() {
SystemState::Initialize(
move(mock_image_loader_proxy_), move(mock_update_engine_proxy_),
std::make_unique<BootSlot>(move(mock_boot_device_)), manifest_path_,
preloaded_content_path_, content_path_, /*for_test=*/true);
dlc_service_ = std::make_unique<DlcService>();
dlc_service_test_observer_ = std::make_unique<DlcServiceTestObserver>();
dlc_service_->AddObserver(dlc_service_test_observer_.get());
}
void SetUp() override {
SetUpDlcWithSlots(content_path_, kFirstDlc, kPackage);
ConstructDlcService();
dlc_service_->LoadDlcModuleImages();
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(
dlc_service_->Install(CreateDlcModuleList({kFirstDlc}, ""), err_ptr_));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
EXPECT_EQ(dlc_service_test_observer_->GetInstallStatus().status(),
Status::COMPLETED);
}
void SetMountPath(const string& mount_path_expected) {
ON_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillByDefault(
DoAll(SetArgPointee<3>(mount_path_expected), Return(true)));
}
inline void CheckDlcState(const DlcId& id_in,
const DlcState::State& state_in,
bool fail = false) {
DlcState state;
if (fail) {
EXPECT_FALSE(dlc_service_->GetState(id_in, &state, err_ptr_));
return;
}
EXPECT_TRUE(dlc_service_->GetState(id_in, &state, err_ptr_));
EXPECT_EQ(state_in, state.state());
}
protected:
ErrorPtr err_;
ErrorPtr* err_ptr_{&err_};
base::MessageLoopForIO base_loop_;
brillo::BaseMessageLoop loop_{&base_loop_};
base::ScopedTempDir scoped_temp_dir_;
base::FilePath testdata_path_;
base::FilePath manifest_path_;
base::FilePath preloaded_content_path_;
base::FilePath content_path_;
base::FilePath mount_path_;
std::unique_ptr<MockBootDevice> mock_boot_device_;
dlcservice::BootSlot::Slot current_slot_;
using ImageLoaderProxyMock = org::chromium::ImageLoaderInterfaceProxyMock;
std::unique_ptr<ImageLoaderProxyMock> mock_image_loader_proxy_;
ImageLoaderProxyMock* mock_image_loader_proxy_ptr_;
using UpdateEngineProxyMock = org::chromium::UpdateEngineInterfaceProxyMock;
std::unique_ptr<UpdateEngineProxyMock> mock_update_engine_proxy_;
UpdateEngineProxyMock* mock_update_engine_proxy_ptr_;
std::unique_ptr<DlcService> dlc_service_;
std::unique_ptr<DlcServiceTestObserver> dlc_service_test_observer_;
private:
DISALLOW_COPY_AND_ASSIGN(DlcServiceTest);
};
class DlcServiceSkipLoadTest : public DlcServiceTest {
public:
// Need this to skip calling |LoadDlcModuleImages()|.
void SetUp() override { ConstructDlcService(); }
};
class DlcServiceSkipConstructionTest : public DlcServiceTest {
public:
// Need this to skip construction of |DlcService|.
void SetUp() override {}
};
TEST_F(DlcServiceSkipLoadTest, PreloadAllowedDlcTest) {
SetUpDlcPreloadAllowed(kFirstDlc, kPackage);
SetUpDlcWithoutSlots(preloaded_content_path_, kFirstDlc, kPackage);
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
dlc_service_->LoadDlcModuleImages();
DlcModuleList dlc_module_list;
EXPECT_TRUE(dlc_service_->GetInstalled(&dlc_module_list, err_ptr_));
EXPECT_EQ(dlc_module_list.dlc_module_infos_size(), 1);
DlcModuleInfo dlc_module = dlc_module_list.dlc_module_infos(0);
EXPECT_EQ(dlc_module.dlc_id(), kFirstDlc);
EXPECT_FALSE(dlc_module.dlc_root().empty());
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceSkipLoadTest, PreloadAllowedWithBadPreinstalledDlcTest) {
SetUpDlcWithSlots(content_path_, kFirstDlc, kPackage);
SetUpDlcPreloadAllowed(kFirstDlc, kPackage);
SetUpDlcWithoutSlots(preloaded_content_path_, kFirstDlc, kPackage);
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
dlc_service_->LoadDlcModuleImages();
DlcModuleList dlc_module_list;
EXPECT_TRUE(dlc_service_->GetInstalled(&dlc_module_list, err_ptr_));
EXPECT_EQ(dlc_module_list.dlc_module_infos_size(), 1);
DlcModuleInfo dlc_module = dlc_module_list.dlc_module_infos(0);
EXPECT_EQ(dlc_module.dlc_id(), kFirstDlc);
EXPECT_FALSE(dlc_module.dlc_root().empty());
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceSkipLoadTest, PreloadNotAllowedDlcTest) {
SetUpDlcWithoutSlots(preloaded_content_path_, kFirstDlc, kPackage);
dlc_service_->LoadDlcModuleImages();
DlcModuleList dlc_module_list;
EXPECT_TRUE(dlc_service_->GetInstalled(&dlc_module_list, err_ptr_));
EXPECT_EQ(dlc_module_list.dlc_module_infos_size(), 0);
CheckDlcState(kFirstDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest,
MimicUpdateRebootInstallWherePreallocatedSizeIncreasedTest) {
// Check A and B images.
for (const auto& slot : {kDlcDirAName, kDlcDirBName})
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc, kPackage,
slot, kDlcImageFileName)));
base::FilePath inactive_img_path =
GetDlcImagePath(content_path_, kFirstDlc, kPackage,
current_slot_ == BootSlot::Slot::A ? BootSlot::Slot::B
: BootSlot::Slot::A);
imageloader::Manifest manifest;
dlcservice::GetDlcManifest(manifest_path_, kFirstDlc, kPackage, &manifest);
int64_t inactive_img_size = manifest.preallocated_size();
int64_t new_inactive_img_size = inactive_img_size / 2;
EXPECT_TRUE(new_inactive_img_size < inactive_img_size);
ResizeImageFile(inactive_img_path, new_inactive_img_size);
EXPECT_EQ(new_inactive_img_size, GetFileSize(inactive_img_path));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
DlcModuleList dlc_module_list = CreateDlcModuleList({kFirstDlc}, "");
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
EXPECT_EQ(inactive_img_size, GetFileSize(inactive_img_path));
}
TEST_F(DlcServiceTest, GetInstalledTest) {
DlcModuleList dlc_module_list;
EXPECT_TRUE(dlc_service_->GetInstalled(&dlc_module_list, err_ptr_));
EXPECT_EQ(dlc_module_list.dlc_module_infos_size(), 1);
DlcModuleInfo dlc_module = dlc_module_list.dlc_module_infos(0);
EXPECT_EQ(dlc_module.dlc_id(), kFirstDlc);
EXPECT_FALSE(dlc_module.dlc_root().empty());
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceTest, UninstallTest) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(true), Return(true)));
EXPECT_TRUE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, UninstallNotInstalledIsValidTest) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(false));
EXPECT_TRUE(dlc_service_->Uninstall(kSecondDlc, err_ptr_));
CheckDlcState(kSecondDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, UninstallFailToSetDlcActiveValueFalse) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kFirstDlc, _, _))
.WillOnce(Return(false));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(true), Return(true)));
EXPECT_TRUE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, UninstallInvalidDlcTest) {
const auto& id = "invalid-dlc-id";
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_FALSE(dlc_service_->Uninstall(id, err_ptr_));
CheckDlcState(id, DlcState::NOT_INSTALLED, /*fail=*/true);
}
TEST_F(DlcServiceTest, UninstallUnmountFailureTest) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(false), Return(true)));
EXPECT_FALSE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceTest, UninstallImageLoaderFailureTest) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(Return(false));
// |ImageLoader| not available.
EXPECT_FALSE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceTest, UninstallUpdateEngineBusyFailureTest) {
StatusResult status_result;
status_result.set_current_operation(Operation::CHECKING_FOR_UPDATE);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(DoAll(SetArgPointee<0>(status_result), Return(true)));
EXPECT_FALSE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceTest, UninstallUpdatedNeedRebootSuccessTest) {
StatusResult status_result;
status_result.set_current_operation(Operation::UPDATED_NEED_REBOOT);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(DoAll(SetArgPointee<0>(status_result), Return(true)));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(true), Return(true)));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, UninstallInstallingFails) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc}, omaha_url_default);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
EXPECT_FALSE(dlc_service_->Uninstall(kSecondDlc, err_ptr_));
EXPECT_EQ(err_->GetCode(), kErrorBusy);
}
TEST_F(DlcServiceTest, UninstallInstallingButInstalledFails) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kFirstDlc, kSecondDlc}, omaha_url_default);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, SetDlcActiveValue(true, _, _, _))
.Times(2)
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(true), Return(true)));
EXPECT_TRUE(dlc_service_->Uninstall(kFirstDlc, err_ptr_));
CheckDlcState(kFirstDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, InstallEmptyDlcModuleListTest) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_FALSE(dlc_service_->Install({}, err_ptr_));
}
TEST_F(DlcServiceTest, InstallInvalidDlcTest) {
const auto& id = "bad-dlc-id";
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_FALSE(dlc_service_->Install(CreateDlcModuleList({id}), err_ptr_));
CheckDlcState(id, DlcState::NOT_INSTALLED, /*fail=*/true);
}
TEST_F(DlcServiceTest, InstallTest) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
constexpr int expected_permissions = 0755;
int permissions;
base::FilePath module_path = JoinPaths(content_path_, kSecondDlc, kPackage);
base::GetPosixFilePermissions(module_path, &permissions);
EXPECT_EQ(permissions, expected_permissions);
base::FilePath image_a_path =
GetDlcImagePath(content_path_, kSecondDlc, kPackage, BootSlot::Slot::A);
base::GetPosixFilePermissions(image_a_path.DirName(), &permissions);
EXPECT_EQ(permissions, expected_permissions);
base::FilePath image_b_path =
GetDlcImagePath(content_path_, kSecondDlc, kPackage, BootSlot::Slot::B);
base::GetPosixFilePermissions(image_b_path.DirName(), &permissions);
EXPECT_EQ(permissions, expected_permissions);
}
TEST_F(DlcServiceTest, InstallAlreadyInstalledValid) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kFirstDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceTest, InstallDuplicatesSucceeds) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc, kSecondDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const auto& id : {kFirstDlc, kSecondDlc})
for (const auto& path : {JoinPaths(content_path_, id)})
EXPECT_TRUE(base::PathExists(path));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
}
TEST_F(DlcServiceTest, InstallAlreadyInstalledAndDuplicatesSucceeds) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list = CreateDlcModuleList(
{kFirstDlc, kSecondDlc, kSecondDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const auto& id : {kFirstDlc, kSecondDlc})
for (const auto& path : {JoinPaths(content_path_, id)})
EXPECT_TRUE(base::PathExists(path));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
}
TEST_F(DlcServiceTest, InstallCannotSetDlcActiveValue) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(false));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
}
TEST_F(DlcServiceTest, InstallUpdateEngineDownThenBackUpTest) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_FALSE(dlc_service_->Install(dlc_module_list, err_ptr_));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
}
TEST_F(DlcServiceTest, InstallUpdateEngineBusyThenFreeTest) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
StatusResult status_result;
status_result.set_current_operation(Operation::UPDATED_NEED_REBOOT);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(DoAll(SetArgPointee<0>(status_result), Return(true)))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_FALSE(dlc_service_->Install(dlc_module_list, err_ptr_));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
}
TEST_F(DlcServiceTest, InstallFailureCleansUp) {
const string omaha_url_default = "";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc, kThirdDlc}, omaha_url_default);
SetMountPath(mount_path_.value());
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
AttemptInstall(ProtoHasUrl(omaha_url_default), _, _))
.WillOnce(Return(false));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_FALSE(dlc_service_->Install(dlc_module_list, err_ptr_));
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, kSecondDlc)));
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, kThirdDlc)));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::NOT_INSTALLED);
CheckDlcState(kThirdDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, InstallUrlTest) {
const string omaha_url_override = "http://random.url";
DlcModuleList dlc_module_list =
CreateDlcModuleList({kSecondDlc}, omaha_url_override);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
dlc_service_->Install(dlc_module_list, err_ptr_);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
}
TEST_F(DlcServiceTest, InstallAlreadyInstalledThatGotUnmountedTest) {
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
const auto mount_path_root = JoinPaths(mount_path_, "root");
EXPECT_TRUE(base::PathExists(mount_path_root));
EXPECT_TRUE(base::DeleteFile(mount_path_root, true));
DlcModuleList dlc_module_list = CreateDlcModuleList({kFirstDlc}, "");
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillRepeatedly(
DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
dlc_service_->Install(dlc_module_list, err_ptr_);
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
}
TEST_F(DlcServiceTest, OnStatusUpdateAdvancedSignalDlcRootTest) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillRepeatedly(
DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
StatusResult status_result;
status_result.set_current_operation(Operation::IDLE);
status_result.set_is_install(true);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLED);
}
DlcModuleList dlc_module_list_after;
EXPECT_TRUE(dlc_service_->GetInstalled(&dlc_module_list_after, err_ptr_));
EXPECT_EQ(dlc_module_list_after.dlc_module_infos_size(), 3);
for (const DlcModuleInfo& dlc_module :
dlc_module_list_after.dlc_module_infos())
EXPECT_FALSE(dlc_module.dlc_root().empty());
}
TEST_F(DlcServiceTest, OnStatusUpdateAdvancedSignalNoRemountTest) {
const vector<DlcId> ids = {kFirstDlc, kSecondDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFirstDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
for (const string& id : ids)
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(kFirstDlc, DlcState::INSTALLED);
CheckDlcState(kSecondDlc, DlcState::INSTALLING);
StatusResult status_result;
status_result.set_current_operation(Operation::IDLE);
status_result.set_is_install(true);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
for (const string& id : ids)
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
}
TEST_F(DlcServiceTest, OnStatusUpdateAdvancedSignalTest) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)))
.WillOnce(DoAll(SetArgPointee<3>(""), Return(true)));
StatusResult status_result;
status_result.set_current_operation(Operation::IDLE);
status_result.set_is_install(true);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kSecondDlc)));
CheckDlcState(kSecondDlc, DlcState::INSTALLED);
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, kThirdDlc)));
CheckDlcState(kThirdDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, ReportingFailureCleanupTest) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
{
StatusResult status_result;
status_result.set_current_operation(Operation::REPORTING_ERROR_EVENT);
status_result.set_is_install(true);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
}
{
StatusResult status_result;
status_result.set_current_operation(Operation::IDLE);
status_result.set_is_install(false);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
}
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
for (const string& id : ids) {
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
}
TEST_F(DlcServiceTest, ReportingFailureSignalTest) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const auto& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
{
StatusResult status_result;
status_result.set_current_operation(Operation::REPORTING_ERROR_EVENT);
status_result.set_is_install(true);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
}
{
StatusResult status_result;
status_result.set_current_operation(Operation::IDLE);
status_result.set_is_install(false);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
}
EXPECT_EQ(dlc_service_test_observer_->GetInstallStatus().status(),
Status::FAILED);
for (const auto& id : ids)
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
TEST_F(DlcServiceTest, ProbableUpdateEngineRestartCleanupTest) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
StatusResult status_result;
status_result.set_current_operation(Operation::IDLE);
status_result.set_is_install(false);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, kFirstDlc)));
for (const string& id : ids) {
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
}
TEST_F(DlcServiceTest, UpdateEngineFailSafeTest) {
const vector<DlcId> ids = {kSecondDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
MessageLoopRunUntil(
&loop_, base::TimeDelta::FromSeconds(DlcService::kUECheckTimeout * 2),
base::Bind([]() { return false; }));
for (const string& id : ids) {
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
}
TEST_F(DlcServiceTest, UpdateEngineFailAfterSignalsSafeTest) {
const vector<DlcId> ids = {kSecondDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const string& id : ids) {
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::INSTALLING);
}
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillRepeatedly(
DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
StatusResult status_result;
status_result.set_current_operation(Operation::DOWNLOADING);
status_result.set_is_install(true);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
MessageLoopRunUntil(
&loop_, base::TimeDelta::FromSeconds(DlcService::kUECheckTimeout * 2),
base::Bind([]() { return false; }));
for (const string& id : ids) {
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
}
TEST_F(DlcServiceTest, OnStatusUpdateAdvancedSignalDownloadProgressTest) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const auto& id : ids)
CheckDlcState(id, DlcState::INSTALLING);
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillRepeatedly(
DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
StatusResult status_result;
status_result.set_is_install(true);
const vector<Operation> install_operation_sequence = {
Operation::CHECKING_FOR_UPDATE, Operation::UPDATE_AVAILABLE,
Operation::FINALIZING};
for (const auto& op : install_operation_sequence) {
status_result.set_current_operation(op);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
EXPECT_FALSE(dlc_service_test_observer_->IsSendInstallStatusCalled());
}
status_result.set_current_operation(Operation::DOWNLOADING);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
EXPECT_EQ(dlc_service_test_observer_->GetInstallStatus().status(),
Status::RUNNING);
status_result.set_current_operation(Operation::IDLE);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
EXPECT_EQ(dlc_service_test_observer_->GetInstallStatus().status(),
Status::COMPLETED);
for (const auto& id : ids)
CheckDlcState(id, DlcState::INSTALLED);
}
TEST_F(
DlcServiceTest,
OnStatusUpdateAdvancedSignalSubsequentialBadOrNonInstalledDlcsNonBlocking) {
const vector<DlcId> ids = {kSecondDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
for (int i = 0; i < 5; i++) {
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
for (const auto& id : ids)
CheckDlcState(id, DlcState::INSTALLING);
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(_, _, _, _, _, _))
.WillOnce(Return(false));
StatusResult status_result;
status_result.set_is_install(true);
status_result.set_current_operation(Operation::IDLE);
dlc_service_->OnStatusUpdateAdvancedSignal(status_result);
for (const auto& id : ids) {
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
}
}
TEST_F(DlcServiceTest, PeriodCheckUpdateEngineInstallSignalRaceChecker) {
const vector<DlcId> ids = {kSecondDlc, kThirdDlc};
DlcModuleList dlc_module_list = CreateDlcModuleList(ids);
EXPECT_CALL(*mock_update_engine_proxy_ptr_, GetStatusAdvanced(_, _, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_, AttemptInstall(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kSecondDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(false, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_TRUE(dlc_service_->Install(dlc_module_list, err_ptr_));
MessageLoopRunUntil(
&loop_, base::TimeDelta::FromSeconds(DlcService::kUECheckTimeout * 5),
base::Bind([]() { return false; }));
for (const string& id : ids) {
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
}
} // namespace dlcservice