Skip to content

Commit 3cb5336

Browse files
authored
test(mapping): add dedicated tests for compose_mappings
Cover gaps not exercised by the per-strategy test files: zero-strategy composition, single-strategy passthrough, all-miss path, three-strategy chain where the second fills and the third is not used, multiple events resolved by different strategies, duplicate-event deduplication, empty events, empty symbols, and result-key ordering.
1 parent 8c4981e commit 3cb5336

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

tests/test_mapping_compose.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""Tests for compose_mappings: strategy chaining and priority ordering.
2+
3+
These tests focus on compose_mappings behavior in isolation and in
4+
combination. Interaction with individual strategies (regex, manual,
5+
embedding, LLM) is covered in the dedicated per-strategy test files.
6+
"""
7+
from __future__ import annotations
8+
9+
from pm_rag.mapping import compose_mappings, manual_mapping, regex_mapping
10+
11+
12+
def test_zero_strategies_returns_empty_for_all_events() -> None:
13+
composed = compose_mappings()
14+
m = composed(["ev"], ["a", "b"])
15+
assert m == {"ev": []}
16+
17+
18+
def test_single_strategy_matches_direct_call() -> None:
19+
symbols = ["foo_handler", "bar_handler"]
20+
composed = compose_mappings(regex_mapping)
21+
direct = regex_mapping(["foo", "bar"], symbols)
22+
result = composed(["foo", "bar"], symbols)
23+
assert result == direct
24+
25+
26+
def test_all_strategies_miss_returns_empty_list_per_event() -> None:
27+
composed = compose_mappings(regex_mapping)
28+
m = composed(["totally_unknown"], ["a", "b"])
29+
assert m == {"totally_unknown": []}
30+
31+
32+
def test_second_fills_gap_third_result_not_used() -> None:
33+
symbols = ["a_handler", "b_handler", "c_handler"]
34+
manual1 = manual_mapping({"ev": ["b_handler"]})
35+
manual2 = manual_mapping({"ev": ["c_handler"]})
36+
composed = compose_mappings(regex_mapping, manual1, manual2)
37+
m = composed(["ev"], symbols)
38+
assert m["ev"] == [1]
39+
40+
41+
def test_different_events_resolved_by_different_strategies() -> None:
42+
symbols = ["pay_handler", "legacy.old"]
43+
overrides = {"obscure": ["legacy.old"]}
44+
composed = compose_mappings(regex_mapping, manual_mapping(overrides))
45+
m = composed(["pay", "obscure", "no_match"], symbols)
46+
assert m["pay"] == [0]
47+
assert m["obscure"] == [1]
48+
assert m["no_match"] == []
49+
50+
51+
def test_duplicate_events_collapsed_in_result() -> None:
52+
composed = compose_mappings(regex_mapping)
53+
m = composed(["x", "x", "x"], ["x_handler"])
54+
assert list(m.keys()) == ["x"]
55+
assert m["x"] == [0]
56+
57+
58+
def test_empty_events_returns_empty_dict() -> None:
59+
composed = compose_mappings(regex_mapping)
60+
assert composed([], ["a", "b"]) == {}
61+
62+
63+
def test_empty_symbols_all_strategies_miss() -> None:
64+
composed = compose_mappings(regex_mapping)
65+
m = composed(["ev"], [])
66+
assert m == {"ev": []}
67+
68+
69+
def test_event_order_preserved_in_result_keys() -> None:
70+
symbols = ["c_fn", "a_fn", "b_fn"]
71+
overrides = {"alpha": ["a_fn"], "beta": ["b_fn"], "gamma": ["c_fn"]}
72+
composed = compose_mappings(manual_mapping(overrides))
73+
events = ["gamma", "alpha", "beta"]
74+
m = composed(events, symbols)
75+
assert list(m.keys()) == events
76+
assert m["gamma"] == [0]
77+
assert m["alpha"] == [1]
78+
assert m["beta"] == [2]

0 commit comments

Comments
 (0)