tests: basic pkgrepo tests, clone pmaports (MR 2252)

Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
Caleb Connolly 2024-06-13 08:05:17 +02:00 committed by Oliver Smith
parent 25e41ff3f7
commit 3f11fa2500
No known key found for this signature in database
GPG key ID: 5AE7F5513E0885CB
9 changed files with 98 additions and 15 deletions

View file

@ -7,6 +7,7 @@ from pmb import commands
from pmb.types import PathString from pmb.types import PathString
from pmb.helpers import run from pmb.helpers import run
from pmb.core.context import get_context from pmb.core.context import get_context
import pmb.config
class Log(commands.Command): class Log(commands.Command):
clear_log: bool clear_log: bool
@ -18,7 +19,7 @@ class Log(commands.Command):
def run(self): def run(self):
context = get_context() context = get_context()
log_testsuite = context.config.work / "log_testsuite.txt" log_testsuite = pmb.config.pmb_src / ".pytest_tmp/log_testsuite.txt"
if self.clear_log: if self.clear_log:
run.user(["truncate", "-s", "0", context.log]) run.user(["truncate", "-s", "0", context.log])

View file

@ -46,7 +46,11 @@ def load(path: Path) -> Config:
# Yeah this really sucks and there isn't a better way to do it without external # Yeah this really sucks and there isn't a better way to do it without external
# libraries # libraries
elif isinstance(getattr(Config, key), List) and isinstance(getattr(Config, key)[0], PosixPath): elif isinstance(getattr(Config, key), List) and isinstance(getattr(Config, key)[0], PosixPath):
setattr(config, key, [Path(p.strip()) for p in cfg["pmbootstrap"][key].split(",")]) value = cfg["pmbootstrap"][key]
if not value:
setattr(config, key, value)
else:
setattr(config, key, [Path(p) for p in value.split(",")])
elif isinstance(getattr(Config, key), bool): elif isinstance(getattr(Config, key), bool):
setattr(config, key, cfg["pmbootstrap"][key].lower() == "true") setattr(config, key, cfg["pmbootstrap"][key].lower() == "true")
elif key in cfg["pmbootstrap"]: elif key in cfg["pmbootstrap"]:

View file

@ -663,7 +663,7 @@ def frontend(args: PmbArgs):
# Choose release channel, possibly switch pmaports branch # Choose release channel, possibly switch pmaports branch
channel = ask_for_channel(config) channel = ask_for_channel(config)
pmb.config.pmaports.switch_to_channel_branch(args, channel) pmb.config.pmaports.switch_to_channel_branch(channel)
# FIXME: ??? # FIXME: ???
config.is_default_channel = False config.is_default_channel = False

View file

@ -174,7 +174,7 @@ def init():
read_config() read_config()
def switch_to_channel_branch(args: PmbArgs, channel_new): def switch_to_channel_branch(channel_new):
"""Checkout the channel's branch in pmaports.git. """Checkout the channel's branch in pmaports.git.
:channel_new: channel name (e.g. "edge", "v21.03") :channel_new: channel name (e.g. "edge", "v21.03")
@ -198,7 +198,7 @@ def switch_to_channel_branch(args: PmbArgs, channel_new):
f" '{channel_new}'...") f" '{channel_new}'...")
# Make sure we don't have mounts related to the old channel # Make sure we don't have mounts related to the old channel
pmb.chroot.shutdown(args) pmb.chroot.shutdown()
# Attempt to switch branch (git gives a nice error message, mentioning # Attempt to switch branch (git gives a nice error message, mentioning
# which files need to be committed/stashed, so just pass it through) # which files need to be committed/stashed, so just pass it through)

View file

@ -92,3 +92,4 @@ def test_migrate_2_to_3(config_file_2_3_x, tmp_path, monkeypatch):
# Check that save was called (which happens on a config migration) # Check that save was called (which happens on a config migration)
assert did_migrate assert did_migrate
# FIXME: add save tests and better type checks

View file

