blob: fcac6e82604ad7b8db8102189b66e14e0c4b385e [file] [log] [blame]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/update_client/patch/patch_impl.h"
#include <utility>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/callback.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "components/services/patch/public/mojom/file_patcher.mojom.h"
#include "components/update_client/update_client_errors.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace update_client {
namespace {
// A no-op callback for the patcher.
mojo::PendingRemote<patch::mojom::FilePatcher> MakePatcher() {
return mojo::PendingRemote<patch::mojom::FilePatcher>();
}
} // namespace
class PatchImplTest : public testing::Test {
protected:
void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
base::File CreateTestFile(const std::string& content) {
base::FilePath file_path;
EXPECT_TRUE(
base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
EXPECT_TRUE(base::WriteFile(file_path, content));
return base::File(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
}
base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
scoped_refptr<Patcher> patcher_ = base::MakeRefCounted<PatchChromiumFactory>(
base::BindRepeating(&MakePatcher))
->Create();
};
TEST_F(PatchImplTest, PuffPatch_InvalidOldFile) {
base::RunLoop run_loop;
patcher_->PatchPuffPatch(
base::File(), CreateTestFile("patch"), CreateTestFile(""),
base::BindOnce(
[](base::OnceClosure quit_closure, int result) {
EXPECT_EQ(result,
static_cast<int>(UnpackerError::kPatchInvalidOldFile));
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
TEST_F(PatchImplTest, PuffPatch_InvalidPatchFile) {
base::RunLoop run_loop;
patcher_->PatchPuffPatch(
CreateTestFile("old"), base::File(), CreateTestFile(""),
base::BindOnce(
[](base::OnceClosure quit_closure, int result) {
EXPECT_EQ(result,
static_cast<int>(UnpackerError::kPatchInvalidPatchFile));
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
TEST_F(PatchImplTest, PuffPatch_InvalidDestinationFile) {
base::RunLoop run_loop;
patcher_->PatchPuffPatch(
CreateTestFile("old"), CreateTestFile("patch"), base::File(),
base::BindOnce(
[](base::OnceClosure quit_closure, int result) {
EXPECT_EQ(result,
static_cast<int>(UnpackerError::kPatchInvalidNewFile));
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
TEST_F(PatchImplTest, ZucchiniPatch_InvalidOldFile) {
base::RunLoop run_loop;
patcher_->PatchZucchini(
base::File(), CreateTestFile("patch"), CreateTestFile(""),
base::BindOnce(
[](base::OnceClosure quit_closure, int result) {
EXPECT_EQ(result,
static_cast<int>(UnpackerError::kPatchInvalidOldFile));
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
TEST_F(PatchImplTest, ZucchiniPatch_InvalidPatchFile) {
base::RunLoop run_loop;
patcher_->PatchZucchini(
CreateTestFile("old"), base::File(), CreateTestFile(""),
base::BindOnce(
[](base::OnceClosure quit_closure, int result) {
EXPECT_EQ(result,
static_cast<int>(UnpackerError::kPatchInvalidPatchFile));
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
TEST_F(PatchImplTest, ZucchiniPatch_InvalidDestinationFile) {
base::RunLoop run_loop;
patcher_->PatchZucchini(
CreateTestFile("old"), CreateTestFile("patch"), base::File(),
base::BindOnce(
[](base::OnceClosure quit_closure, int result) {
EXPECT_EQ(result,
static_cast<int>(UnpackerError::kPatchInvalidNewFile));
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
} // namespace update_client