blob: fcbd47c593f9906897a02d79adb53b7f9968fd2f [file] [log] [blame]
// 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/crostini/crostini_manager.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cicerone_client.h"
#include "chromeos/dbus/fake_concierge_client.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace crostini {
namespace {
const char kOwnerId[] = "owner_id";
const char kVmName[] = "vm_name";
const char kContainerName[] = "container_name";
const char kContainerUserName[] = "container_username";
const char kCryptohomeId[] = "cryptohome_id";
} // namespace
class CrostiniManagerTest : public testing::Test {
public:
void CreateDiskImageClientErrorCallback(base::OnceClosure closure,
ConciergeClientResult result,
const base::FilePath& file_path) {
EXPECT_FALSE(fake_concierge_client_->create_disk_image_called());
EXPECT_EQ(result, ConciergeClientResult::CLIENT_ERROR);
std::move(closure).Run();
}
void DestroyDiskImageClientErrorCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_FALSE(fake_concierge_client_->destroy_disk_image_called());
EXPECT_EQ(result, ConciergeClientResult::CLIENT_ERROR);
std::move(closure).Run();
}
void ListVmDisksClientErrorCallback(base::OnceClosure closure,
ConciergeClientResult result,
int64_t total_size) {
EXPECT_FALSE(fake_concierge_client_->list_vm_disks_called());
EXPECT_EQ(result, ConciergeClientResult::CLIENT_ERROR);
std::move(closure).Run();
}
void StartTerminaVmClientErrorCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_FALSE(fake_concierge_client_->start_termina_vm_called());
EXPECT_EQ(result, ConciergeClientResult::CLIENT_ERROR);
std::move(closure).Run();
}
void StopVmClientErrorCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_FALSE(fake_concierge_client_->stop_vm_called());
EXPECT_EQ(result, ConciergeClientResult::CLIENT_ERROR);
std::move(closure).Run();
}
void StartContainerClientErrorCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_FALSE(fake_concierge_client_->start_container_called());
EXPECT_EQ(result, ConciergeClientResult::CLIENT_ERROR);
std::move(closure).Run();
}
void CreateDiskImageSuccessCallback(base::OnceClosure closure,
ConciergeClientResult result,
const base::FilePath& file_path) {
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
std::move(closure).Run();
}
void DestroyDiskImageSuccessCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_TRUE(fake_concierge_client_->destroy_disk_image_called());
std::move(closure).Run();
}
void ListVmDisksSuccessCallback(base::OnceClosure closure,
ConciergeClientResult result,
int64_t total_size) {
EXPECT_TRUE(fake_concierge_client_->list_vm_disks_called());
std::move(closure).Run();
}
void StartTerminaVmSuccessCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
std::move(closure).Run();
}
void StopVmSuccessCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_TRUE(fake_concierge_client_->stop_vm_called());
std::move(closure).Run();
}
void StartContainerSuccessCallback(base::OnceClosure closure,
ConciergeClientResult result) {
EXPECT_TRUE(fake_concierge_client_->start_container_called());
std::move(closure).Run();
}
CrostiniManagerTest()
: fake_cicerone_client_(new chromeos::FakeCiceroneClient()),
fake_concierge_client_(new chromeos::FakeConciergeClient()),
scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI),
test_browser_thread_bundle_(
content::TestBrowserThreadBundle::REAL_IO_THREAD) {
chromeos::DBusThreadManager::GetSetterForTesting()->SetCiceroneClient(
base::WrapUnique(fake_cicerone_client_));
chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
base::WrapUnique(fake_concierge_client_));
chromeos::DBusThreadManager::Initialize();
}
~CrostiniManagerTest() override { chromeos::DBusThreadManager::Shutdown(); }
void SetUp() override {
run_loop_ = std::make_unique<base::RunLoop>();
profile_ = std::make_unique<TestingProfile>();
}
void TearDown() override {
run_loop_.reset();
profile_.reset();
}
protected:
base::RunLoop* run_loop() { return run_loop_.get(); }
Profile* profile() { return profile_.get(); }
// Owned by chromeos::DBusThreadManager
chromeos::FakeCiceroneClient* fake_cicerone_client_;
chromeos::FakeConciergeClient* fake_concierge_client_;
std::unique_ptr<base::RunLoop>
run_loop_; // run_loop_ must be created on the UI thread.
std::unique_ptr<TestingProfile> profile_;
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
content::TestBrowserThreadBundle test_browser_thread_bundle_;
DISALLOW_COPY_AND_ASSIGN(CrostiniManagerTest);
};
TEST_F(CrostiniManagerTest, CreateDiskImageNameError) {
const base::FilePath& disk_path = base::FilePath("");
CrostiniManager::GetInstance()->CreateDiskImage(
"a_cryptohome_id", disk_path,
vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT,
base::BindOnce(&CrostiniManagerTest::CreateDiskImageClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, CreateDiskImageCryptohomeError) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->CreateDiskImage(
"", disk_path, vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT,
base::BindOnce(&CrostiniManagerTest::CreateDiskImageClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, CreateDiskImageStorageLocationError) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->CreateDiskImage(
"a_cryptohome_id", disk_path,
vm_tools::concierge::StorageLocation_INT_MIN_SENTINEL_DO_NOT_USE_,
base::BindOnce(&CrostiniManagerTest::CreateDiskImageClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, CreateDiskImageSuccess) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->CreateDiskImage(
"a_cryptohome_id", disk_path,
vm_tools::concierge::STORAGE_CRYPTOHOME_DOWNLOADS,
base::BindOnce(&CrostiniManagerTest::CreateDiskImageSuccessCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, DestroyDiskImageNameError) {
const base::FilePath& disk_path = base::FilePath("");
CrostiniManager::GetInstance()->DestroyDiskImage(
"a_cryptohome_id", disk_path,
vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT,
base::BindOnce(&CrostiniManagerTest::DestroyDiskImageClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, DestroyDiskImageCryptohomeError) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->DestroyDiskImage(
"", disk_path, vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT,
base::BindOnce(&CrostiniManagerTest::DestroyDiskImageClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, DestroyDiskImageStorageLocationError) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->DestroyDiskImage(
"a_cryptohome_id", disk_path,
vm_tools::concierge::StorageLocation_INT_MIN_SENTINEL_DO_NOT_USE_,
base::BindOnce(&CrostiniManagerTest::DestroyDiskImageClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, DestroyDiskImageSuccess) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->DestroyDiskImage(
"a_cryptohome_id", disk_path,
vm_tools::concierge::STORAGE_CRYPTOHOME_DOWNLOADS,
base::BindOnce(&CrostiniManagerTest::DestroyDiskImageSuccessCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, ListVmDisksCryptohomeError) {
CrostiniManager::GetInstance()->ListVmDisks(
"", base::BindOnce(&CrostiniManagerTest::ListVmDisksClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, ListVmDisksSuccess) {
CrostiniManager::GetInstance()->ListVmDisks(
"a_cryptohome_id",
base::BindOnce(&CrostiniManagerTest::ListVmDisksSuccessCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartTerminaVmOwnerIdError) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->StartTerminaVm(
"", kVmName, disk_path,
base::BindOnce(&CrostiniManagerTest::StartTerminaVmClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartTerminaVmNameError) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->StartTerminaVm(
kOwnerId, "", disk_path,
base::BindOnce(&CrostiniManagerTest::StartTerminaVmClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartTerminaVmDiskPathError) {
const base::FilePath& disk_path = base::FilePath();
CrostiniManager::GetInstance()->StartTerminaVm(
kOwnerId, kVmName, disk_path,
base::BindOnce(&CrostiniManagerTest::StartTerminaVmClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartTerminaVmSuccess) {
const base::FilePath& disk_path = base::FilePath(kVmName);
CrostiniManager::GetInstance()->StartTerminaVm(
kOwnerId, kVmName, disk_path,
base::BindOnce(&CrostiniManagerTest::StartTerminaVmSuccessCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StopVmNameError) {
CrostiniManager::GetInstance()->StopVm(
profile(), "",
base::BindOnce(&CrostiniManagerTest::StopVmClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StopVmSuccess) {
CrostiniManager::GetInstance()->StopVm(
profile(), kVmName,
base::BindOnce(&CrostiniManagerTest::StopVmSuccessCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerVmNameError) {
CrostiniManager::GetInstance()->StartContainer(
"", kContainerName, kContainerUserName, kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerContainerNameError) {
CrostiniManager::GetInstance()->StartContainer(
kVmName, "", kContainerUserName, kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerContainerUserNameError) {
CrostiniManager::GetInstance()->StartContainer(
kVmName, kContainerName, "", kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerContainerCryptohomeIdError) {
CrostiniManager::GetInstance()->StartContainer(
kVmName, kContainerName, kContainerUserName, "",
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerSignalConciergeNotConnectedError) {
fake_concierge_client_->set_container_started_signal_connected(false);
CrostiniManager::GetInstance()->StartContainer(
kVmName, kContainerName, kContainerUserName, kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerSignalCiceroneNotConnectedError) {
fake_cicerone_client_->set_container_started_signal_connected(false);
CrostiniManager::GetInstance()->StartContainer(
kVmName, kContainerName, kContainerUserName, kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, ShutdownContainerSignalCiceroneNotConnectedError) {
fake_cicerone_client_->set_container_shutdown_signal_connected(false);
CrostiniManager::GetInstance()->StartContainer(
kVmName, kContainerName, kContainerUserName, kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerClientErrorCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
TEST_F(CrostiniManagerTest, StartContainerSuccess) {
CrostiniManager::GetInstance()->StartContainer(
kVmName, kContainerName, kContainerUserName, kCryptohomeId,
base::BindOnce(&CrostiniManagerTest::StartContainerSuccessCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
}
class CrostiniManagerRestartTest : public CrostiniManagerTest,
public CrostiniManager::RestartObserver {
public:
void RestartCrostiniCallback(base::OnceClosure closure,
ConciergeClientResult result) {
restart_crostini_callback_count_++;
std::move(closure).Run();
}
// CrostiniManager::RestartObserver
void OnComponentLoaded(ConciergeClientResult result) override {
if (abort_on_component_loaded_) {
Abort();
}
}
void OnConciergeStarted(ConciergeClientResult result) override {
if (abort_on_concierge_started_) {
Abort();
}
}
void OnDiskImageCreated(ConciergeClientResult result) override {
if (abort_on_disk_image_created_) {
Abort();
}
}
void OnVmStarted(ConciergeClientResult result) override {
if (abort_on_vm_started_) {
Abort();
}
}
protected:
void Abort() {
CrostiniManager::GetInstance()->AbortRestartCrostini(profile(),
restart_id_);
run_loop()->Quit();
}
CrostiniManager::RestartId restart_id_ =
CrostiniManager::kUninitializedRestartId;
bool abort_on_component_loaded_ = false;
bool abort_on_concierge_started_ = false;
bool abort_on_disk_image_created_ = false;
bool abort_on_vm_started_ = false;
int restart_crostini_callback_count_ = 0;
};
TEST_F(CrostiniManagerRestartTest, RestartSuccess) {
restart_id_ = CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()),
this);
run_loop()->Run();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
EXPECT_TRUE(fake_concierge_client_->start_container_called());
EXPECT_EQ(1, restart_crostini_callback_count_);
}
TEST_F(CrostiniManagerRestartTest, AbortOnComponentLoaded) {
abort_on_component_loaded_ = true;
restart_id_ = CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()),
this);
run_loop()->Run();
EXPECT_FALSE(fake_concierge_client_->create_disk_image_called());
EXPECT_FALSE(fake_concierge_client_->start_termina_vm_called());
EXPECT_FALSE(fake_concierge_client_->start_container_called());
EXPECT_EQ(0, restart_crostini_callback_count_);
}
TEST_F(CrostiniManagerRestartTest, AbortOnConciergeStarted) {
abort_on_concierge_started_ = true;
restart_id_ = CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()),
this);
run_loop()->Run();
EXPECT_FALSE(fake_concierge_client_->create_disk_image_called());
EXPECT_FALSE(fake_concierge_client_->start_termina_vm_called());
EXPECT_FALSE(fake_concierge_client_->start_container_called());
EXPECT_EQ(0, restart_crostini_callback_count_);
}
TEST_F(CrostiniManagerRestartTest, AbortOnDiskImageCreated) {
abort_on_disk_image_created_ = true;
restart_id_ = CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()),
this);
run_loop()->Run();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_FALSE(fake_concierge_client_->start_termina_vm_called());
EXPECT_FALSE(fake_concierge_client_->start_container_called());
EXPECT_EQ(0, restart_crostini_callback_count_);
}
TEST_F(CrostiniManagerRestartTest, AbortOnVmStarted) {
abort_on_vm_started_ = true;
restart_id_ = CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()),
this);
run_loop()->Run();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
EXPECT_FALSE(fake_concierge_client_->start_container_called());
EXPECT_EQ(0, restart_crostini_callback_count_);
}
TEST_F(CrostiniManagerRestartTest, MultiRestartAllowed) {
CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()));
CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()));
CrostiniManager::GetInstance()->RestartCrostini(
profile(), kVmName, kContainerName,
base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
base::Unretained(this), run_loop()->QuitClosure()));
run_loop()->Run();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
EXPECT_TRUE(fake_concierge_client_->start_container_called());
EXPECT_EQ(3, restart_crostini_callback_count_);
}
} // namespace crostini