@ -4,21 +4,32 @@ import pytest
import shutil import shutil
import pmb.core import pmb.core
from pmb.core.context import get_context
from pmb.types import PmbArgs from pmb.types import PmbArgs
from pmb.helpers.args import init as init_args from pmb.helpers.args import init as init_args
_testdir = Path(__file__).parent / "data/tests" _testdir = Path(__file__).parent / "data/tests"
@pytest.fixture @pytest.fixture
def config_file(tmp_path_factory): def config_file(tmp_path_factory, request):
"""Fixture to create a temporary pmbootstrap.cfg file.""" """Fixture to create a temporary pmbootstrap.cfg file."""
tmp_path = tmp_path_factory.mktemp("pmbootstrap") tmp_path = tmp_path_factory.mktemp("pmbootstrap")
flavour = "default"
if hasattr(request, "param") and request.param:
flavour = request.param
out_file = tmp_path / "pmbootstrap.cfg" out_file = tmp_path / "pmbootstrap.cfg"
workdir = tmp_path / "work" workdir = tmp_path / "work"
workdir.mkdir() workdir.mkdir()
configs = {"default": f"aports = {workdir / 'cache_git' / 'pmaports'}",
"no-repos": "aports = "}
file = _testdir / "pmbootstrap.cfg" file = _testdir / "pmbootstrap.cfg"
contents = open(file).read().format(workdir) print(f"config_file: {out_file}")
cfg = configs[flavour]
contents = open(file).read().format(workdir, cfg)
open(out_file, "w").write(contents) open(out_file, "w").write(contents)
return out_file return out_file
@ -53,11 +64,14 @@ def mock_devices_find_path(device_package, monkeypatch):
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup_logging(tmp_path: Path): def logfile(tmp_path_factory):
"""Setup logging for all tests.""" """Setup logging for all tests."""
import logging from pmb.helpers import logging
logfile = tmp_path / "test.log" tmp_path = tmp_path_factory.getbasetemp()
logging.basicConfig(level=logging.DEBUG, force=True, filename=logfile) logfile = tmp_path / "log_testsuite.txt"
logging.init(logfile, verbose=True)
return logfile
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -92,7 +106,7 @@ def mock_context(monkeypatch):
# FIXME: get_context() at runtime somehow doesn't return the # FIXME: get_context() at runtime somehow doesn't return the
# custom context we set up here. # custom context we set up here.
@pytest.fixture @pytest.fixture
def pmb_args(config_file, mock_context): def pmb_args(config_file, mock_context, logfile):
"""This is (still) a hack, since a bunch of the codebase still """This is (still) a hack, since a bunch of the codebase still
expects some global state to be initialised. We do that here.""" expects some global state to be initialised. We do that here."""
@ -102,15 +116,18 @@ def pmb_args(config_file, mock_context):
args.timeout = 900 args.timeout = 900
args.details_to_stdout = False args.details_to_stdout = False
args.quiet = False args.quiet = False
args.verbose = False args.verbose = True
args.offline = False args.offline = False
args.action = "init" args.action = "init"
args.cross = False args.cross = False
args.log = Path() args.log = logfile
print("init_args") print("init_args")
init_args(args) init_args(args)
# Sanity check
assert ".pytest_tmp" in get_context().config.work.parts
@pytest.fixture @pytest.fixture
def foreign_arch(): def foreign_arch():
"""Fixture to return the foreign arch.""" """Fixture to return the foreign arch."""
@ -120,3 +137,22 @@ def foreign_arch():
return Arch.x86_64 return Arch.x86_64
@pytest.fixture
def pmaports(pmb_args, monkeypatch):
"""Fixture to clone pmaports."""
from pmb.core import Config
from pmb.core.context import get_context
config = get_context().config
with monkeypatch.context() as m:
# Speed things up by cloning from the local checkout if it exists.
if Config.aports[0].exists():
m.setitem(pmb.config.git_repos, "pmaports", Config.aports)
pmb.helpers.git.clone("pmaports")
assert pmb.helpers.run.user(["git", "checkout", "master"],
working_dir=config.aports[0]) == 0

40
pmb/core/test_pkgrepo.py Normal file
View file

@ -0,0 +1,40 @@
import pytest
import pmb.helpers.git
import pmb.helpers.run
from pmb.core.pkgrepo import pkgrepo_paths, pkgrepo_default_path
@pytest.mark.parametrize("config_file", ["no-repos"], indirect=True)
def test_pkgrepo_paths_no_repos(pmb_args):
"""Test pkgrepo_paths() with no repositories. Should raise a RuntimeError."""
with pytest.raises(RuntimeError):
paths = pkgrepo_paths()
print(paths)
def test_pkgrepo_pmaports(pmaports, monkeypatch):
"""Test pkgrepo_paths() with pmaports repository and systemd extra repo"""
# Disable results caching
pkgrepo_paths.cache_disable()
paths = pkgrepo_paths()
print(f"[master] pkgrepo_paths: {paths}")
assert len(paths) == 1
assert "pmaports" in paths[0].name
default_path = pkgrepo_default_path()
assert default_path.name == "pmaports"
# Test extra-repos
assert pmb.helpers.run.user(["git", "checkout", "master_staging_systemd"],
working_dir=default_path) == 0
paths = pkgrepo_paths()
assert len(paths) == 2
# systemd is the first path, since we want packages there to take priority
assert paths[0].name == "systemd"
# but pmaports is the default rep, since it has channels.cfg/pmaports.cfg
assert pkgrepo_default_path().name == "pmaports"

View file

@ -1,4 +1,5 @@
[pmbootstrap] [pmbootstrap]
{1}
build_default_device_arch = True build_default_device_arch = True
ccache_size = 5G ccache_size = 5G
device = qemu-amd64 device = qemu-amd64

View file

@ -48,7 +48,7 @@ def clone(name_repo: str):
command += [url, path] command += [url, path]
# Create parent dir and clone # Create parent dir and clone
logging.info("Clone git repository: " + url) logging.info(f"Clone git repository: {url}")
(get_context().config.work / "cache_git").mkdir(exist_ok=True) (get_context().config.work / "cache_git").mkdir(exist_ok=True)
pmb.helpers.run.user(command, output="stdout") pmb.helpers.run.user(command, output="stdout")