mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-26 05:22:13 +03:00
In general I think this will keep things neater: 1. Create a directory inside tests/ named after the file the tests are for. 2. Put all files for that test inside this new directory.
231 lines
7.9 KiB
Python
231 lines
7.9 KiB
Python
"""Test the config system."""
|
|
from __future__ import annotations
|
|
|
|
import contextlib
|
|
import itertools
|
|
import pathlib
|
|
import random
|
|
import string
|
|
import sys
|
|
from typing import Any, Iterable, List, cast
|
|
|
|
import pytest
|
|
from pytest import mark
|
|
|
|
# isort: split
|
|
|
|
sys.path += [str(pathlib.Path(__file__).parent.parent.resolve()), "."]
|
|
print(sys.path)
|
|
|
|
from _old_config import old_config # noqa: E402
|
|
|
|
from config import LinuxConfig, config # noqa: E402
|
|
|
|
|
|
def _fuzz_list(length: int) -> List[str]:
|
|
out = []
|
|
for _ in range(length):
|
|
out.append(_fuzz_generators[str](random.randint(0, 1337)))
|
|
|
|
return cast(List[str], out)
|
|
|
|
|
|
_fuzz_generators = { # Type annotating this would be a nightmare.
|
|
int: lambda i: random.randint(min(0, i), max(0, i)),
|
|
# This doesn't cover unicode, or random bytes. Use them at your own peril
|
|
str: lambda l: "".join(random.choice(string.ascii_letters + string.digits + '\r\n') for _ in range(l)),
|
|
bool: lambda _: bool(random.choice((True, False))),
|
|
list: _fuzz_list,
|
|
}
|
|
|
|
|
|
def _get_fuzz(_type: Any, num_values=50, value_length=(0, 10)) -> list:
|
|
return [_fuzz_generators[_type](random.randint(*value_length)) for _ in range(num_values)]
|
|
|
|
|
|
int_tests = [0, 1, 2, 3, (1 << 32)-1, -1337]
|
|
|
|
string_tests = [
|
|
"test", "", "this\nis\na\ntest", "orange sidewinder", "needs \\ more backslashes\\", "\\; \\n", r"\\\\ \\\\; \\\\n",
|
|
r"entry with escapes \\ \\; \\n"
|
|
]
|
|
|
|
list_tests = [
|
|
["test"],
|
|
["multiple", "entries"],
|
|
["multiple", "entries", "with", "", "blanks"],
|
|
["entry", "that ends", "in a", ""],
|
|
["entry with \n", "newlines\nin", "weird\nplaces"],
|
|
[r"entry with escapes \\ \\; \\n"],
|
|
[r"\\\\ \\\\; \\\\n"]
|
|
]
|
|
bool_tests = [True, False]
|
|
|
|
big_int = int(0xFFFFFFFF) # 32 bit int
|
|
|
|
|
|
def _make_params(args: List[Any], id_name: str = 'random_test_{i}') -> list:
|
|
return [pytest.param(x, id=id_name.format(i=i)) for i, x in enumerate(args)]
|
|
|
|
|
|
def _build_test_list(static_data, random_data, random_id_name='random_test_{i}') -> Iterable:
|
|
return itertools.chain(static_data, _make_params(random_data, id_name=random_id_name))
|
|
|
|
|
|
class TestNewConfig:
|
|
"""Test the new config with an array of hand picked and random data."""
|
|
|
|
def __update_linuxconfig(self) -> None:
|
|
"""On linux config uses ConfigParser, which doesn't update from disk changes. Force the update here."""
|
|
if isinstance(config, LinuxConfig) and config.config is not None:
|
|
config.config.read(config.filename)
|
|
|
|
@mark.parametrize("i", _build_test_list(int_tests, _get_fuzz(int, value_length=(-big_int, big_int))))
|
|
def test_ints(self, i: int) -> None:
|
|
"""Save int and then unpack it again."""
|
|
if sys.platform == 'win32':
|
|
i = abs(i)
|
|
|
|
name = f"int_test_{i}"
|
|
config.set(name, i)
|
|
config.save()
|
|
self.__update_linuxconfig()
|
|
assert i == config.get_int(name)
|
|
config.delete(name)
|
|
|
|
@mark.parametrize("string", _build_test_list(string_tests, _get_fuzz(str, value_length=(0, 512))))
|
|
def test_string(self, string: str) -> None:
|
|
"""Save a string and then ask for it back."""
|
|
name = f'str_test_{hash(string)}'
|
|
config.set(name, string)
|
|
config.save()
|
|
self.__update_linuxconfig()
|
|
assert string == config.get_str(name)
|
|
config.delete(name)
|
|
|
|
@mark.parametrize("lst", _build_test_list(list_tests, _get_fuzz(list)))
|
|
def test_list(self, lst: List[str]) -> None:
|
|
"""Save a list and then ask for it back."""
|
|
name = f'list_test_{ hash("".join(lst)) }'
|
|
config.set(name, lst)
|
|
|
|
config.save()
|
|
self.__update_linuxconfig()
|
|
|
|
assert lst == config.get_list(name)
|
|
|
|
config.delete(name)
|
|
|
|
@mark.parametrize('b', bool_tests)
|
|
def test_bool(self, b: bool) -> None:
|
|
"""Save a bool and ask for it back."""
|
|
name = str(b)
|
|
config.set(name, b)
|
|
config.save()
|
|
self.__update_linuxconfig()
|
|
assert b == config.get_bool(name)
|
|
config.delete(name)
|
|
|
|
def test_get_no_error(self) -> None:
|
|
"""Regression test to ensure that get() doesn't throw a TypeError."""
|
|
name = 'test-get'
|
|
config.set(name, '1337')
|
|
config.save()
|
|
self.__update_linuxconfig()
|
|
with pytest.deprecated_call():
|
|
res = config.get(name)
|
|
|
|
assert res == '1337'
|
|
config.delete(name)
|
|
|
|
|
|
class TestOldNewConfig:
|
|
"""Tests going through the old config and out the new config."""
|
|
|
|
KEY_PREFIX = 'oldnew_'
|
|
|
|
def teardown_method(self) -> None:
|
|
"""
|
|
Teardown for all config tests to save out configs.
|
|
|
|
It is expected that tests have cleaned up whatever keys they have aded.
|
|
This is here to ensure that a save out happens for configs that need it.
|
|
"""
|
|
old_config.save()
|
|
config.save()
|
|
|
|
def cleanup_entry(self, entry: str) -> None:
|
|
"""Remove the given key, on both sides if on linux."""
|
|
config.delete(entry)
|
|
if sys.platform == 'linux':
|
|
old_config.delete(entry)
|
|
|
|
def __update_linuxconfig(self) -> None:
|
|
"""On linux config uses ConfigParser, which doesn't update from disk changes. Force the update here."""
|
|
if isinstance(config, LinuxConfig) and config.config is not None:
|
|
config.config.read(config.filename)
|
|
|
|
@mark.parametrize("i", _build_test_list(int_tests, _get_fuzz(int, 50, (-big_int, big_int))))
|
|
def test_int(self, i: int) -> None:
|
|
"""Save an int though the old config, recall it using the new config."""
|
|
if sys.platform == 'win32':
|
|
i = abs(i)
|
|
|
|
name = self.KEY_PREFIX + f'int_{i}'
|
|
old_config.set(name, i)
|
|
old_config.save()
|
|
|
|
self.__update_linuxconfig()
|
|
|
|
res = config.get_int(name)
|
|
with contextlib.ExitStack() as stack:
|
|
stack.callback(self.cleanup_entry, name)
|
|
assert res == i
|
|
|
|
@mark.parametrize("string", _build_test_list(string_tests, _get_fuzz(str, value_length=(0, 512))))
|
|
def test_string(self, string: str) -> None:
|
|
"""Save a string though the old config, recall it using the new config."""
|
|
string = string.replace("\r", "") # The old config does _not_ support \r in its entries. We do.
|
|
name = self.KEY_PREFIX + f'string_{hash(string)}'
|
|
old_config.set(name, string)
|
|
old_config.save()
|
|
|
|
self.__update_linuxconfig()
|
|
|
|
res = config.get_str(name)
|
|
with contextlib.ExitStack() as stack:
|
|
stack.callback(self.cleanup_entry, name)
|
|
assert res == string
|
|
|
|
@mark.parametrize("lst", _build_test_list(list_tests, _get_fuzz(list)))
|
|
def test_list(self, lst: List[str]) -> None:
|
|
"""Save a list though the old config, recall it using the new config."""
|
|
lst = [x.replace("\r", "") for x in lst] # OldConfig on linux fails to store these correctly
|
|
if sys.platform == 'win32':
|
|
# old conf on windows replaces empty entries with spaces as a workaround for a bug. New conf does not
|
|
# So insert those spaces here, to ensure that it works otherwise.
|
|
lst = [e if len(e) > 0 else ' ' for e in lst]
|
|
|
|
name = self.KEY_PREFIX + f'list_test_{ hash("".join(lst)) }'
|
|
old_config.set(name, lst)
|
|
old_config.save()
|
|
|
|
self.__update_linuxconfig()
|
|
|
|
res = config.get_list(name)
|
|
with contextlib.ExitStack() as stack:
|
|
stack.callback(self.cleanup_entry, name)
|
|
assert res == lst
|
|
|
|
@mark.skipif(sys.platform == 'win32', reason="Old Windows config does not support bool types")
|
|
@mark.parametrize("b", bool_tests)
|
|
def test_bool(self, b: bool) -> None:
|
|
"""Save a bool though the old config, recall it using the new config."""
|
|
name = str(b)
|
|
old_config.set(name, b)
|
|
old_config.save()
|
|
self.__update_linuxconfig()
|
|
with contextlib.ExitStack() as stack:
|
|
stack.callback(self.cleanup_entry, name)
|
|
assert config.get_bool(name) == b
|