1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-07-25 15:36:08 +01:00
Files
supervisor/tests/resolution/evaluation/test_evaluate_os_version.py
T
Stefan Agner ed91b18c4b tests: enable flake8-pytest-style (PT) ruff rules (#6857)
* tests: enable flake8-pytest-style (PT) ruff rules

Enable the `PT` ruff rule set and fix the resulting violations across the
test suite:

- PT006: pass parametrize argument names as tuples instead of a single
  comma-separated string.
- PT022: switch fixtures that have no teardown from `yield` to `return`
  so the lack of cleanup is obvious at a glance.
- PT011: add `match=` to broad `pytest.raises(ValueError)` blocks so the
  expected error is anchored to a specific message.
- PT012: hoist setup (patches, branching) out of `pytest.raises()`
  blocks so only the call that is expected to raise remains inside.
- PT013: replace `from pytest import X` with `import pytest` and access
  attributes via the module.
- PT015: replace `try/except` + `assert False` patterns with
  `pytest.raises(...)`.
- PT017: replace `assert` on exceptions inside `except` blocks with
  `pytest.raises(...) as exc_info` and assert on `exc_info.value`.

No behavioral changes to the tests; the full suite still passes.

* tests: address review feedback on PT ruff rule enablement

- Fix fixture return-type annotations after switching `yield` to `return`
  in tests/conftest.py: drop the `Generator[...]`/`AsyncGenerator[...]`
  wrapper for `dns_manager_service`, `supervisor_internet`, `websession`,
  and `mock_update_data` so the annotation matches what the fixture
  actually returns.
- Correct the return-type annotation of `fixture_ip6config_service` from
  `IP4ConfigService` to `IP6ConfigService`.
- Fix recurring "excepiton" typo in tests/utils/test_exception_helper.py.

* tests: verify backup cleanup on permission error

After `test_new_backup_permission_error` raises `BackupPermissionError`,
assert that no tarfile was left behind and `tmp_path` is empty. The
previous version only checked that the exception was raised, which
missed any regression where a partial tarfile would survive the failed
create.

* tests: rename DNS_GOOD_V6 to DNS_V6_UNSUPPORTED

The constant was named "good" but its tests assert that the URLs are
rejected by the DNS validator. The IPv6 URLs are well-formed but
currently rejected because IPv6 doesn't work with the Docker network
(see `dns_url` in supervisor/validate.py). Rename the constant and the
related test to make the intent obvious.
2026-05-20 22:17:54 +02:00

84 lines
3.1 KiB
Python

"""Test OS Version evaluation."""
from unittest.mock import PropertyMock, patch
from awesomeversion import AwesomeVersion
import pytest
from supervisor.const import CoreState
from supervisor.coresys import CoreSys
from supervisor.os.manager import OSManager
from supervisor.resolution.evaluations.os_version import EvaluateOSVersion
@pytest.mark.parametrize(
("current", "latest", "expected"),
[
("10.0", "15.0", True), # 5 major behind, should be unsupported
("10.0", "14.0", False), # 4 major behind, should be supported
("10.2", "11.0", False), # 1 major behind, supported
("10.4", "10.5", False), # same major, supported
("10.5", "10.5", False), # up to date, supported
("10.5", "10.6", False), # same major, supported
("10.0", "13.3", False), # 3 major behind, supported
("10.2.dev20240321", "15.0", True), # 5 major behind, dev version, unsupported
("10.2.dev20240321", "13.0", False), # 3 major behind, dev version, supported
("10.2.rc2", "15.0", True), # 5 major behind, rc version, unsupported
("10.2.rc2", "13.0", False), # 3 major behind, rc version, supported
(None, "15.0", False), # No current version info, check skipped
("2.0", None, False), # No latest version info, check skipped
(
"9ccda431973acf17e4221850b08f3280b723df8d",
"15.0",
True,
), # Dev setup running on a commit hash, check skipped
],
)
@pytest.mark.usefixtures("os_available")
async def test_os_version_evaluation(
coresys: CoreSys, current: str | None, latest: str | None, expected: bool
):
"""Test evaluation logic on versions."""
evaluation = EvaluateOSVersion(coresys)
await coresys.core.set_state(CoreState.RUNNING)
with (
patch.object(
OSManager,
"version",
new=PropertyMock(return_value=current and AwesomeVersion(current)),
),
patch.object(
OSManager,
"latest_version_unrestricted",
new=PropertyMock(return_value=latest and AwesomeVersion(latest)),
),
):
assert evaluation.reason not in coresys.resolution.unsupported
await evaluation()
assert (evaluation.reason in coresys.resolution.unsupported) is expected
async def test_did_run(coresys: CoreSys):
"""Test that the evaluation ran as expected."""
evaluation = EvaluateOSVersion(coresys)
should_run = evaluation.states
should_not_run = [state for state in CoreState if state not in should_run]
assert len(should_run) != 0
assert len(should_not_run) != 0
with patch(
"supervisor.resolution.evaluations.os_version.EvaluateOSVersion.evaluate",
return_value=None,
) as evaluate:
for state in should_run:
await coresys.core.set_state(state)
await evaluation()
evaluate.assert_called_once()
evaluate.reset_mock()
for state in should_not_run:
await coresys.core.set_state(state)
await evaluation()
evaluate.assert_not_called()
evaluate.reset_mock()