blob: 56135ace99b259f0a34d935c2861246995e0c3ac [file] [log] [blame]
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <base/time/time.h>
#include <gtest/gtest.h>
#include "dlcservice/proto_utils.h"
#include "dlcservice/test_utils.h"
#include "dlcservice/utils.h"
using dlcservice::metrics::InstallResult;
using std::string;
using testing::_;
using testing::DoAll;
using testing::ElementsAre;
using testing::Return;
using testing::SetArgPointee;
namespace dlcservice {
class DlcManagerTest : public BaseTest {
public:
DlcManagerTest() { dlc_manager_ = std::make_unique<DlcManager>(); }
void Install(const DlcId& id) {
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlcImage(id, _, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(mount_path_.value()), Return(true)));
EXPECT_CALL(mock_state_change_reporter_, DlcStateChanged(_)).Times(2);
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, id, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_metrics_,
SendInstallResult(InstallResult::kSuccessNewInstall));
bool external_install_needed = false;
EXPECT_TRUE(dlc_manager_->Install(CreateInstallRequest(id),
&external_install_needed, &err_));
CheckDlcState(id, DlcState::INSTALLING);
InstallWithUpdateEngine({id});
EXPECT_TRUE(dlc_manager_->InstallCompleted({id}, &err_));
EXPECT_TRUE(dlc_manager_->FinishInstall(id, &err_));
CheckDlcState(id, DlcState::INSTALLED);
}
void Uninstall(const DlcId& id) {
EXPECT_CALL(*mock_image_loader_proxy_ptr_, UnloadDlcImage(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(true), Return(true)));
EXPECT_CALL(mock_state_change_reporter_, DlcStateChanged(_)).Times(1);
EXPECT_TRUE(dlc_manager_->Uninstall(id, &err_));
CheckDlcState(id, DlcState::NOT_INSTALLED);
}
void CheckDlcState(const DlcId& id, const DlcState::State& expected_state) {
const auto* dlc = dlc_manager_->GetDlc(id, &err_);
EXPECT_NE(dlc, nullptr);
EXPECT_EQ(expected_state, dlc->GetState().state());
}
protected:
std::unique_ptr<DlcManager> dlc_manager_;
private:
DlcManagerTest(const DlcManagerTest&) = delete;
DlcManagerTest& operator=(const DlcManagerTest&) = delete;
};
TEST_F(DlcManagerTest, PreloadAllowedDlcTest) {
// The third DLC has pre-loaded flag on.
SetUpDlcPreloadedImage(kThirdDlc);
EXPECT_CALL(*mock_system_properties_, IsOfficialBuild())
.Times(2)
.WillRepeatedly(Return(false));
dlc_manager_->Initialize();
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(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_metrics_,
SendInstallResult(InstallResult::kSuccessAlreadyInstalled));
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre());
EXPECT_CALL(mock_state_change_reporter_, DlcStateChanged(_)).Times(2);
bool external_install_needed = false;
EXPECT_TRUE(dlc_manager_->Install(CreateInstallRequest(kThirdDlc),
&external_install_needed, &err_));
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre(kThirdDlc));
EXPECT_FALSE(
dlc_manager_->GetDlc(kThirdDlc, &err_)->GetRoot().value().empty());
CheckDlcState(kThirdDlc, DlcState::INSTALLED);
}
#if USE_LVM_STATEFUL_PARTITION
TEST_F(DlcManagerTest, PreloadAllowedDlcLogicalVolumeTest) {
// The fourth DLC has pre-loaded flag on.
// The fourth DLC has logical-volume flag on.
SetUpDlcPreloadedImage(kFourthDlc);
EXPECT_CALL(*mock_system_properties_, IsOfficialBuild())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_system_properties_, IsOfficialBuild())
.Times(2)
.WillRepeatedly(Return(false));
dlc_manager_->Initialize();
EXPECT_CALL(*mock_image_loader_proxy_ptr_, LoadDlc(_, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(mount_path_.value()), Return(true)));
EXPECT_CALL(*mock_update_engine_proxy_ptr_,
SetDlcActiveValue(true, kFourthDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(*mock_metrics_,
SendInstallResult(InstallResult::kSuccessAlreadyInstalled));
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre());
EXPECT_CALL(mock_state_change_reporter_, DlcStateChanged(_)).Times(2);
EXPECT_CALL(*mock_lvmd_proxy_wrapper_ptr_, CreateLogicalVolumes(_))
.WillOnce(Return(true));
// Any path here would work.
auto image_path_a =
GetDlcImagePath(content_path_, kFourthDlc, kPackage, BootSlot::Slot::A);
base::CreateDirectory(image_path_a.DirName());
EXPECT_CALL(*mock_lvmd_proxy_wrapper_ptr_, GetLogicalVolumePath(_))
.WillRepeatedly(Return(image_path_a.value()));
bool external_install_needed = false;
EXPECT_TRUE(dlc_manager_->Install(CreateInstallRequest(kFourthDlc),
&external_install_needed, &err_));
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre(kFourthDlc));
EXPECT_FALSE(
dlc_manager_->GetDlc(kFourthDlc, &err_)->GetRoot().value().empty());
CheckDlcState(kFourthDlc, DlcState::INSTALLED);
}
#endif // USE_LVM_STATEFUL_PARTITION
TEST_F(DlcManagerTest, PreloadAllowedWithBadPreinstalledDlcTest) {
// The third DLC has pre-loaded flag on.
SetUpDlcWithSlots(kThirdDlc);
SetUpDlcPreloadedImage(kThirdDlc);
EXPECT_CALL(*mock_system_properties_, IsOfficialBuild())
.Times(2)
.WillRepeatedly(Return(false));
dlc_manager_->Initialize();
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(true, kThirdDlc, _, _))
.WillOnce(Return(true));
EXPECT_CALL(mock_state_change_reporter_, DlcStateChanged(_)).Times(2);
EXPECT_CALL(*mock_metrics_,
SendInstallResult(InstallResult::kSuccessAlreadyInstalled));
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre());
bool external_install_needed = false;
EXPECT_TRUE(dlc_manager_->Install(CreateInstallRequest(kThirdDlc),
&external_install_needed, &err_));
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre(kThirdDlc));
EXPECT_FALSE(
dlc_manager_->GetDlc(kThirdDlc, &err_)->GetRoot().value().empty());
CheckDlcState(kThirdDlc, DlcState::INSTALLED);
}
TEST_F(DlcManagerTest, PreloadNotAllowedDlcTest) {
SetUpDlcPreloadedImage(kSecondDlc);
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre());
dlc_manager_->Initialize();
EXPECT_THAT(dlc_manager_->GetInstalled(), ElementsAre());
CheckDlcState(kSecondDlc, DlcState::NOT_INSTALLED);
}
TEST_F(DlcManagerTest, UnsupportedContentDlcRemovalCheck) {
auto id = "unsupported-dlc";
for (const auto& slot : {BootSlot::Slot::A, BootSlot::Slot::B}) {
auto image_path = GetDlcImagePath(content_path_, id, kPackage, slot);
base::CreateDirectory(image_path.DirName());
CreateFile(image_path, 1);
}
EXPECT_TRUE(base::CreateDirectory(JoinPaths(prefs_path_, "dlc", id)));
EXPECT_TRUE(base::PathExists(JoinPaths(prefs_path_, "dlc", id)));
EXPECT_TRUE(base::PathExists(JoinPaths(content_path_, id)));
dlc_manager_->Initialize();
EXPECT_FALSE(base::PathExists(JoinPaths(prefs_path_, "dlc", id)));
EXPECT_FALSE(base::PathExists(JoinPaths(content_path_, id)));
}
TEST_F(DlcManagerTest, UnsupportedPreloadedDlcRemovalCheck) {
auto id = "unsupported-dlc";
auto image_path =
JoinPaths(preloaded_content_path_, id, kPackage, kDlcImageFileName);
base::CreateDirectory(image_path.DirName());
CreateFile(image_path, 1);
EXPECT_TRUE(base::PathExists(JoinPaths(preloaded_content_path_, id)));
dlc_manager_->Initialize();
EXPECT_FALSE(base::PathExists(JoinPaths(preloaded_content_path_, id)));
}
} // namespace dlcservice