stages(erofs): add tests and fix small bug in options handling
This adds tests for the erofs stage. The tests are slightly different from the existing tests that run the filesystem utils inside the stages. Depending on what exactly we want to test we may still need a run inside the stages. However running this inside a container should be good enough if we just want to validate that the options are passed correctly and the file is created.
This commit is contained in:
parent
a2ea0b2265
commit
d4a0837cf0
2 changed files with 126 additions and 0 deletions
|
|
@ -87,6 +87,7 @@ def main(inputs, output_dir, options):
|
|||
method += f",{compression['level']}"
|
||||
cmd += ["-z", method]
|
||||
|
||||
options = options.get("options")
|
||||
if options:
|
||||
cmd += ["-E", ",".join(options)]
|
||||
|
||||
|
|
|
|||
125
stages/test/test_erofs.py
Normal file
125
stages/test/test_erofs.py
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import os.path
|
||||
import subprocess
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
import osbuild.meta
|
||||
from osbuild.testutil import has_executable
|
||||
from osbuild.testutil.imports import import_module_from_path
|
||||
|
||||
|
||||
def make_fake_input_tree(tmpdir, fake_content: dict) -> str:
|
||||
basedir = os.path.join(tmpdir, "tree")
|
||||
for path, content in fake_content.items():
|
||||
dirp, name = os.path.split(os.path.join(basedir, path.lstrip("/")))
|
||||
os.makedirs(dirp, exist_ok=True)
|
||||
with open(os.path.join(dirp, name), "w", encoding="utf-8") as fp:
|
||||
fp.write(content)
|
||||
return basedir
|
||||
|
||||
|
||||
TEST_INPUT = [
|
||||
({}, []),
|
||||
({"compression": {"method": "lz4"}}, ["-z", "lz4"]),
|
||||
({"compression": {"method": "lz4hc", "level": 9}}, ["-z", "lz4hc,9"]),
|
||||
({"options": ["dedupe"]}, ["-E", "dedupe"]),
|
||||
({"options": ["all-fragments", "force-inode-compact"]}, ["-E", "all-fragments,force-inode-compact"]),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(not has_executable("mkfs.erofs"), reason="no mkfs.erofs")
|
||||
@pytest.mark.parametrize("test_options,expected", TEST_INPUT)
|
||||
def test_erofs_integration(tmp_path, test_options, expected): # pylint: disable=unused-argument
|
||||
fake_input_tree = make_fake_input_tree(tmp_path, {
|
||||
"/file-in-root.txt": "other content",
|
||||
"/subdir/file-in-subdir.txt": "subdir content",
|
||||
})
|
||||
inputs = {
|
||||
"tree": {
|
||||
"path": fake_input_tree,
|
||||
}
|
||||
}
|
||||
stage_path = os.path.join(os.path.dirname(__file__), "../org.osbuild.erofs")
|
||||
stage = import_module_from_path("erofs_stage", stage_path)
|
||||
filename = "some-file.img"
|
||||
options = {
|
||||
"filename": filename,
|
||||
}
|
||||
options.update(test_options)
|
||||
|
||||
stage.main(inputs, tmp_path, options)
|
||||
|
||||
img_path = os.path.join(tmp_path, "some-file.img")
|
||||
assert os.path.exists(img_path)
|
||||
# validate the content
|
||||
output = subprocess.check_output([
|
||||
"dump.erofs", "--ls", "--path=/", img_path], encoding="utf-8")
|
||||
assert "subdir\n" in output
|
||||
assert "file-in-root.txt\n" in output
|
||||
output = subprocess.check_output([
|
||||
"dump.erofs", "--ls", "--path=/subdir", img_path], encoding="utf-8")
|
||||
assert "file-in-subdir.txt\n" in output
|
||||
|
||||
|
||||
@mock.patch("subprocess.run")
|
||||
@pytest.mark.parametrize("test_options,expected", TEST_INPUT)
|
||||
def test_erofs(mock_run, tmp_path, test_options, expected):
|
||||
fake_input_tree = make_fake_input_tree(tmp_path, {
|
||||
"/some-dir/some-file.txt": "content",
|
||||
})
|
||||
inputs = {
|
||||
"tree": {
|
||||
"path": fake_input_tree,
|
||||
}
|
||||
}
|
||||
stage_path = os.path.join(os.path.dirname(__file__), "../org.osbuild.erofs")
|
||||
stage = import_module_from_path("erofs_stage", stage_path)
|
||||
filename = "some-file.img"
|
||||
options = {
|
||||
"filename": filename,
|
||||
}
|
||||
options.update(test_options)
|
||||
|
||||
stage.main(inputs, tmp_path, options)
|
||||
|
||||
expected = [
|
||||
"mkfs.erofs",
|
||||
f"{os.path.join(tmp_path, filename)}",
|
||||
f"{fake_input_tree}",
|
||||
] + expected
|
||||
mock_run.assert_called_with(expected, check=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_data,expected_err", [
|
||||
# bad
|
||||
({"extra": "option"}, "'extra' was unexpected"),
|
||||
({"compression": {"method": "invalid"}}, "'invalid' is not one of ["),
|
||||
({"compression": {"method": "lz4", "level": "string"}}, "'string' is not of type "),
|
||||
# good
|
||||
({"compression": {"method": "lz4"}}, ""),
|
||||
])
|
||||
def test_schema_validation_erofs(test_data, expected_err):
|
||||
name = "org.osbuild.erofs"
|
||||
root = os.path.join(os.path.dirname(__file__), "../..")
|
||||
mod_info = osbuild.meta.ModuleInfo.load(root, "Stage", name)
|
||||
schema = osbuild.meta.Schema(mod_info.get_schema(version="2"), name)
|
||||
|
||||
test_input = {
|
||||
"type": "org.osbuild.erofs",
|
||||
"options": {
|
||||
"filename": "some-filename.img",
|
||||
}
|
||||
}
|
||||
test_input["options"].update(test_data)
|
||||
res = schema.validate(test_input)
|
||||
|
||||
if expected_err == "":
|
||||
assert res.valid is True, f"err: {[e.as_dict() for e in res.errors]}"
|
||||
else:
|
||||
assert res.valid is False
|
||||
assert len(res.errors) == 1, [e.as_dict() for e in res.errors]
|
||||
err_msgs = [e.as_dict()["message"] for e in res.errors]
|
||||
assert expected_err in err_msgs[0]
|
||||
Loading…
Add table
Add a link
Reference in a new issue