Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: appengine/monorail/services/test/fulltext_helpers_test.py

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is govered by a BSD-style
3 # license that can be found in the LICENSE file or at
4 # https://developers.google.com/open-source/licenses/bsd
5
6 """Tests for the fulltext_helpers module."""
7
8 import unittest
9
10 import mox
11
12 from google.appengine.api import search
13
14 from proto import ast_pb2
15 from proto import tracker_pb2
16 from services import fulltext_helpers
17
18
19 TEXT_HAS = ast_pb2.QueryOp.TEXT_HAS
20 NOT_TEXT_HAS = ast_pb2.QueryOp.NOT_TEXT_HAS
21
22
23 class MockResult(object):
24
25 def __init__(self, doc_id):
26 self.doc_id = doc_id
27
28
29 class MockSearchResponse(object):
30 """Mock object that can be iterated over in batches."""
31
32 def __init__(self, results, cursor):
33 """Constructor.
34
35 Args:
36 results: list of strings for document IDs.
37 cursor: search.Cursor object, if there are more results to
38 retrieve in another round-trip. Or, None if there are not.
39 """
40 self.results = [MockResult(r) for r in results]
41 self.cursor = cursor
42
43 def __iter__(self):
44 """The response itself is an iterator over the results."""
45 return self.results.__iter__()
46
47
48 class FulltextHelpersTest(unittest.TestCase):
49
50 def setUp(self):
51 self.mox = mox.Mox()
52 self.any_field_fd = tracker_pb2.FieldDef(
53 field_name='any_field', field_type=tracker_pb2.FieldTypes.STR_TYPE)
54 self.summary_fd = tracker_pb2.FieldDef(
55 field_name='summary', field_type=tracker_pb2.FieldTypes.STR_TYPE)
56 self.milestone_fd = tracker_pb2.FieldDef(
57 field_name='milestone', field_type=tracker_pb2.FieldTypes.STR_TYPE,
58 field_id=123)
59 self.fulltext_fields = ['summary']
60
61 self.mock_index = self.mox.CreateMockAnything()
62 self.mox.StubOutWithMock(search, 'Index')
63 self.query = None
64
65 def tearDown(self):
66 self.mox.UnsetStubs()
67 self.mox.ResetAll()
68
69 def RecordQuery(self, query):
70 self.query = query
71
72 def testBuildFTSQuery_EmptyQueryConjunction(self):
73 query_ast_conj = ast_pb2.Conjunction()
74 fulltext_query = fulltext_helpers.BuildFTSQuery(
75 query_ast_conj, self.fulltext_fields)
76 self.assertEqual(None, fulltext_query)
77
78 def testBuildFTSQuery_NoFullTextConditions(self):
79 estimated_hours_fd = tracker_pb2.FieldDef(
80 field_name='estimate', field_type=tracker_pb2.FieldTypes.INT_TYPE,
81 field_id=124)
82 query_ast_conj = ast_pb2.Conjunction(conds=[
83 ast_pb2.MakeCond(TEXT_HAS, [estimated_hours_fd], [], [40])])
84 fulltext_query = fulltext_helpers.BuildFTSQuery(
85 query_ast_conj, self.fulltext_fields)
86 self.assertEqual(None, fulltext_query)
87
88 def testBuildFTSQuery_Normal(self):
89 query_ast_conj = ast_pb2.Conjunction(conds=[
90 ast_pb2.MakeCond(TEXT_HAS, [self.summary_fd], ['needle'], []),
91 ast_pb2.MakeCond(TEXT_HAS, [self.milestone_fd], ['Q3', 'Q4'], [])])
92 fulltext_query = fulltext_helpers.BuildFTSQuery(
93 query_ast_conj, self.fulltext_fields)
94 self.assertEqual(
95 '(summary:"needle") (custom_123:"Q3" OR custom_123:"Q4")',
96 fulltext_query)
97
98 def testBuildFTSQuery_WithQuotes(self):
99 query_ast_conj = ast_pb2.Conjunction(conds=[
100 ast_pb2.MakeCond(TEXT_HAS, [self.summary_fd], ['"needle haystack"'],
101 [])])
102 fulltext_query = fulltext_helpers.BuildFTSQuery(
103 query_ast_conj, self.fulltext_fields)
104 self.assertEqual('(summary:"needle haystack")', fulltext_query)
105
106 def testBuildFTSQuery_IngoreColonInText(self):
107 query_ast_conj = ast_pb2.Conjunction(conds=[
108 ast_pb2.MakeCond(TEXT_HAS, [self.summary_fd], ['"needle:haystack"'],
109 [])])
110 fulltext_query = fulltext_helpers.BuildFTSQuery(
111 query_ast_conj, self.fulltext_fields)
112 self.assertEqual('(summary:"needle haystack")', fulltext_query)
113
114 def testBuildFTSQuery_InvalidQuery(self):
115 query_ast_conj = ast_pb2.Conjunction(conds=[
116 ast_pb2.MakeCond(TEXT_HAS, [self.summary_fd], ['haystack"needle'], []),
117 ast_pb2.MakeCond(TEXT_HAS, [self.milestone_fd], ['Q3', 'Q4'], [])])
118 try:
119 fulltext_helpers.BuildFTSQuery(
120 query_ast_conj, self.fulltext_fields)
121 raise Exception('Expected AssertionError')
122 except AssertionError:
123 pass
124
125 def testBuildFTSQuery_SpecialPrefixQuery(self):
126 special_prefix = fulltext_helpers.NON_OP_PREFIXES[0]
127
128 # Test with summary field.
129 query_ast_conj = ast_pb2.Conjunction(conds=[
130 ast_pb2.MakeCond(TEXT_HAS, [self.summary_fd],
131 ['%s//google.com' % special_prefix], []),
132 ast_pb2.MakeCond(TEXT_HAS, [self.milestone_fd], ['Q3', 'Q4'], [])])
133 fulltext_query = fulltext_helpers.BuildFTSQuery(
134 query_ast_conj, self.fulltext_fields)
135 self.assertEqual(
136 '(summary:"%s//google.com") (custom_123:"Q3" OR custom_123:"Q4")' % (
137 special_prefix),
138 fulltext_query)
139
140 # Test with any field.
141 any_fd = tracker_pb2.FieldDef(
142 field_name=ast_pb2.ANY_FIELD,
143 field_type=tracker_pb2.FieldTypes.STR_TYPE)
144 query_ast_conj = ast_pb2.Conjunction(conds=[
145 ast_pb2.MakeCond(
146 TEXT_HAS, [any_fd], ['%s//google.com' % special_prefix], []),
147 ast_pb2.MakeCond(TEXT_HAS, [self.milestone_fd], ['Q3', 'Q4'], [])])
148 fulltext_query = fulltext_helpers.BuildFTSQuery(
149 query_ast_conj, self.fulltext_fields)
150 self.assertEqual(
151 '("%s//google.com") (custom_123:"Q3" OR custom_123:"Q4")' % (
152 special_prefix),
153 fulltext_query)
154
155 def testBuildFTSCondition_BuiltinField(self):
156 query_cond = ast_pb2.MakeCond(
157 TEXT_HAS, [self.summary_fd], ['needle'], [])
158 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
159 query_cond, self.fulltext_fields)
160 self.assertEqual('(summary:"needle")', fulltext_query_clause)
161
162 def testBuildFTSCondition_Negatation(self):
163 query_cond = ast_pb2.MakeCond(
164 NOT_TEXT_HAS, [self.summary_fd], ['needle'], [])
165 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
166 query_cond, self.fulltext_fields)
167 self.assertEqual('NOT (summary:"needle")', fulltext_query_clause)
168
169 def testBuildFTSCondition_QuickOR(self):
170 query_cond = ast_pb2.MakeCond(
171 TEXT_HAS, [self.summary_fd], ['needle', 'pin'], [])
172 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
173 query_cond, self.fulltext_fields)
174 self.assertEqual(
175 '(summary:"needle" OR summary:"pin")',
176 fulltext_query_clause)
177
178 def testBuildFTSCondition_NegatedQuickOR(self):
179 query_cond = ast_pb2.MakeCond(
180 NOT_TEXT_HAS, [self.summary_fd], ['needle', 'pin'], [])
181 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
182 query_cond, self.fulltext_fields)
183 self.assertEqual(
184 'NOT (summary:"needle" OR summary:"pin")',
185 fulltext_query_clause)
186
187 def testBuildFTSCondition_AnyField(self):
188 query_cond = ast_pb2.MakeCond(
189 TEXT_HAS, [self.any_field_fd], ['needle'], [])
190 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
191 query_cond, self.fulltext_fields)
192 self.assertEqual('("needle")', fulltext_query_clause)
193
194 def testBuildFTSCondition_NegatedAnyField(self):
195 query_cond = ast_pb2.MakeCond(
196 NOT_TEXT_HAS, [self.any_field_fd], ['needle'], [])
197 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
198 query_cond, self.fulltext_fields)
199 self.assertEqual('NOT ("needle")', fulltext_query_clause)
200
201 def testBuildFTSCondition_CrossProjectWithMultipleFieldDescriptors(self):
202 other_milestone_fd = tracker_pb2.FieldDef(
203 field_name='milestone', field_type=tracker_pb2.FieldTypes.STR_TYPE,
204 field_id=456)
205 query_cond = ast_pb2.MakeCond(
206 TEXT_HAS, [self.milestone_fd, other_milestone_fd], ['needle'], [])
207 fulltext_query_clause = fulltext_helpers._BuildFTSCondition(
208 query_cond, self.fulltext_fields)
209 self.assertEqual(
210 '(custom_123:"needle" OR custom_456:"needle")', fulltext_query_clause)
211
212 def SetUpComprehensiveSearch(self):
213 search.Index(name='search index name').AndReturn(
214 self.mock_index)
215 self.mock_index.search(mox.IgnoreArg()).WithSideEffects(
216 self.RecordQuery).AndReturn(
217 MockSearchResponse(['123', '234'], search.Cursor()))
218 self.mock_index.search(mox.IgnoreArg()).WithSideEffects(
219 self.RecordQuery).AndReturn(MockSearchResponse(['345'], None))
220
221 def testComprehensiveSearch(self):
222 self.SetUpComprehensiveSearch()
223 self.mox.ReplayAll()
224 project_ids = fulltext_helpers.ComprehensiveSearch(
225 'browser', 'search index name')
226 self.mox.VerifyAll()
227 self.assertItemsEqual([123, 234, 345], project_ids)
228
229
230 if __name__ == '__main__':
231 unittest.main()
OLDNEW
« no previous file with comments | « appengine/monorail/services/test/features_svc_test.py ('k') | appengine/monorail/services/test/issue_svc_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698