blob: 25e188a51985d4fbf97d1d4cb8179f0a7bfde1eb [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "init/clobber/clobber_state.h"
#include <limits.h>
#include <stdlib.h>
#include <sys/sysmacros.h>
#include <memory>
#include <set>
#include <unordered_map>
#include <utility>
#include <vector>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <brillo/blkdev_utils/mock_lvm.h>
#include <brillo/blkdev_utils/lvm.h>
#include <brillo/files/file_util.h>
#include <gtest/gtest.h>
#include <libcrossystem/crossystem.h>
#include <libcrossystem/crossystem_fake.h>
#include <libdlcservice/mock_utils.h>
#include <libdlcservice/utils.h>
#include "gmock/gmock.h"
#include "init/clobber/clobber_wipe_mock.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::StrictMock;
TEST(ParseArgv, EmptyArgs) {
std::vector<const char*> argv{"clobber-state"};
ClobberState::Arguments args = ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_FALSE(args.factory_wipe);
EXPECT_FALSE(args.fast_wipe);
EXPECT_FALSE(args.keepimg);
EXPECT_FALSE(args.safe_wipe);
EXPECT_FALSE(args.rollback_wipe);
EXPECT_FALSE(args.preserve_lvs);
}
TEST(ParseArgv, AllArgsIndividual) {
std::vector<const char*> argv{"clobber-state", "fast", "factory",
"keepimg", "rollback", "safe"};
ClobberState::Arguments args = ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_TRUE(args.factory_wipe);
EXPECT_TRUE(args.fast_wipe);
EXPECT_TRUE(args.keepimg);
EXPECT_TRUE(args.safe_wipe);
EXPECT_TRUE(args.rollback_wipe);
EXPECT_FALSE(args.preserve_lvs);
}
TEST(ParseArgv, AllArgsSquished) {
std::vector<const char*> argv{"clobber-state",
"fast factory keepimg rollback safe"};
ClobberState::Arguments args = ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_TRUE(args.factory_wipe);
EXPECT_TRUE(args.fast_wipe);
EXPECT_TRUE(args.keepimg);
EXPECT_TRUE(args.safe_wipe);
EXPECT_TRUE(args.rollback_wipe);
EXPECT_FALSE(args.preserve_lvs);
}
TEST(ParseArgv, SomeArgsIndividual) {
std::vector<const char*> argv{"clobber-state", "rollback", "fast", "keepimg"};
ClobberState::Arguments args = ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_FALSE(args.factory_wipe);
EXPECT_TRUE(args.fast_wipe);
EXPECT_TRUE(args.keepimg);
EXPECT_FALSE(args.safe_wipe);
EXPECT_TRUE(args.rollback_wipe);
EXPECT_FALSE(args.preserve_lvs);
}
TEST(ParseArgv, SomeArgsSquished) {
std::vector<const char*> argv{"clobber-state", "rollback safe fast"};
ClobberState::Arguments args = ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_FALSE(args.factory_wipe);
EXPECT_TRUE(args.fast_wipe);
EXPECT_FALSE(args.keepimg);
EXPECT_TRUE(args.safe_wipe);
EXPECT_TRUE(args.rollback_wipe);
EXPECT_FALSE(args.preserve_lvs);
}
TEST(ParseArgv, PreserveLogicalVolumesWipe) {
{
std::vector<const char*> argv{"clobber-state", "preserve_lvs"};
ClobberState::Arguments args =
ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_FALSE(args.safe_wipe);
EXPECT_EQ(args.preserve_lvs, USE_LVM_STATEFUL_PARTITION);
}
{
std::vector<const char*> argv{"clobber-state", "safe preserve_lvs"};
ClobberState::Arguments args =
ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_TRUE(args.safe_wipe);
EXPECT_EQ(args.preserve_lvs, USE_LVM_STATEFUL_PARTITION);
}
{
std::vector<const char*> argv{"clobber-state", "safe", "preserve_lvs"};
ClobberState::Arguments args =
ClobberState::ParseArgv(argv.size(), &argv[0]);
EXPECT_TRUE(args.safe_wipe);
EXPECT_EQ(args.preserve_lvs, USE_LVM_STATEFUL_PARTITION);
}
}
TEST(IncrementFileCounter, Nonexistent) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "1\n");
}
TEST(IncrementFileCounter, NegativeNumber) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, "-3\n"));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "1\n");
}
TEST(IncrementFileCounter, SmallNumber) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, "42\n"));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "43\n");
}
TEST(IncrementFileCounter, LargeNumber) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, "1238761\n"));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "1238762\n");
}
TEST(IncrementFileCounter, NonNumber) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, "cruciverbalist"));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "1\n");
}
TEST(IncrementFileCounter, IntMax) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, std::to_string(INT_MAX)));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "1\n");
}
TEST(IncrementFileCounter, LongMax) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, std::to_string(LONG_MAX)));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "1\n");
}
TEST(IncrementFileCounter, InputNoNewline) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath counter = temp_dir.GetPath().Append("counter");
ASSERT_TRUE(CreateDirectoryAndWriteFile(counter, std::to_string(7)));
EXPECT_TRUE(ClobberState::IncrementFileCounter(counter));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(counter, &contents));
EXPECT_EQ(contents, "8\n");
}
TEST(WriteLastPowerwashTime, FileNonexistentWriteSuccess) {
const time_t curr_value = 55;
base::Time parsed_time = base::Time::FromTimeT(curr_value);
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath last_powerwash_time_path =
temp_dir.GetPath().Append("lastPowerwashTime");
EXPECT_TRUE(ClobberState::WriteLastPowerwashTime(last_powerwash_time_path,
parsed_time));
EXPECT_TRUE(base::PathExists(last_powerwash_time_path));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(last_powerwash_time_path, &contents));
EXPECT_EQ(contents, "55\n");
}
TEST(WriteLastPowerwashTime, FileExistentOverwriteSuccess) {
const time_t curr_value = 66;
base::Time parsed_time = base::Time::FromTimeT(curr_value);
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath last_powerwash_time_path =
temp_dir.GetPath().Append("lastPowerwashTime");
ASSERT_TRUE(CreateDirectoryAndWriteFile(last_powerwash_time_path, "55\n"));
EXPECT_TRUE(ClobberState::WriteLastPowerwashTime(last_powerwash_time_path,
parsed_time));
EXPECT_TRUE(base::PathExists(last_powerwash_time_path));
std::string contents;
ASSERT_TRUE(base::ReadFileToString(last_powerwash_time_path, &contents));
EXPECT_EQ(contents, "66\n");
}
TEST(PreserveFiles, NoFiles) {
base::ScopedTempDir fake_stateful_dir;
ASSERT_TRUE(fake_stateful_dir.CreateUniqueTempDir());
base::FilePath fake_stateful = fake_stateful_dir.GetPath();
ASSERT_TRUE(base::CreateDirectory(
fake_stateful.Append("unimportant/directory/structure")));
base::ScopedTempDir fake_tmp_dir;
ASSERT_TRUE(fake_tmp_dir.CreateUniqueTempDir());
base::FilePath tar_file = fake_tmp_dir.GetPath().Append("preserved.tar");
EXPECT_EQ(ClobberState::PreserveFiles(
fake_stateful, std::vector<base::FilePath>(), tar_file),
0);
EXPECT_FALSE(base::PathExists(tar_file));
ASSERT_TRUE(CreateDirectoryAndWriteFile(tar_file, ""));
EXPECT_TRUE(base::PathExists(tar_file));
EXPECT_EQ(ClobberState::PreserveFiles(
fake_stateful, std::vector<base::FilePath>(), tar_file),
0);
// PreserveFiles should have deleted existing tar_file.
EXPECT_FALSE(base::PathExists(tar_file));
}
TEST(PreserveFiles, NoExistingFiles) {
base::ScopedTempDir fake_stateful_dir;
ASSERT_TRUE(fake_stateful_dir.CreateUniqueTempDir());
base::FilePath fake_stateful = fake_stateful_dir.GetPath();
ASSERT_TRUE(base::CreateDirectory(
fake_stateful.Append("unimportant/directory/structure")));
base::ScopedTempDir fake_tmp_dir;
ASSERT_TRUE(fake_tmp_dir.CreateUniqueTempDir());
base::FilePath tar_file = fake_tmp_dir.GetPath().Append("preserved.tar");
base::FilePath nonexistent_file = fake_tmp_dir.GetPath().Append("test.txt");
EXPECT_EQ(ClobberState::PreserveFiles(
fake_stateful, std::vector<base::FilePath>({nonexistent_file}),
tar_file),
0);
EXPECT_FALSE(base::PathExists(tar_file));
ASSERT_TRUE(CreateDirectoryAndWriteFile(tar_file, ""));
EXPECT_TRUE(base::PathExists(tar_file));
EXPECT_EQ(ClobberState::PreserveFiles(
fake_stateful, std::vector<base::FilePath>({nonexistent_file}),
tar_file),
0);
// PreserveFiles should have deleted existing tar_file.
EXPECT_FALSE(base::PathExists(tar_file));
}
TEST(PreserveFiles, OneFile) {
base::FilePath not_preserved_file("unimportant/directory/structure/file.img");
base::FilePath preserved_file("good/directory/file.tiff");
base::ScopedTempDir fake_stateful_dir;
ASSERT_TRUE(fake_stateful_dir.CreateUniqueTempDir());
base::FilePath fake_stateful = fake_stateful_dir.GetPath();
base::FilePath stateful_not_preserved =
fake_stateful.Append(not_preserved_file);
base::FilePath stateful_preserved = fake_stateful.Append(preserved_file);
ASSERT_TRUE(CreateDirectoryAndWriteFile(stateful_not_preserved, "unneeded"));
ASSERT_TRUE(CreateDirectoryAndWriteFile(stateful_preserved, "test_contents"));
base::ScopedTempDir fake_tmp_dir;
ASSERT_TRUE(fake_tmp_dir.CreateUniqueTempDir());
base::FilePath tar_file = fake_tmp_dir.GetPath().Append("preserved.tar");
std::vector<base::FilePath> preserved_files{preserved_file};
EXPECT_EQ(
ClobberState::PreserveFiles(fake_stateful, preserved_files, tar_file), 0);
ASSERT_TRUE(base::PathExists(tar_file));
base::ScopedTempDir expand_tar_dir;
ASSERT_TRUE(expand_tar_dir.CreateUniqueTempDir());
base::FilePath expand_tar_path = expand_tar_dir.GetPath();
brillo::ProcessImpl tar;
tar.AddArg("/bin/tar");
tar.AddArg("-C");
tar.AddArg(expand_tar_path.value());
tar.AddArg("-xf");
tar.AddArg(tar_file.value());
ASSERT_EQ(tar.Run(), 0);
EXPECT_FALSE(base::PathExists(expand_tar_path.Append(not_preserved_file)));
base::FilePath expanded_preserved = expand_tar_path.Append(preserved_file);
EXPECT_TRUE(base::PathExists(expanded_preserved));
std::string contents;
EXPECT_TRUE(base::ReadFileToString(expanded_preserved, &contents));
EXPECT_EQ(contents, "test_contents");
}
TEST(PreserveFiles, ManyFiles) {
base::FilePath not_preserved_file("unimportant/directory/structure/file.img");
base::FilePath preserved_file_a("good/directory/file.tiff");
base::FilePath preserved_file_b("other/folder/saved.bin");
base::ScopedTempDir fake_stateful_dir;
ASSERT_TRUE(fake_stateful_dir.CreateUniqueTempDir());
base::FilePath fake_stateful = fake_stateful_dir.GetPath();
base::FilePath stateful_not_preserved =
fake_stateful.Append(not_preserved_file);
base::FilePath stateful_preserved_a = fake_stateful.Append(preserved_file_a);
base::FilePath stateful_preserved_b = fake_stateful.Append(preserved_file_b);
ASSERT_TRUE(CreateDirectoryAndWriteFile(stateful_not_preserved, "unneeded"));
ASSERT_TRUE(
CreateDirectoryAndWriteFile(stateful_preserved_a, "test_contents"));
ASSERT_TRUE(CreateDirectoryAndWriteFile(stateful_preserved_b, "data"));
base::ScopedTempDir fake_tmp_dir;
ASSERT_TRUE(fake_tmp_dir.CreateUniqueTempDir());
base::FilePath tar_file = fake_tmp_dir.GetPath().Append("preserved.tar");
std::vector<base::FilePath> preserved_files{preserved_file_a,
preserved_file_b};
EXPECT_EQ(
ClobberState::PreserveFiles(fake_stateful, preserved_files, tar_file), 0);
ASSERT_TRUE(base::PathExists(tar_file));
base::ScopedTempDir expand_tar_dir;
ASSERT_TRUE(expand_tar_dir.CreateUniqueTempDir());
base::FilePath expand_tar_path = expand_tar_dir.GetPath();
brillo::ProcessImpl tar;
tar.AddArg("/bin/tar");
tar.AddArg("-C");
tar.AddArg(expand_tar_path.value());
tar.AddArg("-xf");
tar.AddArg(tar_file.value());
ASSERT_EQ(tar.Run(), 0);
EXPECT_FALSE(base::PathExists(expand_tar_path.Append(not_preserved_file)));
base::FilePath expanded_preserved_a =
expand_tar_path.Append(preserved_file_a);
EXPECT_TRUE(base::PathExists(expanded_preserved_a));
std::string contents_a;
EXPECT_TRUE(base::ReadFileToString(expanded_preserved_a, &contents_a));
EXPECT_EQ(contents_a, "test_contents");
base::FilePath expanded_preserved_b =
expand_tar_path.Append(preserved_file_b);
EXPECT_TRUE(base::PathExists(expanded_preserved_b));
std::string contents_b;
EXPECT_TRUE(base::ReadFileToString(expanded_preserved_b, &contents_b));
EXPECT_EQ(contents_b, "data");
}
class MarkDeveloperModeTest : public ::testing::Test {
protected:
MarkDeveloperModeTest()
: crossystem_fake_(std::make_unique<crossystem::fake::CrossystemFake>()),
cros_system_(crossystem_fake_.get()),
clobber_ui_null_(std::make_unique<ClobberUi>(DevNull())),
clobber_wipe_mock_(
std::make_unique<ClobberWipeMock>(clobber_ui_null_.get())),
clobber_(ClobberState::Arguments(),
std::make_unique<crossystem::Crossystem>(
std::move(crossystem_fake_)),
std::move(clobber_ui_null_),
std::move(clobber_wipe_mock_),
std::unique_ptr<ClobberLvm>()) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
fake_stateful_ = temp_dir_.GetPath();
clobber_.SetStatefulForTest(fake_stateful_);
}
std::unique_ptr<crossystem::fake::CrossystemFake> crossystem_fake_;
crossystem::fake::CrossystemFake* cros_system_;
std::unique_ptr<ClobberUi> clobber_ui_null_;
std::unique_ptr<ClobberWipeMock> clobber_wipe_mock_;
ClobberState clobber_;
base::ScopedTempDir temp_dir_;
base::FilePath fake_stateful_;
};
TEST_F(MarkDeveloperModeTest, NotDeveloper) {
clobber_.MarkDeveloperMode();
EXPECT_FALSE(base::PathExists(fake_stateful_.Append(".developer_mode")));
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDevSwitchBoot, 0));
clobber_.MarkDeveloperMode();
EXPECT_FALSE(base::PathExists(fake_stateful_.Append(".developer_mode")));
ASSERT_TRUE(cros_system_->VbSetSystemPropertyString(
crossystem::Crossystem::kMainFirmwareActive, "recovery"));
clobber_.MarkDeveloperMode();
EXPECT_FALSE(base::PathExists(fake_stateful_.Append(".developer_mode")));
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDevSwitchBoot, 1));
clobber_.MarkDeveloperMode();
EXPECT_FALSE(base::PathExists(fake_stateful_.Append(".developer_mode")));
cros_system_->UnsetSystemPropertyValue(
crossystem::Crossystem::kMainFirmwareActive);
clobber_.MarkDeveloperMode();
EXPECT_FALSE(base::PathExists(fake_stateful_.Append(".developer_mode")));
}
TEST_F(MarkDeveloperModeTest, IsDeveloper) {
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDevSwitchBoot, 1));
ASSERT_TRUE(cros_system_->VbSetSystemPropertyString(
crossystem::Crossystem::kMainFirmwareActive, "not_recovery"));
clobber_.MarkDeveloperMode();
EXPECT_TRUE(base::PathExists(fake_stateful_.Append(".developer_mode")));
}
class GetPreservedFilesListTest : public ::testing::Test {
protected:
GetPreservedFilesListTest()
: crossystem_fake_(std::make_unique<crossystem::fake::CrossystemFake>()),
cros_system_(crossystem_fake_.get()),
clobber_ui_null_(std::make_unique<ClobberUi>(DevNull())),
clobber_wipe_mock_(
std::make_unique<ClobberWipeMock>(clobber_ui_null_.get())),
clobber_(ClobberState::Arguments(),
std::make_unique<crossystem::Crossystem>(
std::move(crossystem_fake_)),
std::move(clobber_ui_null_),
std::move(clobber_wipe_mock_),
std::unique_ptr<ClobberLvm>()) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
fake_stateful_ = temp_dir_.GetPath();
clobber_.SetStatefulForTest(fake_stateful_);
base::FilePath extensions =
fake_stateful_.Append("unencrypted/import_extensions/extensions");
ASSERT_TRUE(base::CreateDirectory(extensions));
ASSERT_TRUE(
CreateDirectoryAndWriteFile(extensions.Append("fileA.crx"), ""));
ASSERT_TRUE(
CreateDirectoryAndWriteFile(extensions.Append("fileB.crx"), ""));
ASSERT_TRUE(
CreateDirectoryAndWriteFile(extensions.Append("fileC.tar"), ""));
ASSERT_TRUE(
CreateDirectoryAndWriteFile(extensions.Append("fileD.bmp"), ""));
base::FilePath dlc_factory =
fake_stateful_.Append("unencrypted/dlc-factory-images");
ASSERT_TRUE(base::CreateDirectory(dlc_factory));
ASSERT_TRUE(CreateDirectoryAndWriteFile(
dlc_factory.Append("test-dlc1/package/dlc.img"), ""));
ASSERT_TRUE(CreateDirectoryAndWriteFile(
dlc_factory.Append("test-dlc2/package/dlc.img"), ""));
ASSERT_TRUE(
CreateDirectoryAndWriteFile(dlc_factory.Append("test-dlc3"), ""));
}
void SetCompare(std::set<std::string> expected,
std::set<base::FilePath> actual) {
for (const std::string& s : expected) {
EXPECT_TRUE(actual.count(base::FilePath(s)) == 1)
<< "Expected preserved file not found: " << s;
}
for (const base::FilePath& fp : actual) {
EXPECT_TRUE(expected.count(fp.value()) == 1)
<< "Unexpected preserved file found: " << fp.value();
}
}
std::unique_ptr<crossystem::fake::CrossystemFake> crossystem_fake_;
crossystem::fake::CrossystemFake* cros_system_;
std::unique_ptr<ClobberUi> clobber_ui_null_;
std::unique_ptr<ClobberWipeMock> clobber_wipe_mock_;
ClobberState clobber_;
base::ScopedTempDir temp_dir_;
base::FilePath fake_stateful_;
};
TEST_F(GetPreservedFilesListTest, NoOptions) {
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 0));
EXPECT_EQ(clobber_.GetPreservedFilesList().size(), 0);
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 1));
std::vector<base::FilePath> preserved_files =
clobber_.GetPreservedFilesList();
std::set<base::FilePath> preserved_set(preserved_files.begin(),
preserved_files.end());
std::set<std::string> expected_preserved_set{".labmachine"};
SetCompare(expected_preserved_set, preserved_set);
}
TEST_F(GetPreservedFilesListTest, SafeWipe) {
ClobberState::Arguments args;
args.safe_wipe = true;
clobber_.SetArgsForTest(args);
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 0));
std::vector<base::FilePath> preserved_files =
clobber_.GetPreservedFilesList();
std::set<base::FilePath> preserved_set(preserved_files.begin(),
preserved_files.end());
std::set<std::string> expected_preserved_set{
"unencrypted/cros-components/offline-demo-mode-resources/image.squash",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.json",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.1",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.2",
"unencrypted/cros-components/offline-demo-mode-resources/"
"manifest.fingerprint",
"unencrypted/cros-components/offline-demo-mode-resources/manifest.json",
"unencrypted/cros-components/offline-demo-mode-resources/table",
"unencrypted/preserve/flex/flex_id",
"unencrypted/preserve/flex/flex_state_key",
"unencrypted/preserve/gsc_prev_crash_log_id",
"unencrypted/preserve/last_active_dates",
"unencrypted/preserve/powerwash_count",
"unencrypted/preserve/tpm_firmware_update_request",
"unencrypted/preserve/update_engine/prefs/last-active-ping-day",
"unencrypted/preserve/update_engine/prefs/last-roll-call-ping-day",
"unencrypted/preserve/update_engine/prefs/rollback-happened",
"unencrypted/preserve/update_engine/prefs/rollback-version"};
SetCompare(expected_preserved_set, preserved_set);
}
TEST_F(GetPreservedFilesListTest, SafeAndRollbackWipe) {
ClobberState::Arguments args;
args.safe_wipe = true;
args.rollback_wipe = true;
clobber_.SetArgsForTest(args);
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 0));
std::vector<base::FilePath> preserved_files =
clobber_.GetPreservedFilesList();
std::set<base::FilePath> preserved_set(preserved_files.begin(),
preserved_files.end());
std::set<std::string> expected_preserved_set{
"unencrypted/cros-components/offline-demo-mode-resources/image.squash",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.json",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.1",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.2",
"unencrypted/cros-components/offline-demo-mode-resources/"
"manifest.fingerprint",
"unencrypted/cros-components/offline-demo-mode-resources/manifest.json",
"unencrypted/cros-components/offline-demo-mode-resources/table",
"unencrypted/preserve/enterprise-rollback-metrics-data",
"unencrypted/preserve/flex/flex_id",
"unencrypted/preserve/flex/flex_state_key",
"unencrypted/preserve/gsc_prev_crash_log_id",
"unencrypted/preserve/last_active_dates",
"unencrypted/preserve/powerwash_count",
"unencrypted/preserve/rollback_data",
"unencrypted/preserve/rollback_data_tpm",
"unencrypted/preserve/tpm_firmware_update_request",
"unencrypted/preserve/update_engine/prefs/last-active-ping-day",
"unencrypted/preserve/update_engine/prefs/last-roll-call-ping-day",
"unencrypted/preserve/update_engine/prefs/rollback-happened",
"unencrypted/preserve/update_engine/prefs/rollback-version"};
SetCompare(expected_preserved_set, preserved_set);
}
TEST_F(GetPreservedFilesListTest, SafeAndAdMigrationWipe) {
ClobberState::Arguments args;
args.safe_wipe = true;
args.ad_migration_wipe = true;
clobber_.SetArgsForTest(args);
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 0));
std::vector<base::FilePath> preserved_files =
clobber_.GetPreservedFilesList();
std::set<base::FilePath> preserved_set(preserved_files.begin(),
preserved_files.end());
std::set<std::string> expected_preserved_set{
"unencrypted/cros-components/offline-demo-mode-resources/image.squash",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.json",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.1",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.2",
"unencrypted/cros-components/offline-demo-mode-resources/"
"manifest.fingerprint",
"unencrypted/cros-components/offline-demo-mode-resources/manifest.json",
"unencrypted/cros-components/offline-demo-mode-resources/table",
"unencrypted/preserve/chromad_migration_skip_oobe",
"unencrypted/preserve/flex/flex_id",
"unencrypted/preserve/flex/flex_state_key",
"unencrypted/preserve/gsc_prev_crash_log_id",
"unencrypted/preserve/last_active_dates",
"unencrypted/preserve/powerwash_count",
"unencrypted/preserve/tpm_firmware_update_request",
"unencrypted/preserve/update_engine/prefs/last-active-ping-day",
"unencrypted/preserve/update_engine/prefs/last-roll-call-ping-day",
"unencrypted/preserve/update_engine/prefs/rollback-happened",
"unencrypted/preserve/update_engine/prefs/rollback-version"};
SetCompare(expected_preserved_set, preserved_set);
}
TEST_F(GetPreservedFilesListTest, FactoryWipe) {
ClobberState::Arguments args;
args.factory_wipe = true;
clobber_.SetArgsForTest(args);
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 0));
std::vector<base::FilePath> preserved_files =
clobber_.GetPreservedFilesList();
std::set<base::FilePath> preserved_set(preserved_files.begin(),
preserved_files.end());
std::set<std::string> expected_preserved_set{
"unencrypted/dlc-factory-images/test-dlc1/package/dlc.img",
"unencrypted/dlc-factory-images/test-dlc2/package/dlc.img",
"unencrypted/import_extensions/extensions/fileA.crx",
"unencrypted/import_extensions/extensions/fileB.crx"};
SetCompare(expected_preserved_set, preserved_set);
}
TEST_F(GetPreservedFilesListTest, SafeRollbackFactoryWipe) {
ClobberState::Arguments args;
args.safe_wipe = true;
args.rollback_wipe = true;
args.factory_wipe = true;
clobber_.SetArgsForTest(args);
ASSERT_TRUE(cros_system_->VbSetSystemPropertyInt(
crossystem::Crossystem::kDebugBuild, 0));
std::vector<base::FilePath> preserved_files =
clobber_.GetPreservedFilesList();
std::set<base::FilePath> preserved_set(preserved_files.begin(),
preserved_files.end());
std::set<std::string> expected_preserved_set{
"unencrypted/cros-components/offline-demo-mode-resources/image.squash",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.json",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.1",
"unencrypted/cros-components/offline-demo-mode-resources/"
"imageloader.sig.2",
"unencrypted/cros-components/offline-demo-mode-resources/"
"manifest.fingerprint",
"unencrypted/cros-components/offline-demo-mode-resources/manifest.json",
"unencrypted/cros-components/offline-demo-mode-resources/table",
"unencrypted/dlc-factory-images/test-dlc1/package/dlc.img",
"unencrypted/dlc-factory-images/test-dlc2/package/dlc.img",
"unencrypted/import_extensions/extensions/fileA.crx",
"unencrypted/import_extensions/extensions/fileB.crx",
"unencrypted/preserve/enterprise-rollback-metrics-data",
"unencrypted/preserve/flex/flex_id",
"unencrypted/preserve/flex/flex_state_key",
"unencrypted/preserve/gsc_prev_crash_log_id",
"unencrypted/preserve/last_active_dates",
"unencrypted/preserve/powerwash_count",
"unencrypted/preserve/rollback_data",
"unencrypted/preserve/rollback_data_tpm",
"unencrypted/preserve/tpm_firmware_update_request",
"unencrypted/preserve/update_engine/prefs/last-active-ping-day",
"unencrypted/preserve/update_engine/prefs/last-roll-call-ping-day",
"unencrypted/preserve/update_engine/prefs/rollback-happened",
"unencrypted/preserve/update_engine/prefs/rollback-version"};
SetCompare(expected_preserved_set, preserved_set);
}
class AttemptSwitchToFastWipeTest : public ::testing::Test {
protected:
AttemptSwitchToFastWipeTest()
: clobber_ui_null_(std::make_unique<ClobberUi>(DevNull())),
clobber_wipe_mock_(
std::make_unique<ClobberWipeMock>(clobber_ui_null_.get())),
clobber_wipe_(clobber_wipe_mock_.get()),
clobber_(ClobberState::Arguments(),
std::make_unique<crossystem::Crossystem>(
std::make_unique<crossystem::fake::CrossystemFake>()),
std::move(clobber_ui_null_),
std::move(clobber_wipe_mock_),
std::unique_ptr<ClobberLvm>()) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
temp_path_ = temp_dir_.GetPath();
fake_stateful_ = temp_path_.Append("stateful");
clobber_.SetStatefulForTest(fake_stateful_);
base::FilePath shadow = fake_stateful_.Append("home/.shadow");
encrypted_stateful_paths_ = std::vector<base::FilePath>({
fake_stateful_.Append("encrypted.block"),
fake_stateful_.Append("var_overlay/fileA"),
fake_stateful_.Append("var_overlay/fileB"),
fake_stateful_.Append("dev_image/fileA"),
fake_stateful_.Append("dev_image/fileB"),
shadow.Append("uninteresting/vault/fileA"),
shadow.Append("uninteresting/vault/fileB"),
shadow.Append("uninteresting/vault/fileC"),
shadow.Append("other/vault/fileA"),
shadow.Append("vault/fileA"),
shadow.Append("vault/fileB"),
});
key_material_paths_ = std::vector<base::FilePath>({
fake_stateful_.Append("encrypted.key"),
fake_stateful_.Append("encrypted.needs-finalization"),
fake_stateful_.Append("home/.shadow/cryptohome.key"),
fake_stateful_.Append("home/.shadow/extra_dir/master"),
fake_stateful_.Append("home/.shadow/other_dir/master"),
fake_stateful_.Append("home/.shadow/random_dir/master.0"),
fake_stateful_.Append("home/.shadow/random_dir/master.1"),
fake_stateful_.Append(
"home/.shadow/new_dir/auth_factors/password.first"),
fake_stateful_.Append(
"home/.shadow/new_dir/auth_factors/password.second"),
fake_stateful_.Append("home/.shadow/new_dir/auth_factors/pin.other"),
fake_stateful_.Append("home/.shadow/new_dir/user_secret_stash/uss.0"),
fake_stateful_.Append("home/.shadow/salt"),
fake_stateful_.Append("home/.shadow/salt.sum"),
});
shredded_paths_ = std::vector<base::FilePath>(
{fake_stateful_.Append("really/deeply/buried/random/file/to/delete"),
fake_stateful_.Append("other/file/to/delete")});
for (const base::FilePath& path : encrypted_stateful_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
for (const base::FilePath& path : key_material_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
for (const base::FilePath& path : shredded_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
}
void CheckPathsUntouched(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
std::string contents;
EXPECT_TRUE(base::ReadFileToString(path, &contents))
<< "Couldn't read " << path.value();
EXPECT_EQ(contents, kContents);
}
}
void CheckPathsShredded(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
std::string contents;
EXPECT_TRUE(base::ReadFileToString(path, &contents))
<< "Couldn't read " << path.value();
EXPECT_NE(contents, kContents);
}
}
void CheckPathsDeleted(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
EXPECT_FALSE(base::PathExists(path))
<< path.value() << " should not exist";
}
}
const std::string kContents = "TOP_SECRET_DATA";
std::unique_ptr<ClobberUi> clobber_ui_null_;
std::unique_ptr<ClobberWipeMock> clobber_wipe_mock_;
ClobberWipeMock* clobber_wipe_;
ClobberState clobber_;
base::ScopedTempDir temp_dir_;
base::FilePath temp_path_;
base::FilePath fake_stateful_;
// Files which are deleted by ShredRotationalStatefulPaths.
std::vector<base::FilePath> encrypted_stateful_paths_;
// Files which are deleted by WipeKeyMaterial.
std::vector<base::FilePath> key_material_paths_;
// Files which will be shredded (overwritten) but not deleted by
// ShredRotationalStatefulPaths.
std::vector<base::FilePath> shredded_paths_;
};
TEST_F(AttemptSwitchToFastWipeTest, NotRotationalNoSecureErase) {
ClobberState::Arguments args;
args.fast_wipe = false;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(false);
clobber_.AttemptSwitchToFastWipe(false);
EXPECT_FALSE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsUntouched(encrypted_stateful_paths_);
CheckPathsUntouched(key_material_paths_);
CheckPathsUntouched(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, AlreadyFast) {
ClobberState::Arguments args;
args.fast_wipe = true;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(true);
clobber_.AttemptSwitchToFastWipe(true);
EXPECT_TRUE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsUntouched(encrypted_stateful_paths_);
CheckPathsUntouched(key_material_paths_);
CheckPathsUntouched(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, RotationalNoSecureErase) {
ClobberState::Arguments args;
args.fast_wipe = false;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(false);
clobber_.AttemptSwitchToFastWipe(true);
EXPECT_TRUE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsDeleted(encrypted_stateful_paths_);
CheckPathsShredded(key_material_paths_);
CheckPathsShredded(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, SecureEraseNotRotational) {
ClobberState::Arguments args;
args.fast_wipe = false;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(true);
clobber_.AttemptSwitchToFastWipe(false);
EXPECT_TRUE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsUntouched(encrypted_stateful_paths_);
CheckPathsDeleted(key_material_paths_);
CheckPathsUntouched(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, SecureEraseNotRotationalFactoryWipe) {
ClobberState::Arguments args;
args.fast_wipe = false;
args.factory_wipe = true;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(true);
clobber_.AttemptSwitchToFastWipe(false);
EXPECT_TRUE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsUntouched(encrypted_stateful_paths_);
CheckPathsDeleted(key_material_paths_);
CheckPathsUntouched(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, RotationalSecureErase) {
ClobberState::Arguments args;
args.fast_wipe = false;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(true);
clobber_.AttemptSwitchToFastWipe(true);
EXPECT_TRUE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsDeleted(encrypted_stateful_paths_);
CheckPathsShredded(key_material_paths_);
CheckPathsShredded(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, RotationalSecureEraseFactoryWipe) {
ClobberState::Arguments args;
args.fast_wipe = false;
args.factory_wipe = true;
clobber_.SetArgsForTest(args);
clobber_wipe_->SetSecureEraseSupported(true);
clobber_.AttemptSwitchToFastWipe(true);
EXPECT_TRUE(clobber_.GetArgsForTest().fast_wipe);
CheckPathsDeleted(encrypted_stateful_paths_);
CheckPathsShredded(key_material_paths_);
CheckPathsShredded(shredded_paths_);
}
TEST_F(AttemptSwitchToFastWipeTest, NoLegacySalt) {
ClobberState::Arguments args;
args.fast_wipe = false;
clobber_.SetArgsForTest(args);
ASSERT_TRUE(brillo::DeleteFile(fake_stateful_.Append("home/.shadow/salt")));
clobber_.AttemptSwitchToFastWipe(false);
if (!USE_TPM_INSECURE_FALLBACK) {
ASSERT_TRUE(clobber_.GetArgsForTest().fast_wipe);
} else {
// Missing legacy system salt has no effect on devices that allow non-tpm
// encryption.
ASSERT_FALSE(clobber_.GetArgsForTest().fast_wipe);
}
}
class ShredRotationalStatefulFilesTest : public ::testing::Test {
protected:
ShredRotationalStatefulFilesTest()
: clobber_ui_null_(std::make_unique<ClobberUi>(DevNull())),
clobber_wipe_mock_(
std::make_unique<ClobberWipeMock>(clobber_ui_null_.get())),
clobber_(ClobberState::Arguments(),
std::make_unique<crossystem::Crossystem>(
std::make_unique<crossystem::fake::CrossystemFake>()),
std::move(clobber_ui_null_),
std::move(clobber_wipe_mock_),
std::unique_ptr<ClobberLvm>()) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
temp_path_ = temp_dir_.GetPath();
fake_stateful_ = temp_path_.Append("stateful");
clobber_.SetStatefulForTest(fake_stateful_);
base::FilePath shadow = fake_stateful_.Append("home/.shadow");
deleted_paths_ = std::vector<base::FilePath>({
fake_stateful_.Append("dev_image/fileA"),
fake_stateful_.Append("dev_image/fileB"),
fake_stateful_.Append("encrypted.block"),
fake_stateful_.Append("var_overlay/fileA"),
fake_stateful_.Append("var_overlay/fileB"),
shadow.Append("other/vault/fileA"),
shadow.Append("uninteresting/vault/fileA"),
shadow.Append("uninteresting/vault/fileB"),
shadow.Append("uninteresting/vault/fileC"),
shadow.Append("vault/fileA"),
shadow.Append("vault/fileB"),
});
shredded_paths_ = std::vector<base::FilePath>(
{fake_stateful_.Append("really/deeply/buried/random/file/to/delete"),
fake_stateful_.Append("other/file/to/delete")});
for (const base::FilePath& path : deleted_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
for (const base::FilePath& path : shredded_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
}
void CheckPathsUntouched(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
std::string contents;
EXPECT_TRUE(base::ReadFileToString(path, &contents))
<< "Couldn't read " << path.value();
EXPECT_EQ(contents, kContents);
}
}
void CheckPathsShredded(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
std::string contents;
EXPECT_TRUE(base::ReadFileToString(path, &contents))
<< "Couldn't read " << path.value();
EXPECT_NE(contents, kContents);
}
}
void CheckPathsDeleted(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
EXPECT_FALSE(base::PathExists(path))
<< path.value() << " should not exist";
}
}
const std::string kContents = "TOP_SECRET_DATA";
std::unique_ptr<ClobberUi> clobber_ui_null_;
std::unique_ptr<ClobberWipeMock> clobber_wipe_mock_;
ClobberState clobber_;
base::ScopedTempDir temp_dir_;
base::FilePath temp_path_;
base::FilePath fake_stateful_;
// Files which are deleted by ShredRotationalStatefulPaths.
std::vector<base::FilePath> deleted_paths_;
// Files which will be shredded (overwritten) but not deleted by
// ShredRotationalStatefulPaths.
std::vector<base::FilePath> shredded_paths_;
};
TEST_F(ShredRotationalStatefulFilesTest, Mounted) {
clobber_.ShredRotationalStatefulFiles();
CheckPathsDeleted(deleted_paths_);
CheckPathsShredded(shredded_paths_);
}
class WipeCryptohomeTest : public ::testing::Test {
protected:
WipeCryptohomeTest()
: clobber_ui_null_(std::make_unique<ClobberUi>(DevNull())),
clobber_wipe_mock_(
std::make_unique<ClobberWipeMock>(clobber_ui_null_.get())),
clobber_wipe_(clobber_wipe_mock_.get()),
clobber_(ClobberState::Arguments(),
std::make_unique<crossystem::Crossystem>(
std::make_unique<crossystem::fake::CrossystemFake>()),
std::move(clobber_ui_null_),
std::move(clobber_wipe_mock_),
std::unique_ptr<ClobberLvm>()) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
fake_stateful_ = temp_dir_.GetPath();
clobber_.SetStatefulForTest(fake_stateful_);
deleted_paths_ = std::vector<base::FilePath>({
fake_stateful_.Append("encrypted.key"),
fake_stateful_.Append("encrypted.needs-finalization"),
fake_stateful_.Append("home/.shadow/cryptohome.key"),
fake_stateful_.Append("home/.shadow/extra_dir/master"),
fake_stateful_.Append("home/.shadow/other_dir/master"),
fake_stateful_.Append("home/.shadow/random_dir/master.0"),
fake_stateful_.Append("home/.shadow/random_dir/master.1"),
fake_stateful_.Append(
"home/.shadow/new_dir/auth_factors/password.first"),
fake_stateful_.Append(
"home/.shadow/new_dir/auth_factors/password.second"),
fake_stateful_.Append("home/.shadow/new_dir/auth_factors/pin.other"),
fake_stateful_.Append("home/.shadow/new_dir/user_secret_stash/uss.0"),
fake_stateful_.Append("home/.shadow/salt"),
fake_stateful_.Append("home/.shadow/salt.sum"),
});
ignored_paths_ = std::vector<base::FilePath>({
fake_stateful_.Append("home/.shadow/extra_dir/unimportant"),
fake_stateful_.Append("home/.shadow/other_dir/unimportant"),
fake_stateful_.Append("hopefully/not/a/copy/of/etc/passwd"),
fake_stateful_.Append("uninteresting/file/definitely/not/an/rsa/key"),
});
for (const base::FilePath& path : deleted_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
for (const base::FilePath& path : ignored_paths_) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(path, kContents));
}
}
void CheckPathsUntouched(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
std::string contents;
EXPECT_TRUE(base::ReadFileToString(path, &contents))
<< "Couldn't read " << path.value();
EXPECT_EQ(contents, kContents);
}
}
void CheckPathsDeleted(const std::vector<base::FilePath>& paths) {
for (const base::FilePath& path : paths) {
EXPECT_FALSE(base::PathExists(path))
<< path.value() << " should not exist";
}
}
const std::string kContents = "feebdabdeefedaceddad";
std::unique_ptr<ClobberUi> clobber_ui_null_;
std::unique_ptr<ClobberWipeMock> clobber_wipe_mock_;
ClobberWipeMock* clobber_wipe_;
ClobberState clobber_;
base::ScopedTempDir temp_dir_;
base::FilePath fake_stateful_;
std::vector<base::FilePath> deleted_paths_;
std::vector<base::FilePath> ignored_paths_;
};
TEST_F(WipeCryptohomeTest, NotSupported) {
clobber_wipe_->SetSecureEraseSupported(false);
CheckPathsUntouched(deleted_paths_);
CheckPathsUntouched(ignored_paths_);
EXPECT_FALSE(clobber_.WipeKeyMaterial());
CheckPathsUntouched(ignored_paths_);
}
TEST_F(WipeCryptohomeTest, Supported) {
clobber_wipe_->SetSecureEraseSupported(true);
CheckPathsUntouched(deleted_paths_);
CheckPathsUntouched(ignored_paths_);
EXPECT_TRUE(clobber_.WipeKeyMaterial());
CheckPathsDeleted(deleted_paths_);
CheckPathsUntouched(ignored_paths_);
}
class GetDevicesToWipeTest : public ::testing::Test {
protected:
void SetUp() override {
partitions_.stateful = 1;
partitions_.kernel_a = 2;
partitions_.root_a = 3;
partitions_.kernel_b = 4;
partitions_.root_b = 5;
}
ClobberWipe::PartitionNumbers partitions_;
};
TEST_F(GetDevicesToWipeTest, Error) {
base::FilePath root_disk("/dev/sda");
base::FilePath root_device("/dev/sda4");
ClobberState::DeviceWipeInfo wipe_info;
// Partition number for root_device does not match root_a or root_b in
// partitions_ struct.
EXPECT_FALSE(ClobberState::GetDevicesToWipe(root_disk, root_device,
partitions_, &wipe_info));
}
TEST_F(GetDevicesToWipeTest, MMC) {
base::FilePath root_disk("/dev/mmcblk0");
base::FilePath root_device("/dev/mmcblk0p3");
ClobberState::DeviceWipeInfo wipe_info;
EXPECT_TRUE(ClobberState::GetDevicesToWipe(root_disk, root_device,
partitions_, &wipe_info));
EXPECT_EQ(wipe_info.stateful_partition_device.value(), "/dev/mmcblk0p1");
EXPECT_EQ(wipe_info.inactive_root_device.value(), "/dev/mmcblk0p5");
EXPECT_EQ(wipe_info.inactive_kernel_device.value(), "/dev/mmcblk0p4");
EXPECT_EQ(wipe_info.active_kernel_partition, partitions_.kernel_a);
}
TEST_F(GetDevicesToWipeTest, NVME_a_active) {
base::FilePath root_disk("/dev/nvme0n1");
base::FilePath root_device("/dev/nvme0n1p3");
ClobberState::DeviceWipeInfo wipe_info;
EXPECT_TRUE(ClobberState::GetDevicesToWipe(root_disk, root_device,
partitions_, &wipe_info));
EXPECT_EQ(wipe_info.stateful_partition_device.value(), "/dev/nvme0n1p1");
EXPECT_EQ(wipe_info.inactive_root_device.value(), "/dev/nvme0n1p5");
EXPECT_EQ(wipe_info.inactive_kernel_device.value(), "/dev/nvme0n1p4");
EXPECT_EQ(wipe_info.active_kernel_partition, partitions_.kernel_a);
}
TEST_F(GetDevicesToWipeTest, NVME_b_active) {
base::FilePath root_disk("/dev/nvme0n1");
base::FilePath root_device("/dev/nvme0n1p5");
ClobberState::DeviceWipeInfo wipe_info;
EXPECT_TRUE(ClobberState::GetDevicesToWipe(root_disk, root_device,
partitions_, &wipe_info));
EXPECT_EQ(wipe_info.stateful_partition_device.value(), "/dev/nvme0n1p1");
EXPECT_EQ(wipe_info.inactive_root_device.value(), "/dev/nvme0n1p3");
EXPECT_EQ(wipe_info.inactive_kernel_device.value(), "/dev/nvme0n1p2");
EXPECT_EQ(wipe_info.active_kernel_partition, partitions_.kernel_b);
}
TEST_F(GetDevicesToWipeTest, UFS) {
base::FilePath root_disk("/dev/sda1");
base::FilePath root_device("/dev/sda5");
ClobberState::DeviceWipeInfo wipe_info;
EXPECT_TRUE(ClobberState::GetDevicesToWipe(root_disk, root_device,
partitions_, &wipe_info));
EXPECT_EQ(wipe_info.stateful_partition_device.value(), "/dev/sda1");
EXPECT_EQ(wipe_info.inactive_root_device.value(), "/dev/sda3");
EXPECT_EQ(wipe_info.inactive_kernel_device.value(), "/dev/sda2");
EXPECT_EQ(wipe_info.active_kernel_partition, partitions_.kernel_b);
}
TEST_F(GetDevicesToWipeTest, SDA) {
partitions_.stateful = 7;
partitions_.kernel_a = 1;
partitions_.root_a = 9;
partitions_.kernel_b = 2;
partitions_.root_b = 4;
base::FilePath root_disk("/dev/sda");
base::FilePath root_device("/dev/sda9");
ClobberState::DeviceWipeInfo wipe_info;
EXPECT_TRUE(ClobberState::GetDevicesToWipe(root_disk, root_device,
partitions_, &wipe_info));
EXPECT_EQ(wipe_info.stateful_partition_device.value(), "/dev/sda7");
EXPECT_EQ(wipe_info.inactive_root_device.value(), "/dev/sda4");
EXPECT_EQ(wipe_info.inactive_kernel_device.value(), "/dev/sda2");
EXPECT_EQ(wipe_info.active_kernel_partition, partitions_.kernel_a);
}
class PreserveEncryptedFilesTest : public ::testing::Test {
protected:
PreserveEncryptedFilesTest()
: crossystem_fake_(std::make_unique<crossystem::fake::CrossystemFake>()),
cros_system_(crossystem_fake_.get()),
clobber_ui_null_(std::make_unique<ClobberUi>(DevNull())),
clobber_wipe_mock_(
std::make_unique<ClobberWipeMock>(clobber_ui_null_.get())),
clobber_(ClobberState::Arguments(),
std::make_unique<crossystem::Crossystem>(
std::move(crossystem_fake_)),
std::move(clobber_ui_null_),
std::move(clobber_wipe_mock_),
std::unique_ptr<ClobberLvm>()) {}
void SetUp() override {
ASSERT_TRUE(temp_stateful_.CreateUniqueTempDir());
fake_stateful_ = temp_stateful_.GetPath();
clobber_.SetStatefulForTest(fake_stateful_);
ASSERT_TRUE(temp_root_.CreateUniqueTempDir());
fake_root_ = temp_root_.GetPath();
clobber_.SetRootPathForTest(fake_root_);
}
std::unique_ptr<crossystem::fake::CrossystemFake> crossystem_fake_;
crossystem::fake::CrossystemFake* cros_system_;
std::unique_ptr<ClobberUi> clobber_ui_null_;
std::unique_ptr<ClobberWipeMock> clobber_wipe_mock_;
ClobberState clobber_;
base::ScopedTempDir temp_root_;
base::ScopedTempDir temp_stateful_;
base::FilePath fake_root_;
base::FilePath fake_stateful_;
};
TEST_F(PreserveEncryptedFilesTest, UpdateEnginePrefsArePreserved) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(
fake_root_.Append("var/lib/update_engine/prefs/last-active-ping-day"),
"1234"));
ASSERT_TRUE(CreateDirectoryAndWriteFile(
fake_root_.Append("var/lib/update_engine/prefs/last-roll-call-ping-day"),
"5678"));
clobber_.PreserveEncryptedFiles();
ASSERT_TRUE(base::PathExists(
fake_stateful_.Append("unencrypted/preserve/update_engine/prefs/")));
ASSERT_TRUE(base::PathExists(fake_stateful_.Append(
"unencrypted/preserve/update_engine/prefs/last-active-ping-day")));
ASSERT_TRUE(base::PathExists(fake_stateful_.Append(
"unencrypted/preserve/update_engine/prefs/last-roll-call-ping-day")));
}
TEST_F(PreserveEncryptedFilesTest, PsmPrefsArePreserved) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(
fake_root_.Append("var/lib/private_computing/last_active_dates"),
"1234"));
clobber_.PreserveEncryptedFiles();
ASSERT_TRUE(base::PathExists(
fake_stateful_.Append("unencrypted/preserve/last_active_dates")));
}
TEST_F(PreserveEncryptedFilesTest, FlexFilesArePreserved) {
ASSERT_TRUE(CreateDirectoryAndWriteFile(
fake_root_.Append("var/lib/flex_id/flex_id"), "1234"));
clobber_.PreserveEncryptedFiles();
ASSERT_TRUE(base::PathExists(
fake_stateful_.Append("unencrypted/preserve/flex/flex_id")));
ASSERT_TRUE(CreateDirectoryAndWriteFile(
fake_root_.Append("var/lib/flex_id/flex_state_key"), "abcd"));
clobber_.PreserveEncryptedFiles();
ASSERT_TRUE(base::PathExists(
fake_stateful_.Append("unencrypted/preserve/flex/flex_state_key")));
}