Files
computer-playbook/tests/unit/utils/test_config_utils.py
T

196 lines
6.2 KiB
Python

import os
import shutil
import tempfile
import unittest
from utils.config_utils import (
get_app_conf,
AppConfigKeyError,
ConfigEntryNotSetError,
)
class TestGetAppConf(unittest.TestCase):
def setUp(self):
# Isolate working directory so that schema files can be discovered
self._cwd = os.getcwd()
self.tmpdir = tempfile.mkdtemp(prefix="cfgutilstest_")
os.chdir(self.tmpdir)
# Minimal schema structure:
# roles/web-app-demo/schema/main.yml
os.makedirs(os.path.join("roles", "web-app-demo", "schema"), exist_ok=True)
with open(
os.path.join("roles", "web-app-demo", "schema", "main.yml"), "w"
) as f:
f.write(
# Defines 'features.defined_but_unset' in schema (without a value in applications),
# plus 'features.oidc' and 'features.nested.list'
"features:\n"
" oidc: {}\n"
" defined_but_unset: {}\n"
" nested:\n"
" list:\n"
" - {}\n"
)
# Example configuration with actual values
self.applications = {
"web-app-demo": {
"features": {"oidc": True, "nested": {"list": ["first", "second"]}}
}
}
def tearDown(self):
os.chdir(self._cwd)
shutil.rmtree(self.tmpdir, ignore_errors=True)
# --- Tests ---
def test_missing_app_with_skip_missing_app_returns_default_true(self):
"""If app ID is missing and skip_missing_app=True, it should return the default (True)."""
apps = {"some-other-app": {}}
val = get_app_conf(
apps,
"web-app-nextcloud",
"features.oidc",
strict=True,
default=True,
skip_missing_app=True,
)
self.assertTrue(val)
def test_missing_app_with_skip_missing_app_returns_default_false(self):
"""If app ID is missing and skip_missing_app=True, it should return the default (False)."""
apps = {"svc-bkp-rmt-2-loc": {}}
val = get_app_conf(
apps,
"web-app-nextcloud",
"features.oidc",
strict=True,
default=False,
skip_missing_app=True,
)
self.assertFalse(val)
def test_missing_app_without_skip_missing_app_and_strict_true_raises(self):
"""Missing app ID without skip_missing_app and strict=True should raise."""
apps = {}
with self.assertRaises(AppConfigKeyError):
get_app_conf(
apps,
"web-app-nextcloud",
"features.oidc",
strict=True,
default=True,
skip_missing_app=False,
)
def test_missing_app_without_skip_missing_app_and_strict_false_raises(self):
apps = {}
with self.assertRaises(AppConfigKeyError):
get_app_conf(
apps,
"web-app-nextcloud",
"features.oidc",
strict=False,
default=True,
skip_missing_app=False,
)
def test_existing_app_returns_expected_value(self):
"""Existing app and key should return the configured value."""
val = get_app_conf(
self.applications,
"web-app-demo",
"features.oidc",
strict=True,
default=False,
skip_missing_app=False,
)
self.assertTrue(val)
def test_nested_list_index_access(self):
"""Accessing list indices should work correctly."""
val0 = get_app_conf(
self.applications,
"web-app-demo",
"features.nested.list[0]",
strict=True,
default=None,
skip_missing_app=False,
)
val1 = get_app_conf(
self.applications,
"web-app-demo",
"features.nested.list[1]",
strict=True,
default=None,
skip_missing_app=False,
)
self.assertEqual(val0, "first")
self.assertEqual(val1, "second")
def test_schema_defined_but_unset_raises_in_strict_mode(self):
"""Schema-defined but unset value should raise in strict mode."""
with self.assertRaises(ConfigEntryNotSetError):
get_app_conf(
self.applications,
"web-app-demo",
"features.defined_but_unset",
strict=True,
default=False,
skip_missing_app=False,
)
def test_schema_defined_but_unset_strict_false_returns_default(self):
"""Schema-defined but unset value should return default when strict=False."""
val = get_app_conf(
self.applications,
"web-app-demo",
"features.defined_but_unset",
strict=False,
default=True,
skip_missing_app=False,
)
self.assertTrue(val)
def test_invalid_key_format_raises(self):
"""Invalid key format in path should raise AppConfigKeyError."""
with self.assertRaises(AppConfigKeyError):
get_app_conf(
self.applications,
"web-app-demo",
"features.nested.list[not-an-int]",
strict=True,
default=None,
skip_missing_app=False,
)
def test_index_out_of_range_respects_strict(self):
"""Out-of-range index should respect strict parameter."""
# strict=False returns default
val = get_app_conf(
self.applications,
"web-app-demo",
"features.nested.list[99]",
strict=False,
default="fallback",
skip_missing_app=False,
)
self.assertEqual(val, "fallback")
# strict=True raises
with self.assertRaises(AppConfigKeyError):
get_app_conf(
self.applications,
"web-app-demo",
"features.nested.list[99]",
strict=True,
default=None,
skip_missing_app=False,
)
if __name__ == "__main__":
unittest.main()