]> git.openstreetmap.org Git - nominatim.git/blob - test/python/api/search/test_search_country.py
Merge pull request #3301 from lonvia/fix-class-search-regression
[nominatim.git] / test / python / api / search / test_search_country.py
1 # SPDX-License-Identifier: GPL-3.0-or-later
2 #
3 # This file is part of Nominatim. (https://nominatim.org)
4 #
5 # Copyright (C) 2023 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 """
8 Tests for running the country searcher.
9 """
10 import pytest
11
12 import nominatim.api as napi
13 from nominatim.api.types import SearchDetails
14 from nominatim.api.search.db_searches import CountrySearch
15 from nominatim.api.search.db_search_fields import WeightedStrings
16
17
18 def run_search(apiobj, frontend, global_penalty, ccodes,
19                country_penalties=None, details=SearchDetails()):
20     if country_penalties is None:
21         country_penalties = [0.0] * len(ccodes)
22
23     class MySearchData:
24         penalty = global_penalty
25         countries = WeightedStrings(ccodes, country_penalties)
26
27     search = CountrySearch(MySearchData())
28     api = frontend(apiobj, options=['search'])
29
30     async def run():
31         async with api._async_api.begin() as conn:
32             return await search.lookup(conn, details)
33
34     return api._loop.run_until_complete(run())
35
36
37 def test_find_from_placex(apiobj, frontend):
38     apiobj.add_placex(place_id=55, class_='boundary', type='administrative',
39                       rank_search=4, rank_address=4,
40                       name={'name': 'Lolaland'},
41                       country_code='yw',
42                       centroid=(10, 10),
43                       geometry='POLYGON((9.5 9.5, 9.5 10.5, 10.5 10.5, 10.5 9.5, 9.5 9.5))')
44
45     results = run_search(apiobj, frontend, 0.5, ['de', 'yw'], [0.0, 0.3])
46
47     assert len(results) == 1
48     assert results[0].place_id == 55
49     assert results[0].accuracy == 0.8
50
51 def test_find_from_fallback_countries(apiobj, frontend):
52     apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
53     apiobj.add_country_name('ro', {'name': 'România'})
54
55     results = run_search(apiobj, frontend, 0.0, ['ro'])
56
57     assert len(results) == 1
58     assert results[0].names == {'name': 'România'}
59
60
61 def test_find_none(apiobj, frontend):
62     assert len(run_search(apiobj, frontend, 0.0, ['xx'])) == 0
63
64
65 @pytest.mark.parametrize('coord,numres', [((0.5, 1), 1), ((10, 10), 0)])
66 def test_find_near(apiobj, frontend, coord, numres):
67     apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
68     apiobj.add_country_name('ro', {'name': 'România'})
69
70     results = run_search(apiobj, frontend, 0.0, ['ro'],
71                          details=SearchDetails(near=napi.Point(*coord),
72                                                near_radius=0.1))
73
74     assert len(results) == numres
75
76
77 class TestCountryParameters:
78
79     @pytest.fixture(autouse=True)
80     def fill_database(self, apiobj):
81         apiobj.add_placex(place_id=55, class_='boundary', type='administrative',
82                           rank_search=4, rank_address=4,
83                           name={'name': 'Lolaland'},
84                           country_code='yw',
85                           centroid=(10, 10),
86                           geometry='POLYGON((9.5 9.5, 9.5 10.5, 10.5 10.5, 10.5 9.5, 9.5 9.5))')
87         apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
88         apiobj.add_country_name('ro', {'name': 'România'})
89
90
91     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
92                                       napi.GeometryFormat.KML,
93                                       napi.GeometryFormat.SVG,
94                                       napi.GeometryFormat.TEXT])
95     @pytest.mark.parametrize('cc', ['yw', 'ro'])
96     def test_return_geometries(self, apiobj, frontend, geom, cc):
97         results = run_search(apiobj, frontend, 0.5, [cc],
98                              details=SearchDetails(geometry_output=geom))
99
100         assert len(results) == 1
101         assert geom.name.lower() in results[0].geometry
102
103
104     @pytest.mark.parametrize('pid,rids', [(76, [55]), (55, [])])
105     def test_exclude_place_id(self, apiobj, frontend, pid, rids):
106         results = run_search(apiobj, frontend, 0.5, ['yw', 'ro'],
107                              details=SearchDetails(excluded=[pid]))
108
109         assert [r.place_id for r in results] == rids
110
111
112     @pytest.mark.parametrize('viewbox,rids', [((9, 9, 11, 11), [55]),
113                                               ((-10, -10, -3, -3), [])])
114     def test_bounded_viewbox_in_placex(self, apiobj, frontend, viewbox, rids):
115         results = run_search(apiobj, frontend, 0.5, ['yw'],
116                              details=SearchDetails.from_kwargs({'viewbox': viewbox,
117                                                                 'bounded_viewbox': True}))
118
119         assert [r.place_id for r in results] == rids
120
121
122     @pytest.mark.parametrize('viewbox,numres', [((0, 0, 1, 1), 1),
123                                               ((-10, -10, -3, -3), 0)])
124     def test_bounded_viewbox_in_fallback(self, apiobj, frontend, viewbox, numres):
125         results = run_search(apiobj, frontend, 0.5, ['ro'],
126                              details=SearchDetails.from_kwargs({'viewbox': viewbox,
127                                                                 'bounded_viewbox': True}))
128
129         assert len(results) == numres