| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/crostini/crostini_shared_devices.h" |
| |
| #include "base/run_loop.h" |
| #include "base/test/test_future.h" |
| #include "chrome/browser/ash/crostini/crostini_manager.h" |
| #include "chrome/browser/ash/crostini/crostini_test_helper.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" |
| #include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h" |
| #include "chromeos/ash/components/dbus/concierge/concierge_client.h" |
| #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace crostini { |
| |
| using vm_tools::cicerone::UpdateContainerDevicesResponse; |
| |
| constexpr char kMicrophone[] = "microphone"; |
| constexpr char kInvalidDevice[] = "invalid-device"; |
| |
| class CrostiniSharedDevicesTest : public testing::Test { |
| public: |
| CrostiniSharedDevicesTest() : container_id_(DefaultContainerId()) {} |
| |
| CrostiniSharedDevicesTest(const CrostiniSharedDevicesTest&) = delete; |
| CrostiniSharedDevicesTest& operator=(const CrostiniSharedDevicesTest&) = |
| delete; |
| |
| ~CrostiniSharedDevicesTest() override = default; |
| |
| void SetUp() override { |
| ash::ChunneldClient::InitializeFake(); |
| ash::CiceroneClient::InitializeFake(); |
| ash::ConciergeClient::InitializeFake(); |
| ash::SeneschalClient::InitializeFake(); |
| profile_ = std::make_unique<TestingProfile>(); |
| test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); |
| crostini_shared_devices_ = |
| std::make_unique<CrostiniSharedDevices>(profile()); |
| |
| update_container_devices_response_.set_status( |
| UpdateContainerDevicesResponse::OK); |
| AddContainerToPrefs(profile(), container_id_, {}); |
| } |
| |
| void TearDown() override { |
| crostini_shared_devices_.reset(); |
| test_helper_.reset(); |
| profile_.reset(); |
| ash::SeneschalClient::Shutdown(); |
| ash::ConciergeClient::Shutdown(); |
| ash::CiceroneClient::Shutdown(); |
| ash::ChunneldClient::Shutdown(); |
| } |
| |
| protected: |
| CrostiniManager* crostini_manager() { |
| return CrostiniManager::GetForProfile(profile()); |
| } |
| |
| Profile* profile() { return profile_.get(); } |
| |
| void set_vm_device_result( |
| std::string vm_device, |
| const UpdateContainerDevicesResponse::UpdateResult result) { |
| auto& results_map = *update_container_devices_response_.mutable_results(); |
| results_map[vm_device] = result; |
| ash::FakeCiceroneClient::Get()->set_update_container_devices_response( |
| update_container_devices_response_); |
| } |
| |
| void SetVmDeviceShared(const std::string& vm_device, |
| bool shared, |
| bool expect_applied) { |
| base::test::TestFuture<bool> result_future; |
| crostini_shared_devices_->SetVmDeviceShared( |
| container_id_, vm_device, shared, result_future.GetCallback()); |
| EXPECT_EQ(expect_applied, result_future.Get()); |
| } |
| |
| void AddRunningContainer(const guest_os::GuestId& container_id) { |
| crostini_manager()->AddRunningVmForTesting(container_id.vm_name); |
| // Trigger the running container logic via |
| crostini_manager()->AddRunningContainerForTesting( |
| container_id_.vm_name, |
| ContainerInfo(container_id.container_name, kCrostiniDefaultUsername, |
| "home/testuser1", "CONTAINER_IP_ADDRESS"), |
| true); |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| |
| guest_os::GuestId container_id_; |
| |
| vm_tools::cicerone::UpdateContainerDevicesResponse |
| update_container_devices_response_; |
| std::unique_ptr<CrostiniTestHelper> test_helper_; |
| std::unique_ptr<TestingProfile> profile_; |
| std::unique_ptr<CrostiniSharedDevices> crostini_shared_devices_; |
| content::BrowserTaskEnvironment task_environment_; |
| }; |
| |
| TEST_F(CrostiniSharedDevicesTest, ShareMicSuccess) { |
| AddRunningContainer(container_id_); |
| EXPECT_FALSE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| set_vm_device_result(kMicrophone, UpdateContainerDevicesResponse::SUCCESS); |
| SetVmDeviceShared(kMicrophone, true, true); |
| |
| EXPECT_TRUE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| } |
| |
| TEST_F(CrostiniSharedDevicesTest, ShareMicNoSuchDevice) { |
| AddRunningContainer(container_id_); |
| EXPECT_FALSE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| set_vm_device_result(kMicrophone, |
| UpdateContainerDevicesResponse::NO_SUCH_VM_DEVICE); |
| SetVmDeviceShared(kMicrophone, true, true); |
| EXPECT_FALSE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| } |
| |
| TEST_F(CrostiniSharedDevicesTest, ShareMicActionFailed) { |
| AddRunningContainer(container_id_); |
| EXPECT_FALSE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| set_vm_device_result(kMicrophone, |
| UpdateContainerDevicesResponse::ACTION_FAILED); |
| SetVmDeviceShared(kMicrophone, true, true); |
| EXPECT_FALSE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| } |
| |
| TEST_F(CrostiniSharedDevicesTest, SharedDevicesBeforeContainerRunning) { |
| set_vm_device_result(kMicrophone, UpdateContainerDevicesResponse::SUCCESS); |
| set_vm_device_result(kInvalidDevice, |
| UpdateContainerDevicesResponse::NO_SUCH_VM_DEVICE); |
| |
| EXPECT_FALSE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| EXPECT_FALSE(crostini_shared_devices_->IsVmDeviceShared(container_id_, |
| kInvalidDevice)); |
| |
| SetVmDeviceShared(kMicrophone, true, false); |
| SetVmDeviceShared(kInvalidDevice, true, false); |
| EXPECT_TRUE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| EXPECT_TRUE(crostini_shared_devices_->IsVmDeviceShared(container_id_, |
| kInvalidDevice)); |
| |
| // When the container starts running, we want it to note that there is no |
| // such device as kInvalidDevice. |
| |
| AddRunningContainer(container_id_); |
| EXPECT_TRUE( |
| crostini_shared_devices_->IsVmDeviceShared(container_id_, kMicrophone)); |
| EXPECT_FALSE(crostini_shared_devices_->IsVmDeviceShared(container_id_, |
| kInvalidDevice)); |
| } |
| |
| } // namespace crostini |