blob: 40bbefd2aee0a6b66d04b89dc8255be4004d62d5 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "bootsplash/bootsplash_daemon.h"
#include "bootsplash/paths.h"
#include <string>
#include <sysexits.h>
#include <utility>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/stringprintf.h>
#include <brillo/timers/alarm_timer.h>
#include <gmock/gmock.h>
#include <gmock/gmock-actions.h>
#include <gtest/gtest.h>
using base::FilePath;
namespace bootsplash {
namespace {
class AlarmTimerTester {
public:
AlarmTimerTester(bool* did_run,
base::TimeDelta delay,
base::OnceClosure quit_closure)
: did_run_(did_run),
quit_closure_(std::move(quit_closure)),
delay_(delay),
timer_(brillo::timers::SimpleAlarmTimer::CreateForTesting()) {}
AlarmTimerTester(const AlarmTimerTester&) = delete;
AlarmTimerTester& operator=(const AlarmTimerTester&) = delete;
void Start() {
timer_->Start(
FROM_HERE, delay_,
base::BindRepeating(&AlarmTimerTester::Run, base::Unretained(this)));
}
private:
void Run() {
*did_run_ = true;
if (quit_closure_)
std::move(quit_closure_).Run();
}
bool* did_run_;
base::OnceClosure quit_closure_;
const base::TimeDelta delay_;
std::unique_ptr<brillo::timers::SimpleAlarmTimer> timer_;
};
} // namespace
class BootSplashDaemonMock : public BootSplashDaemon {
public:
BootSplashDaemonMock() : BootSplashDaemon(false) {
OverrideBootLogoAnimationAlarmForTesting();
}
MOCK_METHOD(void, DBusDaemonInit, (), (override));
};
class BootSplashDaemonTest : public ::testing::Test {
protected:
const FilePath& test_dir() const { return scoped_temp_dir_.GetPath(); }
const FilePath& frecon_vt_path() const { return frecon_vt_path_; }
protected:
void SetUp() override {
EXPECT_CALL(boot_splash_daemon_, DBusDaemonInit())
.WillRepeatedly(testing::Return());
ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
paths::SetPrefixForTesting(test_dir());
// Create an empty vt0 file to Write() to, so the Frecon object can be
// created.
frecon_vt_path_ = paths::Get(paths::kFreconVt);
ASSERT_TRUE(base::CreateDirectory(frecon_vt_path_.DirName()));
ASSERT_TRUE(base::WriteFile(frecon_vt_path_, ""));
// Create hi_res file to that's initially "0" (low res).
frecon_hi_res_path_ = paths::Get(paths::kFreconHiRes);
ASSERT_TRUE(base::CreateDirectory(frecon_hi_res_path_.DirName()));
ASSERT_TRUE(base::WriteFile(frecon_hi_res_path_, "0"));
// Create an empty boot splash assets directory, so the Frecon object can be
// created.
boot_splash_assets_dir_ = paths::GetBootSplashAssetsDir(false);
ASSERT_TRUE(base::CreateDirectory(boot_splash_assets_dir_));
}
BootSplashDaemonMock boot_splash_daemon_;
base::ScopedTempDir scoped_temp_dir_;
base::FilePath frecon_vt_path_;
base::FilePath frecon_hi_res_path_;
base::FilePath boot_splash_assets_dir_;
};
TEST_F(BootSplashDaemonTest, DBusDaemonInit) {
// Verify DBus can be initialized without errors.
boot_splash_daemon_.DBusDaemonInit();
}
TEST_F(BootSplashDaemonTest, InitBootSplash) {
ASSERT_EQ(boot_splash_daemon_.OnInit(), EX_OK);
ASSERT_EQ(boot_splash_daemon_.InitBootSplash(), EX_OK);
}
TEST_F(BootSplashDaemonTest, OnShutdown) {
// Verify BootSplashDaemon can be shutdown without errors.
int return_code = -1;
boot_splash_daemon_.OnShutdown(&return_code);
ASSERT_EQ(return_code, EX_OK);
}
TEST_F(BootSplashDaemonTest, SessionManagerLoginPromptVisibleEventReceived) {
// Verify BootSplashDaemon can quit without errors.
boot_splash_daemon_.SessionManagerLoginPromptVisibleEventReceived();
}
TEST_F(BootSplashDaemonTest, OnBootLogoAnimationAlarmFired) {
ASSERT_EQ(boot_splash_daemon_.OnInit(), EX_OK);
// Record the previous file contents, which will be appended to.
std::string prev_file_contents;
ASSERT_TRUE(ReadFileToString(frecon_vt_path(), &prev_file_contents));
// Handle the boot logo alarm firing. This should write the next image file to
// the frecon VT file.
boot_splash_daemon_.OnBootLogoAnimationAlarmFired();
// Build the expected image name.
std::string imageFileName =
base::StringPrintf("%s%02d%s", paths::kBootSplashFilenamePrefix,
0, // BootSplashDaemon starts with frame 0
paths::kImageExtension);
base::FilePath imagePath =
paths::Get(boot_splash_assets_dir_.value()).Append(imageFileName);
// Build the expected file contents.
std::string expected_contents =
prev_file_contents + "\033]image:file=" + imagePath.value() + "\a";
// Validate the new data was written.
std::string curr_file_contents;
ASSERT_TRUE(ReadFileToString(frecon_vt_path(), &curr_file_contents));
EXPECT_EQ(curr_file_contents, expected_contents);
}
} // namespace bootsplash