feat: add retry policy

This commit is contained in:
2026-02-20 02:44:32 +02:00
parent dec025b45a
commit 9ec566f095
11 changed files with 196 additions and 63 deletions

View File

@@ -33,6 +33,14 @@ def test_normalize_coerce_boolean(validator: Validator, mocker: MockerFixture) -
convert_mock.assert_called_once_with("1")
def test_normalize_coerce_float(validator: Validator) -> None:
"""
must convert string value to float by using configuration converters
"""
assert validator._normalize_coerce_float("1.5") == 1.5
assert validator._normalize_coerce_float("0.0") == 0.0
def test_normalize_coerce_integer(validator: Validator) -> None:
"""
must convert string value to integer by using configuration converters

View File

@@ -1,6 +1,5 @@
import pytest
import requests
import requests_unixsocket
from pytest_mock import MockerFixture
@@ -8,31 +7,32 @@ from ahriman.core.http import SyncAhrimanClient
from ahriman.models.user import User
def test_session(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
def test_adapters(ahriman_client: SyncAhrimanClient) -> None:
"""
must create normal requests session
must return native adapters
"""
login_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient._login")
assert isinstance(ahriman_client.session, requests.Session)
assert not isinstance(ahriman_client.session, requests_unixsocket.Session)
login_mock.assert_called_once_with(pytest.helpers.anyvar(int))
assert "http+unix://" not in ahriman_client.adapters()
def test_session_unix_socket(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
def test_adapters_unix_socket(ahriman_client: SyncAhrimanClient) -> None:
"""
must create unix socket session
must register unix socket adapter
"""
login_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient._login")
ahriman_client.address = "http+unix://path"
assert isinstance(ahriman_client.session, requests_unixsocket.Session)
login_mock.assert_not_called()
assert "http+unix://" in ahriman_client.adapters()
def test_login(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
def test_login_url(ahriman_client: SyncAhrimanClient) -> None:
"""
must login user
must generate login url correctly
"""
assert ahriman_client._login_url().startswith(ahriman_client.address)
assert ahriman_client._login_url().endswith("/api/v1/login")
def test_start(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
"""
must log in user on start
"""
ahriman_client.auth = (user.username, user.password)
requests_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient.make_request")
@@ -42,40 +42,32 @@ def test_login(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixt
}
session = requests.Session()
ahriman_client._login(session)
ahriman_client.start(session)
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True), json=payload, session=session)
def test_login_failed(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
def test_start_failed(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
"""
must suppress any exception happened during login
must suppress any exception happened during session start
"""
ahriman_client.user = user
mocker.patch("requests.Session.request", side_effect=Exception)
ahriman_client._login(requests.Session())
ahriman_client.start(requests.Session())
def test_login_failed_http_error(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
def test_start_failed_http_error(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
"""
must suppress HTTP exception happened during login
must suppress HTTP exception happened during session start
"""
ahriman_client.user = user
mocker.patch("requests.Session.request", side_effect=requests.HTTPError)
ahriman_client._login(requests.Session())
ahriman_client.start(requests.Session())
def test_login_skip(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
def test_start_skip(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
"""
must skip login if no user set
"""
requests_mock = mocker.patch("requests.Session.request")
ahriman_client._login(requests.Session())
ahriman_client.start(requests.Session())
requests_mock.assert_not_called()
def test_login_url(ahriman_client: SyncAhrimanClient) -> None:
"""
must generate login url correctly
"""
assert ahriman_client._login_url().startswith(ahriman_client.address)
assert ahriman_client._login_url().endswith("/api/v1/login")

View File

@@ -33,12 +33,15 @@ def test_init_auth_empty() -> None:
assert SyncHttpClient().auth is None
def test_session() -> None:
def test_session(mocker: MockerFixture) -> None:
"""
must generate valid session
"""
start_mock = mocker.patch("ahriman.core.http.sync_http_client.SyncHttpClient.start")
session = SyncHttpClient().session
assert "User-Agent" in session.headers
start_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_exception_response_text() -> None:
@@ -60,6 +63,18 @@ def test_exception_response_text_empty() -> None:
assert SyncHttpClient.exception_response_text(exception) == ""
def test_adapters() -> None:
"""
must create adapters with retry policy
"""
client = SyncHttpClient()
adapers = client.adapters()
assert "http://" in adapers
assert "https://" in adapers
assert all(adapter.max_retries == client.retry for adapter in adapers.values())
def test_make_request(mocker: MockerFixture) -> None:
"""
must make HTTP request
@@ -158,3 +173,11 @@ def test_make_request_session() -> None:
session_mock.request.assert_called_once_with(
"GET", "url", params=None, data=None, headers=None, files=None, json=None,
stream=None, auth=None, timeout=client.timeout)
def test_start() -> None:
"""
must do nothing on start
"""
client = SyncHttpClient()
client.start(client.session)