mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-23 18:59:56 +00:00
Remote call trigger support (#105)
* add support of remote task tracking * add remote call trigger implementation * docs update * add cross-service upload * add notes about user * add more ability to control upload * multipart upload with signatures as well as safe file save * configuration reference update * rename watcher methods * erase logs based on current package version Old implementation has used process id instead, but it leads to log removal in case of remote process trigger * add --server flag for setup command * restore behavior of the httploghandler
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
from ahriman.core.database.migrations.m009_local_source import steps
|
||||
|
||||
|
||||
def test_migration_packagers() -> None:
|
||||
def test_migration_local_source() -> None:
|
||||
"""
|
||||
migration must not be empty
|
||||
"""
|
||||
|
@ -0,0 +1,8 @@
|
||||
from ahriman.core.database.migrations.m010_version_based_logs_removal import steps
|
||||
|
||||
|
||||
def test_migration_version_based_logs_removal() -> None:
|
||||
"""
|
||||
migration must not be empty
|
||||
"""
|
||||
assert steps
|
@ -8,11 +8,11 @@ def test_logs_insert_remove_process(database: SQLite, package_ahriman: Package,
|
||||
"""
|
||||
must clear process specific package logs
|
||||
"""
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, 1), 42.0, "message 1")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, 2), 43.0, "message 2")
|
||||
database.logs_insert(LogRecordId(package_python_schedule.base, 1), 42.0, "message 3")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, "2"), 43.0, "message 2")
|
||||
database.logs_insert(LogRecordId(package_python_schedule.base, "1"), 42.0, "message 3")
|
||||
|
||||
database.logs_remove(package_ahriman.base, 1)
|
||||
database.logs_remove(package_ahriman.base, "1")
|
||||
assert database.logs_get(package_ahriman.base) == "[1970-01-01 00:00:42] message 1"
|
||||
assert database.logs_get(package_python_schedule.base) == "[1970-01-01 00:00:42] message 3"
|
||||
|
||||
@ -21,9 +21,9 @@ def test_logs_insert_remove_full(database: SQLite, package_ahriman: Package, pac
|
||||
"""
|
||||
must clear full package logs
|
||||
"""
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, 1), 42.0, "message 1")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, 2), 43.0, "message 2")
|
||||
database.logs_insert(LogRecordId(package_python_schedule.base, 1), 42.0, "message 3")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, "2"), 43.0, "message 2")
|
||||
database.logs_insert(LogRecordId(package_python_schedule.base, "1"), 42.0, "message 3")
|
||||
|
||||
database.logs_remove(package_ahriman.base, None)
|
||||
assert not database.logs_get(package_ahriman.base)
|
||||
@ -34,6 +34,6 @@ def test_logs_insert_get(database: SQLite, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must insert and get package logs
|
||||
"""
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, 1), 43.0, "message 2")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, 1), 42.0, "message 1")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 43.0, "message 2")
|
||||
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
|
||||
assert database.logs_get(package_ahriman.base) == "[1970-01-01 00:00:42] message 1\n[1970-01-01 00:00:43] message 2"
|
||||
|
@ -43,6 +43,33 @@ def test_is_logs_post() -> None:
|
||||
assert not FilteredAccessLogger.is_logs_post(request)
|
||||
|
||||
|
||||
def test_is_process_get() -> None:
|
||||
"""
|
||||
must correctly define if request belongs to process get
|
||||
"""
|
||||
request = MagicMock()
|
||||
|
||||
request.method = "GET"
|
||||
request.path = "/api/v1/service/process/e7d67119-264a-48f4-b7e4-07bc96a7de00"
|
||||
assert FilteredAccessLogger.is_process_get(request)
|
||||
|
||||
request.method = "POST"
|
||||
request.path = "/api/v1/service/process/e7d67119-264a-48f4-b7e4-07bc96a7de00"
|
||||
assert not FilteredAccessLogger.is_process_get(request)
|
||||
|
||||
request.method = "GET"
|
||||
request.path = "/api/v1/service/process/e7d67119-264a-48f4-b7e4-07bc96a7de00/some/random/path"
|
||||
assert not FilteredAccessLogger.is_process_get(request)
|
||||
|
||||
request.method = "GET"
|
||||
request.path = "/api/v1/service/process"
|
||||
assert not FilteredAccessLogger.is_process_get(request)
|
||||
|
||||
request.method = "GET"
|
||||
request.path = "/api/v1/service/process/"
|
||||
assert not FilteredAccessLogger.is_process_get(request)
|
||||
|
||||
|
||||
def test_log(filtered_access_logger: FilteredAccessLogger, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must emit log record
|
||||
|
@ -4,6 +4,7 @@ from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log.http_log_handler import HttpLogHandler
|
||||
from ahriman.models.log_record_id import LogRecordId
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
@ -39,13 +40,13 @@ def test_emit(configuration: Configuration, log_record: logging.LogRecord, packa
|
||||
"""
|
||||
must emit log record to reporter
|
||||
"""
|
||||
log_record.package_base = package_ahriman.base
|
||||
log_mock = mocker.patch("ahriman.core.status.client.Client.logs")
|
||||
log_record_id = log_record.package_id = LogRecordId(package_ahriman.base, package_ahriman.version)
|
||||
log_mock = mocker.patch("ahriman.core.status.client.Client.package_logs")
|
||||
|
||||
handler = HttpLogHandler(configuration, report=False, suppress_errors=False)
|
||||
|
||||
handler.emit(log_record)
|
||||
log_mock.assert_called_once_with(package_ahriman.base, log_record)
|
||||
log_mock.assert_called_once_with(log_record_id, log_record)
|
||||
|
||||
|
||||
def test_emit_failed(configuration: Configuration, log_record: logging.LogRecord, package_ahriman: Package,
|
||||
@ -53,8 +54,8 @@ def test_emit_failed(configuration: Configuration, log_record: logging.LogRecord
|
||||
"""
|
||||
must call handle error on exception
|
||||
"""
|
||||
log_record.package_base = package_ahriman.base
|
||||
mocker.patch("ahriman.core.status.client.Client.logs", side_effect=Exception())
|
||||
log_record.package_id = LogRecordId(package_ahriman.base, package_ahriman.version)
|
||||
mocker.patch("ahriman.core.status.client.Client.package_logs", side_effect=Exception())
|
||||
handle_error_mock = mocker.patch("logging.Handler.handleError")
|
||||
handler = HttpLogHandler(configuration, report=False, suppress_errors=False)
|
||||
|
||||
@ -67,8 +68,8 @@ def test_emit_suppress_failed(configuration: Configuration, log_record: logging.
|
||||
"""
|
||||
must not call handle error on exception if suppress flag is set
|
||||
"""
|
||||
log_record.package_base = package_ahriman.base
|
||||
mocker.patch("ahriman.core.status.client.Client.logs", side_effect=Exception())
|
||||
log_record.package_id = LogRecordId(package_ahriman.base, package_ahriman.version)
|
||||
mocker.patch("ahriman.core.status.client.Client.package_logs", side_effect=Exception())
|
||||
handle_error_mock = mocker.patch("logging.Handler.handleError")
|
||||
handler = HttpLogHandler(configuration, report=False, suppress_errors=True)
|
||||
|
||||
@ -80,7 +81,7 @@ def test_emit_skip(configuration: Configuration, log_record: logging.LogRecord,
|
||||
"""
|
||||
must skip log record posting if no package base set
|
||||
"""
|
||||
log_mock = mocker.patch("ahriman.core.status.client.Client.logs")
|
||||
log_mock = mocker.patch("ahriman.core.status.client.Client.package_logs")
|
||||
handler = HttpLogHandler(configuration, report=False, suppress_errors=False)
|
||||
|
||||
handler.emit(log_record)
|
||||
|
@ -5,6 +5,7 @@ from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.core.alpm.repo import Repo
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.models.log_record_id import LogRecordId
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
@ -20,16 +21,16 @@ def test_package_logger_set_reset(database: SQLite) -> None:
|
||||
"""
|
||||
must set and reset package base attribute
|
||||
"""
|
||||
package_base = "package base"
|
||||
log_record_id = LogRecordId("base", "version")
|
||||
|
||||
database._package_logger_set(package_base)
|
||||
database._package_logger_set(log_record_id.package_base, log_record_id.version)
|
||||
record = logging.makeLogRecord({})
|
||||
assert record.package_base == package_base
|
||||
assert record.package_id == log_record_id
|
||||
|
||||
database._package_logger_reset()
|
||||
record = logging.makeLogRecord({})
|
||||
with pytest.raises(AttributeError):
|
||||
record.package_base
|
||||
record.package_id
|
||||
|
||||
|
||||
def test_in_package_context(database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
@ -39,10 +40,24 @@ def test_in_package_context(database: SQLite, package_ahriman: Package, mocker:
|
||||
set_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_set")
|
||||
reset_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_reset")
|
||||
|
||||
with database.in_package_context(package_ahriman.base):
|
||||
with database.in_package_context(package_ahriman.base, package_ahriman.version):
|
||||
pass
|
||||
|
||||
set_mock.assert_called_once_with(package_ahriman.base)
|
||||
set_mock.assert_called_once_with(package_ahriman.base, package_ahriman.version)
|
||||
reset_mock.assert_called_once_with()
|
||||
|
||||
|
||||
def test_in_package_context_empty_version(database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set package log context
|
||||
"""
|
||||
set_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_set")
|
||||
reset_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_reset")
|
||||
|
||||
with database.in_package_context(package_ahriman.base, None):
|
||||
pass
|
||||
|
||||
set_mock.assert_called_once_with(package_ahriman.base, None)
|
||||
reset_mock.assert_called_once_with()
|
||||
|
||||
|
||||
@ -54,7 +69,7 @@ def test_in_package_context_failed(database: SQLite, package_ahriman: Package, m
|
||||
reset_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_reset")
|
||||
|
||||
with pytest.raises(Exception):
|
||||
with database.in_package_context(package_ahriman.base):
|
||||
with database.in_package_context(package_ahriman.base, ""):
|
||||
raise Exception()
|
||||
|
||||
reset_mock.assert_called_once_with()
|
||||
|
20
tests/ahriman/core/report/conftest.py
Normal file
20
tests/ahriman/core/report/conftest.py
Normal file
@ -0,0 +1,20 @@
|
||||
import pytest
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.report.remote_call import RemoteCall
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def remote_call(configuration: Configuration) -> RemoteCall:
|
||||
"""
|
||||
fixture for remote update trigger
|
||||
|
||||
Args:
|
||||
configuration(Configuration): configuration fixture
|
||||
|
||||
Returns:
|
||||
RemoteCall: remote update trigger test instance
|
||||
"""
|
||||
configuration.set_option("web", "host", "localhost")
|
||||
configuration.set_option("web", "port", "8080")
|
||||
return RemoteCall("x86_64", configuration, "remote-call")
|
95
tests/ahriman/core/report/test_remote_call.py
Normal file
95
tests/ahriman/core/report/test_remote_call.py
Normal file
@ -0,0 +1,95 @@
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.core.report.remote_call import RemoteCall
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
def test_generate(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly call client
|
||||
"""
|
||||
update_mock = mocker.patch("ahriman.core.report.remote_call.RemoteCall.remote_update", return_value="id")
|
||||
wait_mock = mocker.patch("ahriman.core.report.remote_call.RemoteCall.remote_wait")
|
||||
|
||||
remote_call.generate([], Result())
|
||||
update_mock.assert_called_once_with()
|
||||
wait_mock.assert_called_once_with("id")
|
||||
|
||||
|
||||
def test_is_process_alive(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly define if process is alive
|
||||
"""
|
||||
response_obj = requests.Response()
|
||||
response_obj._content = """{"is_alive": true}""".encode("utf8")
|
||||
response_obj.status_code = 200
|
||||
|
||||
request_mock = mocker.patch("ahriman.core.status.web_client.WebClient.make_request", return_value=response_obj)
|
||||
|
||||
assert remote_call.is_process_alive("id")
|
||||
request_mock.assert_called_once_with("GET", "/api/v1/service/process/id")
|
||||
|
||||
|
||||
def test_is_process_alive_unknown(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly define if process is unknown
|
||||
"""
|
||||
response = requests.Response()
|
||||
response.status_code = 404
|
||||
mocker.patch("ahriman.core.status.web_client.WebClient.make_request",
|
||||
side_effect=requests.RequestException(response=response))
|
||||
|
||||
assert not remote_call.is_process_alive("id")
|
||||
|
||||
|
||||
def test_is_process_alive_error(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must reraise exception on process request
|
||||
"""
|
||||
mocker.patch("ahriman.core.status.web_client.WebClient.make_request", side_effect=Exception)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
remote_call.is_process_alive("id")
|
||||
|
||||
|
||||
def test_is_process_alive_http_error(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must reraise http exception on process request
|
||||
"""
|
||||
response = requests.Response()
|
||||
response.status_code = 500
|
||||
mocker.patch("ahriman.core.status.web_client.WebClient.make_request",
|
||||
side_effect=requests.RequestException(response=response))
|
||||
|
||||
with pytest.raises(requests.RequestException):
|
||||
remote_call.is_process_alive("id")
|
||||
|
||||
|
||||
def test_remote_update(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call remote server for update process
|
||||
"""
|
||||
response_obj = requests.Response()
|
||||
response_obj._content = """{"process_id": "id"}""".encode("utf8")
|
||||
response_obj.status_code = 200
|
||||
|
||||
request_mock = mocker.patch("ahriman.core.status.web_client.WebClient.make_request", return_value=response_obj)
|
||||
|
||||
assert remote_call.remote_update() == "id"
|
||||
request_mock.assert_called_once_with("POST", "/api/v1/service/update", json={
|
||||
"aur": False,
|
||||
"local": False,
|
||||
"manual": True,
|
||||
})
|
||||
|
||||
|
||||
def test_remote_wait(remote_call: RemoteCall, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must wait for remote process to success
|
||||
"""
|
||||
wait_mock = mocker.patch("ahriman.models.waiter.Waiter.wait")
|
||||
remote_call.remote_wait("id")
|
||||
wait_mock.assert_called_once_with(pytest.helpers.anyvar(int), "id")
|
@ -24,6 +24,7 @@ def test_report_dummy(configuration: Configuration, result: Result, mocker: Mock
|
||||
"""
|
||||
mocker.patch("ahriman.models.report_settings.ReportSettings.from_option", return_value=ReportSettings.Disabled)
|
||||
report_mock = mocker.patch("ahriman.core.report.report.Report.generate")
|
||||
|
||||
Report.load("x86_64", configuration, "disabled").run(result, [])
|
||||
report_mock.assert_called_once_with([], result)
|
||||
|
||||
@ -55,6 +56,18 @@ def test_report_html(configuration: Configuration, result: Result, mocker: Mocke
|
||||
report_mock.assert_called_once_with([], result)
|
||||
|
||||
|
||||
def test_report_remote_call(configuration: Configuration, result: Result, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must instantiate remote call trigger
|
||||
"""
|
||||
configuration.set_option("web", "host", "localhost")
|
||||
configuration.set_option("web", "port", "8080")
|
||||
report_mock = mocker.patch("ahriman.core.report.remote_call.RemoteCall.generate")
|
||||
|
||||
Report.load("x86_64", configuration, "remote-call").run(result, [])
|
||||
report_mock.assert_called_once_with([], result)
|
||||
|
||||
|
||||
def test_report_telegram(configuration: Configuration, result: Result, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate telegram report
|
||||
|
@ -85,7 +85,7 @@ def test_process_remove_base(executor: Executor, package_ahriman: Package, mocke
|
||||
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_clear")
|
||||
patches_mock = mocker.patch("ahriman.core.database.SQLite.patches_remove")
|
||||
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.package_remove")
|
||||
|
||||
executor.process_remove([package_ahriman.base])
|
||||
# must remove via alpm wrapper
|
||||
@ -106,7 +106,7 @@ def test_process_remove_base_multiple(executor: Executor, package_python_schedul
|
||||
"""
|
||||
mocker.patch("ahriman.core.repository.executor.Executor.packages", return_value=[package_python_schedule])
|
||||
repo_remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.package_remove")
|
||||
|
||||
executor.process_remove([package_python_schedule.base])
|
||||
# must remove via alpm wrapper
|
||||
@ -125,7 +125,7 @@ def test_process_remove_base_single(executor: Executor, package_python_schedule:
|
||||
"""
|
||||
mocker.patch("ahriman.core.repository.executor.Executor.packages", return_value=[package_python_schedule])
|
||||
repo_remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.package_remove")
|
||||
|
||||
executor.process_remove(["python2-schedule"])
|
||||
# must remove via alpm wrapper
|
||||
@ -171,7 +171,7 @@ def test_process_remove_unknown(executor: Executor, package_ahriman: Package, mo
|
||||
"""
|
||||
mocker.patch("ahriman.core.repository.executor.Executor.packages", return_value=[])
|
||||
repo_remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.package_remove")
|
||||
|
||||
executor.process_remove([package_ahriman.base])
|
||||
repo_remove_mock.assert_not_called()
|
||||
|
@ -76,6 +76,13 @@ def test_sign_options(configuration: Configuration) -> None:
|
||||
assert default_key == "default-key"
|
||||
|
||||
|
||||
def test_signature() -> None:
|
||||
"""
|
||||
must correctly generate the signature path
|
||||
"""
|
||||
assert GPG.signature(Path("path") / "to" / "package.tar.xz") == Path("path") / "to" / "package.tar.xz.sig"
|
||||
|
||||
|
||||
def test_key_download(gpg: GPG, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must download the key from public server
|
||||
@ -222,6 +229,18 @@ def test_process_sign_package_skip_4(gpg: GPG, mocker: MockerFixture) -> None:
|
||||
process_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_process_sign_package_skip_already_signed(gpg_with_key: GPG, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not sign package if it was already signed
|
||||
"""
|
||||
result = [Path("a"), Path("a.sig")]
|
||||
mocker.patch("pathlib.Path.is_file", return_value=True)
|
||||
process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process")
|
||||
|
||||
assert gpg_with_key.process_sign_package(Path("a"), gpg_with_key.default_key) == result
|
||||
process_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_process_sign_repository_1(gpg_with_key: GPG, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must sign repository
|
||||
|
@ -7,6 +7,7 @@ from ahriman.core.status.client import Client
|
||||
from ahriman.core.status.web_client import WebClient
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
from ahriman.models.internal_status import InternalStatus
|
||||
from ahriman.models.log_record_id import LogRecordId
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
@ -51,64 +52,47 @@ def test_load_full_client_from_unix_socket(configuration: Configuration) -> None
|
||||
assert isinstance(Client.load(configuration, report=True), WebClient)
|
||||
|
||||
|
||||
def test_add(client: Client, package_ahriman: Package) -> None:
|
||||
def test_package_add(client: Client, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must process package addition without errors
|
||||
"""
|
||||
client.add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
client.package_add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_get(client: Client, package_ahriman: Package) -> None:
|
||||
def test_package_get(client: Client, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must return empty package list
|
||||
"""
|
||||
assert client.get(package_ahriman.base) == []
|
||||
assert client.get(None) == []
|
||||
assert client.package_get(package_ahriman.base) == []
|
||||
assert client.package_get(None) == []
|
||||
|
||||
|
||||
def test_get_internal(client: Client) -> None:
|
||||
"""
|
||||
must return dummy status for web service
|
||||
"""
|
||||
actual = client.get_internal()
|
||||
expected = InternalStatus(status=BuildStatus(timestamp=actual.status.timestamp))
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_log(client: Client, package_ahriman: Package, log_record: logging.LogRecord) -> None:
|
||||
def test_package_logs(client: Client, package_ahriman: Package, log_record: logging.LogRecord) -> None:
|
||||
"""
|
||||
must process log record without errors
|
||||
"""
|
||||
client.logs(package_ahriman.base, log_record)
|
||||
client.package_logs(LogRecordId(package_ahriman.base, package_ahriman.version), log_record)
|
||||
|
||||
|
||||
def test_remove(client: Client, package_ahriman: Package) -> None:
|
||||
def test_package_remove(client: Client, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must process remove without errors
|
||||
"""
|
||||
client.remove(package_ahriman.base)
|
||||
client.package_remove(package_ahriman.base)
|
||||
|
||||
|
||||
def test_update(client: Client, package_ahriman: Package) -> None:
|
||||
def test_package_update(client: Client, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must update package status without errors
|
||||
"""
|
||||
client.update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_update_self(client: Client) -> None:
|
||||
"""
|
||||
must update self status without errors
|
||||
"""
|
||||
client.update_self(BuildStatusEnum.Unknown)
|
||||
client.package_update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_set_building(client: Client, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set building status to the package
|
||||
"""
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.update")
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.package_update")
|
||||
client.set_building(package_ahriman.base)
|
||||
|
||||
update_mock.assert_called_once_with(package_ahriman.base, BuildStatusEnum.Building)
|
||||
@ -118,7 +102,7 @@ def test_set_failed(client: Client, package_ahriman: Package, mocker: MockerFixt
|
||||
"""
|
||||
must set failed status to the package
|
||||
"""
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.update")
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.package_update")
|
||||
client.set_failed(package_ahriman.base)
|
||||
|
||||
update_mock.assert_called_once_with(package_ahriman.base, BuildStatusEnum.Failed)
|
||||
@ -128,7 +112,7 @@ def test_set_pending(client: Client, package_ahriman: Package, mocker: MockerFix
|
||||
"""
|
||||
must set building status to the package
|
||||
"""
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.update")
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.package_update")
|
||||
client.set_pending(package_ahriman.base)
|
||||
|
||||
update_mock.assert_called_once_with(package_ahriman.base, BuildStatusEnum.Pending)
|
||||
@ -138,7 +122,7 @@ def test_set_success(client: Client, package_ahriman: Package, mocker: MockerFix
|
||||
"""
|
||||
must set success status to the package
|
||||
"""
|
||||
add_mock = mocker.patch("ahriman.core.status.client.Client.add")
|
||||
add_mock = mocker.patch("ahriman.core.status.client.Client.package_add")
|
||||
client.set_success(package_ahriman)
|
||||
|
||||
add_mock.assert_called_once_with(package_ahriman, BuildStatusEnum.Success)
|
||||
@ -148,7 +132,24 @@ def test_set_unknown(client: Client, package_ahriman: Package, mocker: MockerFix
|
||||
"""
|
||||
must add new package with unknown status
|
||||
"""
|
||||
add_mock = mocker.patch("ahriman.core.status.client.Client.add")
|
||||
add_mock = mocker.patch("ahriman.core.status.client.Client.package_add")
|
||||
client.set_unknown(package_ahriman)
|
||||
|
||||
add_mock.assert_called_once_with(package_ahriman, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_status_get(client: Client) -> None:
|
||||
"""
|
||||
must return dummy status for web service
|
||||
"""
|
||||
actual = client.status_get()
|
||||
expected = InternalStatus(status=BuildStatus(timestamp=actual.status.timestamp))
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_status_update(client: Client) -> None:
|
||||
"""
|
||||
must update self status without errors
|
||||
"""
|
||||
client.status_update(BuildStatusEnum.Unknown)
|
||||
|
@ -22,33 +22,6 @@ def test_force_no_report(configuration: Configuration, database: SQLite, mocker:
|
||||
load_mock.assert_called_once_with("x86_64", configuration, database, report=False)
|
||||
|
||||
|
||||
def test_get(watcher: Watcher, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must return package status
|
||||
"""
|
||||
watcher.known = {package_ahriman.base: (package_ahriman, BuildStatus())}
|
||||
package, status = watcher.get(package_ahriman.base)
|
||||
assert package == package_ahriman
|
||||
assert status.status == BuildStatusEnum.Unknown
|
||||
|
||||
|
||||
def test_get_failed(watcher: Watcher, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must fail on unknown package
|
||||
"""
|
||||
with pytest.raises(UnknownPackageError):
|
||||
watcher.get(package_ahriman.base)
|
||||
|
||||
|
||||
def test_get_logs(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return package logs
|
||||
"""
|
||||
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_get")
|
||||
watcher.get_logs(package_ahriman.base)
|
||||
logs_mock.assert_called_once_with(package_ahriman.base)
|
||||
|
||||
|
||||
def test_load(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly load packages
|
||||
@ -77,109 +50,136 @@ def test_load_known(watcher: Watcher, package_ahriman: Package, mocker: MockerFi
|
||||
assert status.status == BuildStatusEnum.Success
|
||||
|
||||
|
||||
def test_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_logs_get(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return package logs
|
||||
"""
|
||||
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_get")
|
||||
watcher.logs_get(package_ahriman.base)
|
||||
logs_mock.assert_called_once_with(package_ahriman.base)
|
||||
|
||||
|
||||
def test_logs_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must remove package logs
|
||||
"""
|
||||
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_remove")
|
||||
watcher.logs_remove(package_ahriman.base, "42")
|
||||
logs_mock.assert_called_once_with(package_ahriman.base, "42")
|
||||
|
||||
|
||||
def test_logs_update_new(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create package logs record for new package
|
||||
"""
|
||||
delete_mock = mocker.patch("ahriman.core.status.watcher.Watcher.logs_remove")
|
||||
insert_mock = mocker.patch("ahriman.core.database.SQLite.logs_insert")
|
||||
|
||||
log_record_id = LogRecordId(package_ahriman.base, watcher._last_log_record_id.version)
|
||||
assert watcher._last_log_record_id != log_record_id
|
||||
|
||||
watcher.logs_update(log_record_id, 42.01, "log record")
|
||||
delete_mock.assert_called_once_with(package_ahriman.base, log_record_id.version)
|
||||
insert_mock.assert_called_once_with(log_record_id, 42.01, "log record")
|
||||
|
||||
assert watcher._last_log_record_id == log_record_id
|
||||
|
||||
|
||||
def test_logs_update_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create package logs record for current package
|
||||
"""
|
||||
delete_mock = mocker.patch("ahriman.core.status.watcher.Watcher.logs_remove")
|
||||
insert_mock = mocker.patch("ahriman.core.database.SQLite.logs_insert")
|
||||
|
||||
log_record_id = LogRecordId(package_ahriman.base, watcher._last_log_record_id.version)
|
||||
watcher._last_log_record_id = log_record_id
|
||||
|
||||
watcher.logs_update(log_record_id, 42.01, "log record")
|
||||
delete_mock.assert_not_called()
|
||||
insert_mock.assert_called_once_with(log_record_id, 42.01, "log record")
|
||||
|
||||
|
||||
def test_package_get(watcher: Watcher, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must return package status
|
||||
"""
|
||||
watcher.known = {package_ahriman.base: (package_ahriman, BuildStatus())}
|
||||
package, status = watcher.package_get(package_ahriman.base)
|
||||
assert package == package_ahriman
|
||||
assert status.status == BuildStatusEnum.Unknown
|
||||
|
||||
|
||||
def test_package_get_failed(watcher: Watcher, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must fail on unknown package
|
||||
"""
|
||||
with pytest.raises(UnknownPackageError):
|
||||
watcher.package_get(package_ahriman.base)
|
||||
|
||||
|
||||
def test_package_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must remove package base
|
||||
"""
|
||||
cache_mock = mocker.patch("ahriman.core.database.SQLite.package_remove")
|
||||
logs_mock = mocker.patch("ahriman.core.status.watcher.Watcher.remove_logs")
|
||||
logs_mock = mocker.patch("ahriman.core.status.watcher.Watcher.logs_remove")
|
||||
watcher.known = {package_ahriman.base: (package_ahriman, BuildStatus())}
|
||||
|
||||
watcher.remove(package_ahriman.base)
|
||||
watcher.package_remove(package_ahriman.base)
|
||||
assert not watcher.known
|
||||
cache_mock.assert_called_once_with(package_ahriman.base)
|
||||
logs_mock.assert_called_once_with(package_ahriman.base, None)
|
||||
|
||||
|
||||
def test_remove_logs(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must remove package logs
|
||||
"""
|
||||
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_remove")
|
||||
watcher.remove_logs(package_ahriman.base, 42)
|
||||
logs_mock.assert_called_once_with(package_ahriman.base, 42)
|
||||
|
||||
|
||||
def test_remove_unknown(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_remove_unknown(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not fail on unknown base removal
|
||||
"""
|
||||
cache_mock = mocker.patch("ahriman.core.database.SQLite.package_remove")
|
||||
|
||||
watcher.remove(package_ahriman.base)
|
||||
watcher.package_remove(package_ahriman.base)
|
||||
cache_mock.assert_called_once_with(package_ahriman.base)
|
||||
|
||||
|
||||
def test_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must update package status
|
||||
"""
|
||||
cache_mock = mocker.patch("ahriman.core.database.SQLite.package_update")
|
||||
|
||||
watcher.update(package_ahriman.base, BuildStatusEnum.Unknown, package_ahriman)
|
||||
watcher.package_update(package_ahriman.base, BuildStatusEnum.Unknown, package_ahriman)
|
||||
cache_mock.assert_called_once_with(package_ahriman, pytest.helpers.anyvar(int))
|
||||
package, status = watcher.known[package_ahriman.base]
|
||||
assert package == package_ahriman
|
||||
assert status.status == BuildStatusEnum.Unknown
|
||||
|
||||
|
||||
def test_update_ping(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_update_ping(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must update package status only for known package
|
||||
"""
|
||||
cache_mock = mocker.patch("ahriman.core.database.SQLite.package_update")
|
||||
watcher.known = {package_ahriman.base: (package_ahriman, BuildStatus())}
|
||||
|
||||
watcher.update(package_ahriman.base, BuildStatusEnum.Success, None)
|
||||
watcher.package_update(package_ahriman.base, BuildStatusEnum.Success, None)
|
||||
cache_mock.assert_called_once_with(package_ahriman, pytest.helpers.anyvar(int))
|
||||
package, status = watcher.known[package_ahriman.base]
|
||||
assert package == package_ahriman
|
||||
assert status.status == BuildStatusEnum.Success
|
||||
|
||||
|
||||
def test_update_unknown(watcher: Watcher, package_ahriman: Package) -> None:
|
||||
def test_package_update_unknown(watcher: Watcher, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must fail on unknown package status update only
|
||||
"""
|
||||
with pytest.raises(UnknownPackageError):
|
||||
watcher.update(package_ahriman.base, BuildStatusEnum.Unknown, None)
|
||||
watcher.package_update(package_ahriman.base, BuildStatusEnum.Unknown, None)
|
||||
|
||||
|
||||
def test_update_logs_new(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create package logs record for new package
|
||||
"""
|
||||
delete_mock = mocker.patch("ahriman.core.status.watcher.Watcher.remove_logs")
|
||||
insert_mock = mocker.patch("ahriman.core.database.SQLite.logs_insert")
|
||||
|
||||
log_record_id = LogRecordId(package_ahriman.base, watcher._last_log_record_id.process_id)
|
||||
assert watcher._last_log_record_id != log_record_id
|
||||
|
||||
watcher.update_logs(log_record_id, 42.01, "log record")
|
||||
delete_mock.assert_called_once_with(package_ahriman.base, log_record_id.process_id)
|
||||
insert_mock.assert_called_once_with(log_record_id, 42.01, "log record")
|
||||
|
||||
assert watcher._last_log_record_id == log_record_id
|
||||
|
||||
|
||||
def test_update_logs_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create package logs record for current package
|
||||
"""
|
||||
delete_mock = mocker.patch("ahriman.core.status.watcher.Watcher.remove_logs")
|
||||
insert_mock = mocker.patch("ahriman.core.database.SQLite.logs_insert")
|
||||
|
||||
log_record_id = LogRecordId(package_ahriman.base, watcher._last_log_record_id.process_id)
|
||||
watcher._last_log_record_id = log_record_id
|
||||
|
||||
watcher.update_logs(log_record_id, 42.01, "log record")
|
||||
delete_mock.assert_not_called()
|
||||
insert_mock.assert_called_once_with(log_record_id, 42.01, "log record")
|
||||
|
||||
|
||||
def test_update_self(watcher: Watcher) -> None:
|
||||
def test_status_update(watcher: Watcher) -> None:
|
||||
"""
|
||||
must update service status
|
||||
"""
|
||||
watcher.update_self(BuildStatusEnum.Success)
|
||||
watcher.status_update(BuildStatusEnum.Success)
|
||||
assert watcher.status.status == BuildStatusEnum.Success
|
||||
|
@ -5,12 +5,13 @@ import requests
|
||||
import requests_unixsocket
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
from requests import Response
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.status.web_client import WebClient
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
from ahriman.models.internal_status import InternalStatus
|
||||
from ahriman.models.log_record_id import LogRecordId
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.user import User
|
||||
|
||||
@ -19,7 +20,6 @@ def test_login_url(web_client: WebClient) -> None:
|
||||
"""
|
||||
must generate login url correctly
|
||||
"""
|
||||
assert web_client._login_url.startswith(web_client.address)
|
||||
assert web_client._login_url.endswith("/api/v1/login")
|
||||
|
||||
|
||||
@ -27,10 +27,24 @@ def test_status_url(web_client: WebClient) -> None:
|
||||
"""
|
||||
must generate package status url correctly
|
||||
"""
|
||||
assert web_client._status_url.startswith(web_client.address)
|
||||
assert web_client._status_url.endswith("/api/v1/status")
|
||||
|
||||
|
||||
def test_logs_url(web_client: WebClient, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must generate logs url correctly
|
||||
"""
|
||||
assert web_client._logs_url(package_ahriman.base).endswith(f"/api/v1/packages/{package_ahriman.base}/logs")
|
||||
|
||||
|
||||
def test_package_url(web_client: WebClient, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must generate package status url correctly
|
||||
"""
|
||||
assert web_client._package_url("").endswith("/api/v1/packages")
|
||||
assert web_client._package_url(package_ahriman.base).endswith(f"/api/v1/packages/{package_ahriman.base}")
|
||||
|
||||
|
||||
def test_parse_address(configuration: Configuration) -> None:
|
||||
"""
|
||||
must extract address correctly
|
||||
@ -74,14 +88,15 @@ def test_login(web_client: WebClient, user: User, mocker: MockerFixture) -> None
|
||||
must login user
|
||||
"""
|
||||
web_client.user = user
|
||||
requests_mock = mocker.patch("requests.Session.post")
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
payload = {
|
||||
"username": user.username,
|
||||
"password": user.password
|
||||
}
|
||||
|
||||
web_client._login(requests.Session())
|
||||
requests_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), json=payload)
|
||||
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True),
|
||||
params=None, json=payload, files=None)
|
||||
|
||||
|
||||
def test_login_failed(web_client: WebClient, user: User, mocker: MockerFixture) -> None:
|
||||
@ -89,7 +104,7 @@ def test_login_failed(web_client: WebClient, user: User, mocker: MockerFixture)
|
||||
must suppress any exception happened during login
|
||||
"""
|
||||
web_client.user = user
|
||||
mocker.patch("requests.Session.post", side_effect=Exception())
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
web_client._login(requests.Session())
|
||||
|
||||
|
||||
@ -98,7 +113,7 @@ def test_login_failed_http_error(web_client: WebClient, user: User, mocker: Mock
|
||||
must suppress HTTP exception happened during login
|
||||
"""
|
||||
web_client.user = user
|
||||
mocker.patch("requests.Session.post", side_effect=requests.exceptions.HTTPError())
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
web_client._login(requests.Session())
|
||||
|
||||
|
||||
@ -106,265 +121,310 @@ def test_login_skip(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must skip login if no user set
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.post")
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
web_client._login(requests.Session())
|
||||
requests_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_logs_url(web_client: WebClient, package_ahriman: Package) -> None:
|
||||
def test_make_request(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate logs url correctly
|
||||
must make HTTP request
|
||||
"""
|
||||
assert web_client._logs_url(package_ahriman.base).startswith(web_client.address)
|
||||
assert web_client._logs_url(package_ahriman.base).endswith(f"/api/v1/packages/{package_ahriman.base}/logs")
|
||||
request_mock = mocker.patch("requests.Session.request")
|
||||
|
||||
assert web_client.make_request("GET", "/url1") is not None
|
||||
assert web_client.make_request("GET", "/url2", params=[("param", "value")]) is not None
|
||||
|
||||
assert web_client.make_request("POST", "/url3") is not None
|
||||
assert web_client.make_request("POST", "/url4", json={"param": "value"}) is not None
|
||||
# we don't want to put full descriptor here
|
||||
assert web_client.make_request("POST", "/url5", files={"file": "tuple"}) is not None
|
||||
|
||||
assert web_client.make_request("DELETE", "/url6") is not None
|
||||
|
||||
request_mock.assert_has_calls([
|
||||
MockCall("GET", f"{web_client.address}/url1", params=None, json=None, files=None),
|
||||
MockCall().raise_for_status(),
|
||||
MockCall("GET", f"{web_client.address}/url2", params=[("param", "value")], json=None, files=None),
|
||||
MockCall().raise_for_status(),
|
||||
MockCall("POST", f"{web_client.address}/url3", params=None, json=None, files=None),
|
||||
MockCall().raise_for_status(),
|
||||
MockCall("POST", f"{web_client.address}/url4", params=None, json={"param": "value"}, files=None),
|
||||
MockCall().raise_for_status(),
|
||||
MockCall("POST", f"{web_client.address}/url5", params=None, json=None, files={"file": "tuple"}),
|
||||
MockCall().raise_for_status(),
|
||||
MockCall("DELETE", f"{web_client.address}/url6", params=None, json=None, files=None),
|
||||
MockCall().raise_for_status(),
|
||||
])
|
||||
|
||||
|
||||
def test_package_url(web_client: WebClient, package_ahriman: Package) -> None:
|
||||
def test_make_request_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate package status url correctly
|
||||
must make HTTP request
|
||||
"""
|
||||
assert web_client._package_url("").startswith(web_client.address)
|
||||
assert web_client._package_url("").endswith(f"/api/v1/packages")
|
||||
|
||||
assert web_client._package_url(package_ahriman.base).startswith(web_client.address)
|
||||
assert web_client._package_url(package_ahriman.base).endswith(f"/api/v1/packages/{package_ahriman.base}")
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
with pytest.raises(Exception):
|
||||
web_client.make_request("GET", "url")
|
||||
|
||||
|
||||
def test_add(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_add(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process package addition
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.post")
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
payload = pytest.helpers.get_package_status(package_ahriman)
|
||||
|
||||
web_client.add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
requests_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), json=payload)
|
||||
web_client.package_add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True),
|
||||
params=None, json=payload, files=None)
|
||||
|
||||
|
||||
def test_add_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_add_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during addition
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=Exception())
|
||||
web_client.add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
web_client.package_add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_add_failed_http_error(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_add_failed_http_error(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during addition
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.package_add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_add_failed_suppress(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_add_failed_suppress(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during addition and don't log
|
||||
"""
|
||||
web_client.suppress_errors = True
|
||||
mocker.patch("requests.Session.post", side_effect=Exception())
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
logging_mock = mocker.patch("logging.exception")
|
||||
|
||||
web_client.add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
web_client.package_add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
logging_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_add_failed_http_error_suppress(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_add_failed_http_error_suppress(web_client: WebClient, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during addition and don't log
|
||||
"""
|
||||
web_client.suppress_errors = True
|
||||
mocker.patch("requests.Session.post", side_effect=requests.exceptions.HTTPError())
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
logging_mock = mocker.patch("logging.exception")
|
||||
|
||||
web_client.add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
web_client.package_add(package_ahriman, BuildStatusEnum.Unknown)
|
||||
logging_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_get_all(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_get_all(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return all packages status
|
||||
"""
|
||||
response = [pytest.helpers.get_package_status_extended(package_ahriman)]
|
||||
response_obj = Response()
|
||||
response_obj = requests.Response()
|
||||
response_obj._content = json.dumps(response).encode("utf8")
|
||||
response_obj.status_code = 200
|
||||
|
||||
requests_mock = mocker.patch("requests.Session.get", return_value=response_obj)
|
||||
requests_mock = mocker.patch("requests.Session.request", return_value=response_obj)
|
||||
|
||||
result = web_client.get(None)
|
||||
requests_mock.assert_called_once_with(web_client._package_url())
|
||||
result = web_client.package_get(None)
|
||||
requests_mock.assert_called_once_with("GET", f"{web_client.address}{web_client._package_url()}",
|
||||
params=None, json=None, files=None)
|
||||
assert len(result) == len(response)
|
||||
assert (package_ahriman, BuildStatusEnum.Unknown) in [(package, status.status) for package, status in result]
|
||||
|
||||
|
||||
def test_get_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_package_get_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during status getting
|
||||
"""
|
||||
mocker.patch("requests.Session.get", side_effect=Exception())
|
||||
assert web_client.get(None) == []
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
assert web_client.package_get(None) == []
|
||||
|
||||
|
||||
def test_get_failed_http_error(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_package_get_failed_http_error(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during status getting
|
||||
"""
|
||||
mocker.patch("requests.Session.get", side_effect=requests.exceptions.HTTPError())
|
||||
assert web_client.get(None) == []
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
assert web_client.package_get(None) == []
|
||||
|
||||
|
||||
def test_get_single(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
def test_package_get_single(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return single package status
|
||||
"""
|
||||
response = [pytest.helpers.get_package_status_extended(package_ahriman)]
|
||||
response_obj = Response()
|
||||
response_obj = requests.Response()
|
||||
response_obj._content = json.dumps(response).encode("utf8")
|
||||
response_obj.status_code = 200
|
||||
|
||||
requests_mock = mocker.patch("requests.Session.get", return_value=response_obj)
|
||||
requests_mock = mocker.patch("requests.Session.request", return_value=response_obj)
|
||||
|
||||
result = web_client.get(package_ahriman.base)
|
||||
requests_mock.assert_called_once_with(web_client._package_url(package_ahriman.base))
|
||||
result = web_client.package_get(package_ahriman.base)
|
||||
requests_mock.assert_called_once_with("GET",
|
||||
f"{web_client.address}{web_client._package_url(package_ahriman.base)}",
|
||||
params=None, json=None, files=None)
|
||||
assert len(result) == len(response)
|
||||
assert (package_ahriman, BuildStatusEnum.Unknown) in [(package, status.status) for package, status in result]
|
||||
|
||||
|
||||
def test_get_internal(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_package_logs(web_client: WebClient, log_record: logging.LogRecord, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process log record
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
payload = {
|
||||
"created": log_record.created,
|
||||
"message": log_record.getMessage(),
|
||||
"version": package_ahriman.version,
|
||||
}
|
||||
|
||||
web_client.package_logs(LogRecordId(package_ahriman.base, package_ahriman.version), log_record)
|
||||
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True),
|
||||
params=None, json=payload, files=None)
|
||||
|
||||
|
||||
def test_package_logs_failed(web_client: WebClient, log_record: logging.LogRecord, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must pass exception during log post
|
||||
"""
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
log_record.package_base = package_ahriman.base
|
||||
with pytest.raises(Exception):
|
||||
web_client.package_logs(LogRecordId(package_ahriman.base, package_ahriman.version), log_record)
|
||||
|
||||
|
||||
def test_package_logs_failed_http_error(web_client: WebClient, log_record: logging.LogRecord, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must pass exception during log post
|
||||
"""
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
log_record.package_base = package_ahriman.base
|
||||
with pytest.raises(Exception):
|
||||
web_client.package_logs(LogRecordId(package_ahriman.base, package_ahriman.version), log_record)
|
||||
|
||||
|
||||
def test_package_remove(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process package removal
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
|
||||
web_client.package_remove(package_ahriman.base)
|
||||
requests_mock.assert_called_once_with("DELETE", pytest.helpers.anyvar(str, True),
|
||||
params=None, json=None, files=None)
|
||||
|
||||
|
||||
def test_package_remove_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during removal
|
||||
"""
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
web_client.package_remove(package_ahriman.base)
|
||||
|
||||
|
||||
def test_package_remove_failed_http_error(web_client: WebClient, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during removal
|
||||
"""
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.package_remove(package_ahriman.base)
|
||||
|
||||
|
||||
def test_package_update(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process package update
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
|
||||
web_client.package_update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True), params=None, json={
|
||||
"status": BuildStatusEnum.Unknown.value
|
||||
}, files=None)
|
||||
|
||||
|
||||
def test_package_update_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during update
|
||||
"""
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
web_client.package_update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_package_update_failed_http_error(web_client: WebClient, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during update
|
||||
"""
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.package_update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_status_get(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return web service status
|
||||
"""
|
||||
status = InternalStatus(status=BuildStatus(), architecture="x86_64")
|
||||
response_obj = Response()
|
||||
response_obj = requests.Response()
|
||||
response_obj._content = json.dumps(status.view()).encode("utf8")
|
||||
response_obj.status_code = 200
|
||||
|
||||
requests_mock = mocker.patch("requests.Session.get", return_value=response_obj)
|
||||
requests_mock = mocker.patch("requests.Session.request", return_value=response_obj)
|
||||
|
||||
result = web_client.get_internal()
|
||||
requests_mock.assert_called_once_with(web_client._status_url)
|
||||
result = web_client.status_get()
|
||||
requests_mock.assert_called_once_with("GET", f"{web_client.address}{web_client._status_url}",
|
||||
params=None, json=None, files=None)
|
||||
assert result.architecture == "x86_64"
|
||||
|
||||
|
||||
def test_get_internal_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_status_get_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during web service status getting
|
||||
"""
|
||||
mocker.patch("requests.Session.get", side_effect=Exception())
|
||||
assert web_client.get_internal().architecture is None
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
assert web_client.status_get().architecture is None
|
||||
|
||||
|
||||
def test_get_internal_failed_http_error(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_status_get_failed_http_error(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during web service status getting
|
||||
"""
|
||||
mocker.patch("requests.Session.get", side_effect=requests.exceptions.HTTPError())
|
||||
assert web_client.get_internal().architecture is None
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
assert web_client.status_get().architecture is None
|
||||
|
||||
|
||||
def test_logs(web_client: WebClient, log_record: logging.LogRecord, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process log record
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.post")
|
||||
payload = {
|
||||
"created": log_record.created,
|
||||
"message": log_record.getMessage(),
|
||||
"process_id": log_record.process,
|
||||
}
|
||||
|
||||
web_client.logs(package_ahriman.base, log_record)
|
||||
requests_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), json=payload)
|
||||
|
||||
|
||||
def test_log_failed(web_client: WebClient, log_record: logging.LogRecord, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must pass exception during log post
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=Exception())
|
||||
log_record.package_base = package_ahriman.base
|
||||
with pytest.raises(Exception):
|
||||
web_client.logs(package_ahriman.base, log_record)
|
||||
|
||||
|
||||
def test_remove(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process package removal
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.delete")
|
||||
|
||||
web_client.remove(package_ahriman.base)
|
||||
requests_mock.assert_called_once_with(pytest.helpers.anyvar(str, True))
|
||||
|
||||
|
||||
def test_remove_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during removal
|
||||
"""
|
||||
mocker.patch("requests.Session.delete", side_effect=Exception())
|
||||
web_client.remove(package_ahriman.base)
|
||||
|
||||
|
||||
def test_remove_failed_http_error(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during removal
|
||||
"""
|
||||
mocker.patch("requests.Session.delete", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.remove(package_ahriman.base)
|
||||
|
||||
|
||||
def test_update(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process package update
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.post")
|
||||
|
||||
web_client.update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
requests_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), json={
|
||||
"status": BuildStatusEnum.Unknown.value})
|
||||
|
||||
|
||||
def test_update_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during update
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=Exception())
|
||||
web_client.update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_update_failed_http_error(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during update
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.update(package_ahriman.base, BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_update_self(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_status_update(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must process service update
|
||||
"""
|
||||
requests_mock = mocker.patch("requests.Session.post")
|
||||
requests_mock = mocker.patch("requests.Session.request")
|
||||
|
||||
web_client.update_self(BuildStatusEnum.Unknown)
|
||||
requests_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), json={
|
||||
"status": BuildStatusEnum.Unknown.value})
|
||||
web_client.status_update(BuildStatusEnum.Unknown)
|
||||
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True), params=None, json={
|
||||
"status": BuildStatusEnum.Unknown.value
|
||||
}, files=None)
|
||||
|
||||
|
||||
def test_update_self_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_status_update_self_failed(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during service update
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=Exception())
|
||||
web_client.update_self(BuildStatusEnum.Unknown)
|
||||
mocker.patch("requests.Session.request", side_effect=Exception())
|
||||
web_client.status_update(BuildStatusEnum.Unknown)
|
||||
|
||||
|
||||
def test_update_self_failed_http_error(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
def test_status_update_failed_http_error(web_client: WebClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress HTTP exception happened during service update
|
||||
"""
|
||||
mocker.patch("requests.Session.post", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.update_self(BuildStatusEnum.Unknown)
|
||||
mocker.patch("requests.Session.request", side_effect=requests.exceptions.HTTPError())
|
||||
web_client.status_update(BuildStatusEnum.Unknown)
|
||||
|
@ -1,9 +1,17 @@
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import MagicMock, call as MockCall
|
||||
|
||||
from ahriman.core.spawn import Spawn
|
||||
|
||||
|
||||
def test_boolean_action_argument() -> None:
|
||||
"""
|
||||
must correctly convert argument to boolean flag
|
||||
"""
|
||||
assert Spawn.boolean_action_argument("option", True) == "option"
|
||||
assert Spawn.boolean_action_argument("option", False) == "no-option"
|
||||
|
||||
|
||||
def test_process(spawner: Spawn) -> None:
|
||||
"""
|
||||
must process external process run correctly
|
||||
@ -15,9 +23,10 @@ def test_process(spawner: Spawn) -> None:
|
||||
spawner.process(callback, args, spawner.architecture, "id", spawner.queue)
|
||||
|
||||
callback.assert_called_once_with(args, spawner.architecture)
|
||||
(uuid, status) = spawner.queue.get()
|
||||
(uuid, status, time) = spawner.queue.get()
|
||||
assert uuid == "id"
|
||||
assert status
|
||||
assert time >= 0
|
||||
assert spawner.queue.empty()
|
||||
|
||||
|
||||
@ -30,9 +39,10 @@ def test_process_error(spawner: Spawn) -> None:
|
||||
|
||||
spawner.process(callback, MagicMock(), spawner.architecture, "id", spawner.queue)
|
||||
|
||||
(uuid, status) = spawner.queue.get()
|
||||
(uuid, status, time) = spawner.queue.get()
|
||||
assert uuid == "id"
|
||||
assert not status
|
||||
assert time >= 0
|
||||
assert spawner.queue.empty()
|
||||
|
||||
|
||||
@ -42,7 +52,7 @@ def test_spawn_process(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
start_mock = mocker.patch("multiprocessing.Process.start")
|
||||
|
||||
spawner._spawn_process("add", "ahriman", now="", maybe="?", none=None)
|
||||
assert spawner._spawn_process("add", "ahriman", now="", maybe="?", none=None)
|
||||
start_mock.assert_called_once_with()
|
||||
spawner.args_parser.parse_args.assert_called_once_with(
|
||||
spawner.command_arguments + [
|
||||
@ -51,12 +61,22 @@ def test_spawn_process(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
)
|
||||
|
||||
|
||||
def test_has_process(spawner: Spawn) -> None:
|
||||
"""
|
||||
must correctly determine if there is a process
|
||||
"""
|
||||
assert not spawner.has_process("id")
|
||||
|
||||
spawner.active["id"] = MagicMock()
|
||||
assert spawner.has_process("id")
|
||||
|
||||
|
||||
def test_key_import(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call key import
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.key_import("0xdeadbeaf", None)
|
||||
assert spawner.key_import("0xdeadbeaf", None)
|
||||
spawn_mock.assert_called_once_with("service-key-import", "0xdeadbeaf")
|
||||
|
||||
|
||||
@ -65,7 +85,7 @@ def test_key_import_with_server(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
must call key import with server specified
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.key_import("0xdeadbeaf", "keyserver.ubuntu.com")
|
||||
assert spawner.key_import("0xdeadbeaf", "keyserver.ubuntu.com")
|
||||
spawn_mock.assert_called_once_with("service-key-import", "0xdeadbeaf", **{"key-server": "keyserver.ubuntu.com"})
|
||||
|
||||
|
||||
@ -74,7 +94,7 @@ def test_packages_add(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
must call package addition
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.packages_add(["ahriman", "linux"], None, now=False)
|
||||
assert spawner.packages_add(["ahriman", "linux"], None, now=False)
|
||||
spawn_mock.assert_called_once_with("package-add", "ahriman", "linux", username=None)
|
||||
|
||||
|
||||
@ -83,7 +103,7 @@ def test_packages_add_with_build(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
must call package addition with update
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.packages_add(["ahriman", "linux"], None, now=True)
|
||||
assert spawner.packages_add(["ahriman", "linux"], None, now=True)
|
||||
spawn_mock.assert_called_once_with("package-add", "ahriman", "linux", username=None, now="")
|
||||
|
||||
|
||||
@ -92,7 +112,7 @@ def test_packages_add_with_username(spawner: Spawn, mocker: MockerFixture) -> No
|
||||
must call package addition with username
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.packages_add(["ahriman", "linux"], "username", now=False)
|
||||
assert spawner.packages_add(["ahriman", "linux"], "username", now=False)
|
||||
spawn_mock.assert_called_once_with("package-add", "ahriman", "linux", username="username")
|
||||
|
||||
|
||||
@ -101,7 +121,7 @@ def test_packages_rebuild(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
must call package rebuild
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.packages_rebuild("python", "packager")
|
||||
assert spawner.packages_rebuild("python", "packager")
|
||||
spawn_mock.assert_called_once_with("repo-rebuild", **{"depends-on": "python", "username": "packager"})
|
||||
|
||||
|
||||
@ -110,7 +130,7 @@ def test_packages_remove(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
must call package removal
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.packages_remove(["ahriman", "linux"])
|
||||
assert spawner.packages_remove(["ahriman", "linux"])
|
||||
spawn_mock.assert_called_once_with("package-remove", "ahriman", "linux")
|
||||
|
||||
|
||||
@ -119,8 +139,26 @@ def test_packages_update(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
must call repo update
|
||||
"""
|
||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn._spawn_process")
|
||||
spawner.packages_update("packager")
|
||||
spawn_mock.assert_called_once_with("repo-update", username="packager")
|
||||
|
||||
assert spawner.packages_update("packager", aur=True, local=True, manual=True)
|
||||
args = {"username": "packager", "aur": "", "local": "", "manual": ""}
|
||||
spawn_mock.assert_called_once_with("repo-update", **args)
|
||||
spawn_mock.reset_mock()
|
||||
|
||||
assert spawner.packages_update("packager", aur=False, local=True, manual=True)
|
||||
args = {"username": "packager", "no-aur": "", "local": "", "manual": ""}
|
||||
spawn_mock.assert_called_once_with("repo-update", **args)
|
||||
spawn_mock.reset_mock()
|
||||
|
||||
assert spawner.packages_update("packager", aur=True, local=False, manual=True)
|
||||
args = {"username": "packager", "aur": "", "no-local": "", "manual": ""}
|
||||
spawn_mock.assert_called_once_with("repo-update", **args)
|
||||
spawn_mock.reset_mock()
|
||||
|
||||
assert spawner.packages_update("packager", aur=True, local=True, manual=False)
|
||||
args = {"username": "packager", "aur": "", "local": "", "no-manual": ""}
|
||||
spawn_mock.assert_called_once_with("repo-update", **args)
|
||||
spawn_mock.reset_mock()
|
||||
|
||||
|
||||
def test_run(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
@ -129,8 +167,8 @@ def test_run(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
logging_mock = mocker.patch("logging.Logger.info")
|
||||
|
||||
spawner.queue.put(("1", False))
|
||||
spawner.queue.put(("2", True))
|
||||
spawner.queue.put(("1", False, 1))
|
||||
spawner.queue.put(("2", True, 1))
|
||||
spawner.queue.put(None) # terminate
|
||||
|
||||
spawner.run()
|
||||
@ -144,8 +182,8 @@ def test_run_pop(spawner: Spawn) -> None:
|
||||
first = spawner.active["1"] = MagicMock()
|
||||
second = spawner.active["2"] = MagicMock()
|
||||
|
||||
spawner.queue.put(("1", False))
|
||||
spawner.queue.put(("2", True))
|
||||
spawner.queue.put(("1", False, 1))
|
||||
spawner.queue.put(("2", True, 1))
|
||||
spawner.queue.put(None) # terminate
|
||||
|
||||
spawner.run()
|
||||
|
@ -273,6 +273,15 @@ def test_package_like(package_ahriman: Package) -> None:
|
||||
assert package_like(package_ahriman.packages[package_ahriman.base].filepath)
|
||||
|
||||
|
||||
def test_package_like_hidden(package_ahriman: Package) -> None:
|
||||
"""
|
||||
package_like must return false for hidden files
|
||||
"""
|
||||
package_file = package_ahriman.packages[package_ahriman.base].filepath
|
||||
hidden_file = package_file.parent / f".{package_file.name}"
|
||||
assert not package_like(hidden_file)
|
||||
|
||||
|
||||
def test_package_like_sig(package_ahriman: Package) -> None:
|
||||
"""
|
||||
package_like must return false for signature files
|
||||
|
@ -5,6 +5,7 @@ from unittest.mock import MagicMock
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.upload.github import Github
|
||||
from ahriman.core.upload.remote_service import RemoteService
|
||||
from ahriman.core.upload.rsync import Rsync
|
||||
from ahriman.core.upload.s3 import S3
|
||||
|
||||
@ -45,6 +46,22 @@ def github_release() -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def remote_service(configuration: Configuration) -> RemoteService:
|
||||
"""
|
||||
fixture for remote service synchronization
|
||||
|
||||
Args:
|
||||
configuration(Configuration): configuration fixture
|
||||
|
||||
Returns:
|
||||
RemoteService: remote service test instance
|
||||
"""
|
||||
configuration.set_option("web", "host", "localhost")
|
||||
configuration.set_option("web", "port", "8080")
|
||||
return RemoteService("x86_64", configuration, "remote-service")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rsync(configuration: Configuration) -> Rsync:
|
||||
"""
|
||||
|
@ -47,7 +47,7 @@ def test_request(github: Github, mocker: MockerFixture) -> None:
|
||||
must call request method
|
||||
"""
|
||||
response_mock = MagicMock()
|
||||
request_mock = mocker.patch("requests.request", return_value=response_mock)
|
||||
request_mock = mocker.patch("requests.Session.request", return_value=response_mock)
|
||||
|
||||
github._request("GET", "url", arg="arg")
|
||||
request_mock.assert_called_once_with("GET", "url", auth=github.auth, timeout=github.timeout, arg="arg")
|
||||
@ -58,6 +58,6 @@ def test_request_exception(github: Github, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call request method and log HTTPError exception
|
||||
"""
|
||||
mocker.patch("requests.request", side_effect=requests.HTTPError())
|
||||
mocker.patch("requests.Session.request", side_effect=requests.HTTPError())
|
||||
with pytest.raises(requests.HTTPError):
|
||||
github._request("GET", "url", arg="arg")
|
||||
|
82
tests/ahriman/core/upload/test_remote_service.py
Normal file
82
tests/ahriman/core/upload/test_remote_service.py
Normal file
@ -0,0 +1,82 @@
|
||||
import pytest
|
||||
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import MagicMock, call as MockCall
|
||||
|
||||
from ahriman.core.upload.remote_service import RemoteService
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
def test_session(remote_service: RemoteService, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate ahriman session
|
||||
"""
|
||||
upload_mock = mocker.patch("ahriman.core.status.web_client.WebClient._create_session")
|
||||
assert remote_service.session
|
||||
upload_mock.assert_called_once_with(use_unix_socket=False)
|
||||
|
||||
|
||||
def test_package_upload(remote_service: RemoteService, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must upload package to remote host
|
||||
"""
|
||||
mocker.patch("pathlib.Path.is_file", return_value=False)
|
||||
file_mock = MagicMock()
|
||||
open_mock = mocker.patch("pathlib.Path.open", return_value=file_mock)
|
||||
upload_mock = mocker.patch("ahriman.core.upload.http_upload.HttpUpload._request")
|
||||
filename = package_ahriman.packages[package_ahriman.base].filename
|
||||
|
||||
remote_service.sync(Path("local"), [package_ahriman])
|
||||
open_mock.assert_called_once_with("rb")
|
||||
file_mock.close.assert_called_once()
|
||||
upload_mock.assert_called_once_with("POST", f"{remote_service.client.address}/api/v1/service/upload", files={
|
||||
"package": (filename, pytest.helpers.anyvar(int), "application/octet-stream", {})
|
||||
})
|
||||
|
||||
|
||||
def test_package_upload_with_signature(remote_service: RemoteService, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must upload package to remote host with signatures
|
||||
"""
|
||||
mocker.patch("pathlib.Path.is_file", return_value=True)
|
||||
file_mock = MagicMock()
|
||||
open_mock = mocker.patch("pathlib.Path.open", return_value=file_mock)
|
||||
upload_mock = mocker.patch("ahriman.core.upload.http_upload.HttpUpload._request")
|
||||
filename = package_ahriman.packages[package_ahriman.base].filename
|
||||
|
||||
remote_service.sync(Path("local"), [package_ahriman])
|
||||
open_mock.assert_has_calls([MockCall("rb"), MockCall("rb")])
|
||||
file_mock.close.assert_has_calls([MockCall(), MockCall()])
|
||||
upload_mock.assert_called_once_with(
|
||||
"POST", f"{remote_service.client.address}/api/v1/service/upload", files={
|
||||
"package": (filename, pytest.helpers.anyvar(int), "application/octet-stream", {}),
|
||||
"signature": (f"{filename}.sig", pytest.helpers.anyvar(int), "application/octet-stream", {})
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_package_upload_no_filename(remote_service: RemoteService, package_ahriman: Package,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must skip upload if no filename set
|
||||
"""
|
||||
open_mock = mocker.patch("pathlib.Path.open")
|
||||
upload_mock = mocker.patch("ahriman.core.status.web_client.WebClient.make_request")
|
||||
package_ahriman.packages[package_ahriman.base].filename = None
|
||||
|
||||
remote_service.sync(Path("local"), [package_ahriman])
|
||||
open_mock.assert_not_called()
|
||||
upload_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_sync(remote_service: RemoteService, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must run sync command
|
||||
"""
|
||||
upload_mock = mocker.patch("ahriman.core.upload.remote_service.RemoteService.package_upload")
|
||||
local = Path("local")
|
||||
|
||||
remote_service.sync(local, [package_ahriman])
|
||||
upload_mock.assert_called_once_with(local, package_ahriman)
|
@ -53,3 +53,15 @@ def test_upload_github(configuration: Configuration, mocker: MockerFixture) -> N
|
||||
upload_mock = mocker.patch("ahriman.core.upload.github.Github.sync")
|
||||
Upload.load("x86_64", configuration, "github").run(Path("path"), [])
|
||||
upload_mock.assert_called_once_with(Path("path"), [])
|
||||
|
||||
|
||||
def test_upload_ahriman(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must upload via ahriman
|
||||
"""
|
||||
upload_mock = mocker.patch("ahriman.core.upload.remote_service.RemoteService.sync")
|
||||
configuration.set_option("web", "host", "localhost")
|
||||
configuration.set_option("web", "port", "8080")
|
||||
|
||||
Upload.load("x86_64", configuration, "remote-service").run(Path("path"), [])
|
||||
upload_mock.assert_called_once_with(Path("path"), [])
|
||||
|
Reference in New Issue
Block a user