]> git.openstreetmap.org Git - nominatim.git/blob - test/python/api/search/test_api_search_query.py
replace PhraseType enum with simple int constants
[nominatim.git] / test / python / api / search / test_api_search_query.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) 2024 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 """
8 Tests for tokenized query data structures.
9 """
10 import pytest
11
12 from nominatim_api.search import query
13
14 class MyToken(query.Token):
15
16     def get_category(self):
17         return 'this', 'that'
18
19
20 def mktoken(tid: int):
21     return MyToken(penalty=3.0, token=tid, count=1, addr_count=1,
22                    lookup_word='foo')
23
24
25 @pytest.mark.parametrize('ptype,ttype', [(query.PHRASE_ANY, 'W'),
26                                          (query.PHRASE_AMENITY, 'Q'),
27                                          (query.PHRASE_STREET, 'w'),
28                                          (query.PHRASE_CITY, 'W'),
29                                          (query.PHRASE_COUNTRY, 'C'),
30                                          (query.PHRASE_POSTCODE, 'P')])
31 def test_phrase_compatible(ptype, ttype):
32     assert query._phrase_compatible_with(ptype, ttype, False)
33
34
35 @pytest.mark.parametrize('ptype', [query.PHRASE_COUNTRY, query.PHRASE_POSTCODE])
36 def test_phrase_incompatible(ptype):
37     assert not query._phrase_compatible_with(ptype, query.TOKEN_PARTIAL, True)
38
39
40 def test_query_node_empty():
41     qn = query.QueryNode(query.BREAK_PHRASE, query.PHRASE_ANY)
42
43     assert not qn.has_tokens(3, query.TOKEN_PARTIAL)
44     assert qn.get_tokens(3, query.TOKEN_WORD) is None
45
46
47 def test_query_node_with_content():
48     qn = query.QueryNode(query.BREAK_PHRASE, query.PHRASE_ANY)
49     qn.starting.append(query.TokenList(2, query.TOKEN_PARTIAL, [mktoken(100), mktoken(101)]))
50     qn.starting.append(query.TokenList(2, query.TOKEN_WORD, [mktoken(1000)]))
51
52     assert not qn.has_tokens(3, query.TOKEN_PARTIAL)
53     assert not qn.has_tokens(2, query.TOKEN_COUNTRY)
54     assert qn.has_tokens(2, query.TOKEN_PARTIAL)
55     assert qn.has_tokens(2, query.TOKEN_WORD)
56
57     assert qn.get_tokens(3, query.TOKEN_PARTIAL) is None
58     assert qn.get_tokens(2, query.TOKEN_COUNTRY) is None
59     assert len(qn.get_tokens(2, query.TOKEN_PARTIAL)) == 2
60     assert len(qn.get_tokens(2, query.TOKEN_WORD)) == 1
61
62
63 def test_query_struct_empty():
64     q = query.QueryStruct([])
65
66     assert q.num_token_slots() == 0
67
68
69 def test_query_struct_with_tokens():
70     q = query.QueryStruct([query.Phrase(query.PHRASE_ANY, 'foo bar')])
71     q.add_node(query.BREAK_WORD, query.PHRASE_ANY)
72     q.add_node(query.BREAK_END, query.PHRASE_ANY)
73
74     assert q.num_token_slots() == 2
75
76     q.add_token(query.TokenRange(0, 1), query.TOKEN_PARTIAL, mktoken(1))
77     q.add_token(query.TokenRange(1, 2), query.TOKEN_PARTIAL, mktoken(2))
78     q.add_token(query.TokenRange(1, 2), query.TOKEN_WORD, mktoken(99))
79     q.add_token(query.TokenRange(1, 2), query.TOKEN_WORD, mktoken(98))
80
81     assert q.get_tokens(query.TokenRange(0, 2), query.TOKEN_WORD) == []
82     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_WORD)) == 2
83
84     partials = q.get_partials_list(query.TokenRange(0, 2))
85
86     assert len(partials) == 2
87     assert [t.token for t in partials] == [1, 2]
88
89     assert q.find_lookup_word_by_id(4) == 'None'
90     assert q.find_lookup_word_by_id(99) == '[W]foo'
91
92
93 def test_query_struct_incompatible_token():
94     q = query.QueryStruct([query.Phrase(query.PHRASE_COUNTRY, 'foo bar')])
95     q.add_node(query.BREAK_WORD, query.PHRASE_COUNTRY)
96     q.add_node(query.BREAK_END, query.PHRASE_ANY)
97
98     q.add_token(query.TokenRange(0, 1), query.TOKEN_PARTIAL, mktoken(1))
99     q.add_token(query.TokenRange(1, 2), query.TOKEN_COUNTRY, mktoken(100))
100
101     assert q.get_tokens(query.TokenRange(0, 1), query.TOKEN_PARTIAL) == []
102     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_COUNTRY)) == 1
103
104
105 def test_query_struct_amenity_single_word():
106     q = query.QueryStruct([query.Phrase(query.PHRASE_AMENITY, 'bar')])
107     q.add_node(query.BREAK_END, query.PHRASE_ANY)
108
109     q.add_token(query.TokenRange(0, 1), query.TOKEN_PARTIAL, mktoken(1))
110     q.add_token(query.TokenRange(0, 1), query.TOKEN_NEAR_ITEM, mktoken(2))
111     q.add_token(query.TokenRange(0, 1), query.TOKEN_QUALIFIER, mktoken(3))
112
113     assert len(q.get_tokens(query.TokenRange(0, 1), query.TOKEN_PARTIAL)) == 1
114     assert len(q.get_tokens(query.TokenRange(0, 1), query.TOKEN_NEAR_ITEM)) == 1
115     assert len(q.get_tokens(query.TokenRange(0, 1), query.TOKEN_QUALIFIER)) == 0
116
117
118 def test_query_struct_amenity_two_words():
119     q = query.QueryStruct([query.Phrase(query.PHRASE_AMENITY, 'foo bar')])
120     q.add_node(query.BREAK_WORD, query.PHRASE_AMENITY)
121     q.add_node(query.BREAK_END, query.PHRASE_ANY)
122
123     for trange in [(0, 1), (1, 2)]:
124         q.add_token(query.TokenRange(*trange), query.TOKEN_PARTIAL, mktoken(1))
125         q.add_token(query.TokenRange(*trange), query.TOKEN_NEAR_ITEM, mktoken(2))
126         q.add_token(query.TokenRange(*trange), query.TOKEN_QUALIFIER, mktoken(3))
127
128     assert len(q.get_tokens(query.TokenRange(0, 1), query.TOKEN_PARTIAL)) == 1
129     assert len(q.get_tokens(query.TokenRange(0, 1), query.TOKEN_NEAR_ITEM)) == 0
130     assert len(q.get_tokens(query.TokenRange(0, 1), query.TOKEN_QUALIFIER)) == 1
131
132     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_PARTIAL)) == 1
133     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_NEAR_ITEM)) == 0
134     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_QUALIFIER)) == 1
135