community.docker/tests/unit/plugins/module_utils/test__util.py
Felix Fontein 6ad4bfcd40
Add typing information, 2/n (#1178)
* Add typing to Docker Stack modules. Clean modules up.

* Add typing to Docker Swarm modules.

* Add typing to unit tests.

* Add more typing.

* Add ignore.txt entries.
2025-10-25 01:16:04 +02:00

471 lines
10 KiB
Python

# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import typing as t
import pytest
from ansible_collections.community.docker.plugins.module_utils._util import (
compare_dict_allow_more_present,
compare_generic,
convert_duration_to_nanosecond,
parse_healthcheck,
)
if t.TYPE_CHECKING:
class DAMSpec(t.TypedDict):
av: dict[str, t.Any]
bv: dict[str, t.Any]
result: bool
class Spec(t.TypedDict):
a: t.Any
b: t.Any
method: t.Literal["strict", "ignore", "allow_more_present"]
type: t.Literal["value", "list", "set", "set(dict)", "dict"]
result: bool
DICT_ALLOW_MORE_PRESENT: list[DAMSpec] = [
{"av": {}, "bv": {"a": 1}, "result": True},
{"av": {"a": 1}, "bv": {"a": 1, "b": 2}, "result": True},
{"av": {"a": 1}, "bv": {"b": 2}, "result": False},
{"av": {"a": 1}, "bv": {"a": None, "b": 1}, "result": False},
{"av": {"a": None}, "bv": {"b": 1}, "result": False},
]
DICT_ALLOW_MORE_PRESENT_SPECS: list[Spec] = [
{
"a": entry["av"],
"b": entry["bv"],
"method": "allow_more_present",
"type": "dict",
"result": entry["result"],
}
for entry in DICT_ALLOW_MORE_PRESENT
]
COMPARE_GENERIC: list[Spec] = [
########################################################################################
# value
{"a": 1, "b": 2, "method": "strict", "type": "value", "result": False},
{"a": "hello", "b": "hello", "method": "strict", "type": "value", "result": True},
{"a": None, "b": "hello", "method": "strict", "type": "value", "result": False},
{"a": None, "b": None, "method": "strict", "type": "value", "result": True},
{"a": 1, "b": 2, "method": "ignore", "type": "value", "result": True},
{"a": None, "b": 2, "method": "ignore", "type": "value", "result": True},
########################################################################################
# list
{
"a": [
"x",
],
"b": [
"y",
],
"method": "strict",
"type": "list",
"result": False,
},
{
"a": [
"x",
],
"b": [
"x",
"x",
],
"method": "strict",
"type": "list",
"result": False,
},
{
"a": [
"x",
"y",
],
"b": [
"x",
"y",
],
"method": "strict",
"type": "list",
"result": True,
},
{
"a": [
"x",
"y",
],
"b": [
"y",
"x",
],
"method": "strict",
"type": "list",
"result": False,
},
{
"a": [
"x",
"y",
],
"b": [
"x",
],
"method": "allow_more_present",
"type": "list",
"result": False,
},
{
"a": [
"x",
],
"b": [
"x",
"y",
],
"method": "allow_more_present",
"type": "list",
"result": True,
},
{
"a": [
"x",
"x",
"y",
],
"b": [
"x",
"y",
],
"method": "allow_more_present",
"type": "list",
"result": False,
},
{
"a": [
"x",
"z",
],
"b": [
"x",
"y",
"x",
"z",
],
"method": "allow_more_present",
"type": "list",
"result": True,
},
{
"a": [
"x",
"y",
],
"b": [
"y",
"x",
],
"method": "ignore",
"type": "list",
"result": True,
},
########################################################################################
# set
{
"a": [
"x",
],
"b": [
"y",
],
"method": "strict",
"type": "set",
"result": False,
},
{
"a": [
"x",
],
"b": [
"x",
"x",
],
"method": "strict",
"type": "set",
"result": True,
},
{
"a": [
"x",
"y",
],
"b": [
"x",
"y",
],
"method": "strict",
"type": "set",
"result": True,
},
{
"a": [
"x",
"y",
],
"b": [
"y",
"x",
],
"method": "strict",
"type": "set",
"result": True,
},
{
"a": [
"x",
"y",
],
"b": [
"x",
],
"method": "allow_more_present",
"type": "set",
"result": False,
},
{
"a": [
"x",
],
"b": [
"x",
"y",
],
"method": "allow_more_present",
"type": "set",
"result": True,
},
{
"a": [
"x",
"x",
"y",
],
"b": [
"x",
"y",
],
"method": "allow_more_present",
"type": "set",
"result": True,
},
{
"a": [
"x",
"z",
],
"b": [
"x",
"y",
"x",
"z",
],
"method": "allow_more_present",
"type": "set",
"result": True,
},
{
"a": [
"x",
"a",
],
"b": [
"y",
"z",
],
"method": "ignore",
"type": "set",
"result": True,
},
########################################################################################
# set(dict)
{
"a": [
{"x": 1},
],
"b": [
{"y": 1},
],
"method": "strict",
"type": "set(dict)",
"result": False,
},
{
"a": [
{"x": 1},
],
"b": [
{"x": 1},
],
"method": "strict",
"type": "set(dict)",
"result": True,
},
{
"a": [
{"x": 1},
],
"b": [
{"x": 1, "y": 2},
],
"method": "strict",
"type": "set(dict)",
"result": True,
},
{
"a": [
{"x": 1},
{"x": 2, "y": 3},
],
"b": [
{"x": 1},
{"x": 2, "y": 3},
],
"method": "strict",
"type": "set(dict)",
"result": True,
},
{
"a": [
{"x": 1},
],
"b": [
{"x": 1, "z": 2},
{"x": 2, "y": 3},
],
"method": "allow_more_present",
"type": "set(dict)",
"result": True,
},
{
"a": [
{"x": 1, "y": 2},
],
"b": [
{"x": 1},
{"x": 2, "y": 3},
],
"method": "allow_more_present",
"type": "set(dict)",
"result": False,
},
{
"a": [
{"x": 1, "y": 3},
],
"b": [
{"x": 1},
{"x": 1, "y": 3, "z": 4},
],
"method": "allow_more_present",
"type": "set(dict)",
"result": True,
},
{
"a": [
{"x": 1},
{"x": 2, "y": 3},
],
"b": [
{"x": 1},
],
"method": "ignore",
"type": "set(dict)",
"result": True,
},
########################################################################################
# dict
{"a": {"x": 1}, "b": {"y": 1}, "method": "strict", "type": "dict", "result": False},
{
"a": {"x": 1},
"b": {"x": 1, "y": 2},
"method": "strict",
"type": "dict",
"result": False,
},
{"a": {"x": 1}, "b": {"x": 1}, "method": "strict", "type": "dict", "result": True},
{
"a": {"x": 1, "z": 2},
"b": {"x": 1, "y": 2},
"method": "strict",
"type": "dict",
"result": False,
},
{
"a": {"x": 1, "z": 2},
"b": {"x": 1, "y": 2},
"method": "ignore",
"type": "dict",
"result": True,
},
]
@pytest.mark.parametrize("entry", DICT_ALLOW_MORE_PRESENT)
def test_dict_allow_more_present(entry: DAMSpec) -> None:
assert compare_dict_allow_more_present(entry["av"], entry["bv"]) == entry["result"]
@pytest.mark.parametrize("entry", COMPARE_GENERIC + DICT_ALLOW_MORE_PRESENT_SPECS)
def test_compare_generic(entry: Spec) -> None:
assert (
compare_generic(entry["a"], entry["b"], entry["method"], entry["type"])
== entry["result"]
)
def test_convert_duration_to_nanosecond() -> None:
nanoseconds = convert_duration_to_nanosecond("5s")
assert nanoseconds == 5000000000
nanoseconds = convert_duration_to_nanosecond("1m5s")
assert nanoseconds == 65000000000
with pytest.raises(ValueError):
convert_duration_to_nanosecond([1, 2, 3]) # type: ignore
with pytest.raises(ValueError):
convert_duration_to_nanosecond("10x")
def test_parse_healthcheck() -> None:
result, disabled = parse_healthcheck(
{
"test": "sleep 1",
"interval": "1s",
}
)
assert disabled is False
assert result == {"test": ["CMD-SHELL", "sleep 1"], "interval": 1000000000}
result, disabled = parse_healthcheck(
{
"test": ["NONE"],
}
)
assert result is None
assert disabled
result, disabled = parse_healthcheck({"test": "sleep 1", "interval": "1s423ms"})
assert result == {"test": ["CMD-SHELL", "sleep 1"], "interval": 1423000000}
assert disabled is False
result, disabled = parse_healthcheck(
{"test": "sleep 1", "interval": "1h1m2s3ms4us"}
)
assert result == {"test": ["CMD-SHELL", "sleep 1"], "interval": 3662003004000}
assert disabled is False