Files
Commonwealth-Online-Server/server/tests/test_config_portability.py
T

110 lines
4.0 KiB
Python

from __future__ import annotations
from pathlib import Path
import pytest
from config import (
Config,
ensure_writable_directory,
load_config,
save_config,
validate_config,
)
def test_save_and_load_utf8_lf(tmp_path: Path) -> None:
path = tmp_path / "commonwealth-server.json"
cfg = Config(
host="0.0.0.0",
port=7777,
server_name="Café Server",
server_description="résumé",
max_players=8,
log_verbosity="info",
admin_port=7779,
enable_gns_transport=True,
gns_bridge_path="/opt/commonwealth/libcommonwealth_online_gns_bridge.so",
)
save_config(cfg, str(path))
raw = path.read_bytes()
assert b"\r\n" not in raw
assert "Café Server".encode("utf-8") in raw
loaded = load_config(str(path))
assert loaded.server_name == "Café Server"
assert loaded.server_description == "résumé"
assert loaded.admin_port == 7779
assert loaded.enable_gns_transport is True
assert loaded.gns_bridge_path == "/opt/commonwealth/libcommonwealth_online_gns_bridge.so"
def test_gns_boolean_config_parsing_does_not_treat_false_string_as_true() -> None:
assert Config.from_dict({"enable_gns_transport": "false"}).enable_gns_transport is False
assert Config.from_dict({"enable_gns_transport": "off"}).enable_gns_transport is False
assert Config.from_dict({"enable_gns_transport": "0"}).enable_gns_transport is False
assert Config.from_dict({"enable_gns_transport": "true"}).enable_gns_transport is True
assert Config.from_dict({"enable_gns_transport": "yes"}).enable_gns_transport is True
assert Config.from_dict({"enable_gns_transport": 1}).enable_gns_transport is True
assert Config.from_dict({"enable_gns_transport": 0}).enable_gns_transport is False
with pytest.raises(ValueError, match="enable_gns_transport"):
Config.from_dict({"enable_gns_transport": "sometimes"})
def test_gns_bridge_path_normalizes_blank_to_none_and_rejects_nonstring() -> None:
assert Config.from_dict({"gns_bridge_path": ""}).gns_bridge_path is None
assert Config.from_dict({"gns_bridge_path": " "}).gns_bridge_path is None
assert Config.from_dict({"gns_bridge_path": None}).gns_bridge_path is None
with pytest.raises(ValueError, match="gns_bridge_path"):
Config.from_dict({"gns_bridge_path": 123})
def test_validate_rejects_bad_ports_and_max_players() -> None:
cfg = Config(port=70000, admin_port=7777, max_players=0)
ok, errors = validate_config(cfg)
assert not ok
assert any("port must be 1-65535" in error for error in errors)
assert any("max_players must be >= 1" in error for error in errors)
collide = Config(port=7777, admin_port=7777)
ok, errors = validate_config(collide)
assert not ok
assert any("admin_port must differ" in error for error in errors)
def test_validate_rejects_unresolvable_host() -> None:
cfg = Config(host="this-host-should-not-resolve.invalid")
ok, errors = validate_config(cfg)
assert not ok
assert any("not a valid IPv4" in error for error in errors)
def test_gns_requires_explicit_ipv4_bind_host() -> None:
explicit = Config(host="127.0.0.1", enable_gns_transport=True)
ok, errors = validate_config(explicit)
assert ok, errors
wildcard = Config(host="0.0.0.0", enable_gns_transport=True)
ok, errors = validate_config(wildcard)
assert ok, errors
hostname = Config(host="localhost", enable_gns_transport=True)
ok, errors = validate_config(hostname)
assert not ok
assert any("explicit IPv4 bind address" in error for error in errors)
def test_ensure_writable_directory(tmp_path: Path) -> None:
target = tmp_path / "state"
ensure_writable_directory(target)
assert target.is_dir()
assert not (target / ".commonwealth-write-probe").exists()
def test_load_invalid_json(tmp_path: Path) -> None:
path = tmp_path / "bad.json"
path.write_text("{not json", encoding="utf-8")
with pytest.raises(Exception):
load_config(str(path))