blob: 5a77b04c15657d5e361ecf5ba148b2e8bab548f7 [file] [log] [blame]
// Copyright 2021 The Fuchsia 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 "src/developer/forensics/feedback/migration/utils/migrate.h"
#include <lib/async/cpp/executor.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "fbl/unique_fd.h"
#include "src/developer/forensics/feedback/migration/utils/tests/directory_migrator_stubs.h"
#include "src/developer/forensics/testing/unit_test_fixture.h"
#include "src/lib/files/file.h"
#include "src/lib/files/path.h"
#include "src/lib/files/scoped_temp_dir.h"
namespace forensics::feedback {
namespace {
using LastRebootDirectoryMigrator =
DirectoryMigratorStub<fuchsia::feedback::internal::LastRebootDirectoryMigrator>;
using LastRebootDirectoryMigratorClosesConnection =
DirectoryMigratorStubClosesConnection<fuchsia::feedback::internal::LastRebootDirectoryMigrator>;
using CrashReportsDirectoryMigrator =
DirectoryMigratorStub<fuchsia::feedback::internal::CrashReportsDirectoryMigrator>;
using CrashReportsDirectoryMigratorClosesConnection = DirectoryMigratorStubClosesConnection<
fuchsia::feedback::internal::CrashReportsDirectoryMigrator>;
using FeedbackDataDirectoryMigrator =
DirectoryMigratorStub<fuchsia::feedback::internal::FeedbackDataDirectoryMigrator>;
using FeedbackDataDirectoryMigratorClosesConnection = DirectoryMigratorStubClosesConnection<
fuchsia::feedback::internal::FeedbackDataDirectoryMigrator>;
class MigrateTest : public UnitTestFixture {
public:
MigrateTest() : executor_(dispatcher()) {
FX_CHECK(temp_dir_.NewTempDir(&to_data_path_));
to_data_fd_ = fbl::unique_fd(open(to_data_path_.c_str(), O_DIRECTORY | O_RDWR, 0777));
FX_CHECK(to_data_fd_.is_valid());
FX_CHECK(temp_dir_.NewTempDir(&to_cache_path_));
to_cache_fd_ = fbl::unique_fd(open(to_cache_path_.c_str(), O_DIRECTORY | O_RDWR, 0777));
FX_CHECK(to_cache_fd_.is_valid());
}
::fpromise::result<void, Error> MigrateLastReboot(
const zx::duration timeout = zx::duration::infinite()) {
std::optional<::fpromise::result<void, Error>> result;
executor_.schedule_task(
MigrateLastRebootData(dispatcher(), services(), to_data_fd_, to_cache_fd_, timeout)
.then([&](::fpromise::result<void, Error>& r) { result = std::move(r); }));
RunLoopUntilIdle();
FX_CHECK(result);
return *result;
}
::fpromise::result<void, Error> MigrateCrashReports(
const zx::duration timeout = zx::duration::infinite()) {
std::optional<::fpromise::result<void, Error>> result;
executor_.schedule_task(
MigrateCrashReportsData(dispatcher(), services(), to_data_fd_, to_cache_fd_, timeout)
.then([&](::fpromise::result<void, Error>& r) { result = std::move(r); }));
RunLoopUntilIdle();
FX_CHECK(result);
return *result;
}
::fpromise::result<void, Error> MigrateFeedbackData(
const zx::duration timeout = zx::duration::infinite()) {
std::optional<::fpromise::result<void, Error>> result;
executor_.schedule_task(
MigrateFeedbackDataData(dispatcher(), services(), to_data_fd_, to_cache_fd_, timeout)
.then([&](::fpromise::result<void, Error>& r) { result = std::move(r); }));
RunLoopUntilIdle();
FX_CHECK(result);
return *result;
}
std::string DataRoot() const { return to_data_path_; }
std::string CacheRoot() const { return to_cache_path_; }
private:
async::Executor executor_;
files::ScopedTempDir temp_dir_;
std::string to_data_path_;
fbl::unique_fd to_data_fd_;
std::string to_cache_path_;
fbl::unique_fd to_cache_fd_;
};
TEST_F(MigrateTest, MigrateLastRebootData) {
files::ScopedTempDir data_dir;
files::ScopedTempDir cache_dir;
LastRebootDirectoryMigrator last_reboot_server(data_dir.path(), cache_dir.path());
InjectServiceProvider(&last_reboot_server);
EXPECT_TRUE(files::WriteFile(files::JoinPath(data_dir.path(), "data.txt"), "data"));
EXPECT_TRUE(files::WriteFile(files::JoinPath(cache_dir.path(), "cache.txt"), "cache"));
EXPECT_TRUE(MigrateLastReboot().is_ok());
// The original files should be deleted.
EXPECT_FALSE(files::IsFile(files::JoinPath(data_dir.path(), "data.txt")));
EXPECT_FALSE(files::IsFile(files::JoinPath(cache_dir.path(), "cache.txt")));
// The new files should have the content of the original files.
EXPECT_TRUE(files::IsFile(files::JoinPath(DataRoot(), "data.txt")));
EXPECT_TRUE(files::IsFile(files::JoinPath(CacheRoot(), "cache.txt")));
std::string content;
ASSERT_TRUE(files::ReadFileToString(files::JoinPath(DataRoot(), "data.txt"), &content));
EXPECT_EQ(content, "data");
ASSERT_TRUE(files::ReadFileToString(files::JoinPath(CacheRoot(), "cache.txt"), &content));
EXPECT_EQ(content, "cache");
}
TEST_F(MigrateTest, MigrateLastRebootDataConnectionErrors) {
LastRebootDirectoryMigratorClosesConnection last_reboot_server;
InjectServiceProvider(&last_reboot_server);
EXPECT_FALSE(MigrateLastReboot().is_ok());
}
TEST_F(MigrateTest, MigrateCrashReportsData) {
files::ScopedTempDir data_dir;
files::ScopedTempDir cache_dir;
CrashReportsDirectoryMigrator last_reboot_server(data_dir.path(), cache_dir.path());
InjectServiceProvider(&last_reboot_server);
EXPECT_TRUE(files::WriteFile(files::JoinPath(data_dir.path(), "data.txt"), "data"));
EXPECT_TRUE(files::WriteFile(files::JoinPath(cache_dir.path(), "cache.txt"), "cache"));
EXPECT_TRUE(MigrateCrashReports().is_ok());
// The original files should be deleted.
EXPECT_FALSE(files::IsFile(files::JoinPath(data_dir.path(), "data.txt")));
EXPECT_FALSE(files::IsFile(files::JoinPath(cache_dir.path(), "cache.txt")));
// The new files should have the content of the original files.
EXPECT_TRUE(files::IsFile(files::JoinPath(DataRoot(), "data.txt")));
EXPECT_TRUE(files::IsFile(files::JoinPath(CacheRoot(), "cache.txt")));
std::string content;
ASSERT_TRUE(files::ReadFileToString(files::JoinPath(DataRoot(), "data.txt"), &content));
EXPECT_EQ(content, "data");
ASSERT_TRUE(files::ReadFileToString(files::JoinPath(CacheRoot(), "cache.txt"), &content));
EXPECT_EQ(content, "cache");
}
TEST_F(MigrateTest, MigrateCrashReportsDataConnectionErrors) {
CrashReportsDirectoryMigratorClosesConnection last_reboot_server;
InjectServiceProvider(&last_reboot_server);
EXPECT_FALSE(MigrateCrashReports().is_ok());
}
TEST_F(MigrateTest, MigrateFeedbackDataData) {
files::ScopedTempDir data_dir;
files::ScopedTempDir cache_dir;
FeedbackDataDirectoryMigrator feedback_data_server(data_dir.path(), cache_dir.path());
InjectServiceProvider(&feedback_data_server);
EXPECT_TRUE(files::WriteFile(files::JoinPath(data_dir.path(), "data.txt"), "data"));
EXPECT_TRUE(files::WriteFile(files::JoinPath(cache_dir.path(), "cache.txt"), "cache"));
EXPECT_TRUE(MigrateFeedbackData().is_ok());
// The original files should be deleted.
EXPECT_FALSE(files::IsFile(files::JoinPath(data_dir.path(), "data.txt")));
EXPECT_FALSE(files::IsFile(files::JoinPath(cache_dir.path(), "cache.txt")));
// The new files should have the content of the original files.
EXPECT_TRUE(files::IsFile(files::JoinPath(DataRoot(), "data.txt")));
EXPECT_TRUE(files::IsFile(files::JoinPath(CacheRoot(), "cache.txt")));
std::string content;
ASSERT_TRUE(files::ReadFileToString(files::JoinPath(DataRoot(), "data.txt"), &content));
EXPECT_EQ(content, "data");
ASSERT_TRUE(files::ReadFileToString(files::JoinPath(CacheRoot(), "cache.txt"), &content));
EXPECT_EQ(content, "cache");
}
TEST_F(MigrateTest, MigrateFeedbackDataDataConnectionErrors) {
FeedbackDataDirectoryMigratorClosesConnection feedback_data_server;
InjectServiceProvider(&feedback_data_server);
EXPECT_FALSE(MigrateFeedbackData().is_ok());
}
} // namespace
} // namespace forensics::feedback