Skip to content

Commit

Permalink
[feat][test] add tests on cat-file & hash-object
Browse files Browse the repository at this point in the history
  • Loading branch information
smd1121 committed Jan 4, 2024
1 parent b8c9888 commit b8ea839
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: test

on: [push]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r xgit/test/requirements.txt
pip install .
- name: Config Git
run: |
git config --global user.email "[email protected]"
git config --global user.name "Your Name"
- name: Run tests
run: |
cd xgit
coverage run -m pytest .
coverage report -m
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__pycache__
.mypy_cache
*.egg-info/
.pytest_cache/
Empty file added xgit/test/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions xgit/test/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
loguru
pytest
coverage
46 changes: 46 additions & 0 deletions xgit/test/test_cat_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import subprocess
from pathlib import Path

from typer.testing import CliRunner

from xgit.test.test_utils import gen_random_sha, check_same_output, gen_random_string, temp_git_workspace

runner = CliRunner()


def test_cat_blob():
with temp_git_workspace() as dir:
file1 = Path(dir) / "test"
with open(file1, "w", encoding="utf-8") as f:
f.write(gen_random_string())

file2 = Path(dir) / "a" / "b"
file2.parent.mkdir(exist_ok=True, parents=True)
file2.touch()

subprocess.run(["git", "add", "."], check=True)
subprocess.run(["git", "commit", "-m", "test"], check=True)

to_test = ["-p", "-e", "-t", "-s", "blob"]

# on tree object
sha = subprocess.run(
["git", "rev-parse", "HEAD^{tree}"], check=True, capture_output=True, text=True
).stdout.strip()
for i in to_test:
assert check_same_output(["cat-file", i, sha])

# on contents (including blob object)
objs = subprocess.run(
["git", "ls-tree", "-r", "HEAD^{tree}"], check=True, capture_output=True, text=True
).stdout.strip()
obj_lst = objs.split("\n")
for obj in obj_lst:
sha = obj.split()[2]
for i in to_test:
assert check_same_output(["cat-file", i, sha])

# on not exist object
random_sha = gen_random_sha()
for i in to_test:
assert check_same_output(["cat-file", i, random_sha])
47 changes: 47 additions & 0 deletions xgit/test/test_hash_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import tempfile
import subprocess

from typer.testing import CliRunner

from xgit.cli import app
from xgit.test.test_utils import gen_random_string, temp_xgit_workspace

runner = CliRunner()


def test_hash_value():
content = gen_random_string()

with tempfile.NamedTemporaryFile() as f:
with open(f.name, "w", encoding="utf-8") as f:
f.write(content)

expected_by_file = subprocess.run(
["git", "hash-object", f.name], check=True, capture_output=True, text=True
).stdout
result_by_file = runner.invoke(app, ["hash-object", f.name]).stdout
assert result_by_file == expected_by_file

expected_by_stdin = subprocess.run(
["git", "hash-object", "--stdin"], input=content, check=True, capture_output=True, text=True
).stdout
result_by_stdin = runner.invoke(app, ["hash-object", "--stdin"], input=content).stdout
assert result_by_stdin == expected_by_stdin


def test_hash_object_write():
content = gen_random_string()

with temp_xgit_workspace():
with tempfile.NamedTemporaryFile() as f:
with open(f.name, "w", encoding="utf-8") as f:
f.write(content)

result = runner.invoke(app, ["hash-object", "-w", f.name])
object_id = result.stdout.strip()

read_by_git = subprocess.run(
["git", "cat-file", "blob", object_id], check=True, capture_output=True, text=True
).stdout

assert content == read_by_git
67 changes: 67 additions & 0 deletions xgit/test/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import os
import random
import string
import tempfile
import contextlib
import subprocess

from loguru import logger
from typer.testing import CliRunner

from xgit.cli import app

runner = CliRunner(mix_stderr=False)


@contextlib.contextmanager
def temp_git_workspace(use_xgit: bool = False):
original_dir = os.getcwd()
with tempfile.TemporaryDirectory() as dir:
try:
os.chdir(dir)
git = "xgit" if use_xgit else "git"
subprocess.run([git, "init", dir], check=True)
yield dir
finally:
os.chdir(original_dir)


@contextlib.contextmanager
def temp_xgit_workspace():
with temp_git_workspace(use_xgit=True) as dir:
yield dir


def gen_random_string(len: int = 1000):
# 关于 `\r` 的事情有点脏,我不想管。有关换行符的事情,关心的朋友可以搜索 autocrlf
# 具体来说,如果不去掉 `\r`,那么在下面测试的一些情况中(尤其是有和 stdout 交互的情况中) `\r` 会变成 `\n`
# 这会导致内容不一致,进而导致 SHA 不正确。
# 如果您感兴趣,可以把下面的 `.replace` 去掉试试!
# 如果有更正确的方案,也请您告诉我~
alphabet = string.octdigits + string.whitespace.replace("\r", "")
return "".join(random.choice(alphabet) for _ in range(len))


def gen_random_sha():
return "".join(random.choice(string.hexdigits) for _ in range(40))


def check_same_output(cmd: list[str]) -> bool:
git_result = subprocess.run(["git"] + cmd, capture_output=True, check=False)
xgit_result = runner.invoke(app, cmd)
xgit_stdout = xgit_result.stdout.encode()

if git_result.returncode != xgit_result.exit_code:
logger.info(f"cmd: {cmd}")
logger.info(f"exit_code not equal: {git_result.returncode} != {xgit_result.exit_code}")
return False

if git_result.returncode != 0:
return True

if git_result.stdout != xgit_stdout:
logger.info(f"cmd: {cmd}")
logger.info(f"stdout not equal: {git_result.stdout} != {xgit_stdout}")
return False

return True

0 comments on commit b8ea839

Please sign in to comment.