| Index: appengine/monorail/features/test/filterrules_helpers_test.py
|
| diff --git a/appengine/monorail/features/test/filterrules_helpers_test.py b/appengine/monorail/features/test/filterrules_helpers_test.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8c481072d0dc49021bdb373366c1de11964a2a7b
|
| --- /dev/null
|
| +++ b/appengine/monorail/features/test/filterrules_helpers_test.py
|
| @@ -0,0 +1,633 @@
|
| +# Copyright 2016 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is govered by a BSD-style
|
| +# license that can be found in the LICENSE file or at
|
| +# https://developers.google.com/open-source/licenses/bsd
|
| +
|
| +"""Unit tests for filterrules_helpers feature."""
|
| +
|
| +import unittest
|
| +
|
| +import mox
|
| +
|
| +from google.appengine.api import taskqueue
|
| +
|
| +import settings
|
| +from features import filterrules_helpers
|
| +from framework import template_helpers
|
| +from framework import urls
|
| +from proto import ast_pb2
|
| +from proto import tracker_pb2
|
| +from search import query2ast
|
| +from services import service_manager
|
| +from testing import fake
|
| +from tracker import tracker_bizobj
|
| +
|
| +
|
| +ORIG_SUMMARY = 'this is the orginal summary'
|
| +ORIG_LABELS = ['one', 'two']
|
| +
|
| +# Fake user id mapping
|
| +TEST_ID_MAP = {
|
| + 'mike.j.parent': 1,
|
| + 'jrobbins': 2,
|
| + 'ningerso': 3,
|
| + }
|
| +
|
| +
|
| +class MockTaskQueue(object):
|
| + def __init__(self):
|
| + self.work_items = []
|
| +
|
| + def add(self, **kwargs):
|
| + self.work_items.append(kwargs)
|
| +
|
| +
|
| +class RecomputeAllDerivedFieldsTest(unittest.TestCase):
|
| +
|
| + BLOCK = filterrules_helpers.BLOCK
|
| +
|
| + def setUp(self):
|
| + self.features = fake.FeaturesService()
|
| + self.user = fake.UserService()
|
| + self.services = service_manager.Services(
|
| + features=self.features,
|
| + user=self.user,
|
| + issue=fake.IssueService())
|
| + self.project = fake.Project(project_name='proj')
|
| + self.config = 'fake config'
|
| + self.cnxn = 'fake cnxn'
|
| + self.mox = mox.Mox()
|
| + self.mock_task_queue = MockTaskQueue()
|
| + self.mox.StubOutWithMock(taskqueue, 'add')
|
| +
|
| + def tearDown(self):
|
| + self.mox.UnsetStubs()
|
| + self.mox.ResetAll()
|
| +
|
| + def testRecomputeDerivedFields_Disabled(self):
|
| + """Servlet should just call RecomputeAllDerivedFieldsNow with no bounds."""
|
| + saved_flag = settings.recompute_derived_fields_in_worker
|
| + settings.recompute_derived_fields_in_worker = False
|
| + self.mox.ReplayAll()
|
| +
|
| + filterrules_helpers.RecomputeAllDerivedFields(
|
| + self.cnxn, self.services, self.project, self.config)
|
| + self.assertTrue(self.services.issue.get_all_issues_in_project_called)
|
| + self.assertTrue(self.services.issue.update_issues_called)
|
| + self.assertTrue(self.services.issue.enqueue_issues_called)
|
| +
|
| + self.mox.VerifyAll()
|
| + settings.recompute_derived_fields_in_worker = saved_flag
|
| +
|
| + def testRecomputeDerivedFields_DisabledNextIDSet(self):
|
| + """Servlet should just call RecomputeAllDerivedFields with no bounds."""
|
| + saved_flag = settings.recompute_derived_fields_in_worker
|
| + settings.recompute_derived_fields_in_worker = False
|
| + self.services.issue.next_id = 1234
|
| + self.mox.ReplayAll()
|
| +
|
| + filterrules_helpers.RecomputeAllDerivedFields(
|
| + self.cnxn, self.services, self.project, self.config)
|
| + self.services.issue.UpdateIssues('no', ['1'])
|
| + self.assertTrue(self.services.issue.get_all_issues_in_project_called)
|
| + self.assertTrue(self.services.issue.update_issues_called)
|
| + self.assertTrue(self.services.issue.enqueue_issues_called)
|
| +
|
| + self.mox.VerifyAll()
|
| + settings.recompute_derived_fields_in_worker = saved_flag
|
| +
|
| + def testRecomputeDerivedFields_NoIssues(self):
|
| + """Servlet should not call because there is no work to do."""
|
| + saved_flag = settings.recompute_derived_fields_in_worker
|
| + settings.recompute_derived_fields_in_worker = True
|
| + self.mox.ReplayAll()
|
| +
|
| + filterrules_helpers.RecomputeAllDerivedFields(
|
| + self.cnxn, self.services, self.project, self.config)
|
| + self.assertFalse(self.services.issue.get_all_issues_in_project_called)
|
| + self.assertFalse(self.services.issue.update_issues_called)
|
| + self.assertFalse(self.services.issue.enqueue_issues_called)
|
| +
|
| + self.mox.VerifyAll()
|
| + settings.recompute_derived_fields_in_worker = saved_flag
|
| +
|
| + def testRecomputeDerivedFields_SomeIssues(self):
|
| + """Servlet should enqueue one work item rather than call directly."""
|
| + saved_flag = settings.recompute_derived_fields_in_worker
|
| + settings.recompute_derived_fields_in_worker = True
|
| + self.services.issue.next_id = 1234
|
| + num_calls = (self.services.issue.next_id // self.BLOCK + 1)
|
| + for _ in range(num_calls):
|
| + taskqueue.add(
|
| + params=mox.IsA(dict),
|
| + url='/_task/recomputeDerivedFields.do').WithSideEffects(
|
| + self.mock_task_queue.add)
|
| + self.mox.ReplayAll()
|
| +
|
| + filterrules_helpers.RecomputeAllDerivedFields(
|
| + self.cnxn, self.services, self.project, self.config)
|
| + self.assertFalse(self.services.issue.get_all_issues_in_project_called)
|
| + self.assertFalse(self.services.issue.update_issues_called)
|
| + self.assertFalse(self.services.issue.enqueue_issues_called)
|
| + work_items = self.mock_task_queue.work_items
|
| + self.assertEqual(num_calls, len(work_items))
|
| +
|
| + self.mox.VerifyAll()
|
| + settings.recompute_derived_fields_in_worker = saved_flag
|
| +
|
| + def testRecomputeDerivedFields_LotsOfIssues(self):
|
| + """Servlet should enqueue multiple work items."""
|
| + saved_flag = settings.recompute_derived_fields_in_worker
|
| + settings.recompute_derived_fields_in_worker = True
|
| + self.services.issue.next_id = 12345
|
| + num_calls = (self.services.issue.next_id // self.BLOCK + 1)
|
| + for _ in range(num_calls):
|
| + taskqueue.add(
|
| + params=mox.IsA(dict),
|
| + url='/_task/recomputeDerivedFields.do').WithSideEffects(
|
| + self.mock_task_queue.add)
|
| + self.mox.ReplayAll()
|
| +
|
| + filterrules_helpers.RecomputeAllDerivedFields(
|
| + self.cnxn, self.services, self.project, self.config)
|
| + self.assertFalse(self.services.issue.get_all_issues_in_project_called)
|
| + self.assertFalse(self.services.issue.update_issues_called)
|
| + self.assertFalse(self.services.issue.enqueue_issues_called)
|
| +
|
| + work_items = self.mock_task_queue.work_items
|
| + self.assertEqual(num_calls, len(work_items))
|
| + url, params = work_items[0]['url'], work_items[0]['params']
|
| + self.assertEqual(urls.RECOMPUTE_DERIVED_FIELDS_TASK + '.do', url)
|
| + self.assertEqual(self.project.project_id, params['project_id'])
|
| + self.assertEqual(12345 // self.BLOCK * self.BLOCK + 1,
|
| + params['lower_bound'])
|
| + self.assertEqual(12345, params['upper_bound'])
|
| +
|
| + url, params = work_items[-1]['url'], work_items[-1]['params']
|
| + self.assertEqual(urls.RECOMPUTE_DERIVED_FIELDS_TASK + '.do', url)
|
| + self.assertEqual(self.project.project_id, params['project_id'])
|
| + self.assertEqual(1, params['lower_bound'])
|
| + self.assertEqual(self.BLOCK + 1, params['upper_bound'])
|
| +
|
| + self.mox.VerifyAll()
|
| + settings.recompute_derived_fields_in_worker = saved_flag
|
| +
|
| + def testRecomputeAllDerivedFieldsNow(self):
|
| + """Servlet should reapply all filter rules to project's issues."""
|
| + self.services.issue.next_id = 12345
|
| + test_issue_1 = fake.MakeTestIssue(
|
| + project_id=self.project.project_id, local_id=1, issue_id=1001,
|
| + summary='sum1', owner_id=100, status='New')
|
| + test_issue_2 = fake.MakeTestIssue(
|
| + project_id=self.project.project_id, local_id=2, issue_id=1002,
|
| + summary='sum2', owner_id=100, status='New')
|
| + test_issues = [test_issue_1, test_issue_2]
|
| + self.services.issue.TestAddIssue(test_issue_1)
|
| + self.services.issue.TestAddIssue(test_issue_2)
|
| +
|
| + self.mox.StubOutWithMock(filterrules_helpers, 'ApplyGivenRules')
|
| + for test_issue in test_issues:
|
| + filterrules_helpers.ApplyGivenRules(
|
| + self.cnxn, self.services, test_issue, self.config,
|
| + [], []).AndReturn(True)
|
| + self.mox.ReplayAll()
|
| +
|
| + filterrules_helpers.RecomputeAllDerivedFieldsNow(
|
| + self.cnxn, self.services, self.project, self.config)
|
| +
|
| + self.assertTrue(self.services.issue.get_all_issues_in_project_called)
|
| + self.assertTrue(self.services.issue.update_issues_called)
|
| + self.assertTrue(self.services.issue.enqueue_issues_called)
|
| + self.assertEqual(test_issues, self.services.issue.updated_issues)
|
| + self.assertEqual([issue.issue_id for issue in test_issues],
|
| + self.services.issue.enqueued_issues)
|
| + self.mox.VerifyAll()
|
| +
|
| +
|
| +class FilterRulesHelpersTest(unittest.TestCase):
|
| +
|
| + def setUp(self):
|
| + self.cnxn = 'fake cnxn'
|
| + self.services = service_manager.Services()
|
| + self.services.user = fake.UserService()
|
| + self.services.project = fake.ProjectService()
|
| + self.services.issue = fake.IssueService()
|
| + self.project = self.services.project.TestAddProject('proj', project_id=789)
|
| + self.other_project = self.services.project.TestAddProject(
|
| + 'otherproj', project_id=890)
|
| + for email, user_id in TEST_ID_MAP.iteritems():
|
| + self.services.user.TestAddUser(email, user_id)
|
| +
|
| + def testApplyRule(self):
|
| + cnxn = 'fake sql connection'
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 111L, labels=ORIG_LABELS)
|
| + config = tracker_pb2.ProjectIssueConfig()
|
| + # Empty label set cannot satisfy rule looking for labels.
|
| + pred = 'label:a label:b'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (None, None, [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, set(), config))
|
| +
|
| + pred = 'label:a -label:b'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (None, None, [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, set(), config))
|
| +
|
| + # Empty label set will satisfy rule looking for missing labels.
|
| + pred = '-label:a -label:b'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (1, 'S', [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, set(), config))
|
| +
|
| + # Label set has the needed labels.
|
| + pred = 'label:a label:b'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (1, 'S', [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, {'a', 'b'},
|
| + config))
|
| +
|
| + # Label set has the needed labels with test for unicode.
|
| + pred = 'label:a label:b'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (1, 'S', [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, {u'a', u'b'},
|
| + config))
|
| +
|
| + # Label set has the needed labels, capitalization irrelevant.
|
| + pred = 'label:A label:B'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (1, 'S', [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, {'a', 'b'},
|
| + config))
|
| +
|
| + # Label set has a label, the rule negates.
|
| + pred = 'label:a -label:b'
|
| + rule = filterrules_helpers.MakeRule(
|
| + pred, default_owner_id=1, default_status='S')
|
| + predicate_ast = query2ast.ParseUserQuery(
|
| + pred, '', query2ast.BUILTIN_ISSUE_FIELDS, config)
|
| + self.assertEquals(
|
| + (None, None, [], [], []),
|
| + filterrules_helpers._ApplyRule(
|
| + cnxn, self.services, rule, predicate_ast, issue, {'a', 'b'},
|
| + config))
|
| +
|
| + def testComputeDerivedFields(self):
|
| + cnxn = 'fake sql connection'
|
| + rules = [
|
| + filterrules_helpers.MakeRule(
|
| + 'label:HasWorkaround', add_labels=['Priority-Low']),
|
| + filterrules_helpers.MakeRule(
|
| + 'label:Security', add_labels=['Private']),
|
| + filterrules_helpers.MakeRule(
|
| + 'label:Security', add_labels=['Priority-High'],
|
| + add_notify=['jrobbins@chromium.org']),
|
| + filterrules_helpers.MakeRule(
|
| + 'Priority=High label:Regression', add_labels=['Urgent']),
|
| + filterrules_helpers.MakeRule(
|
| + 'Size=L', default_owner_id=444L),
|
| + ]
|
| + excl_prefixes = ['priority', 'type', 'milestone']
|
| + config = tracker_pb2.ProjectIssueConfig(
|
| + exclusive_label_prefixes=excl_prefixes)
|
| + predicate_asts = filterrules_helpers.ParsePredicateASTs(rules, config, None)
|
| +
|
| + # No rules fire.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L, labels=ORIG_LABELS)
|
| + self.assertEquals(
|
| + (0, '', [], [], []),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L, labels=['foo', 'bar'])
|
| + self.assertEquals(
|
| + (0, '', [], [], []),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # One rule fires.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L, labels=['Size-L'])
|
| + self.assertEquals(
|
| + (444L, '', [], [], []),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # One rule fires, but no effect because of explicit fields.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L,
|
| + labels=['HasWorkaround', 'Priority-Critical'])
|
| + self.assertEquals(
|
| + (0, '', [], [], []),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # One rule fires, but limited effect because of explicit exclusive label.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L,
|
| + labels=['Security', 'Priority-Critical'])
|
| + self.assertEquals(
|
| + (0, '', [], ['Private'], ['jrobbins@chromium.org']),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # Multiple rules have cumulative effect.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L, labels=['HasWorkaround', 'Size-L'])
|
| + self.assertEquals(
|
| + (444L, '', [], ['Priority-Low'], []),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # Two rules fire, second overwrites the first.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L, labels=['HasWorkaround', 'Security'])
|
| + self.assertEquals(
|
| + (0, '', [], ['Private', 'Priority-High'], ['jrobbins@chromium.org']),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # Two rules fire, second triggered by the first.
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 0L, labels=['Security', 'Regression'])
|
| + self.assertEquals(
|
| + (0, '', [], ['Private', 'Priority-High', 'Urgent'],
|
| + ['jrobbins@chromium.org']),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + # Two rules fire, each one wants to add the same CC: only add once.
|
| + rules.append(filterrules_helpers.MakeRule('Watch', add_cc_ids=[111L]))
|
| + rules.append(filterrules_helpers.MakeRule('Monitor', add_cc_ids=[111L]))
|
| + config = tracker_pb2.ProjectIssueConfig(
|
| + exclusive_label_prefixes=excl_prefixes)
|
| + predicate_asts = filterrules_helpers.ParsePredicateASTs(rules, config, None)
|
| + issue = fake.MakeTestIssue(
|
| + 789, 1, ORIG_SUMMARY, 'New', 111L, labels=['Watch', 'Monitor'])
|
| + self.assertEquals(
|
| + (0, '', [111L], [], []),
|
| + filterrules_helpers._ComputeDerivedFields(
|
| + cnxn, self.services, issue, config, rules, predicate_asts))
|
| +
|
| + def testCompareComponents_Trivial(self):
|
| + config = tracker_pb2.ProjectIssueConfig()
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.IS_DEFINED, [], [123]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.IS_NOT_DEFINED, [], [123]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.IS_DEFINED, [], []))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.IS_NOT_DEFINED, [], []))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, [123], []))
|
| +
|
| + def testCompareComponents_Normal(self):
|
| + config = tracker_pb2.ProjectIssueConfig()
|
| + config.component_defs.append(tracker_bizobj.MakeComponentDef(
|
| + 100, 789, 'UI', 'doc', False, [], [], 0, 0))
|
| + config.component_defs.append(tracker_bizobj.MakeComponentDef(
|
| + 110, 789, 'UI>Help', 'doc', False, [], [], 0, 0))
|
| + config.component_defs.append(tracker_bizobj.MakeComponentDef(
|
| + 200, 789, 'Networking', 'doc', False, [], [], 0, 0))
|
| +
|
| + # Check if the issue is in a specified component or subcomponent.
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI'], [100]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI>Help'], [110]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI'], [100, 110]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI'], []))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI'], [110]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI'], [200]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI>Help'], [100]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['Networking'], [100]))
|
| +
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.NE, ['UI'], []))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.NE, ['UI'], [100]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.NE, ['Networking'], [100]))
|
| +
|
| + # Exact vs non-exact.
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['Help'], [110]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.TEXT_HAS, ['UI'], [110]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.TEXT_HAS, ['Help'], [110]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.NOT_TEXT_HAS, ['UI'], [110]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.NOT_TEXT_HAS, ['Help'], [110]))
|
| +
|
| + # Multivalued issues and Quick-OR notation
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['Networking'], [200]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['Networking'], [100, 110]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI', 'Networking'], [100]))
|
| + self.assertFalse(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI', 'Networking'], [110]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI', 'Networking'], [200]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI', 'Networking'], [110, 200]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.TEXT_HAS, ['UI', 'Networking'], [110, 200]))
|
| + self.assertTrue(filterrules_helpers._CompareComponents(
|
| + config, ast_pb2.QueryOp.EQ, ['UI>Help', 'Networking'], [110, 200]))
|
| +
|
| + def testCompareIssueRefs_Trivial(self):
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.IS_DEFINED, [], [123]))
|
| + self.assertFalse(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.IS_NOT_DEFINED, [], [123]))
|
| + self.assertFalse(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.IS_DEFINED, [], []))
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.IS_NOT_DEFINED, [], []))
|
| + self.assertFalse(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.EQ, ['1'], []))
|
| +
|
| + def testCompareIssueRefs_Normal(self):
|
| + self.services.issue.TestAddIssue(fake.MakeTestIssue(
|
| + 789, 1, 'summary', 'New', 0L, issue_id=123))
|
| + self.services.issue.TestAddIssue(fake.MakeTestIssue(
|
| + 789, 2, 'summary', 'New', 0L, issue_id=124))
|
| + self.services.issue.TestAddIssue(fake.MakeTestIssue(
|
| + 890, 1, 'other summary', 'New', 0L, issue_id=125))
|
| +
|
| + # EQ and NE, implict references to the current project.
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.EQ, ['1'], [123]))
|
| + self.assertFalse(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.NE, ['1'], [123]))
|
| +
|
| + # EQ and NE, explicit project references.
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.EQ, ['proj:1'], [123]))
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.EQ, ['otherproj:1'], [125]))
|
| +
|
| + # Inequalities
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.GE, ['1'], [123]))
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.GE, ['1'], [124]))
|
| + self.assertTrue(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.GE, ['2'], [124]))
|
| + self.assertFalse(filterrules_helpers._CompareIssueRefs(
|
| + self.cnxn, self.services, self.project,
|
| + ast_pb2.QueryOp.GT, ['2'], [124]))
|
| +
|
| + def testCompareUsers(self):
|
| + pass # TODO(jrobbins): Add this test.
|
| +
|
| + def testCompareUserIDs(self):
|
| + pass # TODO(jrobbins): Add this test.
|
| +
|
| + def testCompareEmails(self):
|
| + pass # TODO(jrobbins): Add this test.
|
| +
|
| + def testCompare(self):
|
| + pass # TODO(jrobbins): Add this test.
|
| +
|
| + def testParseOneRuleAddLabels(self):
|
| + cnxn = 'fake SQL connection'
|
| + error_list = []
|
| + rule_pb = filterrules_helpers._ParseOneRule(
|
| + cnxn, 'label:lab1 label:lab2', 'add_labels', 'hot cOld, ', None, 1,
|
| + error_list)
|
| + self.assertEquals('label:lab1 label:lab2', rule_pb.predicate)
|
| + self.assertEquals(error_list, [])
|
| + self.assertEquals(len(rule_pb.add_labels), 2)
|
| + self.assertEquals(rule_pb.add_labels[0], 'hot')
|
| + self.assertEquals(rule_pb.add_labels[1], 'cOld')
|
| +
|
| + rule_pb = filterrules_helpers._ParseOneRule(
|
| + cnxn, '', 'default_status', 'hot cold', None, 1, error_list)
|
| + self.assertEquals(len(rule_pb.predicate), 0)
|
| + self.assertEquals(error_list, [])
|
| +
|
| + def testParseOneRuleDefaultOwner(self):
|
| + cnxn = 'fake SQL connection'
|
| + error_list = []
|
| + rule_pb = filterrules_helpers._ParseOneRule(
|
| + cnxn, 'label:lab1, label:lab2 ', 'default_owner', 'jrobbins',
|
| + self.services.user, 1, error_list)
|
| + self.assertEquals(error_list, [])
|
| + self.assertEquals(rule_pb.default_owner_id, TEST_ID_MAP['jrobbins'])
|
| +
|
| + def testParseOneRuleDefaultStatus(self):
|
| + cnxn = 'fake SQL connection'
|
| + error_list = []
|
| + rule_pb = filterrules_helpers._ParseOneRule(
|
| + cnxn, 'label:lab1', 'default_status', 'InReview',
|
| + None, 1, error_list)
|
| + self.assertEquals(error_list, [])
|
| + self.assertEquals(rule_pb.default_status, 'InReview')
|
| +
|
| + def testParseOneRuleAddCcs(self):
|
| + cnxn = 'fake SQL connection'
|
| + error_list = []
|
| + rule_pb = filterrules_helpers._ParseOneRule(
|
| + cnxn, 'label:lab1', 'add_ccs', 'jrobbins, mike.j.parent',
|
| + self.services.user, 1, error_list)
|
| + self.assertEquals(error_list, [])
|
| + self.assertEquals(rule_pb.add_cc_ids[0], TEST_ID_MAP['jrobbins'])
|
| + self.assertEquals(rule_pb.add_cc_ids[1], TEST_ID_MAP['mike.j.parent'])
|
| + self.assertEquals(len(rule_pb.add_cc_ids), 2)
|
| +
|
| + def testParseRulesNone(self):
|
| + cnxn = 'fake SQL connection'
|
| + post_data = {}
|
| + rules = filterrules_helpers.ParseRules(
|
| + cnxn, post_data, None, template_helpers.EZTError())
|
| + self.assertEquals(rules, [])
|
| +
|
| + def testParseRules(self):
|
| + cnxn = 'fake SQL connection'
|
| + post_data = {
|
| + 'predicate1': 'a, b c',
|
| + 'action_type1': 'default_status',
|
| + 'action_value1': 'Reviewed',
|
| + 'predicate2': 'a, b c',
|
| + 'action_type2': 'default_owner',
|
| + 'action_value2': 'jrobbins',
|
| + 'predicate3': 'a, b c',
|
| + 'action_type3': 'add_ccs',
|
| + 'action_value3': 'jrobbins, mike.j.parent',
|
| + 'predicate4': 'a, b c',
|
| + 'action_type4': 'add_labels',
|
| + 'action_value4': 'hot, cold',
|
| + }
|
| + errors = template_helpers.EZTError()
|
| + rules = filterrules_helpers.ParseRules(
|
| + cnxn, post_data, self.services.user, errors)
|
| + self.assertEquals(rules[0].predicate, 'a, b c')
|
| + self.assertEquals(rules[0].default_status, 'Reviewed')
|
| + self.assertEquals(rules[1].default_owner_id, TEST_ID_MAP['jrobbins'])
|
| + self.assertEquals(rules[2].add_cc_ids[0], TEST_ID_MAP['jrobbins'])
|
| + self.assertEquals(rules[2].add_cc_ids[1], TEST_ID_MAP['mike.j.parent'])
|
| + self.assertEquals(rules[3].add_labels[0], 'hot')
|
| + self.assertEquals(rules[3].add_labels[1], 'cold')
|
| + self.assertEquals(len(rules), 4)
|
| + self.assertFalse(errors.AnyErrors())
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + unittest.main()
|
|
|