test: add test for export option

This commit is contained in:
Michael Vogt 2023-12-19 18:54:45 +01:00 committed by Achilleas Koutsou
parent 8cce659ec5
commit 962b7f4d4b
4 changed files with 123 additions and 2 deletions

89
test/run/test_exports.py Normal file
View file

@ -0,0 +1,89 @@
import contextlib
import json
import os
import pathlib
import shutil
import subprocess
import pytest
from .. import test
@pytest.fixture(name="jsondata", scope="module")
def jsondata_fixture():
return json.dumps({
"version": "2",
"pipelines": [
{
"name": "image",
"stages": [
{
"type": "org.osbuild.truncate",
"options": {
"filename": "foo.img",
"size": "10",
},
},
{
# cannot use org.osbuild.chown as it needs the chown
# binary in the stage
"type": "org.osbuild.testing.injectpy",
"options": {
"code": [
'import os',
'os.chown(f"{tree}/foo.img", 1000, 1000)',
],
},
},
]
}
]
})
@pytest.fixture(name="osb", scope="module")
def osbuild_fixture():
with test.OSBuild() as osb:
yield osb
@pytest.fixture(name="testing_libdir", scope="module")
def testing_libdir_fixture(tmpdir_factory):
tests_path = pathlib.Path(__file__).parent.parent
project_path = tests_path.parent
testing_libdir_path = tests_path / "stages"
fake_libdir_path = tmpdir_factory.mktemp("fake-libdir")
# there must be an empty "osbild" dir for a "os.listdir(self._libdir)"
# in buildroot.py
(fake_libdir_path / "osbuild").mkdir()
# construct minimal viable libdir from current checkout
for d in ["stages", "runners", ]:
subprocess.run(
["cp", "-a", os.fspath(project_path / d), f"{fake_libdir_path}"],
check=True)
# now inject testing stages
for p in testing_libdir_path.glob("org.osbuild.testing.*"):
shutil.copy2(p, fake_libdir_path / "stages")
yield fake_libdir_path
@pytest.mark.skipif(os.getuid() != 0, reason="root-only")
def test_exports_normal(osb, tmp_path, jsondata, testing_libdir): # pylint: disable=unused-argument
osb.compile(jsondata, output_dir=tmp_path, exports=["image"], libdir=testing_libdir)
expected_export = tmp_path / "image/foo.img"
assert expected_export.exists()
assert expected_export.stat().st_uid == 1000
@pytest.mark.skipif(os.getuid() != 0, reason="root-only")
def test_exports_with_force_no_preserve_owner(osb, tmp_path, jsondata, testing_libdir):
with contextlib.ExitStack() as cm:
k = "OSBUILD_EXPORT_FORCE_NO_PRESERVE_OWNER"
os.environ[k] = "1"
cm.callback(os.unsetenv, k)
osb.compile(jsondata, output_dir=tmp_path, exports=["image"], libdir=testing_libdir)
expected_export = tmp_path / "image/foo.img"
assert expected_export.exists()
assert expected_export.stat().st_uid == 0

5
test/stages/README.md Normal file
View file

@ -0,0 +1,5 @@
This directory contains stages that can only be used during testing and
will be dynamically added to the library directory.
See `test/run/test_exports.py` for an example usage of the `pyinject`
stage.

View file

@ -0,0 +1,27 @@
#!/usr/bin/python3
"""
Inject arbitrary python code.
ONLY USE FOR TESTING
"""
import sys
import osbuild.api
SCHEMA_2 = """
"options": {
"additionalProperties": true
}
"""
def main(tree, options): # pylint: disable=unused-argument
script = "\n".join(options.get("code", []))
exec(script) # pylint: disable=exec-used
if __name__ == '__main__':
args = osbuild.api.arguments()
r = main(args["tree"], args.get("options", {}))
sys.exit(r)

View file

@ -347,7 +347,7 @@ class OSBuild(contextlib.AbstractContextManager):
print(log)
print("-- END ---------------------------------")
def compile(self, data_stdin, output_dir=None, checkpoints=None, check=False, exports=None):
def compile(self, data_stdin, output_dir=None, checkpoints=None, check=False, exports=None, libdir="."):
"""Compile an Artifact
This takes a manifest as `data_stdin`, executes the pipeline, and
@ -377,7 +377,7 @@ class OSBuild(contextlib.AbstractContextManager):
cmd_args = [sys.executable, "-m", "osbuild"]
cmd_args += ["--json"]
cmd_args += ["--libdir", "."]
cmd_args += ["--libdir", libdir]
cmd_args += ["--output-directory", output_dir]
cmd_args += ["--store", self._cachedir]