blob: 537171dd7acba6fe509f990ab37c775878652c91 [file] [log] [blame]
// Copyright 2020 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/ash/crosapi/browser_loader.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/component_updater/fake_cros_component_manager.h"
#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h"
#include "chromeos/dbus/upstart/fake_upstart_client.h"
#include "components/component_updater/mock_component_updater_service.h"
#include "components/update_client/update_client.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Return;
using update_client::UpdateClient;
namespace crosapi {
namespace {
// Copied from browser_loader.cc
constexpr char kLacrosComponentName[] = "lacros-dogfood-dev";
constexpr char kLacrosComponentId[] = "ldobopbhiamakmncndpkeelenhdmgfhk";
constexpr char kLacrosMounterUpstartJob[] = "lacros_2dmounter";
} // namespace
// Delegate for testing.
class DelegateImpl : public BrowserLoader::Delegate {
public:
DelegateImpl() = default;
DelegateImpl(const DelegateImpl&) = delete;
DelegateImpl& operator=(const DelegateImpl&) = delete;
~DelegateImpl() override = default;
// BrowserLoader::Delegate:
void SetLacrosUpdateAvailable() override { ++set_lacros_update_available_; }
// Public because this is test code.
int set_lacros_update_available_ = 0;
};
class BrowserLoaderTest : public testing::Test {
public:
BrowserLoaderTest() {
browser_util::SetLacrosEnabledForTest(true);
// Create dependencies for object under test.
component_manager_ =
base::MakeRefCounted<component_updater::FakeCrOSComponentManager>();
component_manager_->set_supported_components({kLacrosComponentName});
component_manager_->ResetComponentState(
kLacrosComponentName,
component_updater::FakeCrOSComponentManager::ComponentInfo(
component_updater::CrOSComponentManager::Error::NONE,
base::FilePath("/install/path"), base::FilePath("/mount/path")));
browser_part_ = std::make_unique<BrowserProcessPlatformPartTestApi>(
g_browser_process->platform_part());
browser_part_->InitializeCrosComponentManager(component_manager_);
// Create object under test.
auto delegate_ptr = std::make_unique<DelegateImpl>();
delegate_ = delegate_ptr.get();
browser_loader_ = std::make_unique<BrowserLoader>(
std::move(delegate_ptr), component_manager_,
&mock_component_update_service_, &fake_upstart_client_);
}
~BrowserLoaderTest() override {
browser_part_->ShutdownCrosComponentManager();
browser_util::SetLacrosEnabledForTest(false);
}
// Public because this is test code.
content::BrowserTaskEnvironment task_environment_;
protected:
DelegateImpl* delegate_;
component_updater::MockComponentUpdateService mock_component_update_service_;
scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_;
chromeos::FakeUpstartClient fake_upstart_client_;
std::unique_ptr<BrowserProcessPlatformPartTestApi> browser_part_;
std::unique_ptr<BrowserLoader> browser_loader_;
};
TEST_F(BrowserLoaderTest, ShowUpdateNotification) {
// Creating the loader does not trigger an update notification.
EXPECT_EQ(0, delegate_->set_lacros_update_available_);
// The initial load of the component does not trigger an update notification.
base::RunLoop run_loop;
browser_loader_->Load(base::BindLambdaForTesting(
[&](const base::FilePath&, LacrosSelection) { run_loop.Quit(); }));
run_loop.Run();
EXPECT_EQ(0, delegate_->set_lacros_update_available_);
// Update check does not trigger an update notification.
browser_loader_->OnEvent(
UpdateClient::Observer::Events::COMPONENT_CHECKING_FOR_UPDATES,
kLacrosComponentId);
EXPECT_EQ(0, delegate_->set_lacros_update_available_);
// Update download does not trigger an update notification.
browser_loader_->OnEvent(
UpdateClient::Observer::Events::COMPONENT_UPDATE_DOWNLOADING,
kLacrosComponentId);
EXPECT_EQ(0, delegate_->set_lacros_update_available_);
// Update completion trigger the notification.
browser_loader_->OnEvent(UpdateClient::Observer::Events::COMPONENT_UPDATED,
kLacrosComponentId);
EXPECT_EQ(1, delegate_->set_lacros_update_available_);
}
TEST_F(BrowserLoaderTest, OnLoadSelectionQuicklyChooseRootfs) {
bool callback_called = false;
fake_upstart_client_.set_start_job_cb(base::BindRepeating(
[](bool* b, const std::string& job,
const std::vector<std::string>& upstart_env) {
EXPECT_EQ(job, kLacrosMounterUpstartJob);
*b = true;
return true;
},
&callback_called));
// Set `was_installed` to false, in order to quickly mount rootfs
// lacros-chrome.
browser_loader_->OnLoadSelection(
base::BindOnce([](const base::FilePath&, LacrosSelection selection) {
EXPECT_EQ(LacrosSelection::kRootfs, selection);
}),
false);
task_environment_.RunUntilIdle();
EXPECT_TRUE(callback_called);
}
TEST_F(BrowserLoaderTest, OnLoadVersionSelectionStateful) {
// Use stateful when a rootfs lacros-chrome version is invalid.
bool callback_called = false;
fake_upstart_client_.set_start_job_cb(base::BindRepeating(
[](bool* b, const std::string& job,
const std::vector<std::string>& upstart_env) {
*b = true;
return true;
},
&callback_called));
// Pass in an invalid `base::Version`.
browser_loader_->OnLoadVersionSelection({}, base::Version());
EXPECT_FALSE(callback_called);
}
TEST_F(BrowserLoaderTest, OnLoadVersionSelectionRootfs) {
std::u16string lacros_component_name =
base::UTF8ToUTF16(base::StringPiece(kLacrosComponentName));
EXPECT_CALL(mock_component_update_service_, GetComponents())
.WillOnce(Return(std::vector<component_updater::ComponentInfo>{
{kLacrosComponentId, "", lacros_component_name,
base::Version("1.0.0")}}));
bool callback_called = false;
fake_upstart_client_.set_start_job_cb(base::BindRepeating(
[](bool* b, const std::string& job,
const std::vector<std::string>& upstart_env) {
EXPECT_EQ(job, kLacrosMounterUpstartJob);
*b = true;
return true;
},
&callback_called));
// Pass in a rootfs lacros-chrome version that is newer.
browser_loader_->OnLoadVersionSelection(
base::BindOnce([](const base::FilePath&, LacrosSelection selection) {
EXPECT_EQ(LacrosSelection::kRootfs, selection);
}),
base::Version("2.0.0"));
task_environment_.RunUntilIdle();
EXPECT_TRUE(callback_called);
}
TEST_F(BrowserLoaderTest, OnLoadVersionSelectionRootfsIsOlder) {
// Use stateful when a rootfs lacros-chrome version is older.
std::u16string lacros_component_name =
base::UTF8ToUTF16(base::StringPiece(kLacrosComponentName));
EXPECT_CALL(mock_component_update_service_, GetComponents())
.WillOnce(Return(std::vector<component_updater::ComponentInfo>{
{kLacrosComponentId, "", lacros_component_name,
base::Version("3.0.0")}}));
bool callback_called = false;
fake_upstart_client_.set_start_job_cb(base::BindRepeating(
[](bool* b, const std::string& job,
const std::vector<std::string>& upstart_env) {
*b = true;
return true;
},
&callback_called));
// Pass in a rootfs lacros-chrome version that is older.
browser_loader_->OnLoadVersionSelection({}, base::Version("2.0.0"));
EXPECT_FALSE(callback_called);
}
} // namespace crosapi