blob: 228461c46aef2dc2fd3a39e2b695f860cac7f86a [file] [log] [blame] [edit]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2024 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.
"""Unit tests for compute_content_hash.py"""
import os
import subprocess
import sys
import tempfile
import typing as T
import unittest
from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
import compute_content_hash as cch
def _git_cmd(git_dir: Path, args: T.Sequence[str | Path]) -> str:
"""Run git command in a given directory. Return output as a string."""
ret = subprocess.run(
["git", "-C", str(git_dir)] + [str(a) for a in args],
check=True,
text=True,
capture_output=True,
)
return ret.stdout.strip()
def _setup_first_git_dir(git_dir: Path) -> tuple[str, str]:
git_dir.mkdir(parents=True)
_git_cmd(git_dir, ["init"])
# required to avoid errors on CI build bots when running this test.
_git_cmd(git_dir, ["config", "--local", "user.email", "test@example.com"])
_git_cmd(git_dir, ["config", "--local", "user.name", "Test User"])
(git_dir / "foo").write_text("1")
_git_cmd(git_dir, ["add", "foo"])
_git_cmd(git_dir, ["commit", "-m", "first commit"])
first_commit = _git_cmd(git_dir, ["rev-parse", "HEAD"])
(git_dir / "foo").write_text("2")
_git_cmd(git_dir, ["commit", "-am", "second commit"])
second_commit = _git_cmd(git_dir, ["rev-parse", "HEAD"])
return (first_commit, second_commit)
def _setup_second_git_dir(git_dir: Path, submodule_path: Path) -> str:
git_dir.mkdir(parents=True)
_git_cmd(git_dir, ["init"])
# required to avoid errors on CI build bots when running this test.
_git_cmd(git_dir, ["config", "--local", "user.email", "test@example.com"])
_git_cmd(git_dir, ["config", "--local", "user.name", "Test User"])
# Add a submodule. Using -c protocol.file.allow=always
# is required to avoid an error message that says:
# "fatal: transport 'file' not allowed".
# See https://github.com/flatpak/flatpak-builder/issues/495#issuecomment-1297413908
_git_cmd(
git_dir,
[
"-c",
"protocol.file.allow=always",
"submodule",
"add",
submodule_path,
"sub1",
],
)
_git_cmd(git_dir, ["commit", "-m", "first commit"])
return _git_cmd(git_dir, ["rev-parse", "HEAD"])
class ComputeContentHashTest(unittest.TestCase):
def setUp(self):
self._td = tempfile.TemporaryDirectory()
self._dir = Path(self._td.name)
self.datadir = self._dir / "data"
self.datadir.mkdir(parents=True)
(self.datadir / "README.txt").write_text("Example input file.\n")
(self.datadir / "subdir").mkdir()
(self.datadir / "subdir" / "data").write_text("42")
(self.datadir / "data.link").symlink_to("subdir/data")
self.prebuiltdir = self._dir / "cipd_prebuilt"
self.prebuiltdir.mkdir()
(self.prebuiltdir / ".versions").mkdir()
(self.prebuiltdir / ".versions" / "bar.cipd_version").write_text(
"version 1.0"
)
def tearDown(self):
self._td.cleanup()
def _setup_git_repos(self):
self.gitdir1 = self._dir / "git_project1"
self.first_commit, self.second_commit = _setup_first_git_dir(
self.gitdir1
)
self.gitdir2 = self._dir / "git_project2"
self.first_commit2 = _setup_second_git_dir(self.gitdir2, self.gitdir1)
def test_file_content_hash(self):
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.datadir / "README.txt")
self.assertEqual(
descriptor, "F49d18153ca1983adefbe9c3a2cb91676c73b1024"
)
def test_symlink_content_hash(self):
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.datadir / "data.link")
self.assertEqual(descriptor, "Ssubdir/data")
def test_directory_content_hash(self):
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.datadir)
self.assertEqual(
descriptor,
"""D
README.txt F49d18153ca1983adefbe9c3a2cb91676c73b1024
data.link Ssubdir/data
subdir/data F92cfceb39d57d914ed8b14d0e37643de0797ae56
""",
)
def test_cipd_content_hash(self):
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.prebuiltdir)
self.assertEqual(
descriptor,
"""D
.versions/bar.cipd_version F105a6be87e08ee0d67f397a498315de3afaba803
""",
)
fstate = cch.FileState(cipd_names=["bar"])
descriptor = fstate.process_source_path(self.prebuiltdir)
self.assertEqual(
descriptor, "F105a6be87e08ee0d67f397a498315de3afaba803"
)
def test_git_content_hash_no_submodules(self):
self._setup_git_repos()
# on branch on first git repository.
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.gitdir1)
self.assertEqual(descriptor, "G" + self.second_commit)
# detached HEAD on first git repository.
_git_cmd(self.gitdir1, ["checkout", self.first_commit])
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.gitdir1)
self.assertEqual(descriptor, "G" + self.first_commit)
# on branch on second git repository + on branch in submodule
fstate = cch.FileState()
descriptor = fstate.process_source_path(self.gitdir2)
self.assertEqual(descriptor, "G" + self.first_commit2)
if __name__ == "__main__":
unittest.main()