Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 1 | # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | # Use of this source code is governed 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 ast2ast module.""" |
| 7 | from __future__ import print_function |
| 8 | from __future__ import division |
| 9 | from __future__ import absolute_import |
| 10 | |
| 11 | import unittest |
| 12 | |
| 13 | from proto import ast_pb2 |
| 14 | from proto import tracker_pb2 |
| 15 | from search import ast2ast |
| 16 | from search import query2ast |
| 17 | from services import service_manager |
| 18 | from testing import fake |
| 19 | from tracker import tracker_bizobj |
| 20 | |
| 21 | |
| 22 | BUILTIN_ISSUE_FIELDS = query2ast.BUILTIN_ISSUE_FIELDS |
| 23 | ANY_FIELD = query2ast.BUILTIN_ISSUE_FIELDS['any_field'] |
| 24 | OWNER_FIELD = query2ast.BUILTIN_ISSUE_FIELDS['owner'] |
| 25 | OWNER_ID_FIELD = query2ast.BUILTIN_ISSUE_FIELDS['owner_id'] |
| 26 | |
| 27 | |
| 28 | class AST2ASTTest(unittest.TestCase): |
| 29 | |
| 30 | def setUp(self): |
| 31 | self.cnxn = 'fake cnxn' |
| 32 | self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
| 33 | self.config.component_defs.append( |
| 34 | tracker_bizobj.MakeComponentDef( |
| 35 | 101, 789, 'UI', 'doc', False, [], [], 0, 0)) |
| 36 | self.config.component_defs.append( |
| 37 | tracker_bizobj.MakeComponentDef( |
| 38 | 102, 789, 'UI>Search', 'doc', False, [], [], 0, 0)) |
| 39 | self.config.component_defs.append( |
| 40 | tracker_bizobj.MakeComponentDef( |
| 41 | 201, 789, 'DB', 'doc', False, [], [], 0, 0)) |
| 42 | self.config.component_defs.append( |
| 43 | tracker_bizobj.MakeComponentDef( |
| 44 | 301, 789, 'Search', 'doc', False, [], [], 0, 0)) |
| 45 | self.services = service_manager.Services( |
| 46 | user=fake.UserService(), |
| 47 | project=fake.ProjectService(), |
| 48 | issue=fake.IssueService(), |
| 49 | config=fake.ConfigService(), |
| 50 | features=fake.FeaturesService()) |
| 51 | self.services.user.TestAddUser('a@example.com', 111) |
| 52 | self.project = self.services.project.TestAddProject( |
| 53 | 'proj', project_id=100) |
| 54 | |
| 55 | def testPreprocessAST_EmptyAST(self): |
| 56 | ast = ast_pb2.QueryAST() # No conjunctions in it. |
| 57 | new_ast = ast2ast.PreprocessAST( |
| 58 | self.cnxn, ast, [789], self.services, self.config) |
| 59 | self.assertEqual(ast, new_ast) |
| 60 | |
| 61 | def testPreprocessAST_Normal(self): |
| 62 | open_field = BUILTIN_ISSUE_FIELDS['open'] |
| 63 | label_field = BUILTIN_ISSUE_FIELDS['label'] |
| 64 | label_id_field = BUILTIN_ISSUE_FIELDS['label_id'] |
| 65 | status_id_field = BUILTIN_ISSUE_FIELDS['status_id'] |
| 66 | conds = [ |
| 67 | ast_pb2.MakeCond(ast_pb2.QueryOp.EQ, [open_field], [], []), |
| 68 | ast_pb2.MakeCond(ast_pb2.QueryOp.EQ, [label_field], ['Hot'], [])] |
| 69 | self.services.config.TestAddLabelsDict({'Hot': 0}) |
| 70 | |
| 71 | ast = ast_pb2.QueryAST() |
| 72 | ast.conjunctions.append(ast_pb2.Conjunction(conds=conds)) |
| 73 | new_ast = ast2ast.PreprocessAST( |
| 74 | self.cnxn, ast, [789], self.services, self.config) |
| 75 | self.assertEqual(2, len(new_ast.conjunctions[0].conds)) |
| 76 | new_cond_1, new_cond_2 = new_ast.conjunctions[0].conds |
| 77 | self.assertEqual(ast_pb2.QueryOp.NE, new_cond_1.op) |
| 78 | self.assertEqual([status_id_field], new_cond_1.field_defs) |
| 79 | self.assertEqual([7, 8, 9], new_cond_1.int_values) |
| 80 | self.assertEqual([], new_cond_1.str_values) |
| 81 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond_2.op) |
| 82 | self.assertEqual([label_id_field], new_cond_2.field_defs) |
| 83 | self.assertEqual([0], new_cond_2.int_values) |
| 84 | self.assertEqual([], new_cond_2.str_values) |
| 85 | |
| 86 | def testPreprocessIsOpenCond(self): |
| 87 | open_field = BUILTIN_ISSUE_FIELDS['open'] |
| 88 | status_id_field = BUILTIN_ISSUE_FIELDS['status_id'] |
| 89 | |
| 90 | # is:open -> status_id!=closed_status_ids |
| 91 | cond = ast_pb2.MakeCond( |
| 92 | ast_pb2.QueryOp.EQ, [open_field], [], []) |
| 93 | new_cond = ast2ast._PreprocessIsOpenCond( |
| 94 | self.cnxn, cond, [789], self.services, self.config, True) |
| 95 | self.assertEqual(ast_pb2.QueryOp.NE, new_cond.op) |
| 96 | self.assertEqual([status_id_field], new_cond.field_defs) |
| 97 | self.assertEqual([7, 8, 9], new_cond.int_values) |
| 98 | self.assertEqual([], new_cond.str_values) |
| 99 | |
| 100 | # -is:open -> status_id=closed_status_ids |
| 101 | cond = ast_pb2.MakeCond( |
| 102 | ast_pb2.QueryOp.NE, [open_field], [], []) |
| 103 | new_cond = ast2ast._PreprocessIsOpenCond( |
| 104 | self.cnxn, cond, [789], self.services, self.config, True) |
| 105 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 106 | self.assertEqual([status_id_field], new_cond.field_defs) |
| 107 | self.assertEqual([7, 8, 9], new_cond.int_values) |
| 108 | self.assertEqual([], new_cond.str_values) |
| 109 | |
| 110 | def testPreprocessBlockedOnCond_WithSingleProjectID(self): |
| 111 | blockedon_field = BUILTIN_ISSUE_FIELDS['blockedon'] |
| 112 | blockedon_id_field = BUILTIN_ISSUE_FIELDS['blockedon_id'] |
| 113 | self.services.project.TestAddProject('Project1', project_id=1) |
| 114 | issue1 = fake.MakeTestIssue( |
| 115 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 116 | issue_id=101) |
| 117 | issue2 = fake.MakeTestIssue( |
| 118 | project_id=1, local_id=2, summary='sum', status='new', owner_id=2, |
| 119 | issue_id=102) |
| 120 | self.services.issue.TestAddIssue(issue1) |
| 121 | self.services.issue.TestAddIssue(issue2) |
| 122 | |
| 123 | for local_ids, expected in ( |
| 124 | (['1'], [101]), # One existing issue. |
| 125 | (['Project1:1'], [101]), # One existing issue with project prefix. |
| 126 | (['1', '2'], [101, 102]), # Two existing issues. |
| 127 | (['3'], [])): # Non-existant issue. |
| 128 | cond = ast_pb2.MakeCond( |
| 129 | ast_pb2.QueryOp.TEXT_HAS, [blockedon_field], local_ids, []) |
| 130 | new_cond = ast2ast._PreprocessBlockedOnCond( |
| 131 | self.cnxn, cond, [1], self.services, None, True) |
| 132 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 133 | self.assertEqual([blockedon_id_field], new_cond.field_defs) |
| 134 | self.assertEqual(expected, new_cond.int_values) |
| 135 | self.assertEqual([], new_cond.str_values) |
| 136 | |
| 137 | def testPreprocessBlockedOnCond_WithMultipleProjectIDs(self): |
| 138 | blockedon_field = BUILTIN_ISSUE_FIELDS['blockedon'] |
| 139 | blockedon_id_field = BUILTIN_ISSUE_FIELDS['blockedon_id'] |
| 140 | self.services.project.TestAddProject('Project1', project_id=1) |
| 141 | self.services.project.TestAddProject('Project2', project_id=2) |
| 142 | issue1 = fake.MakeTestIssue( |
| 143 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 144 | issue_id=101) |
| 145 | issue2 = fake.MakeTestIssue( |
| 146 | project_id=2, local_id=2, summary='sum', status='new', owner_id=2, |
| 147 | issue_id=102) |
| 148 | self.services.issue.TestAddIssue(issue1) |
| 149 | self.services.issue.TestAddIssue(issue2) |
| 150 | |
| 151 | for local_ids, expected in ( |
| 152 | (['Project1:1'], [101]), |
| 153 | (['Project1:1', 'Project2:2'], [101, 102])): |
| 154 | cond = ast_pb2.MakeCond( |
| 155 | ast_pb2.QueryOp.TEXT_HAS, [blockedon_field], local_ids, []) |
| 156 | new_cond = ast2ast._PreprocessBlockedOnCond( |
| 157 | self.cnxn, cond, [1, 2], self.services, None, True) |
| 158 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 159 | self.assertEqual([blockedon_id_field], new_cond.field_defs) |
| 160 | self.assertEqual(expected, new_cond.int_values) |
| 161 | self.assertEqual([], new_cond.str_values) |
| 162 | |
| 163 | def testPreprocessBlockedOnCond_WithMultipleProjectIDs_NoPrefix(self): |
| 164 | blockedon_field = BUILTIN_ISSUE_FIELDS['blockedon'] |
| 165 | self.services.project.TestAddProject('Project1', project_id=1) |
| 166 | self.services.project.TestAddProject('Project2', project_id=2) |
| 167 | issue1 = fake.MakeTestIssue( |
| 168 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 169 | issue_id=101) |
| 170 | issue2 = fake.MakeTestIssue( |
| 171 | project_id=2, local_id=2, summary='sum', status='new', owner_id=2, |
| 172 | issue_id=102) |
| 173 | self.services.issue.TestAddIssue(issue1) |
| 174 | self.services.issue.TestAddIssue(issue2) |
| 175 | |
| 176 | for local_ids in (['1'], ['1', '2'], ['3']): |
| 177 | cond = ast_pb2.MakeCond( |
| 178 | ast_pb2.QueryOp.TEXT_HAS, [blockedon_field], local_ids, []) |
| 179 | with self.assertRaises(ValueError) as cm: |
| 180 | ast2ast._PreprocessBlockedOnCond( |
| 181 | self.cnxn, cond, [1, 2], self.services, None, True) |
| 182 | self.assertEqual( |
| 183 | 'Searching for issues accross multiple/all projects without ' |
| 184 | 'project prefixes is ambiguous and is currently not supported.', |
| 185 | cm.exception.message) |
| 186 | |
| 187 | def testPreprocessBlockedOnCond_WithExternalIssues(self): |
| 188 | blockedon_field = BUILTIN_ISSUE_FIELDS['blockedon'] |
| 189 | blockedon_id_field = BUILTIN_ISSUE_FIELDS['blockedon_id'] |
| 190 | self.services.project.TestAddProject('Project1', project_id=1) |
| 191 | issue1 = fake.MakeTestIssue( |
| 192 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 193 | issue_id=101) |
| 194 | issue2 = fake.MakeTestIssue( |
| 195 | project_id=1, local_id=2, summary='sum', status='new', owner_id=2, |
| 196 | issue_id=102) |
| 197 | self.services.issue.TestAddIssue(issue1) |
| 198 | self.services.issue.TestAddIssue(issue2) |
| 199 | |
| 200 | for local_ids, expected_issues, expected_ext_issues in ( |
| 201 | (['b/1234'], [], ['b/1234']), |
| 202 | (['Project1:1', 'b/1234'], [101], ['b/1234']), |
| 203 | (['1', 'b/1234', 'b/1551', 'Project1:2'], |
| 204 | [101, 102], ['b/1234', 'b/1551'])): |
| 205 | cond = ast_pb2.MakeCond( |
| 206 | ast_pb2.QueryOp.TEXT_HAS, [blockedon_field], local_ids, []) |
| 207 | new_cond = ast2ast._PreprocessBlockedOnCond( |
| 208 | self.cnxn, cond, [1], self.services, None, True) |
| 209 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 210 | self.assertEqual([blockedon_id_field], new_cond.field_defs) |
| 211 | self.assertEqual(expected_issues, new_cond.int_values) |
| 212 | self.assertEqual(expected_ext_issues, new_cond.str_values) |
| 213 | |
| 214 | def testPreprocessIsBlockedCond(self): |
| 215 | blocked_field = BUILTIN_ISSUE_FIELDS['blockedon_id'] |
| 216 | for input_op, expected_op in ( |
| 217 | (ast_pb2.QueryOp.EQ, ast_pb2.QueryOp.IS_DEFINED), |
| 218 | (ast_pb2.QueryOp.NE, ast_pb2.QueryOp.IS_NOT_DEFINED)): |
| 219 | cond = ast_pb2.MakeCond( |
| 220 | input_op, [blocked_field], [], []) |
| 221 | new_cond = ast2ast._PreprocessIsBlockedCond( |
| 222 | self.cnxn, cond, [100], self.services, None, True) |
| 223 | self.assertEqual(expected_op, new_cond.op) |
| 224 | self.assertEqual([blocked_field], new_cond.field_defs) |
| 225 | self.assertEqual([], new_cond.int_values) |
| 226 | self.assertEqual([], new_cond.str_values) |
| 227 | |
| 228 | def testPreprocessHasBlockedOnCond(self): |
| 229 | blocked_field = BUILTIN_ISSUE_FIELDS['blockedon_id'] |
| 230 | for op in (ast_pb2.QueryOp.IS_DEFINED, ast_pb2.QueryOp.IS_NOT_DEFINED): |
| 231 | cond = ast_pb2.MakeCond(op, [blocked_field], [], []) |
| 232 | new_cond = ast2ast._PreprocessBlockedOnCond( |
| 233 | self.cnxn, cond, [100], self.services, None, True) |
| 234 | self.assertEqual(op, op) |
| 235 | self.assertEqual([blocked_field], new_cond.field_defs) |
| 236 | self.assertEqual([], new_cond.int_values) |
| 237 | self.assertEqual([], new_cond.str_values) |
| 238 | |
| 239 | def testPreprocessHasBlockingCond(self): |
| 240 | blocking_field = BUILTIN_ISSUE_FIELDS['blocking_id'] |
| 241 | for op in (ast_pb2.QueryOp.IS_DEFINED, ast_pb2.QueryOp.IS_NOT_DEFINED): |
| 242 | cond = ast_pb2.MakeCond(op, [blocking_field], [], []) |
| 243 | new_cond = ast2ast._PreprocessBlockingCond( |
| 244 | self.cnxn, cond, [100], self.services, None, True) |
| 245 | self.assertEqual(op, op) |
| 246 | self.assertEqual([blocking_field], new_cond.field_defs) |
| 247 | self.assertEqual([], new_cond.int_values) |
| 248 | self.assertEqual([], new_cond.str_values) |
| 249 | |
| 250 | def testPreprocessBlockingCond_WithSingleProjectID(self): |
| 251 | blocking_field = BUILTIN_ISSUE_FIELDS['blocking'] |
| 252 | blocking_id_field = BUILTIN_ISSUE_FIELDS['blocking_id'] |
| 253 | self.services.project.TestAddProject('Project1', project_id=1) |
| 254 | issue1 = fake.MakeTestIssue( |
| 255 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 256 | issue_id=101) |
| 257 | issue2 = fake.MakeTestIssue( |
| 258 | project_id=1, local_id=2, summary='sum', status='new', owner_id=2, |
| 259 | issue_id=102) |
| 260 | self.services.issue.TestAddIssue(issue1) |
| 261 | self.services.issue.TestAddIssue(issue2) |
| 262 | |
| 263 | for local_ids, expected in ( |
| 264 | (['1'], [101]), # One existing issue. |
| 265 | (['Project1:1'], [101]), # One existing issue with project prefix. |
| 266 | (['1', '2'], [101, 102]), # Two existing issues. |
| 267 | (['3'], [])): # Non-existant issue. |
| 268 | cond = ast_pb2.MakeCond( |
| 269 | ast_pb2.QueryOp.TEXT_HAS, [blocking_field], local_ids, []) |
| 270 | new_cond = ast2ast._PreprocessBlockingCond( |
| 271 | self.cnxn, cond, [1], self.services, None, True) |
| 272 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 273 | self.assertEqual([blocking_id_field], new_cond.field_defs) |
| 274 | self.assertEqual(expected, new_cond.int_values) |
| 275 | self.assertEqual([], new_cond.str_values) |
| 276 | |
| 277 | def testPreprocessBlockingCond_WithMultipleProjectIDs(self): |
| 278 | blocking_field = BUILTIN_ISSUE_FIELDS['blocking'] |
| 279 | blocking_id_field = BUILTIN_ISSUE_FIELDS['blocking_id'] |
| 280 | self.services.project.TestAddProject('Project1', project_id=1) |
| 281 | self.services.project.TestAddProject('Project2', project_id=2) |
| 282 | issue1 = fake.MakeTestIssue( |
| 283 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 284 | issue_id=101) |
| 285 | issue2 = fake.MakeTestIssue( |
| 286 | project_id=2, local_id=2, summary='sum', status='new', owner_id=2, |
| 287 | issue_id=102) |
| 288 | self.services.issue.TestAddIssue(issue1) |
| 289 | self.services.issue.TestAddIssue(issue2) |
| 290 | |
| 291 | for local_ids, expected in ( |
| 292 | (['Project1:1'], [101]), |
| 293 | (['Project1:1', 'Project2:2'], [101, 102])): |
| 294 | cond = ast_pb2.MakeCond( |
| 295 | ast_pb2.QueryOp.TEXT_HAS, [blocking_field], local_ids, []) |
| 296 | new_cond = ast2ast._PreprocessBlockingCond( |
| 297 | self.cnxn, cond, [1, 2], self.services, None, True) |
| 298 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 299 | self.assertEqual([blocking_id_field], new_cond.field_defs) |
| 300 | self.assertEqual(expected, new_cond.int_values) |
| 301 | self.assertEqual([], new_cond.str_values) |
| 302 | |
| 303 | def testPreprocessBlockingCond_WithMultipleProjectIDs_NoPrefix(self): |
| 304 | blocking_field = BUILTIN_ISSUE_FIELDS['blocking'] |
| 305 | self.services.project.TestAddProject('Project1', project_id=1) |
| 306 | self.services.project.TestAddProject('Project2', project_id=2) |
| 307 | issue1 = fake.MakeTestIssue( |
| 308 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 309 | issue_id=101) |
| 310 | issue2 = fake.MakeTestIssue( |
| 311 | project_id=2, local_id=2, summary='sum', status='new', owner_id=2, |
| 312 | issue_id=102) |
| 313 | self.services.issue.TestAddIssue(issue1) |
| 314 | self.services.issue.TestAddIssue(issue2) |
| 315 | |
| 316 | for local_ids in (['1'], ['1', '2'], ['3']): |
| 317 | cond = ast_pb2.MakeCond( |
| 318 | ast_pb2.QueryOp.TEXT_HAS, [blocking_field], local_ids, []) |
| 319 | with self.assertRaises(ValueError) as cm: |
| 320 | ast2ast._PreprocessBlockingCond( |
| 321 | self.cnxn, cond, [1, 2], self.services, None, True) |
| 322 | self.assertEqual( |
| 323 | 'Searching for issues accross multiple/all projects without ' |
| 324 | 'project prefixes is ambiguous and is currently not supported.', |
| 325 | cm.exception.message) |
| 326 | |
| 327 | def testPreprocessBlockingCond_WithExternalIssues(self): |
| 328 | blocking_field = BUILTIN_ISSUE_FIELDS['blocking'] |
| 329 | blocking_id_field = BUILTIN_ISSUE_FIELDS['blocking_id'] |
| 330 | self.services.project.TestAddProject('Project1', project_id=1) |
| 331 | issue1 = fake.MakeTestIssue( |
| 332 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 333 | issue_id=101) |
| 334 | issue2 = fake.MakeTestIssue( |
| 335 | project_id=1, local_id=2, summary='sum', status='new', owner_id=2, |
| 336 | issue_id=102) |
| 337 | self.services.issue.TestAddIssue(issue1) |
| 338 | self.services.issue.TestAddIssue(issue2) |
| 339 | |
| 340 | for local_ids, expected_issues, expected_ext_issues in ( |
| 341 | (['b/1234'], [], ['b/1234']), |
| 342 | (['Project1:1', 'b/1234'], [101], ['b/1234']), |
| 343 | (['1', 'b/1234', 'b/1551', 'Project1:2'], |
| 344 | [101, 102], ['b/1234', 'b/1551'])): |
| 345 | cond = ast_pb2.MakeCond( |
| 346 | ast_pb2.QueryOp.TEXT_HAS, [blocking_field], local_ids, []) |
| 347 | new_cond = ast2ast._PreprocessBlockingCond( |
| 348 | self.cnxn, cond, [1], self.services, None, True) |
| 349 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 350 | self.assertEqual([blocking_id_field], new_cond.field_defs) |
| 351 | self.assertEqual(expected_issues, new_cond.int_values) |
| 352 | self.assertEqual(expected_ext_issues, new_cond.str_values) |
| 353 | |
| 354 | def testPreprocessMergedIntoCond_WithSingleProjectID(self): |
| 355 | field = BUILTIN_ISSUE_FIELDS['mergedinto'] |
| 356 | id_field = BUILTIN_ISSUE_FIELDS['mergedinto_id'] |
| 357 | self.services.project.TestAddProject('Project1', project_id=1) |
| 358 | issue1 = fake.MakeTestIssue( |
| 359 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 360 | issue_id=101) |
| 361 | issue2 = fake.MakeTestIssue( |
| 362 | project_id=1, local_id=2, summary='sum', status='new', owner_id=2, |
| 363 | issue_id=102) |
| 364 | self.services.issue.TestAddIssue(issue1) |
| 365 | self.services.issue.TestAddIssue(issue2) |
| 366 | |
| 367 | for local_ids, expected in ( |
| 368 | (['1'], [101]), # One existing issue. |
| 369 | (['Project1:1'], [101]), # One existing issue with project prefix. |
| 370 | (['1', '2'], [101, 102]), # Two existing issues. |
| 371 | (['3'], [])): # Non-existant issue. |
| 372 | cond = ast_pb2.MakeCond( |
| 373 | ast_pb2.QueryOp.TEXT_HAS, [field], local_ids, []) |
| 374 | new_cond = ast2ast._PreprocessMergedIntoCond( |
| 375 | self.cnxn, cond, [1], self.services, None, True) |
| 376 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 377 | self.assertEqual([id_field], new_cond.field_defs) |
| 378 | self.assertEqual(expected, new_cond.int_values) |
| 379 | self.assertEqual([], new_cond.str_values) |
| 380 | |
| 381 | def testPreprocessMergedIntoCond_WithExternalIssues(self): |
| 382 | blocking_field = BUILTIN_ISSUE_FIELDS['mergedinto'] |
| 383 | blocking_id_field = BUILTIN_ISSUE_FIELDS['mergedinto_id'] |
| 384 | self.services.project.TestAddProject('Project1', project_id=1) |
| 385 | issue1 = fake.MakeTestIssue( |
| 386 | project_id=1, local_id=1, summary='sum', status='new', owner_id=2, |
| 387 | issue_id=101) |
| 388 | issue2 = fake.MakeTestIssue( |
| 389 | project_id=1, local_id=2, summary='sum', status='new', owner_id=2, |
| 390 | issue_id=102) |
| 391 | self.services.issue.TestAddIssue(issue1) |
| 392 | self.services.issue.TestAddIssue(issue2) |
| 393 | |
| 394 | for local_ids, expected_issues, expected_ext_issues in ( |
| 395 | (['b/1234'], [], ['b/1234']), |
| 396 | (['Project1:1', 'b/1234'], [101], ['b/1234']), |
| 397 | (['1', 'b/1234', 'b/1551', 'Project1:2'], |
| 398 | [101, 102], ['b/1234', 'b/1551'])): |
| 399 | cond = ast_pb2.MakeCond( |
| 400 | ast_pb2.QueryOp.TEXT_HAS, [blocking_field], local_ids, []) |
| 401 | new_cond = ast2ast._PreprocessMergedIntoCond( |
| 402 | self.cnxn, cond, [1], self.services, None, True) |
| 403 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 404 | self.assertEqual([blocking_id_field], new_cond.field_defs) |
| 405 | self.assertEqual(expected_issues, new_cond.int_values) |
| 406 | self.assertEqual(expected_ext_issues, new_cond.str_values) |
| 407 | |
| 408 | def testPreprocessIsSpamCond(self): |
| 409 | spam_field = BUILTIN_ISSUE_FIELDS['spam'] |
| 410 | is_spam_field = BUILTIN_ISSUE_FIELDS['is_spam'] |
| 411 | for input_op, int_values in ( |
| 412 | (ast_pb2.QueryOp.EQ, [1]), (ast_pb2.QueryOp.NE, [0])): |
| 413 | cond = ast_pb2.MakeCond( |
| 414 | input_op, [spam_field], [], []) |
| 415 | new_cond = ast2ast._PreprocessIsSpamCond( |
| 416 | self.cnxn, cond, [789], self.services, None, True) |
| 417 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 418 | self.assertEqual([is_spam_field], new_cond.field_defs) |
| 419 | self.assertEqual(int_values, new_cond.int_values) |
| 420 | self.assertEqual([], new_cond.str_values) |
| 421 | |
| 422 | def testPreprocessStatusCond(self): |
| 423 | status_field = BUILTIN_ISSUE_FIELDS['status'] |
| 424 | status_id_field = BUILTIN_ISSUE_FIELDS['status_id'] |
| 425 | |
| 426 | cond = ast_pb2.MakeCond( |
| 427 | ast_pb2.QueryOp.IS_DEFINED, [status_field], [], []) |
| 428 | new_cond = ast2ast._PreprocessStatusCond( |
| 429 | self.cnxn, cond, [789], self.services, self.config, True) |
| 430 | self.assertEqual(ast_pb2.QueryOp.IS_DEFINED, new_cond.op) |
| 431 | self.assertEqual([status_id_field], new_cond.field_defs) |
| 432 | self.assertEqual([], new_cond.int_values) |
| 433 | self.assertEqual([], new_cond.str_values) |
| 434 | |
| 435 | cond = ast_pb2.MakeCond( |
| 436 | ast_pb2.QueryOp.EQ, [status_field], ['New', 'Assigned'], []) |
| 437 | new_cond = ast2ast._PreprocessStatusCond( |
| 438 | self.cnxn, cond, [789], self.services, self.config, True) |
| 439 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 440 | self.assertEqual([status_id_field], new_cond.field_defs) |
| 441 | self.assertEqual([0, 1], new_cond.int_values) |
| 442 | self.assertEqual([], new_cond.str_values) |
| 443 | |
| 444 | cond = ast_pb2.MakeCond( |
| 445 | ast_pb2.QueryOp.TEXT_HAS, [status_field], [], []) |
| 446 | new_cond = ast2ast._PreprocessStatusCond( |
| 447 | self.cnxn, cond, [789], self.services, self.config, True) |
| 448 | self.assertEqual([], new_cond.int_values) |
| 449 | |
| 450 | def testPrefixRegex(self): |
| 451 | cond = ast_pb2.MakeCond( |
| 452 | ast_pb2.QueryOp.IS_DEFINED, [BUILTIN_ISSUE_FIELDS['label']], |
| 453 | ['Priority', 'Severity'], []) |
| 454 | regex = ast2ast._MakePrefixRegex(cond) |
| 455 | self.assertRegexpMatches('Priority-1', regex) |
| 456 | self.assertRegexpMatches('Severity-3', regex) |
| 457 | self.assertNotRegexpMatches('My-Priority', regex) |
| 458 | |
| 459 | def testKeyValueRegex(self): |
| 460 | cond = ast_pb2.MakeCond( |
| 461 | ast_pb2.QueryOp.KEY_HAS, [BUILTIN_ISSUE_FIELDS['label']], |
| 462 | ['Type-Feature', 'Type-Security'], []) |
| 463 | regex = ast2ast._MakeKeyValueRegex(cond) |
| 464 | self.assertRegexpMatches('Type-Feature', regex) |
| 465 | self.assertRegexpMatches('Type-Bug-Security', regex) |
| 466 | self.assertNotRegexpMatches('Type-Bug', regex) |
| 467 | self.assertNotRegexpMatches('Security-Feature', regex) |
| 468 | |
| 469 | def testKeyValueRegex_multipleKeys(self): |
| 470 | cond = ast_pb2.MakeCond( |
| 471 | ast_pb2.QueryOp.KEY_HAS, [BUILTIN_ISSUE_FIELDS['label']], |
| 472 | ['Type-Bug', 'Security-Bug'], []) |
| 473 | with self.assertRaises(ValueError): |
| 474 | ast2ast._MakeKeyValueRegex(cond) |
| 475 | |
| 476 | def testWordBoundryRegex(self): |
| 477 | cond = ast_pb2.MakeCond( |
| 478 | ast_pb2.QueryOp.TEXT_HAS, [BUILTIN_ISSUE_FIELDS['label']], |
| 479 | ['Type-Bug'], []) |
| 480 | regex = ast2ast._MakeKeyValueRegex(cond) |
| 481 | self.assertRegexpMatches('Type-Bug-Security', regex) |
| 482 | self.assertNotRegexpMatches('Type-BugSecurity', regex) |
| 483 | |
| 484 | def testPreprocessLabelCond(self): |
| 485 | label_field = BUILTIN_ISSUE_FIELDS['label'] |
| 486 | label_id_field = BUILTIN_ISSUE_FIELDS['label_id'] |
| 487 | |
| 488 | cond = ast_pb2.MakeCond( |
| 489 | ast_pb2.QueryOp.IS_DEFINED, [label_field], ['Priority'], []) |
| 490 | new_cond = ast2ast._PreprocessLabelCond( |
| 491 | self.cnxn, cond, [789], self.services, self.config, True) |
| 492 | self.assertEqual(ast_pb2.QueryOp.IS_DEFINED, new_cond.op) |
| 493 | self.assertEqual([label_id_field], new_cond.field_defs) |
| 494 | self.assertEqual([1, 2, 3], new_cond.int_values) |
| 495 | self.assertEqual([], new_cond.str_values) |
| 496 | |
| 497 | self.services.config.TestAddLabelsDict( |
| 498 | { |
| 499 | 'Priority-Low': 0, |
| 500 | 'Priority-High': 1 |
| 501 | }) |
| 502 | cond = ast_pb2.MakeCond( |
| 503 | ast_pb2.QueryOp.EQ, [label_field], |
| 504 | ['Priority-Low', 'Priority-High'], []) |
| 505 | self.services.config.TestAddLabelsDict( |
| 506 | { |
| 507 | 'Priority-Low': 0, |
| 508 | 'Priority-High': 1 |
| 509 | }) |
| 510 | new_cond = ast2ast._PreprocessLabelCond( |
| 511 | self.cnxn, cond, [789], self.services, self.config, True) |
| 512 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 513 | self.assertEqual([label_id_field], new_cond.field_defs) |
| 514 | self.assertEqual([0, 1], new_cond.int_values) |
| 515 | self.assertEqual([], new_cond.str_values) |
| 516 | |
| 517 | cond = ast_pb2.MakeCond( |
| 518 | ast_pb2.QueryOp.KEY_HAS, [label_field], |
| 519 | ['Priority-Low', 'Priority-High'], []) |
| 520 | new_cond = ast2ast._PreprocessLabelCond( |
| 521 | self.cnxn, cond, [789], self.services, self.config, True) |
| 522 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 523 | self.assertEqual([label_id_field], new_cond.field_defs) |
| 524 | self.assertEqual([1, 2, 3], new_cond.int_values) |
| 525 | self.assertEqual([], new_cond.str_values) |
| 526 | |
| 527 | def testPreprocessComponentCond_QuickOR(self): |
| 528 | component_field = BUILTIN_ISSUE_FIELDS['component'] |
| 529 | component_id_field = BUILTIN_ISSUE_FIELDS['component_id'] |
| 530 | |
| 531 | cond = ast_pb2.MakeCond( |
| 532 | ast_pb2.QueryOp.IS_DEFINED, [component_field], ['UI', 'DB'], []) |
| 533 | new_cond = ast2ast._PreprocessComponentCond( |
| 534 | self.cnxn, cond, [789], self.services, self.config, True) |
| 535 | self.assertEqual(ast_pb2.QueryOp.IS_DEFINED, new_cond.op) |
| 536 | self.assertEqual([component_id_field], new_cond.field_defs) |
| 537 | self.assertEqual([101, 102, 201], new_cond.int_values) |
| 538 | self.assertEqual([], new_cond.str_values) |
| 539 | |
| 540 | cond = ast_pb2.MakeCond( |
| 541 | ast_pb2.QueryOp.TEXT_HAS, [component_field], ['UI', 'DB'], []) |
| 542 | new_cond = ast2ast._PreprocessComponentCond( |
| 543 | self.cnxn, cond, [789], self.services, self.config, True) |
| 544 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 545 | self.assertEqual([component_id_field], new_cond.field_defs) |
| 546 | self.assertEqual([101, 102, 201], new_cond.int_values) |
| 547 | self.assertEqual([], new_cond.str_values) |
| 548 | |
| 549 | cond = ast_pb2.MakeCond( |
| 550 | ast_pb2.QueryOp.TEXT_HAS, [component_field], [], []) |
| 551 | new_cond = ast2ast._PreprocessComponentCond( |
| 552 | self.cnxn, cond, [789], self.services, self.config, True) |
| 553 | self.assertEqual([], new_cond.int_values) |
| 554 | |
| 555 | cond = ast_pb2.MakeCond( |
| 556 | ast_pb2.QueryOp.TEXT_HAS, [component_field], ['unknown@example.com'], |
| 557 | []) |
| 558 | new_cond = ast2ast._PreprocessComponentCond( |
| 559 | self.cnxn, cond, [789], self.services, self.config, True) |
| 560 | self.assertEqual([], new_cond.int_values) |
| 561 | |
| 562 | def testPreprocessComponentCond_RootedAndNonRooted(self): |
| 563 | component_field = BUILTIN_ISSUE_FIELDS['component'] |
| 564 | component_id_field = BUILTIN_ISSUE_FIELDS['component_id'] |
| 565 | |
| 566 | cond = ast_pb2.MakeCond( |
| 567 | ast_pb2.QueryOp.TEXT_HAS, [component_field], ['UI'], []) |
| 568 | new_cond = ast2ast._PreprocessComponentCond( |
| 569 | self.cnxn, cond, [789], self.services, self.config, True) |
| 570 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 571 | self.assertEqual([component_id_field], new_cond.field_defs) |
| 572 | self.assertEqual([101, 102], new_cond.int_values) |
| 573 | self.assertEqual([], new_cond.str_values) |
| 574 | |
| 575 | cond = ast_pb2.MakeCond( |
| 576 | ast_pb2.QueryOp.EQ, [component_field], ['UI'], []) |
| 577 | new_cond = ast2ast._PreprocessComponentCond( |
| 578 | self.cnxn, cond, [789], self.services, self.config, True) |
| 579 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 580 | self.assertEqual([component_id_field], new_cond.field_defs) |
| 581 | self.assertEqual([101], new_cond.int_values) |
| 582 | self.assertEqual([], new_cond.str_values) |
| 583 | |
| 584 | def testPreprocessExactUsers_IsDefined(self): |
| 585 | """Anyone can search for [has:owner].""" |
| 586 | cond = ast_pb2.MakeCond( |
| 587 | ast_pb2.QueryOp.IS_DEFINED, [OWNER_FIELD], ['a@example.com'], []) |
| 588 | new_cond = ast2ast._PreprocessExactUsers( |
| 589 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], True) |
| 590 | self.assertEqual(ast_pb2.QueryOp.IS_DEFINED, new_cond.op) |
| 591 | self.assertEqual([OWNER_ID_FIELD], new_cond.field_defs) |
| 592 | self.assertEqual([], new_cond.int_values) |
| 593 | self.assertEqual([], new_cond.str_values) |
| 594 | |
| 595 | # Non-members do not raise an exception. |
| 596 | ast2ast._PreprocessExactUsers( |
| 597 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], False) |
| 598 | |
| 599 | |
| 600 | def testPreprocessExactUsers_UserFound(self): |
| 601 | """Anyone can search for a know user, [owner:user@example.com].""" |
| 602 | cond = ast_pb2.MakeCond( |
| 603 | ast_pb2.QueryOp.TEXT_HAS, [OWNER_FIELD], ['a@example.com'], []) |
| 604 | new_cond = ast2ast._PreprocessExactUsers( |
| 605 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], True) |
| 606 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 607 | self.assertEqual([OWNER_ID_FIELD], new_cond.field_defs) |
| 608 | self.assertEqual([111], new_cond.int_values) |
| 609 | self.assertEqual([], new_cond.str_values) |
| 610 | |
| 611 | # Non-members do not raise an exception. |
| 612 | ast2ast._PreprocessExactUsers( |
| 613 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], False) |
| 614 | |
| 615 | def testPreprocessExactUsers_UserSpecifiedByID(self): |
| 616 | """Anyone may search for users by ID, [owner:1234].""" |
| 617 | cond = ast_pb2.MakeCond( |
| 618 | ast_pb2.QueryOp.TEXT_HAS, [OWNER_FIELD], ['123'], []) |
| 619 | new_cond = ast2ast._PreprocessExactUsers( |
| 620 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], True) |
| 621 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 622 | self.assertEqual([OWNER_ID_FIELD], new_cond.field_defs) |
| 623 | self.assertEqual([123], new_cond.int_values) |
| 624 | self.assertEqual([], new_cond.str_values) |
| 625 | |
| 626 | # Non-members do not raise an exception. |
| 627 | ast2ast._PreprocessExactUsers( |
| 628 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], False) |
| 629 | |
| 630 | def testPreprocessExactUsers_NonEquality(self): |
| 631 | """Project members may search for [owner_id>111].""" |
| 632 | cond = ast_pb2.MakeCond( |
| 633 | ast_pb2.QueryOp.GE, [OWNER_ID_FIELD], ['111'], []) |
| 634 | new_cond = ast2ast._PreprocessExactUsers( |
| 635 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], True) |
| 636 | self.assertEqual(cond, new_cond) |
| 637 | |
| 638 | with self.assertRaises(ast2ast.MalformedQuery): |
| 639 | ast2ast._PreprocessExactUsers( |
| 640 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], False) |
| 641 | |
| 642 | def testPreprocessExactUsers_UserNotFound(self): |
| 643 | cond = ast_pb2.MakeCond( |
| 644 | ast_pb2.QueryOp.TEXT_HAS, [OWNER_FIELD], ['unknown@example.com'], []) |
| 645 | new_cond = ast2ast._PreprocessExactUsers( |
| 646 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], True) |
| 647 | self.assertEqual(cond, new_cond) |
| 648 | |
| 649 | with self.assertRaises(ast2ast.MalformedQuery): |
| 650 | ast2ast._PreprocessExactUsers( |
| 651 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], False) |
| 652 | |
| 653 | def testPreprocessExactUsers_KeywordMe(self): |
| 654 | cond = ast_pb2.MakeCond( |
| 655 | ast_pb2.QueryOp.TEXT_HAS, [OWNER_FIELD], ['me'], []) |
| 656 | new_cond = ast2ast._PreprocessExactUsers( |
| 657 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], True) |
| 658 | self.assertEqual(cond, new_cond) |
| 659 | |
| 660 | new_cond = ast2ast._PreprocessExactUsers( |
| 661 | self.cnxn, cond, self.services.user, [OWNER_ID_FIELD], False) |
| 662 | self.assertEqual(cond, new_cond) |
| 663 | |
| 664 | def testPreprocessHotlistCond(self): |
| 665 | hotlist_field = BUILTIN_ISSUE_FIELDS['hotlist'] |
| 666 | hotlist_id_field = BUILTIN_ISSUE_FIELDS['hotlist_id'] |
| 667 | |
| 668 | self.services.user.TestAddUser('gatsby@example.org', 111) |
| 669 | self.services.user.TestAddUser('daisy@example.com', 222) |
| 670 | self.services.user.TestAddUser('nick@example.org', 333) |
| 671 | |
| 672 | # Setup hotlists |
| 673 | self.services.features.TestAddHotlist( |
| 674 | 'Hotlist1', owner_ids=[111], hotlist_id=10) |
| 675 | self.services.features.TestAddHotlist( |
| 676 | 'Hotlist2', owner_ids=[111], hotlist_id=20) |
| 677 | self.services.features.TestAddHotlist( |
| 678 | 'Hotlist3', owner_ids=[222], hotlist_id=30) |
| 679 | self.services.features.TestAddHotlist( |
| 680 | 'Hotlist4', owner_ids=[222], hotlist_id=40) |
| 681 | self.services.features.TestAddHotlist( |
| 682 | 'Hotlist5', owner_ids=[333], hotlist_id=50) |
| 683 | self.services.features.TestAddHotlist( |
| 684 | 'Hotlist6', owner_ids=[333], hotlist_id=60) |
| 685 | |
| 686 | hotlist_query_vals = [ |
| 687 | 'gatsby@example.org:Hotlist1', |
| 688 | 'nick@example.org:', |
| 689 | 'daisy@example.com:Hotlist3', 'Hotlist4'] |
| 690 | cond = ast_pb2.MakeCond( |
| 691 | ast_pb2.QueryOp.TEXT_HAS, [hotlist_field], hotlist_query_vals, []) |
| 692 | actual = ast2ast._PreprocessHotlistCond( |
| 693 | self.cnxn, cond, [1], self.services, None, True) |
| 694 | self.assertEqual(ast_pb2.QueryOp.EQ, actual.op) |
| 695 | self.assertEqual([hotlist_id_field], actual.field_defs) |
| 696 | self.assertItemsEqual([10, 30, 40, 50, 60], actual.int_values) |
| 697 | |
| 698 | def testPreprocessHotlistCond_UserNotFound(self): |
| 699 | hotlist_field = BUILTIN_ISSUE_FIELDS['hotlist'] |
| 700 | hotlist_query_vals = ['gatsby@chromium.org:Hotlist1', 'Hotlist3'] |
| 701 | cond = ast_pb2.MakeCond( |
| 702 | ast_pb2.QueryOp.TEXT_HAS, [hotlist_field], hotlist_query_vals, []) |
| 703 | actual = ast2ast._PreprocessHotlistCond( |
| 704 | self.cnxn, cond, [1], self.services, None, True) |
| 705 | self.assertEqual(cond, actual) |
| 706 | |
| 707 | def testPreprocessCustomCond_User(self): |
| 708 | fd = tracker_pb2.FieldDef( |
| 709 | field_id=1, field_name='TPM', |
| 710 | field_type=tracker_pb2.FieldTypes.USER_TYPE) |
| 711 | cond = ast_pb2.MakeCond( |
| 712 | ast_pb2.QueryOp.TEXT_HAS, [fd], ['a@example.com'], []) |
| 713 | new_cond = ast2ast._PreprocessCustomCond( |
| 714 | self.cnxn, cond, self.services, True) |
| 715 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 716 | self.assertEqual(cond.field_defs, new_cond.field_defs) |
| 717 | self.assertEqual([111], new_cond.int_values) |
| 718 | self.assertEqual([], new_cond.str_values) |
| 719 | |
| 720 | cond = ast_pb2.MakeCond( |
| 721 | ast_pb2.QueryOp.TEXT_HAS, [fd], ['111'], []) |
| 722 | new_cond = ast2ast._PreprocessCustomCond( |
| 723 | self.cnxn, cond, self.services, True) |
| 724 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 725 | self.assertEqual(cond.field_defs, new_cond.field_defs) |
| 726 | self.assertEqual([111], new_cond.int_values) |
| 727 | self.assertEqual([], new_cond.str_values) |
| 728 | |
| 729 | cond = ast_pb2.MakeCond( |
| 730 | ast_pb2.QueryOp.TEXT_HAS, [fd], ['unknown@example.com'], []) |
| 731 | new_cond = ast2ast._PreprocessCustomCond( |
| 732 | self.cnxn, cond, self.services, True) |
| 733 | self.assertEqual(cond, new_cond) |
| 734 | |
| 735 | def testPreprocessCustomCond_NonUser(self): |
| 736 | fd = tracker_pb2.FieldDef( |
| 737 | field_id=1, field_name='TPM', |
| 738 | field_type=tracker_pb2.FieldTypes.INT_TYPE) |
| 739 | cond = ast_pb2.MakeCond( |
| 740 | ast_pb2.QueryOp.TEXT_HAS, [fd], ['foo'], [123]) |
| 741 | new_cond = ast2ast._PreprocessCustomCond( |
| 742 | self.cnxn, cond, self.services, True) |
| 743 | self.assertEqual(cond, new_cond) |
| 744 | |
| 745 | fd.field_type = tracker_pb2.FieldTypes.STR_TYPE |
| 746 | new_cond = ast2ast._PreprocessCustomCond( |
| 747 | self.cnxn, cond, self.services, True) |
| 748 | self.assertEqual(cond, new_cond) |
| 749 | |
| 750 | def testPreprocessCustomCond_ApprovalUser(self): |
| 751 | fd = tracker_pb2.FieldDef( |
| 752 | field_id=1, field_name='UXReview', |
| 753 | field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE) |
| 754 | cond = ast_pb2.MakeCond( |
| 755 | ast_pb2.QueryOp.TEXT_HAS, [fd], ['a@example.com'], [], |
| 756 | key_suffix=query2ast.APPROVER_SUFFIX) |
| 757 | new_cond = ast2ast._PreprocessCustomCond( |
| 758 | self.cnxn, cond, self.services, True) |
| 759 | self.assertEqual(ast_pb2.QueryOp.EQ, new_cond.op) |
| 760 | self.assertEqual(cond.field_defs, new_cond.field_defs) |
| 761 | self.assertEqual([111], new_cond.int_values) |
| 762 | self.assertEqual([], new_cond.str_values) |
| 763 | self.assertEqual(query2ast.APPROVER_SUFFIX, new_cond.key_suffix) |
| 764 | |
| 765 | def testPreprocessCond_NoChange(self): |
| 766 | cond = ast_pb2.MakeCond(ast_pb2.QueryOp.TEXT_HAS, [ANY_FIELD], ['foo'], []) |
| 767 | self.assertEqual( |
| 768 | cond, ast2ast._PreprocessCond(self.cnxn, cond, [], None, None, True)) |
| 769 | |
| 770 | def testTextOpToIntOp(self): |
| 771 | self.assertEqual(ast_pb2.QueryOp.EQ, |
| 772 | ast2ast._TextOpToIntOp(ast_pb2.QueryOp.TEXT_HAS)) |
| 773 | self.assertEqual(ast_pb2.QueryOp.EQ, |
| 774 | ast2ast._TextOpToIntOp(ast_pb2.QueryOp.KEY_HAS)) |
| 775 | self.assertEqual(ast_pb2.QueryOp.NE, |
| 776 | ast2ast._TextOpToIntOp(ast_pb2.QueryOp.NOT_TEXT_HAS)) |
| 777 | |
| 778 | for enum_name, _enum_id in ast_pb2.QueryOp.to_dict().items(): |
| 779 | no_change_op = ast_pb2.QueryOp(enum_name) |
| 780 | if no_change_op not in ( |
| 781 | ast_pb2.QueryOp.TEXT_HAS, |
| 782 | ast_pb2.QueryOp.NOT_TEXT_HAS, |
| 783 | ast_pb2.QueryOp.KEY_HAS): |
| 784 | self.assertEqual(no_change_op, |
| 785 | ast2ast._TextOpToIntOp(no_change_op)) |