blob: 41666ae58ce4098990cb2b302a5e0be958c6b572 [file] [log] [blame]
// Copyright 2021 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_data_migrator.h"
#include <algorithm>
#include "ash/constants/ash_features.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
using user_manager::User;
namespace ash {
namespace {
constexpr char kFileName[] = "file";
constexpr char kDirName[] = "directory";
constexpr char kFileData[] = "Hello";
constexpr int kFileSize = sizeof(kFileData);
constexpr char kDownloads[] = "Downloads";
constexpr char kFirstRun[] = "First Run";
} // namespace
class BrowserDataMigratorTest : public ::testing::Test {
public:
void SetUp() override {
// Setup `user_data_dir_` as below.
// ./ /* user_data_dir_ */
// |- 'First Run'
// |- user/ /* from_dir_ */
// |- file
// |- directory/
// |- file
// |- Downloads/file
// |- Downloads/file
ASSERT_TRUE(user_data_dir_.CreateUniqueTempDir());
from_dir_ = user_data_dir_.GetPath().Append("user");
ASSERT_TRUE(base::WriteFile(user_data_dir_.GetPath().Append(
kFirstRun) /* .../'First Run' */,
"", 0) == 0);
ASSERT_TRUE(base::CreateDirectory(
from_dir_.Append(kDirName) /* .../user/directory/ */));
ASSERT_TRUE(base::CreateDirectory(from_dir_.Append(kDirName).Append(
kDownloads) /* .../user/directory/Downloads/ */));
ASSERT_TRUE(base::CreateDirectory(
from_dir_.Append(kDownloads) /* .../user/Downloads/ */));
ASSERT_TRUE(
base::WriteFile(from_dir_.Append(kFileName) /* .../user/file/ */,
kFileData, kFileSize));
ASSERT_TRUE(base::WriteFile(from_dir_.Append(kDirName).Append(
kFileName) /* .../user/directory/file/ */,
kFileData, kFileSize));
ASSERT_TRUE(base::WriteFile(
from_dir_.Append(kDirName)
.Append(kDownloads)
.Append(kFileName) /* .../user/directory/Downloads/file/ */,
kFileData, kFileSize));
ASSERT_TRUE(
base::WriteFile(from_dir_.Append(kDownloads)
.Append(kFileName) /* .../user/Downloads/file/ */,
kFileData, kFileSize));
}
void TearDown() override { EXPECT_TRUE(user_data_dir_.Delete()); }
base::ScopedTempDir user_data_dir_;
base::FilePath from_dir_;
};
TEST_F(BrowserDataMigratorTest, IsMigrationRequiredOnWorker) {
const std::string user_id_hash = "user";
const base::FilePath user_data_dir_path = user_data_dir_.GetPath();
// Lacros UDD does not exist.
EXPECT_TRUE(BrowserDataMigrator::IsMigrationRequiredOnWorker(
user_data_dir_path, user_id_hash));
// Create lacros user data dir.
ASSERT_TRUE(base::CreateDirectory(
user_data_dir_path.Append("user").Append(kLacrosDir)));
// Lacros UDD exists.
EXPECT_FALSE(BrowserDataMigrator::IsMigrationRequiredOnWorker(
user_data_dir_path, user_id_hash));
}
TEST_F(BrowserDataMigratorTest, CopyDirectory) {
BrowserDataMigrator browser_data_migrator(from_dir_);
const base::FilePath from_dir = user_data_dir_.GetPath().Append("user");
const base::FilePath to_dir = user_data_dir_.GetPath().Append("to_dir");
base::CreateSymbolicLink(user_data_dir_.GetPath().Append(kFirstRun),
from_dir.Append(kFirstRun));
ASSERT_TRUE(browser_data_migrator.CopyDirectory(from_dir, to_dir));
// Setup `from_dir` as below.
// |- user/ /* from_dir_ */
// |- file
// |- directory/
// |- file
// |- Downloads/file
// |- Downloads/file
// |- 'First Run' /* symlink */
//
// Expected `to_dir` structure after `CopyDirectory()`.
// |- to_dir/
// |- file
// |- directory
// |- file
// |- Downloads/file
// |- Downloads/file
EXPECT_TRUE(base::PathExists(to_dir));
EXPECT_TRUE(base::PathExists(to_dir.Append(kFileName)));
EXPECT_TRUE(base::PathExists(to_dir.Append(kDirName).Append(kFileName)));
EXPECT_TRUE(base::PathExists(
to_dir.Append(kDirName).Append(kDownloads).Append(kFileName)));
EXPECT_TRUE(base::PathExists(to_dir.Append(kDownloads).Append(kFileName)));
// Make sure that symlink does not get copied.
EXPECT_FALSE(base::PathExists(to_dir.Append(kFirstRun)));
}
TEST_F(BrowserDataMigratorTest, GetTargetInfo) {
BrowserDataMigrator browser_data_migrator(from_dir_);
BrowserDataMigrator::TargetInfo target_info =
browser_data_migrator.GetTargetInfo();
EXPECT_EQ(target_info.total_byte_count,
kFileSize * 3 /* expect three files */);
ASSERT_EQ(target_info.user_data_items.size(), 1);
std::vector<BrowserDataMigrator::TargetItem> expected_user_data_items = {
BrowserDataMigrator::TargetItem{
from_dir_.DirName().Append(kFirstRun),
BrowserDataMigrator::TargetItem::ItemType::kFile}};
EXPECT_EQ(target_info.user_data_items[0], expected_user_data_items[0]);
ASSERT_EQ(target_info.profile_data_items.size(), 2);
std::vector<BrowserDataMigrator::TargetItem> expected_profile_data_items = {
BrowserDataMigrator::TargetItem{
from_dir_.Append(kDirName),
BrowserDataMigrator::TargetItem::ItemType::kDirectory},
BrowserDataMigrator::TargetItem{
from_dir_.Append(kFileName),
BrowserDataMigrator::TargetItem::ItemType::kFile}};
std::sort(
target_info.profile_data_items.begin(),
target_info.profile_data_items.end(),
[](BrowserDataMigrator::TargetItem i1,
BrowserDataMigrator::TargetItem i2) { return i1.path < i2.path; });
for (int i = 0; i < target_info.profile_data_items.size(); i++) {
SCOPED_TRACE(target_info.profile_data_items[i].path);
EXPECT_EQ(target_info.profile_data_items[i],
expected_profile_data_items[i]);
}
}
TEST_F(BrowserDataMigratorTest, RecordStatus) {
{
// If `FinalStatus::kSkipped`, only record the status and do not record
// copied data size or total time.
base::HistogramTester histogram_tester;
BrowserDataMigrator::RecordStatus(
BrowserDataMigrator::FinalStatus::kSkipped);
histogram_tester.ExpectTotalCount(kFinalStatus, 1);
histogram_tester.ExpectTotalCount(kCopiedDataSize, 0);
histogram_tester.ExpectTotalCount(kTotalTime, 0);
histogram_tester.ExpectBucketCount(
kFinalStatus, BrowserDataMigrator::FinalStatus::kSkipped, 1);
}
{
// If `FInalStatus::kSuccess`, the three UMA `kFinalStatus`,
// `kCopiedDataSize`, `kTotalTime` should be recorded.
base::HistogramTester histogram_tester;
BrowserDataMigrator browser_data_migrator(from_dir_);
BrowserDataMigrator::TargetInfo target_info;
target_info.total_byte_count = /* 200 MBs */ 200 * 1024 * 1024;
base::ElapsedTimer timer;
BrowserDataMigrator::RecordStatus(
BrowserDataMigrator::FinalStatus::kSuccess, &target_info, &timer);
histogram_tester.ExpectTotalCount(kFinalStatus, 1);
histogram_tester.ExpectTotalCount(kCopiedDataSize, 1);
histogram_tester.ExpectTotalCount(kTotalTime, 1);
histogram_tester.ExpectBucketCount(
kFinalStatus, BrowserDataMigrator::FinalStatus::kSuccess, 1);
histogram_tester.ExpectBucketCount(
kCopiedDataSize, target_info.total_byte_count / (1024 * 1024), 1);
}
}
TEST_F(BrowserDataMigratorTest, Migrate) {
base::HistogramTester histogram_tester;
{
BrowserDataMigrator browser_data_migrator(from_dir_);
browser_data_migrator.MigrateInternal();
// Expected dir structure after migration.
// ./ /* user_data_dir_ */
// |- 'First Run'
// |- user/ /* from_dir_ */
// |- Downloads/file
// |- lacros
// |- 'First Run'
// |- Default/
// |- file
// |- directory
// |- file
// |- Downloads/file
EXPECT_FALSE(base::PathExists(from_dir_.Append(kLacrosDir)
.Append("Default")
.Append(kDownloads)
.Append(kFileName)));
const base::FilePath new_user_data_dir = from_dir_.Append(kLacrosDir);
EXPECT_TRUE(base::PathExists(new_user_data_dir.Append(kFirstRun)));
EXPECT_TRUE(
base::PathExists(from_dir_.Append(kDownloads).Append(kFileName)));
EXPECT_TRUE(base::PathExists(
new_user_data_dir.Append("Default").Append(kFileName)));
EXPECT_TRUE(base::PathExists(
new_user_data_dir.Append("Default").Append(kDirName).Append(
kFileName)));
EXPECT_TRUE(base::PathExists(new_user_data_dir.Append("Default")
.Append(kDirName)
.Append(kDownloads)
.Append(kFileName)));
} // `browser_data_migrator` is destructed and `RecordStatus()` is called.
histogram_tester.ExpectTotalCount(kFinalStatus, 1);
histogram_tester.ExpectTotalCount(kCopiedDataSize, 1);
histogram_tester.ExpectTotalCount(kTotalTime, 1);
histogram_tester.ExpectTotalCount(kCreateDirectoryFail, 0);
histogram_tester.ExpectBucketCount(
kFinalStatus, BrowserDataMigrator::FinalStatus::kSuccess, 1);
histogram_tester.ExpectBucketCount(kCopiedDataSize,
kFileSize * 3 / (1024 * 1024), 1);
}
} // namespace ash