Changeset View
Changeset View
Standalone View
Standalone View
swh/deposit/tests/cli/test_client.py
# Copyright (C) 2019-2020 The Software Heritage developers | # Copyright (C) 2019-2020 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
import contextlib | import contextlib | ||||
import logging | import logging | ||||
import os | import os | ||||
import re | import re | ||||
from unittest.mock import MagicMock | from unittest.mock import MagicMock | ||||
from click.testing import CliRunner | from click.testing import CliRunner | ||||
import pytest | import pytest | ||||
from swh.deposit.client import PublicApiDepositClient | from swh.deposit.client import PublicApiDepositClient, MaintenanceError | ||||
from swh.deposit.cli.client import generate_slug, _url, _client, _collection, InputError | from swh.deposit.cli.client import generate_slug, _url, _client, _collection, InputError | ||||
from swh.deposit.cli import deposit as cli | from swh.deposit.cli import deposit as cli | ||||
from ..conftest import TEST_USER | from ..conftest import TEST_USER | ||||
EXAMPLE_SERVICE_DOCUMENT = { | EXAMPLE_SERVICE_DOCUMENT = { | ||||
"service": {"workspace": {"collection": {"sword:name": "softcol",}}} | "service": {"workspace": {"collection": {"sword:name": "softcol",}}} | ||||
} | } | ||||
Show All 13 Lines | def client_mock(mocker, slug): | ||||
mock_client = MagicMock() | mock_client = MagicMock() | ||||
mocker.patch("swh.deposit.cli.client._client", return_value=mock_client) | mocker.patch("swh.deposit.cli.client._client", return_value=mock_client) | ||||
mock_client.service_document.return_value = EXAMPLE_SERVICE_DOCUMENT | mock_client.service_document.return_value = EXAMPLE_SERVICE_DOCUMENT | ||||
mock_client.deposit_create.return_value = '{"foo": "bar"}' | mock_client.deposit_create.return_value = '{"foo": "bar"}' | ||||
return mock_client | return mock_client | ||||
@pytest.fixture | @pytest.fixture | ||||
def client_mock_down(mocker, slug): | def client_mock_api_down(mocker, slug): | ||||
"""A mock client whose connection with api fails due to maintenance issue | |||||
""" | |||||
mocker.patch("swh.deposit.cli.client.generate_slug", return_value=slug) | mocker.patch("swh.deposit.cli.client.generate_slug", return_value=slug) | ||||
mock_client = MagicMock() | mock_client = MagicMock() | ||||
mocker.patch("swh.deposit.cli.client._client", return_value=mock_client) | mocker.patch("swh.deposit.cli.client._client", return_value=mock_client) | ||||
mock_client.service_document.return_value = EXAMPLE_SERVICE_DOCUMENT | mock_client.service_document.side_effect = MaintenanceError( | ||||
mock_client.deposit_create.return_value = '{"foo": "bar"}' | "Database backend maintenance: Temporarily unavailable, try again later." | ||||
) | |||||
return mock_client | return mock_client | ||||
def test_url(): | def test_url(): | ||||
assert _url("http://deposit") == "http://deposit/1" | assert _url("http://deposit") == "http://deposit/1" | ||||
assert _url("https://other/1") == "https://other/1" | assert _url("https://other/1") == "https://other/1" | ||||
Show All 15 Lines | |||||
def test_collection_ok(): | def test_collection_ok(): | ||||
mock_client = MagicMock() | mock_client = MagicMock() | ||||
mock_client.service_document.return_value = EXAMPLE_SERVICE_DOCUMENT | mock_client.service_document.return_value = EXAMPLE_SERVICE_DOCUMENT | ||||
collection_name = _collection(mock_client) | collection_name = _collection(mock_client) | ||||
assert collection_name == "softcol" | assert collection_name == "softcol" | ||||
def test_deposit_with_server_ok_backend_down( | def test_collection_ko_because_downtime(): | ||||
ardumont: This was committed by mistake... | |||||
sample_archive, mocker, caplog, client_mock, slug, tmp_path | mock_client = MagicMock() | ||||
mock_client.service_document.side_effect = MaintenanceError("downtime") | |||||
with pytest.raises(MaintenanceError, match="downtime"): | |||||
_collection(mock_client) | |||||
def test_deposit_with_server_down_for_maintenance( | |||||
sample_archive, mocker, caplog, client_mock_api_down, slug, tmp_path | |||||
): | ): | ||||
""" Deposit failure due to maintenance down time should be explicit in error msg | """ Deposit failure due to maintenance down time should be explicit | ||||
""" | |||||
metadata_path = os.path.join(tmp_path, "metadata.xml") | |||||
mocker.patch( | |||||
"swh.deposit.cli.client.tempfile.TemporaryDirectory", | |||||
return_value=contextlib.nullcontext(str(tmp_path)), | |||||
) | |||||
""" | |||||
runner = CliRunner() | runner = CliRunner() | ||||
result = runner.invoke( | result = runner.invoke( | ||||
cli, | cli, | ||||
[ | [ | ||||
"upload", | "upload", | ||||
"--url", | "--url", | ||||
"mock://deposit.swh/1", | "mock://deposit.swh/1", | ||||
"--username", | "--username", | ||||
TEST_USER["username"], | TEST_USER["username"], | ||||
"--password", | "--password", | ||||
TEST_USER["password"], | TEST_USER["password"], | ||||
"--name", | "--name", | ||||
"test-project", | "test-project", | ||||
"--archive", | "--archive", | ||||
sample_archive["path"], | sample_archive["path"], | ||||
"--author", | "--author", | ||||
"Jane Doe", | "Jane Doe", | ||||
], | ], | ||||
) | ) | ||||
assert result.exit_code == 0, result.output | assert result.exit_code == 1, result.output | ||||
assert result.output == "" | assert result.output == "" | ||||
assert caplog.record_tuples == [ | assert caplog.record_tuples == [ | ||||
("swh.deposit.cli.client", logging.INFO, '{"foo": "bar"}'), | ( | ||||
] | "swh.deposit.cli.client", | ||||
logging.ERROR, | |||||
client_mock.deposit_create.assert_called_once_with( | "Database backend maintenance: Temporarily unavailable, try again later.", | ||||
archive=sample_archive["path"], | |||||
collection="softcol", | |||||
in_progress=False, | |||||
metadata=metadata_path, | |||||
slug=slug, | |||||
) | ) | ||||
] | |||||
with open(metadata_path) as fd: | client_mock_api_down.service_document.assert_called_once_with() | ||||
assert ( | |||||
fd.read() | |||||
== f"""\ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<entry xmlns="http://www.w3.org/2005/Atom" \ | |||||
xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"> | |||||
\t<codemeta:name>test-project</codemeta:name> | |||||
\t<codemeta:identifier>{slug}</codemeta:identifier> | |||||
\t<codemeta:author> | |||||
\t\t<codemeta:name>Jane Doe</codemeta:name> | |||||
\t</codemeta:author> | |||||
</entry>""" | |||||
) | |||||
def test_single_minimal_deposit( | def test_single_minimal_deposit( | ||||
sample_archive, mocker, caplog, client_mock, slug, tmp_path | sample_archive, mocker, caplog, client_mock, slug, tmp_path | ||||
): | ): | ||||
""" from: | """ from: | ||||
https://docs.softwareheritage.org/devel/swh-deposit/getting-started.html#single-deposit | https://docs.softwareheritage.org/devel/swh-deposit/getting-started.html#single-deposit | ||||
""" # noqa | """ # noqa | ||||
▲ Show 20 Lines • Show All 320 Lines • Show Last 20 Lines |
This was committed by mistake...