Changeset View
Changeset View
Standalone View
Standalone View
swh/icinga_plugins/tests/test_vault.py
# Copyright (C) 2019 The Software Heritage developers | # Copyright (C) 2019 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 enum | import enum | ||||
import json | import json | ||||
import re | import re | ||||
import time | |||||
from click.testing import CliRunner | from click.testing import CliRunner | ||||
from swh.icinga_plugins.cli import cli | from swh.icinga_plugins.cli import cli | ||||
dir_id = 'ab'*20 | dir_id = 'ab'*20 | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | result = invoke([ | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
]) | ]) | ||||
assert re.match( | assert re.match( | ||||
rf'VAULT OK - cooking directory {dir_id} took ' | rf'VAULT OK - cooking directory {dir_id} took ' | ||||
r'[0-9]\.[0-9]{2}s and succeeded.\n' | r'[0-9]\.[0-9]{2}s and succeeded.\n' | ||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | r"| 'total time' = [0-9]\.[0-9]{2}s", | ||||
result.output) | result.output) | ||||
assert result.exit_code == 0, result.output | |||||
sleep_mock.assert_called_once_with(10) | sleep_mock.assert_called_once_with(10) | ||||
def test_vault_delayed_success(requests_mock, mocker): | def test_vault_delayed_success(requests_mock, mocker): | ||||
class Step(enum.Enum): | class Step(enum.Enum): | ||||
NOTHING_DONE = 0 | NOTHING_DONE = 0 | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | result = invoke([ | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
]) | ]) | ||||
assert re.match( | assert re.match( | ||||
rf'VAULT OK - cooking directory {dir_id} took ' | rf'VAULT OK - cooking directory {dir_id} took ' | ||||
r'[0-9]\.[0-9]{2}s and succeeded.\n' | r'[0-9]\.[0-9]{2}s and succeeded.\n' | ||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | r"| 'total time' = [0-9]\.[0-9]{2}s", | ||||
result.output) | result.output) | ||||
assert result.exit_code == 0, result.output | |||||
assert sleep_mock.call_count == 2 | assert sleep_mock.call_count == 2 | ||||
def test_vault_failure(requests_mock, mocker): | def test_vault_failure(requests_mock, mocker): | ||||
class Step(enum.Enum): | class Step(enum.Enum): | ||||
NOTHING_DONE = 0 | NOTHING_DONE = 0 | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | result = invoke([ | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
], catch_exceptions=True) | ], catch_exceptions=True) | ||||
assert re.match( | assert re.match( | ||||
rf'VAULT CRITICAL - cooking directory {dir_id} took ' | rf'VAULT CRITICAL - cooking directory {dir_id} took ' | ||||
r'[0-9]\.[0-9]{2}s and failed with: foobar\n' | r'[0-9]\.[0-9]{2}s and failed with: foobar\n' | ||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | r"| 'total time' = [0-9]\.[0-9]{2}s", | ||||
result.output) | result.output) | ||||
assert result.exit_code == 2, result.output | |||||
sleep_mock.assert_called_once_with(10) | sleep_mock.assert_called_once_with(10) | ||||
def test_vault_timeout(requests_mock, mocker): | |||||
class Step(enum.Enum): | |||||
NOTHING_DONE = 0 | |||||
CHECKED_UNCOOKED = 1 | |||||
REQUESTED_COOKING = 2 | |||||
PENDING = 3 | |||||
step = Step.NOTHING_DONE | |||||
def post_callback(request, context): | |||||
nonlocal step | |||||
if step == Step.CHECKED_UNCOOKED: | |||||
step = Step.REQUESTED_COOKING | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
def get_callback(request, context): | |||||
context.json = True | |||||
nonlocal step, time_offset | |||||
if step == Step.NOTHING_DONE: | |||||
context.status_code = 404 | |||||
step = Step.CHECKED_UNCOOKED | |||||
elif step == Step.CHECKED_UNCOOKED: | |||||
assert False | |||||
elif step == Step.REQUESTED_COOKING: | |||||
step = Step.PENDING | |||||
return json.dumps(response_pending) | |||||
elif step == Step.PENDING: | |||||
time_offset += 4000 # jump forward in time more than 1h | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
requests_mock.get( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=get_callback) | |||||
requests_mock.post( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=post_callback) | |||||
get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | |||||
get_storage_mock.side_effect = FakeStorage | |||||
sleep_mock = mocker.patch('time.sleep') | |||||
real_time = time.time | |||||
time_offset = 0 | |||||
mocker.patch( | |||||
'time.time', side_effect=lambda: real_time() + time_offset) | |||||
result = invoke([ | |||||
'--swh-web-url', 'mock://swh-web.example.org', | |||||
'--swh-storage-url', 'foo://example.org', | |||||
'check-vault', 'directory', | |||||
], catch_exceptions=True) | |||||
assert re.match( | |||||
rf'VAULT CRITICAL - cooking directory {dir_id} took more than ' | |||||
r'[0-9]+\.[0-9]{2}s and has status: foo\n' | |||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | |||||
result.output) | |||||
assert result.exit_code == 2, result.output | |||||
assert sleep_mock.call_count == 2 |