mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 10:18:14 +00:00
- SSRF: test local transport rejection, allowlist enforcement, private/loopback/ link-local IP blocking, allowlist with port, public host permitted without list - GET /preview: happy path, invalid scheme, local transport rejection - Tier 2 LRU: eviction at capacity, LRU promotion, cache miss - git: heads/<branch> ref form (was only tested via HEAD/tag/hash) - clear_caches fixture now also resets _allowed_hosts between tests 103 → 118 passing tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
99 lines
3.7 KiB
Python
99 lines
3.7 KiB
Python
"""Tests for ifcurl.git — git repository access."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from ifcurl.git import fetch_ifc, fetch_ifc_bytes
|
|
from ifcurl.url import IfcUrl
|
|
|
|
|
|
def _local_url(repo_path: str, ref: str = "HEAD", path: str = "model.ifc") -> IfcUrl:
|
|
"""Build an ifc:// URL pointing at a local repo fixture."""
|
|
return IfcUrl.parse(f"ifc://{repo_path}@{ref}?path={path}")
|
|
|
|
|
|
class TestFetchIfc:
|
|
def test_returns_hexsha_and_bytes(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"])
|
|
hexsha, data = fetch_ifc(url)
|
|
assert len(hexsha) == 40
|
|
assert all(c in "0123456789abcdef" for c in hexsha)
|
|
assert isinstance(data, bytes)
|
|
assert len(data) > 0
|
|
|
|
def test_hexsha_matches_commit(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"])
|
|
hexsha, _ = fetch_ifc(url)
|
|
assert hexsha == local_ifc_repo["hexsha"]
|
|
|
|
def test_bytes_match_committed_file(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"])
|
|
_, data = fetch_ifc(url)
|
|
assert data == local_ifc_repo["bytes"]
|
|
|
|
def test_explicit_commit_hash_ref(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"], ref=local_ifc_repo["hexsha"])
|
|
hexsha, data = fetch_ifc(url)
|
|
assert hexsha == local_ifc_repo["hexsha"]
|
|
assert data == local_ifc_repo["bytes"]
|
|
|
|
def test_tag_ref(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"], ref="tags/v1.0")
|
|
hexsha, data = fetch_ifc(url)
|
|
assert hexsha == local_ifc_repo["hexsha"]
|
|
|
|
def test_branch_ref(self, local_ifc_repo):
|
|
import git as gitpkg
|
|
branch = gitpkg.Repo(local_ifc_repo["path"]).active_branch.name
|
|
url = _local_url(local_ifc_repo["path"], ref=f"heads/{branch}")
|
|
hexsha, data = fetch_ifc(url)
|
|
assert hexsha == local_ifc_repo["hexsha"]
|
|
assert data == local_ifc_repo["bytes"]
|
|
|
|
def test_bad_ref_raises(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"], ref="heads/nonexistent")
|
|
with pytest.raises(ValueError, match="not found"):
|
|
fetch_ifc(url)
|
|
|
|
def test_bad_path_raises(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"], path="missing.ifc")
|
|
with pytest.raises(ValueError, match="not found"):
|
|
fetch_ifc(url)
|
|
|
|
def test_directory_path_raises(self, local_ifc_repo):
|
|
# Committing a subdir would be complex; test that asking for a
|
|
# non-blob raises — here we ask for the root tree entry.
|
|
url = _local_url(local_ifc_repo["path"], path=".")
|
|
with pytest.raises((ValueError, KeyError)):
|
|
fetch_ifc(url)
|
|
|
|
def test_no_path_raises(self, local_ifc_repo):
|
|
url = IfcUrl.parse(f"ifc://{local_ifc_repo['path']}@HEAD")
|
|
with pytest.raises(ValueError, match="'path' parameter"):
|
|
fetch_ifc(url)
|
|
|
|
|
|
class TestFetchIfcBytes:
|
|
def test_returns_bytes(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"])
|
|
data = fetch_ifc_bytes(url)
|
|
assert data == local_ifc_repo["bytes"]
|
|
|
|
def test_backwards_compat_with_fetch_ifc(self, local_ifc_repo):
|
|
url = _local_url(local_ifc_repo["path"])
|
|
_, expected = fetch_ifc(url)
|
|
assert fetch_ifc_bytes(url) == expected
|
|
|
|
|
|
class TestInvalidRepo:
|
|
def test_nonexistent_path_raises(self, tmp_path):
|
|
url = IfcUrl.parse(f"ifc://{tmp_path / 'no_such_repo'}@HEAD?path=m.ifc")
|
|
with pytest.raises(ValueError):
|
|
fetch_ifc(url)
|
|
|
|
def test_non_git_directory_raises(self, tmp_path):
|
|
(tmp_path / "model.ifc").write_text("not a repo")
|
|
url = IfcUrl.parse(f"ifc://{tmp_path}@HEAD?path=model.ifc")
|
|
with pytest.raises(ValueError):
|
|
fetch_ifc(url)
|