1 # SPDX-License-Identifier: GPL-3.0-or-later
3 # This file is part of Nominatim. (https://nominatim.org)
5 # Copyright (C) 2026 by the Nominatim developer community.
6 # For a full list of authors see the git log.
8 Tests for the sanitizer that deletes names.
12 from nominatim_db.data.place_info import PlaceInfo
13 from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
16 class TestWithDefault:
18 @pytest.fixture(autouse=True)
19 def setup_country(self, def_config):
20 self.config = def_config
22 def run_sanitizer_on(self, type, **kwargs):
24 place = PlaceInfo({type: {k.replace('_', ':'): v for k, v in kwargs.items()},
25 'country_code': 'de', 'rank_address': 30})
27 sanitizer_args = {'step': 'delete-names'}
29 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
31 return {'name': sorted([(p.name, p.kind, p.suffix or '')
32 for p in place.searchable_names]),
33 'address': sorted([(p.name, p.kind, p.suffix or '')
34 for p in place.searchable_address])}
36 def test_on_name(self):
37 res = self.run_sanitizer_on('name', name='foo', ref='bar', ref_abc='baz')
39 assert res.get('name') == []
41 def test_on_address(self):
42 res = self.run_sanitizer_on('address', name='foo', ref='bar', ref_abc='baz')
44 assert res.get('address') == [('bar', 'ref', ''), ('baz', 'ref', 'abc'),
50 @pytest.fixture(autouse=True)
51 def setup_country(self, def_config):
52 self.config = def_config
54 def run_sanitizer_on(self, type, **kwargs):
56 place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
57 'country_code': 'de', 'rank_address': 30})
59 sanitizer_args = {'step': 'delete-names',
62 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
64 return sorted([(p.name, p.kind, p.suffix or '') for p in place.searchable_names])
66 def test_name_type(self):
67 res = self.run_sanitizer_on('name', name='foo', ref='bar', ref_abc='baz')
71 def test_address_type(self):
72 res = self.run_sanitizer_on('address', name='foo', ref='bar', ref_abc='baz')
74 assert res == [('bar', 'ref', ''), ('baz', 'ref', 'abc'),
80 @pytest.fixture(autouse=True)
81 def setup_country(self, def_config):
82 self.config = def_config
84 def run_sanitizer_on(self, filt, **kwargs):
86 place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
87 'country_code': 'de', 'rank_address': 30})
89 sanitizer_args = {'step': 'delete-names',
92 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
94 return sorted([(p.name, p.kind, p.suffix or '') for p in place.searchable_names])
96 def test_single_exact_name(self):
97 res = self.run_sanitizer_on(['name'], ref='foo', name='foo',
98 name_abc='bar', ref_abc='bar')
100 assert res == [('bar', 'ref', 'abc'), ('foo', 'ref', '')]
102 def test_single_pattern(self):
103 res = self.run_sanitizer_on(['.*name'],
104 name_fr='foo', ref_fr='foo', namexx_fr='bar',
105 shortname_fr='bar', name='bar')
107 assert res == [('bar', 'namexx', 'fr'), ('foo', 'ref', 'fr')]
109 def test_multiple_patterns(self):
110 res = self.run_sanitizer_on(['.*name', 'ref'],
111 name_fr='foo', ref_fr='foo', oldref_fr='foo',
112 namexx_fr='bar', shortname_fr='baz', name='baz')
114 assert res == [('bar', 'namexx', 'fr'), ('foo', 'oldref', 'fr')]
117 class TestRankAddress:
119 @pytest.fixture(autouse=True)
120 def setup_country(self, def_config):
121 self.config = def_config
123 def run_sanitizer_on(self, rank_addr, **kwargs):
125 place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
126 'country_code': 'de', 'rank_address': 30})
128 sanitizer_args = {'step': 'delete-names',
129 'filter-rank': rank_addr}
131 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
133 return sorted([(p.name, p.kind, p.suffix or '') for p in place.searchable_names])
135 def test_single_rank(self):
136 res = self.run_sanitizer_on('30', name='foo', ref='bar')
140 def test_single_rank_fail(self):
141 res = self.run_sanitizer_on('28', name='foo', ref='bar')
143 assert res == [('bar', 'ref', ''), ('foo', 'name', '')]
145 def test_ranged_rank_pass(self):
146 res = self.run_sanitizer_on('26-30', name='foo', ref='bar')
150 def test_ranged_rank_fail(self):
151 res = self.run_sanitizer_on('26-29', name='foo', ref='bar')
153 assert res == [('bar', 'ref', ''), ('foo', 'name', '')]
155 def test_mixed_rank_pass(self):
156 res = self.run_sanitizer_on(['4', '20-28', '30', '10-12'], name='foo', ref='bar')
160 def test_mixed_rank_fail(self):
161 res = self.run_sanitizer_on(['4-8', '10', '26-29', '18'], name='foo', ref='bar')
163 assert res == [('bar', 'ref', ''), ('foo', 'name', '')]
168 @pytest.fixture(autouse=True)
169 def setup_country(self, def_config):
170 self.config = def_config
172 def run_sanitizer_on(self, suffix, **kwargs):
174 place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
175 'country_code': 'de', 'rank_address': 30})
177 sanitizer_args = {'step': 'delete-names',
178 'filter-suffix': suffix}
180 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
182 return sorted([(p.name, p.kind, p.suffix or '') for p in place.searchable_names])
184 def test_single_suffix(self):
185 res = self.run_sanitizer_on('abc', name='foo', name_abc='foo',
186 name_pqr='bar', ref='bar', ref_abc='baz')
188 assert res == [('bar', 'name', 'pqr'), ('bar', 'ref', ''), ('foo', 'name', '')]
190 def test_multiple_suffix(self):
191 res = self.run_sanitizer_on(['abc.*', 'pqr'], name='foo', name_abcxx='foo',
192 ref_pqr='bar', name_pqrxx='baz')
194 assert res == [('baz', 'name', 'pqrxx'), ('foo', 'name', '')]
197 class TestCountryCodes:
199 @pytest.fixture(autouse=True)
200 def setup_country(self, def_config):
201 self.config = def_config
203 def run_sanitizer_on(self, country_code, **kwargs):
205 place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
206 'country_code': 'de', 'rank_address': 30})
208 sanitizer_args = {'step': 'delete-names',
209 'filter-country': country_code}
211 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
213 return sorted([(p.name, p.kind) for p in place.searchable_names])
215 def test_single_country_code_pass(self):
216 res = self.run_sanitizer_on('de', name='foo', ref='bar')
220 def test_single_country_code_fail(self):
221 res = self.run_sanitizer_on('in', name='foo', ref='bar')
223 assert res == [('bar', 'ref'), ('foo', 'name')]
225 def test_empty_country_code_list(self):
226 res = self.run_sanitizer_on([], name='foo', ref='bar')
228 assert res == [('bar', 'ref'), ('foo', 'name')]
230 def test_multiple_country_code_pass(self):
231 res = self.run_sanitizer_on(['in', 'de', 'fr'], name='foo', ref='bar')
235 def test_multiple_country_code_fail(self):
236 res = self.run_sanitizer_on(['in', 'au', 'fr'], name='foo', ref='bar')
238 assert res == [('bar', 'ref'), ('foo', 'name')]
241 class TestAllParameters:
243 @pytest.fixture(autouse=True)
244 def setup_country(self, def_config):
245 self.config = def_config
247 def run_sanitizer_on(self, country_code, rank_addr, suffix, **kwargs):
249 place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
250 'country_code': 'de', 'rank_address': 30})
253 'step': 'delete-names',
255 'filter-kind': ['name', 'ref'],
256 'filter-country': country_code,
257 'filter-rank': rank_addr,
258 'filter-suffix': suffix,
259 'filter-name': r'[\s\S]*',
262 PlaceSanitizer([sanitizer_args], self.config).process_names(place)
264 return sorted([(p.name, p.kind, p.suffix or '') for p in place.searchable_names])
266 def test_string_arguments_pass(self):
267 res = self.run_sanitizer_on('de', '25-30', r'[\s\S]*',
268 name='foo', ref='foo', name_abc='bar', ref_abc='baz')
272 def test_string_arguments_fail(self):
273 res = self.run_sanitizer_on('in', '25-30', r'[\s\S]*',
274 name='foo', ref='foo', name_abc='bar', ref_abc='baz')
276 assert res == [('bar', 'name', 'abc'), ('baz', 'ref', 'abc'),
277 ('foo', 'name', ''), ('foo', 'ref', '')]
279 def test_list_arguments_pass(self):
280 res = self.run_sanitizer_on(['de', 'in'], ['20-28', '30'], [r'abc.*', r'[\s\S]*'],
281 name='foo', ref='foo', name_abcxx='bar', ref_pqr='baz')
285 def test_list_arguments_fail(self):
286 res = self.run_sanitizer_on(['de', 'in'], ['14', '20-29'], [r'abc.*', r'pqr'],
287 name='foo', ref_abc='foo', name_abcxx='bar', ref_pqr='baz')
289 assert res == [('bar', 'name', 'abcxx'), ('baz', 'ref', 'pqr'),
290 ('foo', 'name', ''), ('foo', 'ref', 'abc')]
292 def test_mix_arguments_pass(self):
293 res = self.run_sanitizer_on('de', ['10', '20-28', '30'], r'[\s\S]*',
294 name_abc='foo', ref_abc='foo', name_abcxx='bar', ref_pqr='baz')
298 def test_mix_arguments_fail(self):
299 res = self.run_sanitizer_on(['de', 'in'], ['10', '20-28', '30'], r'abc.*',
300 name='foo', ref='foo', name_pqr='bar', ref_pqr='baz')
302 assert res == [('bar', 'name', 'pqr'), ('baz', 'ref', 'pqr'),
303 ('foo', 'name', ''), ('foo', 'ref', '')]