123 lines
3.7 KiB
Python
123 lines
3.7 KiB
Python
# Copyright: (c) 2025, Luca Bilke <luca@bil.ke>
|
|
# MIT License (see LICENSE)
|
|
|
|
from typing import Any
|
|
from unittest import TestCase
|
|
|
|
import pytest
|
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import common
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("test_input", "expected"),
|
|
[ # pyright: ignore[reportUnknownArgumentType]
|
|
# Basic nested update (using existing test variables)
|
|
(
|
|
(
|
|
{"one": {"one": "keep", "two": "rewrite"}},
|
|
{"one": {"two": "new"}},
|
|
),
|
|
{"one": {"one": "keep", "two": "new"}},
|
|
),
|
|
# Deep nested update
|
|
(
|
|
(
|
|
{"a": {"b": {"c": "old", "d": "keep"}}},
|
|
{"a": {"b": {"c": "new"}}},
|
|
),
|
|
{"a": {"b": {"c": "new", "d": "keep"}}},
|
|
),
|
|
# Adding new keys at different levels
|
|
(
|
|
(
|
|
{"x": {"y": "original"}},
|
|
{"x": {"z": "new", "y": "updated"}, "new_key": "value"},
|
|
),
|
|
{"x": {"y": "updated", "z": "new"}, "new_key": "value"},
|
|
),
|
|
# Empty dict cases
|
|
(
|
|
(
|
|
{},
|
|
{"new": "data"},
|
|
),
|
|
{"new": "data"},
|
|
),
|
|
(
|
|
(
|
|
{"existing": "data"},
|
|
{},
|
|
),
|
|
{"existing": "data"},
|
|
),
|
|
# Lists within dictionaries
|
|
(
|
|
(
|
|
{"items": ["a", "b"], "nested": {"list": ["1", "2"]}},
|
|
{"items": ["c"], "nested": {"list": ["3"]}},
|
|
),
|
|
{"items": ["a", "b", "c"], "nested": {"list": ["1", "2", "3"]}},
|
|
),
|
|
# Lists of dictionaries
|
|
(
|
|
(
|
|
{
|
|
"configs": [
|
|
{"name": "config1", "value": "old"},
|
|
{"name": "config2", "enabled": True},
|
|
],
|
|
},
|
|
{
|
|
"configs": [
|
|
{"name": "config3", "value": "new"},
|
|
{"name": "config4", "enabled": False},
|
|
],
|
|
},
|
|
),
|
|
{
|
|
"configs": [
|
|
{"name": "config1", "value": "old"},
|
|
{"name": "config2", "enabled": True},
|
|
{"name": "config3", "value": "new"},
|
|
{"name": "config4", "enabled": False},
|
|
],
|
|
},
|
|
),
|
|
# Nested lists of dictionaries
|
|
(
|
|
(
|
|
{
|
|
"services": {
|
|
"web": [
|
|
{"port": 80, "protocol": "http"},
|
|
{"port": 443, "protocol": "https"},
|
|
],
|
|
},
|
|
},
|
|
{"services": {"web": [{"port": 8080, "protocol": "http"}]}},
|
|
),
|
|
{
|
|
"services": {
|
|
"web": [
|
|
{"port": 80, "protocol": "http"},
|
|
{"port": 443, "protocol": "https"},
|
|
{"port": 8080, "protocol": "http"},
|
|
],
|
|
},
|
|
},
|
|
),
|
|
# Mixed types update
|
|
(
|
|
(
|
|
{"mixed": {"num": 42, "list": [1, 2], "str": "old"}},
|
|
{"mixed": {"num": 43, "list": [3], "str": "new"}},
|
|
),
|
|
{"mixed": {"num": 43, "list": [1, 2, 3], "str": "new"}},
|
|
),
|
|
],
|
|
)
|
|
def test_recursive_update(
|
|
test_input: tuple[dict[str, Any], dict[str, Any]],
|
|
expected: dict[str, Any],
|
|
) -> None:
|
|
TestCase().assertDictEqual(common.recursive_update(*test_input), expected)
|