Changeset View
Changeset View
Standalone View
Standalone View
swh/counters/tests/test_history.py
- This file was added.
# Copyright (C) 2021 The Software Heritage developers | ||||||||||||
# See the AUTHORS file at the top-level directory of this distribution | ||||||||||||
# License: GNU General Public License version 3, or any later version | ||||||||||||
# See top-level LICENSE file for more information | ||||||||||||
import json | ||||||||||||
import os | ||||||||||||
import pytest | ||||||||||||
from swh.counters.api.history import load_history_data | ||||||||||||
from swh.counters.history import History | ||||||||||||
TEST_HISTORY_CONFIG = { | ||||||||||||
"prometheus_host": "prometheus", | ||||||||||||
"prometheus_port": 8888, | ||||||||||||
"prometheus_collection": "swh.collection", | ||||||||||||
"cache_base_directory": "/tmp", | ||||||||||||
"live_data_start": "10", | ||||||||||||
"interval": "20h", | ||||||||||||
"query_range_uri": "/my/uri", | ||||||||||||
"labels": {"label1": "value1", "label2": "value2"}, | ||||||||||||
} | ||||||||||||
TEST_JSON = {"key1": "value1", "key2": "value2"} | ||||||||||||
CACHED_DATA = {"content": [[10, 1.5], [12, 2.0]], "revision": [[11, 4], [13, 5]]} | ||||||||||||
@pytest.fixture | ||||||||||||
def history(): | ||||||||||||
return History(**TEST_HISTORY_CONFIG) | ||||||||||||
def test_history_load_data(datadir): | ||||||||||||
datatest = os.path.join(datadir, "foo.json") | ||||||||||||
result = load_history_data(datatest) | ||||||||||||
assert result == {"key1": "value1", "key2": "value2"} | ||||||||||||
def test_history_compute_url(history): | ||||||||||||
end = 99 | ||||||||||||
object_type = "content" | ||||||||||||
url = history._compute_url(object=object_type, end=end,) | ||||||||||||
assert url == ( | ||||||||||||
f'http://{TEST_HISTORY_CONFIG["prometheus_host"]}:' | ||||||||||||
f'{TEST_HISTORY_CONFIG["prometheus_port"]}/' | ||||||||||||
f'{TEST_HISTORY_CONFIG["query_range_uri"]}?' | ||||||||||||
f'query=sum({TEST_HISTORY_CONFIG["prometheus_collection"]}' | ||||||||||||
f'{{label1="value1",label2="value2",' | ||||||||||||
f'object_type="{object_type}"}})&' | ||||||||||||
f'start={TEST_HISTORY_CONFIG["live_data_start"]}&end={end}' | ||||||||||||
f'&step={TEST_HISTORY_CONFIG["interval"]}' | ||||||||||||
) | ||||||||||||
@pytest.mark.parametrize( | ||||||||||||
"source, expected", [([1, "10"], [1000, 10.0]), ([2, "10.1"], [2000, 10.1]),] | ||||||||||||
) | ||||||||||||
def test_history__adapt_format(history, source, expected): | ||||||||||||
result = history._adapt_format(source) | ||||||||||||
assert expected == result | ||||||||||||
def test_history__validate_filename(history): | ||||||||||||
with pytest.raises(ValueError, match="path information"): | ||||||||||||
history._validate_filename("/test.json") | ||||||||||||
with pytest.raises(ValueError, match="path information"): | ||||||||||||
history._validate_filename("../../test.json") | ||||||||||||
history._validate_filename("test.json") | ||||||||||||
def test_history_get_history(history, tmp_path): | ||||||||||||
history.cache_base_directory = tmp_path | ||||||||||||
json_file = "test.json" | ||||||||||||
full_path = f"{tmp_path}/{json_file}" | ||||||||||||
with open(full_path, "w") as f: | ||||||||||||
f.write(json.dumps(TEST_JSON)) | ||||||||||||
result = history.get_history(json_file) | ||||||||||||
assert result == TEST_JSON | ||||||||||||
def test_history_get_history_relative_path_failed(history): | ||||||||||||
with pytest.raises(ValueError, match="path information"): | ||||||||||||
history.get_history("/test.json") | ||||||||||||
def test_history__get_timestamp_history(history, requests_mock, datadir, mocker): | ||||||||||||
object = "content" | ||||||||||||
end = 100 | ||||||||||||
url = history._compute_url(object, end) | ||||||||||||
mock = mocker.patch("time.time") | ||||||||||||
mock.return_value = end | ||||||||||||
request_content_file = os.path.join(datadir, "content.json") | ||||||||||||
with open(request_content_file, "r") as f: | ||||||||||||
content = f.read() | ||||||||||||
requests_mock.get( | ||||||||||||
url, [{"content": bytes(content, "utf-8"), "status_code": 200},], | ||||||||||||
) | ||||||||||||
result = history._get_timestamp_history(object) | ||||||||||||
assert result == [[100000, 10.0], [100000, 20.0], [110000, 30.0]] | ||||||||||||
def test_history__get_timestamp_history_request_failed( | ||||||||||||
history, requests_mock, datadir, mocker | ||||||||||||
): | ||||||||||||
object = "content" | ||||||||||||
end = 100 | ||||||||||||
url = history._compute_url(object, end) | ||||||||||||
mock = mocker.patch("time.time") | ||||||||||||
mock.return_value = end | ||||||||||||
requests_mock.get( | ||||||||||||
url, [{"content": None, "status_code": 503},], | ||||||||||||
) | ||||||||||||
ardumont: Please add a docstring describing in one line what this test checks.
The test name might not be… | ||||||||||||
result = history._get_timestamp_history(object) | ||||||||||||
assert result == [] | ||||||||||||
def test_history__refresh_history_with_historical( | ||||||||||||
history, requests_mock, mocker, datadir, tmp_path | ||||||||||||
): | ||||||||||||
objects = ["content", "revision"] | ||||||||||||
static_file_name = "static.json" | ||||||||||||
cache_file = "result.json" | ||||||||||||
end = 100 | ||||||||||||
with open(f"{tmp_path}/{static_file_name}", "w") as f: | ||||||||||||
f.write(json.dumps(CACHED_DATA)) | ||||||||||||
Not Done Inline ActionsMake that a test utility function configure_request_mocks or even a fixture? ardumont: Make that a test utility function `configure_request_mocks` or even a fixture?
As you are… | ||||||||||||
for object_type in objects: | ||||||||||||
url = history._compute_url(object_type, end) | ||||||||||||
request_content_file = os.path.join(datadir, f"{object_type}.json") | ||||||||||||
with open(request_content_file, "r") as f: | ||||||||||||
content = f.read() | ||||||||||||
requests_mock.get( | ||||||||||||
url, [{"content": bytes(content, "utf-8"), "status_code": 200},], | ||||||||||||
) | ||||||||||||
mock = mocker.patch("time.time") | ||||||||||||
mock.return_value = end | ||||||||||||
history.cache_base_directory = tmp_path | ||||||||||||
Not Done Inline Actions
ardumont: | ||||||||||||
history.refresh_history( | ||||||||||||
cache_file=cache_file, objects=objects, static_file=static_file_name | ||||||||||||
) | ||||||||||||
result_file = f"{tmp_path}/{cache_file}" | ||||||||||||
assert os.path.isfile(result_file) | ||||||||||||
expected = { | ||||||||||||
"content": [ | ||||||||||||
[10, 1.5], | ||||||||||||
[12, 2.0], | ||||||||||||
[100000, 10.0], | ||||||||||||
Done Inline Actions
ardumont: | ||||||||||||
[100000, 20.0], | ||||||||||||
[110000, 30.0], | ||||||||||||
Done Inline Actions
with the renaming all around. content is a bit overloaded in our context in general ;) ardumont: with the renaming all around.
content is a bit overloaded in our context in general ;) | ||||||||||||
], | ||||||||||||
"revision": [[11, 4], [13, 5], [80000, 1.0], [90000, 2.0], [95000, 5.0]], | ||||||||||||
} | ||||||||||||
with open(result_file, "r") as f: | ||||||||||||
content = json.load(f) | ||||||||||||
assert expected == content | ||||||||||||
def test_history__refresh_history_without_historical( | ||||||||||||
history, requests_mock, mocker, datadir, tmp_path | ||||||||||||
): | ||||||||||||
objects = ["content", "revision"] | ||||||||||||
cache_file = "result.json" | ||||||||||||
end = 100 | ||||||||||||
for object_type in objects: | ||||||||||||
url = history._compute_url(object_type, end) | ||||||||||||
request_content_file = os.path.join(datadir, f"{object_type}.json") | ||||||||||||
with open(request_content_file, "r") as f: | ||||||||||||
content = f.read() | ||||||||||||
requests_mock.get( | ||||||||||||
url, [{"content": bytes(content, "utf-8"), "status_code": 200},], | ||||||||||||
) | ||||||||||||
mock = mocker.patch("time.time") | ||||||||||||
mock.return_value = end | ||||||||||||
history.cache_base_directory = tmp_path | ||||||||||||
history.refresh_history(cache_file=cache_file, objects=objects) | ||||||||||||
result_file = f"{tmp_path}/{cache_file}" | ||||||||||||
assert os.path.isfile(result_file) | ||||||||||||
expected = { | ||||||||||||
Done Inline Actionssame suggestions as previous test. ardumont: same suggestions as previous test. | ||||||||||||
"content": [[100000, 10.0], [100000, 20.0], [110000, 30.0]], | ||||||||||||
"revision": [[80000, 1.0], [90000, 2.0], [95000, 5.0]], | ||||||||||||
} | ||||||||||||
with open(result_file, "r") as f: | ||||||||||||
content = json.load(f) | ||||||||||||
assert expected == content |
Please add a docstring describing in one line what this test checks.
The test name might not be enough.