Files
2026-02-27 05:09:59 +01:00

77 lines
2.8 KiB
Python

# tests/test_parse_kv_string.py
import pytest
from hypothesis import given, strategies as st
from utils import parse_kv_string
# Helper to build a kv string using given separators
def build_kv_string(d: dict, pair_sep: str = "|", kv_sep: str = ":") -> str:
return f" {pair_sep} ".join(f"{k}{kv_sep}{v}" for k, v in d.items())
class TestParseKvString:
def test_empty_input_returns_empty_dict(self):
assert parse_kv_string("") == {}
assert parse_kv_string(None) == {} if False else parse_kv_string("") == {} # keep explicit empty-string behavior
def test_basic_parsing(self):
s = "a:1 | b:2 | c:3"
assert parse_kv_string(s) == {"a": "1", "b": "2", "c": "3"}
def test_whitespace_and_trimming(self):
s = " a : 1 | b:2 "
assert parse_kv_string(s) == {"a": "1", "b": "2"}
def test_duplicate_keys_last_wins(self):
s = "a:1 | a:2 | a:3"
assert parse_kv_string(s) == {"a": "3"}
def test_value_can_contain_kv_sep(self):
s = "path:/some:weird:path | other:ok"
# split only on first kv_sep
assert parse_kv_string(s) == {"path": "/some:weird:path", "other": "ok"}
def test_custom_separators(self):
s = "x=10; y=20;z=30"
assert parse_kv_string(s, pair_sep=";", kv_sep="=") == {"x": "10", "y": "20", "z": "30"}
def test_malformed_pair_skipped_when_not_strict(self):
s = "a:1 | badpair | b:2"
assert parse_kv_string(s, strict=False) == {"a": "1", "b": "2"}
def test_malformed_pair_raises_in_strict_mode(self):
s = "a:1 | badpair | b:2"
with pytest.raises(ValueError):
parse_kv_string(s, strict=True)
def test_empty_key_skipped_when_not_strict(self):
s = ":no_key | a:1"
assert parse_kv_string(s, strict=False) == {"a": "1"}
def test_empty_key_raises_in_strict_mode(self):
s = ":no_key | a:1"
with pytest.raises(ValueError):
parse_kv_string(s, strict=True)
@given(
st.dictionaries(
keys=st.text(min_size=1).filter(lambda t: "|" not in t and ":" not in t and t.strip() != "" and t.strip() == t),
values=st.text().filter(lambda t: "|" not in t and t.strip() == t),
max_size=100,
)
)
def test_roundtrip_with_default_separators(self, data):
"""
Property test: build a string from a dict using the default separators
and ensure parse_kv_string returns the original mapping.
"""
s = build_kv_string(data, pair_sep="|", kv_sep=":")
assert parse_kv_string(s) == data
def test_trailing_and_leading_empty_pairs_ignored(self):
s = " | a:1 | | b:2 | "
assert parse_kv_string(s) == {"a": "1", "b": "2"}
def test_pairs_with_only_whitespace_ignored(self):
s = " | |a:1| "
assert parse_kv_string(s) == {"a": "1"}