diff --git a/pyproject.toml b/pyproject.toml index 9fe44bc..bfdd79b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,7 @@ dev = [ "pyright>=1.1.400", "pytest>=8.3.5", "ruff>=0.11.10", + "toml>=0.10.2", ] [tool.uv.sources] diff --git a/tests/test_arg_opts.py b/tests/test_arg_opts.py index f0ecf7d..b1e1abc 100644 --- a/tests/test_arg_opts.py +++ b/tests/test_arg_opts.py @@ -36,7 +36,7 @@ def test_args_empty(): ) def test_args_single_int(name: str, arg_tag: str): """ - Test command line arguments for single integer option. + Test command line arguments of single integer option. """ sys.argv += [arg_tag, '0'] assert boot.load_from_args() == {name: 0} @@ -58,7 +58,7 @@ def test_args_single_int(name: str, arg_tag: str): ) def test_args_single_str(name: str, arg_tag: str): """ - Test command line arguments for single string option. + Test command line arguments of single string option. """ sys.argv += [arg_tag, ''] assert boot.load_from_args() == {name: ''} @@ -81,7 +81,7 @@ def test_args_single_str(name: str, arg_tag: str): ) def test_args_single_bool(name: str, arg_tag: str): """ - Test command line arguments for single boolean option. + Test command line arguments of single boolean option. """ sys.argv += [arg_tag] assert boot.load_from_args() == {name: True} diff --git a/tests/test_cfg_opts.py b/tests/test_cfg_opts.py new file mode 100644 index 0000000..4458209 --- /dev/null +++ b/tests/test_cfg_opts.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import json +import toml +import yaml +import pytest +import tempfile +from src import boot + + +@pytest.fixture(autouse=True) +def config_init(): + boot.init_opts() + yield + + +def verify_config(data: dict, excepted: dict) -> None: + """ + Verify configure loading from different sequence formats. + """ + files = { + '.json': json.dumps(data), + '.toml': toml.dumps(data), + '.yaml': (tmp := yaml.dump(data)), + '.unknown': tmp, # YAML format in default + } + for suffix, content in files.items(): + with tempfile.NamedTemporaryFile(mode='w', suffix=suffix) as fp: + fp.write(content) + fp.flush() + assert boot.load_from_config(fp.name) == excepted + + +def test_config_empty(): + """ + Test configuration file in the empty case. + """ + verify_config({}, {}) + + +@pytest.mark.parametrize( + 'name, cfg_tag', + [ + ('port', 'port'), + ('max_username', 'max-username'), + ('max_chat_message', 'max-chat-message'), + ], +) +def test_config_single_int(name: str, cfg_tag: str): + """ + Test configuration file of single integer option. + """ + verify_config({cfg_tag: 0}, {name: 0}) + verify_config({cfg_tag: 42}, {name: 42}) + + +@pytest.mark.parametrize( + 'name, cfg_tag', + [ + ('config', 'config'), + ('password', 'password'), + ('motd', 'motd'), + ('salt', 'salt'), + ('listen_ipv4', 'listen-ipv4'), + ('listen_ipv6', 'listen-ipv6'), + ], +) +def test_config_single_str(name: str, cfg_tag: str): + """ + Test configuration file of single string option. + """ + verify_config({cfg_tag: ''}, {name: ''}) + verify_config({cfg_tag: 'TeSt \n0123456789\t'}, {name: 'TeSt \n0123456789\t'}) + + +@pytest.mark.parametrize( + 'name, cfg_tag', + [ + ('random_salt', 'random-salt'), + ('isolate_rooms', 'isolate-rooms'), + ('disable_chat', 'disable-chat'), + ('disable_ready', 'disable-ready'), + ('enable_stats', 'enable-stats'), + ('enable_tls', 'enable-tls'), + ('persistent', 'persistent'), + ], +) +def test_config_single_bool(name: str, cfg_tag: str): + """ + Test configuration file of single boolean option. + """ + verify_config({cfg_tag: True}, {name: True}) + verify_config({cfg_tag: False}, {name: False}) + + +def test_config_full(): + """ + Test all configuration file options. + """ + cfg_data = { + 'config': 'config.yml', + 'port': 8999, + 'password': 'PASSWD', + 'motd': 'MESSAGE', + 'salt': 'SALT', + 'random-salt': False, + 'isolate-rooms': True, + 'disable-chat': False, + 'disable-ready': True, + 'enable-stats': False, + 'enable-tls': True, + 'persistent': False, + 'max-username': 120, + 'max-chat-message': 240, + 'listen-ipv4': '127.0.0.1', + 'listen-ipv6': '::1', + } + excepted_opts = { + 'config': 'config.yml', + 'port': 8999, + 'password': 'PASSWD', + 'motd': 'MESSAGE', + 'salt': 'SALT', + 'random_salt': False, + 'isolate_rooms': True, + 'disable_chat': False, + 'disable_ready': True, + 'enable_stats': False, + 'enable_tls': True, + 'persistent': False, + 'max_username': 120, + 'max_chat_message': 240, + 'listen_ipv4': '127.0.0.1', + 'listen_ipv6': '::1', + } + verify_config(cfg_data, excepted_opts) diff --git a/uv.lock b/uv.lock index 3ccb67a..34f39b5 100644 --- a/uv.lock +++ b/uv.lock @@ -409,6 +409,7 @@ dev = [ { name = "pyright" }, { name = "pytest" }, { name = "ruff" }, + { name = "toml" }, ] [package.metadata] @@ -422,6 +423,16 @@ dev = [ { name = "pyright", specifier = ">=1.1.400" }, { name = "pytest", specifier = ">=8.3.5" }, { name = "ruff", specifier = ">=0.11.10" }, + { name = "toml", specifier = ">=0.10.2" }, +] + +[[package]] +name = "toml" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" }, ] [[package]]