def testStatusView(self): view = framework_views.StatusView('', None) self.assertEquals('', view.name) view = framework_views.StatusView('Accepted', None) self.assertEquals('Accepted', view.name) self.assertEquals('', view.docstring) self.assertEquals('yes', view.means_open) view = framework_views.StatusView(LONG_STR, None) self.assertEquals(LONG_STR, view.name) self.assertEquals('', view.docstring) self.assertEquals('yes', view.means_open) config = tracker_pb2.ProjectIssueConfig() config.well_known_statuses.append(tracker_pb2.StatusDef( status='SlamDunk', status_docstring='Code fixed and taught a lesson', means_open=False)) view = framework_views.StatusView('SlamDunk', config) self.assertEquals('Code fixed and taught a lesson', view.docstring) self.assertFalse(view.means_open) view = framework_views.StatusView('SlammedBack', config) self.assertEquals('', view.docstring)
def testLabelView(self): view = framework_views.LabelView('', None) self.assertEquals('', view.name) view = framework_views.LabelView('Priority-High', None) self.assertEquals('Priority-High', view.name) self.assertIsNone(view.is_restrict) self.assertEquals('', view.docstring) self.assertEquals('Priority', view.prefix) self.assertEquals('High', view.value) view = framework_views.LabelView('%s-%s' % (LONG_STR, LONG_STR), None) self.assertEquals('%s-%s' % (LONG_STR, LONG_STR), view.name) self.assertEquals('', view.docstring) self.assertEquals(LONG_STR, view.prefix) self.assertEquals(LONG_STR, view.value) view = framework_views.LabelView(LONG_PART_STR, None) self.assertEquals(LONG_PART_STR, view.name) self.assertEquals('', view.docstring) self.assertEquals('OnePartThatWillNotFit', view.prefix) self.assertEquals('OneShort', view.value) config = tracker_pb2.ProjectIssueConfig() config.well_known_labels.append(tracker_pb2.LabelDef( label='Priority-High', label_docstring='Must ship in this milestone')) view = framework_views.LabelView('Priority-High', config) self.assertEquals('Must ship in this milestone', view.docstring) view = framework_views.LabelView('Priority-Foo', config) self.assertEquals('', view.docstring) view = framework_views.LabelView('Restrict-View-Commit', None) self.assertTrue(view.is_restrict)
def _MakeConfig(): config = tracker_pb2.ProjectIssueConfig() config.well_known_statuses.append(tracker_pb2.StatusDef( status='New', means_open=True)) config.well_known_statuses.append(tracker_pb2.StatusDef( status='Old', means_open=False)) return config
def MakeProjectIssueConfig(project_id, well_known_statuses, statuses_offer_merge, well_known_labels, excl_label_prefixes, templates, col_spec): """Return a ProjectIssueConfig with the given values.""" # pylint: disable=multiple-statements if not well_known_statuses: well_known_statuses = [] if not statuses_offer_merge: statuses_offer_merge = [] if not well_known_labels: well_known_labels = [] if not excl_label_prefixes: excl_label_prefixes = [] if not templates: templates = [] if not col_spec: col_spec = ' ' project_config = tracker_pb2.ProjectIssueConfig() if project_id: # There is no ID for harmonized configs. project_config.project_id = project_id SetConfigStatuses(project_config, well_known_statuses) project_config.statuses_offer_merge = statuses_offer_merge SetConfigLabels(project_config, well_known_labels) SetConfigTemplates(project_config, templates) project_config.exclusive_label_prefixes = excl_label_prefixes # ID 0 means that nothing has been specified, so use hard-coded defaults. project_config.default_template_for_developers = 0 project_config.default_template_for_users = 0 project_config.default_col_spec = col_spec # Note: default project issue config has no filter rules. return project_config
def setUp(self): self.project = project_pb2.Project() self.project.project_name = 'proj' self.config = tracker_pb2.ProjectIssueConfig() self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_user_stub() self.testbed.init_memcache_stub() self.testbed.init_datastore_v3_stub()
def testComputeColSpec(self): # No config passed, and nothing in URL mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123') mr.ComputeColSpec(None) self.assertEquals(tracker_constants.DEFAULT_COL_SPEC, mr.col_spec) # No config passed, but set in URL mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&colspec=a b C') mr.ComputeColSpec(None) self.assertEquals('a b C', mr.col_spec) config = tracker_pb2.ProjectIssueConfig() # No default in the config, and nothing in URL mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123') mr.ComputeColSpec(config) self.assertEquals(tracker_constants.DEFAULT_COL_SPEC, mr.col_spec) # No default in the config, but set in URL mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&colspec=a b C') mr.ComputeColSpec(config) self.assertEquals('a b C', mr.col_spec) config.default_col_spec = 'd e f' # Default in the config, and nothing in URL mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123') mr.ComputeColSpec(config) self.assertEquals('d e f', mr.col_spec) # Default in the config, but overrided via URL mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&colspec=a b C') mr.ComputeColSpec(config) self.assertEquals('a b C', mr.col_spec) # project colspec contains hotlist columns mr = testing_helpers.MakeMonorailRequest( path='p/proj/issues/detail?id=123&colspec=Rank Adder Adder Owner') mr.ComputeColSpec(None) self.assertEquals(tracker_constants.DEFAULT_COL_SPEC, mr.col_spec) # hotlist columns are not deleted when page is a hotlist page mr = testing_helpers.MakeMonorailRequest( path= 'u/[email protected]/hotlists/TestHotlist?colspec=Rank Adder', hotlist=self.hotlist) mr.ComputeColSpec(None) self.assertEquals('Rank Adder', mr.col_spec)
def testComputeColSpec_XSS(self): config_1 = tracker_pb2.ProjectIssueConfig() config_2 = tracker_pb2.ProjectIssueConfig() config_2.default_col_spec = "id '+alert(1)+'" mr_1 = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123') mr_2 = testing_helpers.MakeMonorailRequest( path="/p/proj/issues/detail?id=123&colspec=id '+alert(1)+'") # Normal colspec in config but malicious request self.assertRaises(monorailrequest.InputException, mr_2.ComputeColSpec, config_1) # Malicious colspec in config but normal request self.assertRaises(monorailrequest.InputException, mr_1.ComputeColSpec, config_2) # Malicious colspec in config and malicious request self.assertRaises(monorailrequest.InputException, mr_2.ComputeColSpec, config_2)
def _MakeConfig(): config = tracker_pb2.ProjectIssueConfig() config.well_known_labels = [ tracker_pb2.LabelDef(label='Priority-High', label_docstring='Must be resolved'), tracker_pb2.LabelDef(label='Priority-Low', label_docstring='Can be slipped'), ] config.well_known_statuses.append( tracker_pb2.StatusDef(status='New', means_open=True)) config.well_known_statuses.append( tracker_pb2.StatusDef(status='Old', means_open=False)) return config
def testMakeBounceFieldValueViews(self): config = tracker_pb2.ProjectIssueConfig() fd = tracker_pb2.FieldDef(field_id=3, field_type=tracker_pb2.FieldTypes.INT_TYPE, applicable_type='', field_name='EstDays') phase_fd = tracker_pb2.FieldDef( field_id=4, field_type=tracker_pb2.FieldTypes.INT_TYPE, applicable_type='', field_name='Gump') config.field_defs = [ fd, phase_fd, tracker_pb2.FieldDef(field_id=5, field_type=tracker_pb2.FieldTypes.STR_TYPE) ] parsed_fvs = {3: [455]} parsed_phase_fvs = { 4: { 'stable': [73, 74], 'beta': [8], 'beta-exp': [75] }, } fvs = tracker_views.MakeBounceFieldValueViews(parsed_fvs, parsed_phase_fvs, config) self.assertEqual(len(fvs), 4) estdays_ezt_fv = template_helpers.EZTItem(val=455, docstring='', idx=0) expected = tracker_views.FieldValueView(fd, config, [estdays_ezt_fv], [], []) self.assertEqual(fvs[0].field_name, expected.field_name) self.assertEqual(fvs[0].values[0].val, expected.values[0].val) self.assertEqual(fvs[0].values[0].idx, expected.values[0].idx) self.assertTrue(fvs[0].applicable) self.assertEqual(fvs[1].field_name, phase_fd.field_name) self.assertEqual(fvs[2].field_name, phase_fd.field_name) self.assertEqual(fvs[3].field_name, phase_fd.field_name) fd.approval_id = 23 config.field_defs = [ fd, tracker_pb2.FieldDef( field_id=23, field_name='Legal', field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE) ] fvs = tracker_views.MakeBounceFieldValueViews(parsed_fvs, {}, config) self.assertTrue(fvs[0].applicable)
def setUp(self): self.cnxn = 'fake cnxn' self.services = service_manager.Services( config=fake.ConfigService(), issue=fake.IssueService(), user=fake.UserService(), project=fake.ProjectService(), issue_star=fake.IssueStarService(), spam=fake.SpamService()) self.project = self.services.project.TestAddProject('proj', project_id=987) self.config = tracker_pb2.ProjectIssueConfig() self.config.statuses_offer_merge.append('Duplicate') self.services.config.StoreConfig(self.cnxn, self.config)
def testSimpleIssueView(self): config = tracker_pb2.ProjectIssueConfig() view1 = self.CheckSimpleIssueView(config) self.assertEqual('', view1.status.docstring) config.well_known_statuses.append(tracker_pb2.StatusDef( status='New', status_docstring='Issue has not had review yet')) view1 = self.CheckSimpleIssueView(config) self.assertEqual('Issue has not had review yet', view1.status.docstring) self.assertIsNone(view1.restrictions.has_restrictions) self.assertEqual('', view1.restrictions.view) self.assertEqual('', view1.restrictions.add_comment) self.assertEqual('', view1.restrictions.edit)
def testChooseNextPage_ForMoveRequest(self): mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&q=term') mr.col_spec = '' config = tracker_pb2.ProjectIssueConfig() issue = fake.MakeTestIssue(987, 123, 'summary', 'New', 111L) moved_to_project_name = 'projB' moved_to_project_local_id = 543 moved_to_project_name_and_local_id = (moved_to_project_name, moved_to_project_local_id) url = issuedetail._ChooseNextPage(mr, issue.local_id, config, moved_to_project_name_and_local_id, None, user_pb2.IssueUpdateNav.UP_TO_LIST, '124') self.assertTrue( url.startswith( 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&moved_to_id=' + str(moved_to_project_local_id) + '&moved_to_project=' + moved_to_project_name + '&q=term')) url = issuedetail._ChooseNextPage( mr, issue.local_id, config, moved_to_project_name_and_local_id, None, user_pb2.IssueUpdateNav.STAY_SAME_ISSUE, '124') self.assertEqual( 'http://127.0.0.1/p/%s/issues/detail?id=123&q=term' % (moved_to_project_name), url) mr.project_name = 'proj' # reset project name back. url = issuedetail._ChooseNextPage(mr, issue.local_id, config, moved_to_project_name_and_local_id, None, user_pb2.IssueUpdateNav.NEXT_IN_LIST, '124') self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=124&q=term', url) # If this is the last in the list, the next_id from the form will be ''. url = issuedetail._ChooseNextPage(mr, issue.local_id, config, moved_to_project_name_and_local_id, None, user_pb2.IssueUpdateNav.NEXT_IN_LIST, '') self.assertTrue( url.startswith( 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&moved_to_id=' + str(moved_to_project_local_id) + '&moved_to_project=' + moved_to_project_name + '&q=term'))
def testComputeSortDirectives(self): config = tracker_pb2.ProjectIssueConfig() self.assertEquals(['project', 'id'], sorting.ComputeSortDirectives(config, '', '')) self.assertEquals(['a', 'b', 'c', 'project', 'id'], sorting.ComputeSortDirectives(config, '', 'a b C')) config.default_sort_spec = 'id -reporter Owner' self.assertEquals(['id', '-reporter', 'owner', 'project'], sorting.ComputeSortDirectives(config, '', '')) self.assertEquals( ['x', '-b', 'a', 'c', '-owner', 'id', '-reporter', 'project'], sorting.ComputeSortDirectives(config, 'x -b', 'A -b c -owner'))
def MakeProjectIssueConfig(prefix): return tracker_pb2.ProjectIssueConfig( restrict_to_known=True, default_col_spec='ID Type Priority Summary', default_sort_spec='ID Priority', well_known_statuses=[ MakeStatus('%s-status1' % prefix), MakeStatus('%s-status2' % prefix), ], well_known_labels=[ MakeLabel('%s-label1' % prefix), MakeLabel('%s-label2' % prefix), ], default_template_for_developers=1, default_template_for_users=2)
def HarmonizeConfigs(config_list): """Combine several ProjectIssueConfigs into one for cross-project sorting. Args: config_list: a list of ProjectIssueConfig PBs with labels and statuses among other fields. Returns: A new ProjectIssueConfig with just the labels and status values filled in to be a logical union of the given configs. Specifically, the order of the combined status and label lists should be maintained. """ if not config_list: return MakeDefaultProjectIssueConfig(None) harmonized_status_names = _CombineOrderedLists( [[stat.status for stat in config.well_known_statuses] for config in config_list]) harmonized_label_names = _CombineOrderedLists( [[lab.label for lab in config.well_known_labels] for config in config_list]) harmonized_default_sort_spec = ' '.join(config.default_sort_spec for config in config_list) # This col_spec is probably not what the user wants to view because it is # too much information. We join all the col_specs here so that we are sure # to lookup all users needed for sorting, even if it is more than needed. # xxx we need to look up users based on colspec rather than sortspec? harmonized_default_col_spec = ' '.join(config.default_col_spec for config in config_list) result_config = tracker_pb2.ProjectIssueConfig() # The combined config is only used during sorting, never stored. result_config.default_col_spec = harmonized_default_col_spec result_config.default_sort_spec = harmonized_default_sort_spec for status_name in harmonized_status_names: result_config.well_known_statuses.append( tracker_pb2.StatusDef(status=status_name, means_open=True)) for label_name in harmonized_label_names: result_config.well_known_labels.append( tracker_pb2.LabelDef(label=label_name)) for config in config_list: result_config.field_defs.extend(config.field_defs) result_config.component_defs.extend(config.component_defs) return result_config
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 testChooseNextPage(self): mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&q=term') mr.col_spec = '' config = tracker_pb2.ProjectIssueConfig() issue = fake.MakeTestIssue(987, 123, 'summary', 'New', 111L) url = issuedetail._ChooseNextPage(mr, issue.local_id, config, None, None, user_pb2.IssueUpdateNav.UP_TO_LIST, '124') self.assertTrue( url.startswith( 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&q=term') ) self.assertTrue(url.endswith('&updated=123')) url = issuedetail._ChooseNextPage( mr, issue.local_id, config, None, None, user_pb2.IssueUpdateNav.STAY_SAME_ISSUE, '124') self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=123&q=term', url) url = issuedetail._ChooseNextPage(mr, issue.local_id, config, None, None, user_pb2.IssueUpdateNav.NEXT_IN_LIST, '124') self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=124&q=term', url) # If this is the last in the list, the next_id from the form will be ''. url = issuedetail._ChooseNextPage(mr, issue.local_id, config, None, None, user_pb2.IssueUpdateNav.NEXT_IN_LIST, '') self.assertTrue( url.startswith( 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&q=term') ) self.assertTrue(url.endswith('&updated=123'))
def testComputeSortDirectives(self): config = tracker_pb2.ProjectIssueConfig() mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123') self.assertEquals(['project', 'id'], sorting.ComputeSortDirectives(mr, config)) mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&sort=a b C') self.assertEquals(['a', 'b', 'c', 'project', 'id'], sorting.ComputeSortDirectives(mr, config)) config.default_sort_spec = 'id -reporter Owner' mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123') self.assertEquals(['id', '-reporter', 'owner', 'project'], sorting.ComputeSortDirectives(mr, config)) mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/detail?id=123&sort=A -b c -owner') self.assertEquals( ['a', '-b', 'c', '-owner', 'id', '-reporter', 'project'], sorting.ComputeSortDirectives(mr, config))
def setUp(self): self.config = tracker_pb2.ProjectIssueConfig() self.estdays_fd = tracker_bizobj.MakeFieldDef( 1, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, 3, 99, None, False, None, None, None, 'no_action', 'descriptive docstring', False, None, False) self.os_fd = tracker_bizobj.MakeFieldDef( 2, 789, 'OS', tracker_pb2.FieldTypes.ENUM_TYPE, 'Enhancement', None, False, False, False, None, None, None, False, None, None, None, 'no_action', 'descriptive docstring', False, None, False) self.milestone_fd = tracker_bizobj.MakeFieldDef( 3, 789, 'Launch-Milestone', tracker_pb2.FieldTypes.ENUM_TYPE, 'Enhancement', None, False, False, False, None, None, None, False, None, None, None, 'no_action', 'descriptive docstring', False, None, False) self.config.field_defs = [ self.estdays_fd, self.os_fd, self.milestone_fd ] self.config.well_known_labels = [ tracker_pb2.LabelDef(label='Priority-High', label_docstring='Must be resolved'), tracker_pb2.LabelDef(label='Priority-Low', label_docstring='Can be slipped'), ]
def setUp(self): self.project = project_pb2.Project() self.project.project_name = 'proj' self.project.owner_ids = [111L] self.config = tracker_pb2.ProjectIssueConfig()
def testComputeDerivedFields_Components(self): cnxn = 'fake sql connection' rules = [] component_defs = [ tracker_bizobj.MakeComponentDef( 10, 789, 'DB', 'database', False, [], [ TEST_ID_MAP['*****@*****.**'], TEST_ID_MAP['*****@*****.**'] ], 0, 0, label_ids=[ TEST_LABEL_IDS['i18n'], TEST_LABEL_IDS['Priority-High'] ]), tracker_bizobj.MakeComponentDef(20, 789, 'Install', 'installer', False, [], [], 0, 0), tracker_bizobj.MakeComponentDef( 30, 789, 'UI', 'doc', False, [], [ TEST_ID_MAP['*****@*****.**'], TEST_ID_MAP['*****@*****.**'] ], 0, 0, label_ids=[ TEST_LABEL_IDS['i18n'], TEST_LABEL_IDS['l10n'], TEST_LABEL_IDS['Priority-Medium'] ]), ] excl_prefixes = ['Priority', 'type', 'milestone'] config = tracker_pb2.ProjectIssueConfig( exclusive_label_prefixes=excl_prefixes, component_defs=component_defs) predicate_asts = filterrules_helpers.ParsePredicateASTs( rules, config, None) # No components. 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)) # One component, no CCs or labels added issue.component_ids = [20] 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)) # One component, some CCs and labels added issue = fake.MakeTestIssue(789, 1, ORIG_SUMMARY, 'New', 0L, labels=ORIG_LABELS, component_ids=[10]) self.assertEquals( (0, '', [ TEST_ID_MAP['*****@*****.**'], TEST_ID_MAP['*****@*****.**'] ], ['i18n', 'Priority-High'], []), filterrules_helpers._ComputeDerivedFields(cnxn, self.services, issue, config, rules, predicate_asts)) # One component, CCs and labels not added because of labels on the issue. issue = fake.MakeTestIssue(789, 1, ORIG_SUMMARY, 'New', 0L, labels=['Priority-Low', 'i18n'], component_ids=[10]) issue.cc_ids = [TEST_ID_MAP['*****@*****.**']] self.assertEquals( (0, '', [TEST_ID_MAP['*****@*****.**']], [], []), filterrules_helpers._ComputeDerivedFields(cnxn, self.services, issue, config, rules, predicate_asts)) # Multiple components, added CCs treated as a set, exclusive labels in later # components take priority over earlier ones. issue = fake.MakeTestIssue(789, 1, ORIG_SUMMARY, 'New', 0L, labels=ORIG_LABELS, component_ids=[10, 30]) self.assertEquals( (0, '', [ TEST_ID_MAP['*****@*****.**'], TEST_ID_MAP['*****@*****.**'], TEST_ID_MAP['*****@*****.**'] ], ['i18n', 'l10n', 'Priority-Medium'], []), filterrules_helpers._ComputeDerivedFields(cnxn, self.services, issue, config, rules, predicate_asts))
def testFindFieldDefByID_Empty(self): config = tracker_pb2.ProjectIssueConfig() self.assertIsNone(tracker_bizobj.FindFieldDefByID(1, config))
def testFindFieldDef_Empty(self): config = tracker_pb2.ProjectIssueConfig() self.assertIsNone(tracker_bizobj.FindFieldDef('EstDays', config))
def testFindFieldDef_None(self): config = tracker_pb2.ProjectIssueConfig() self.assertIsNone(tracker_bizobj.FindFieldDef(None, config))
def testUsersInvolvedInConfig_Empty(self): config = tracker_pb2.ProjectIssueConfig() self.assertEqual(set(), tracker_bizobj.UsersInvolvedInConfig(config))
def testGetGrantedPerms_Empty(self): config = tracker_pb2.ProjectIssueConfig() issue = tracker_pb2.Issue() self.assertEqual( set(), tracker_bizobj.GetGrantedPerms(issue, {111L}, config))
def setUp(self): self.config = tracker_pb2.ProjectIssueConfig() self.estdays_fd = tracker_bizobj.MakeFieldDef( 1, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, 3, 99, None, False, None, None, None, 'no_action', 'descriptive docstring', False, approval_id=None, is_phase_field=False) self.designdoc_fd = tracker_bizobj.MakeFieldDef( 2, 789, 'DesignDoc', tracker_pb2.FieldTypes.STR_TYPE, 'Enhancement', None, False, False, False, None, None, None, False, None, None, None, 'no_action', 'descriptive docstring', False, approval_id=None, is_phase_field=False) self.mtarget_fd = tracker_bizobj.MakeFieldDef( 3, 789, 'M-Target', tracker_pb2.FieldTypes.INT_TYPE, 'Enhancement', None, False, False, False, None, None, None, False, None, None, None, 'no_action', 'doc doc', False, approval_id=None, is_phase_field=True) self.config.field_defs = [self.estdays_fd, self.designdoc_fd]
def testComputeDerivedFields_Rules(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=['*****@*****.**']), 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'], ['*****@*****.**']), 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' ], ['*****@*****.**']), 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' ], ['*****@*****.**']), 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_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 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))