autoscan / tests /test_bootstrap.py
Chris4K's picture
Initial commit v5.0.0.
5248e3b verified
"""Tests for core.bootstrap β€” binary download and installation (all I/O mocked)."""
import io
import os
import tarfile as tarfile_mod
import zipfile as zipfile_mod
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
import requests as req
# ── _stream_download ──────────────────────────────────────────────────────────
class TestStreamDownload:
def test_writes_chunks_to_file(self, tmp_path):
dest = tmp_path / "output.bin"
mock_resp = MagicMock()
mock_resp.iter_content.return_value = iter([b"hello", b"", b"world"])
with patch("core.bootstrap.requests.get", return_value=mock_resp):
from core.bootstrap import _stream_download
_stream_download("https://github.com/owner/repo/releases/download/v1/file", dest)
assert dest.exists()
assert dest.read_bytes() == b"helloworld"
def test_skips_empty_chunks(self, tmp_path):
dest = tmp_path / "empty_chunk.bin"
mock_resp = MagicMock()
mock_resp.iter_content.return_value = iter([b"", b"", b"data"])
with patch("core.bootstrap.requests.get", return_value=mock_resp):
from core.bootstrap import _stream_download
_stream_download("https://github.com/owner/repo/releases/download/v1/file", dest)
assert dest.read_bytes() == b"data"
def test_raises_on_http_error(self, tmp_path):
dest = tmp_path / "out.bin"
mock_resp = MagicMock()
mock_resp.raise_for_status.side_effect = req.HTTPError("404 Not Found")
with patch("core.bootstrap.requests.get", return_value=mock_resp):
from core.bootstrap import _stream_download
with pytest.raises(req.HTTPError):
_stream_download("https://github.com/owner/repo/releases/download/v1/missing", dest)
def test_passes_timeout_to_get(self, tmp_path):
dest = tmp_path / "out.bin"
mock_resp = MagicMock()
mock_resp.iter_content.return_value = iter([])
with patch("core.bootstrap.requests.get", return_value=mock_resp) as mock_get:
from core.bootstrap import _stream_download
_stream_download("https://github.com/owner/repo/releases/download/v1/file", dest, timeout=42)
assert mock_get.call_args[1]["timeout"] == 42
# ── install_gitleaks ──────────────────────────────────────────────────────────
class TestInstallGitleaks:
def test_already_installed_skips_download(self):
with patch("core.bootstrap.have_binary", return_value=True):
from core.bootstrap import install_gitleaks
result = install_gitleaks()
assert result == "already installed"
def test_download_failure_returns_error(self, tmp_path):
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._stream_download",
side_effect=ConnectionError("network down")):
from core.bootstrap import install_gitleaks
result = install_gitleaks()
assert result.startswith("install failed:")
def test_windows_zip_install(self, tmp_path):
"""Windows path: download zip, extract gitleaks.exe."""
buf = io.BytesIO()
with zipfile_mod.ZipFile(buf, "w") as z:
z.writestr("gitleaks.exe", b"fake gitleaks binary")
zip_bytes = buf.getvalue()
def fake_download(url, dest_path, timeout=120):
dest_path.write_bytes(zip_bytes)
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", True), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_gitleaks
result = install_gitleaks()
assert result == "installed"
assert (tmp_path / "gitleaks.exe").exists()
def test_windows_zip_with_lowercase_gitleaks_name(self, tmp_path):
"""Zip contains 'gitleaks' (not '.exe') β€” still extracted and renamed."""
buf = io.BytesIO()
with zipfile_mod.ZipFile(buf, "w") as z:
z.writestr("gitleaks", b"fake binary")
zip_bytes = buf.getvalue()
def fake_download(url, dest_path, timeout=120):
dest_path.write_bytes(zip_bytes)
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", True), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_gitleaks
result = install_gitleaks()
assert result == "installed"
assert (tmp_path / "gitleaks.exe").exists()
def test_linux_tarball_install(self, tmp_path):
"""Linux path: download tar.gz, extract and chmod gitleaks binary."""
buf = io.BytesIO()
with tarfile_mod.open(fileobj=buf, mode="w:gz") as t:
content = b"fake gitleaks"
info = tarfile_mod.TarInfo(name="gitleaks")
info.size = len(content)
t.addfile(info, io.BytesIO(content))
tar_bytes = buf.getvalue()
def fake_download(url, dest_path, timeout=120):
dest_path.write_bytes(tar_bytes)
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", False), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_gitleaks
result = install_gitleaks()
assert result == "installed"
assert (tmp_path / "gitleaks").exists()
def test_linux_tarball_no_matching_member(self, tmp_path):
"""Tar has no 'gitleaks' member β€” loop completes without extraction."""
buf = io.BytesIO()
with tarfile_mod.open(fileobj=buf, mode="w:gz") as t:
content = b"something else"
info = tarfile_mod.TarInfo(name="README.md")
info.size = len(content)
t.addfile(info, io.BytesIO(content))
tar_bytes = buf.getvalue()
def fake_download(url, dest_path, timeout=120):
dest_path.write_bytes(tar_bytes)
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", False), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_gitleaks
result = install_gitleaks()
# Result is "installed" even without gitleaks (chmod line will fail gracefully in except)
# or succeeds if chmod doesn't raise
assert isinstance(result, str)
# ── install_hadolint ──────────────────────────────────────────────────────────
class TestInstallHadolint:
def test_already_installed_skips_download(self):
with patch("core.bootstrap.have_binary", return_value=True):
from core.bootstrap import install_hadolint
result = install_hadolint()
assert result == "already installed"
def test_download_failure_returns_error(self, tmp_path):
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._stream_download",
side_effect=OSError("disk full")):
from core.bootstrap import install_hadolint
result = install_hadolint()
assert result.startswith("install failed:")
def test_windows_download_installs_exe(self, tmp_path):
def fake_download(url, dest_path, timeout=120):
dest_path.write_bytes(b"fake hadolint")
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", True), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_hadolint
result = install_hadolint()
assert result == "installed"
assert (tmp_path / "hadolint.exe").exists()
def test_linux_download_installs_and_chmods(self, tmp_path):
def fake_download(url, dest_path, timeout=120):
dest_path.write_bytes(b"fake hadolint")
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", False), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_hadolint
result = install_hadolint()
assert result == "installed"
assert (tmp_path / "hadolint").exists()
def test_windows_url_contains_windows_in_path(self, tmp_path):
captured = {}
def fake_download(url, dest_path, timeout=120):
captured["url"] = url
dest_path.write_bytes(b"x")
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", True), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_hadolint
install_hadolint()
assert "Windows" in captured["url"] or "windows" in captured["url"]
def test_linux_url_contains_linux_in_path(self, tmp_path):
captured = {}
def fake_download(url, dest_path, timeout=120):
captured["url"] = url
dest_path.write_bytes(b"x")
with patch("core.bootstrap.have_binary", return_value=False), \
patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap._IS_WINDOWS", False), \
patch("core.bootstrap._stream_download", side_effect=fake_download):
from core.bootstrap import install_hadolint
install_hadolint()
assert "Linux" in captured["url"] or "linux" in captured["url"]
# ── bootstrap_binaries ────────────────────────────────────────────────────────
class TestBootstrapBinaries:
def test_returns_dict_with_gitleaks_and_hadolint(self, tmp_path):
with patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap.install_gitleaks", return_value="already installed"), \
patch("core.bootstrap.install_hadolint", return_value="ok"):
from core.bootstrap import bootstrap_binaries
result = bootstrap_binaries()
assert "gitleaks" in result
assert "hadolint" in result
def test_adds_bin_dir_to_path_if_missing(self, tmp_path, monkeypatch):
monkeypatch.setenv("PATH", "/usr/bin")
with patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap.install_gitleaks", return_value="ok"), \
patch("core.bootstrap.install_hadolint", return_value="ok"):
from core.bootstrap import bootstrap_binaries
bootstrap_binaries()
assert str(tmp_path) in os.environ["PATH"]
def test_does_not_duplicate_bin_dir_in_path(self, tmp_path, monkeypatch):
monkeypatch.setenv("PATH", str(tmp_path) + os.pathsep + "/usr/bin")
with patch("core.bootstrap.BIN_DIR", tmp_path), \
patch("core.bootstrap.install_gitleaks", return_value="ok"), \
patch("core.bootstrap.install_hadolint", return_value="ok"):
from core.bootstrap import bootstrap_binaries
bootstrap_binaries()
path_parts = os.environ["PATH"].split(os.pathsep)
assert path_parts.count(str(tmp_path)) == 1
def test_creates_bin_dir_if_missing(self, tmp_path):
new_dir = tmp_path / "new_bin_dir"
with patch("core.bootstrap.BIN_DIR", new_dir), \
patch("core.bootstrap.install_gitleaks", return_value="ok"), \
patch("core.bootstrap.install_hadolint", return_value="ok"):
from core.bootstrap import bootstrap_binaries
bootstrap_binaries()
assert new_dir.exists()