From 488eee7bc01ea62157d79ad33fe00bac69799a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= Date: Thu, 21 Mar 2024 23:20:44 +0100 Subject: [PATCH] Tests: Add unit tests for org.osbuild.mkfs.btrfs stage --- stages/test/test_mkfs_btrfs.py | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 stages/test/test_mkfs_btrfs.py diff --git a/stages/test/test_mkfs_btrfs.py b/stages/test/test_mkfs_btrfs.py new file mode 100644 index 00000000..70286d82 --- /dev/null +++ b/stages/test/test_mkfs_btrfs.py @@ -0,0 +1,106 @@ +#!/usr/bin/python3 + +import os.path +import subprocess +import uuid +from unittest import mock + +import pytest + +from osbuild import testutil +from osbuild.testutil import has_executable + +STAGE_NAME = "org.osbuild.mkfs.btrfs" + + +# Prepare dataset containing good and bad API call parameters +@pytest.mark.parametrize("test_data, expected_err", [ + # Bad API parameters + ({}, "'uuid' is a required property"), + ({"uuid": 123}, "123 is not of type 'string'"), + ({"uuid": "text", "label": 1234}, "1234 is not of type 'string'"), + # Good API parameters + # mkfs requires valid UUID, but API will accept any string right now. + # Bellow will fail when API will be more restricted in the future. + ({"uuid": "text"}, ""), + ({"uuid": "text", "label": "osbuild"}, ""), + ({"uuid": "text", "label": "osbuild", "metadata": "single"}, ""), +]) +# This test validates only API calls using correct and incorrect queries +def test_schema_validation_mkfs_btrfs(stage_schema, test_data, expected_err): + test_input = { + "type": STAGE_NAME, + "devices": { + "device": { + "path": "some-path", + }, + }, + "options": { + } + } + test_input["options"].update(test_data) + res = stage_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 + testutil.assert_jsonschema_error_contains(res, expected_err, expected_num_errs=1) + + +# This test creates dummy filesystem using predefined parameters and verifies +# that end result has those parameters set +@pytest.mark.skipif(not has_executable("mkfs.btrfs"), reason="need mkfs.btrfs") +def test_mkfs_btrfs_integration(tmp_path, stage_module): + fake_disk_path = tmp_path / "fake.img" + with fake_disk_path.open("w") as fp: + fp.truncate(110 * 1024 * 1024) + devices = { + "device": { + "path": fake_disk_path, + }, + } + fake_uuid = str(uuid.uuid4()) + fake_label = "osbuild" + options = { + "uuid": fake_uuid, + "label": fake_label, + } + stage_module.main(devices, options) + assert os.path.exists(fake_disk_path) + output = subprocess.check_output([ + "btrfs", "filesystem", "show", fake_disk_path], encoding="utf-8") + assert f'uuid: {fake_uuid}' in output, \ + f'expected UUID not found in: {output}' + assert f'Label: \'{fake_label}\'' in output, \ + f'expected label not found in: {output}' + + +@pytest.mark.parametrize("test_input, expected", [ + ({}, []), + ({"label": "osbuild"}, ["-L", "osbuild"]), + ({"metadata": "single"}, ["-m", "single"]), +]) +@mock.patch("subprocess.run") +def test_mkfs_btrfs_cmdline(mock_run, stage_module, test_input, expected): + fake_disk_path = "/dev/xxd1" + devices = { + "device": { + "path": fake_disk_path, + }, + } + fake_uuid = str(uuid.uuid4()) + options = { + "uuid": fake_uuid, + } + options.update(test_input) + stage_module.main(devices, options) + + expected = [ + "mkfs.btrfs", + "-U", + f"{fake_uuid}", + ] + expected + [ + fake_disk_path, + ] + mock_run.assert_called_once_with(expected, encoding="utf8", check=True)