@@ -103,3 +103,74 @@ def test_no_match(self):
103103
104104 def test_empty_configs (self ):
105105 assert find_matching_config ('/tf' , []) is None
106+
107+
108+ # ---------------------------------------------------------------------------
109+ # find_matching_config – type-based and combined selectors
110+ # ---------------------------------------------------------------------------
111+
112+ class TestFindMatchingConfigByType :
113+
114+ _CONFIGS = [
115+ {'type' : 'geometry_msgs/msg/Twist' },
116+ {'pattern' : '/tf' , 'qos' : {'depth' : 100 }},
117+ {'type' : 'std_msgs/msg/String' , 'pattern' : '/chatter' },
118+ ]
119+
120+ def test_type_only_match (self ):
121+ # Any topic that publishes Twist should match the first entry.
122+ cfg = find_matching_config ('/cmd_vel' , self ._CONFIGS , 'geometry_msgs/msg/Twist' )
123+ assert cfg is not None
124+ assert cfg ['type' ] == 'geometry_msgs/msg/Twist'
125+
126+ def test_type_only_different_topic_name (self ):
127+ # A different topic name publishing Twist also matches.
128+ cfg = find_matching_config ('/robot/cmd_vel' , self ._CONFIGS , 'geometry_msgs/msg/Twist' )
129+ assert cfg is not None
130+ assert cfg ['type' ] == 'geometry_msgs/msg/Twist'
131+
132+ def test_type_only_wrong_type (self ):
133+ # The Twist-only entry should NOT match a String topic.
134+ # The pattern-only /tf entry should NOT match /cmd_vel.
135+ # The combined entry requires /chatter, so /cmd_vel also misses.
136+ cfg = find_matching_config ('/cmd_vel' , self ._CONFIGS , 'std_msgs/msg/String' )
137+ assert cfg is None
138+
139+ def test_type_no_type_name_provided (self ):
140+ # When type_name is not provided, type-only configs are skipped.
141+ cfg = find_matching_config ('/cmd_vel' , self ._CONFIGS )
142+ assert cfg is None
143+
144+ def test_pattern_config_unaffected_by_type (self ):
145+ # Pattern-only configs still match regardless of type_name.
146+ cfg = find_matching_config ('/tf' , self ._CONFIGS , 'tf2_msgs/msg/TFMessage' )
147+ assert cfg is not None
148+ assert cfg ['qos' ]['depth' ] == 100
149+
150+ def test_pattern_config_with_no_type_arg (self ):
151+ # Pattern-only configs still work when type_name is omitted.
152+ cfg = find_matching_config ('/tf' , self ._CONFIGS )
153+ assert cfg is not None
154+ assert cfg ['qos' ]['depth' ] == 100
155+
156+ def test_combined_both_match (self ):
157+ # Entry requires BOTH /chatter pattern AND String type.
158+ cfg = find_matching_config ('/chatter' , self ._CONFIGS , 'std_msgs/msg/String' )
159+ assert cfg is not None
160+ assert cfg ['type' ] == 'std_msgs/msg/String'
161+
162+ def test_combined_pattern_no_match (self ):
163+ # Type matches but topic name doesn't match the pattern.
164+ cfg = find_matching_config ('/wrong_topic' , self ._CONFIGS , 'std_msgs/msg/String' )
165+ assert cfg is None
166+
167+ def test_combined_type_no_match (self ):
168+ # Pattern matches (/chatter) but type is wrong.
169+ cfg = find_matching_config ('/chatter' , self ._CONFIGS , 'geometry_msgs/msg/Pose' )
170+ assert cfg is None
171+
172+ def test_entry_without_either_key_is_skipped (self ):
173+ configs = [{'max_frequency' : 5.0 }, {'pattern' : '/tf' }]
174+ cfg = find_matching_config ('/tf' , configs )
175+ assert cfg is not None
176+ assert 'pattern' in cfg
0 commit comments