diff --git a/server/tests/test_config_portability.py b/server/tests/test_config_portability.py index 9dc964f..fea3d55 100644 --- a/server/tests/test_config_portability.py +++ b/server/tests/test_config_portability.py @@ -23,6 +23,8 @@ def test_save_and_load_utf8_lf(tmp_path: Path) -> None: 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)) @@ -34,6 +36,28 @@ def test_save_and_load_utf8_lf(tmp_path: Path) -> None: 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: @@ -56,6 +80,21 @@ def test_validate_rejects_unresolvable_host() -> None: 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)