OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is govered by a BSD-style |
| 3 # license that can be found in the LICENSE file or at |
| 4 # https://developers.google.com/open-source/licenses/bsd |
| 5 |
| 6 """Unit tests for sorting.py functions.""" |
| 7 |
| 8 import unittest |
| 9 |
| 10 import mox |
| 11 |
| 12 from framework import sorting |
| 13 from proto import tracker_pb2 |
| 14 from testing import fake |
| 15 from testing import testing_helpers |
| 16 from tracker import tracker_bizobj |
| 17 |
| 18 |
| 19 def MakeDescending(accessor): |
| 20 return sorting._MaybeMakeDescending(accessor, True) |
| 21 |
| 22 |
| 23 class SortingTest(unittest.TestCase): |
| 24 |
| 25 def setUp(self): |
| 26 self.mox = mox.Mox() |
| 27 self.default_cols = 'a b c' |
| 28 self.builtin_cols = 'a b x y z' |
| 29 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
| 30 self.config.component_defs.append(tracker_bizobj.MakeComponentDef( |
| 31 11, 789, 'Database', 'doc', False, [], [], 0, 0)) |
| 32 self.config.component_defs.append(tracker_bizobj.MakeComponentDef( |
| 33 22, 789, 'User Interface', 'doc', True, [], [], 0, 0)) |
| 34 self.config.component_defs.append(tracker_bizobj.MakeComponentDef( |
| 35 33, 789, 'Installer', 'doc', False, [], [], 0, 0)) |
| 36 |
| 37 def tearDown(self): |
| 38 self.mox.UnsetStubs() |
| 39 self.mox.ResetAll() |
| 40 |
| 41 def testMakeSingleSortKeyAccessor_Status(self): |
| 42 """Sorting by status should create an accessor for that column.""" |
| 43 self.mox.StubOutWithMock(sorting, '_IndexOrLexical') |
| 44 status_names = [wks.status for wks in self.config.well_known_statuses] |
| 45 sorting._IndexOrLexical(status_names, 'status accessor') |
| 46 self.mox.ReplayAll() |
| 47 |
| 48 sorting._MakeSingleSortKeyAccessor( |
| 49 'status', self.config, {'status': 'status accessor'}, [], {}, []) |
| 50 self.mox.VerifyAll() |
| 51 |
| 52 def testMakeSingleSortKeyAccessor_Component(self): |
| 53 """Sorting by component should create an accessor for that column.""" |
| 54 self.mox.StubOutWithMock(sorting, '_IndexListAccessor') |
| 55 component_ids = [11, 33, 22] |
| 56 sorting._IndexListAccessor(component_ids, 'component accessor') |
| 57 self.mox.ReplayAll() |
| 58 |
| 59 sorting._MakeSingleSortKeyAccessor( |
| 60 'component', self.config, {'component': 'component accessor'}, [], {}, []) |
| 61 self.mox.VerifyAll() |
| 62 |
| 63 def testMakeSingleSortKeyAccessor_OtherBuiltInColunms(self): |
| 64 """Sorting a built-in column should create an accessor for that column.""" |
| 65 accessor = sorting._MakeSingleSortKeyAccessor( |
| 66 'buildincol', self.config, {'buildincol': 'accessor'}, [], {}, []) |
| 67 self.assertEqual('accessor', accessor) |
| 68 |
| 69 def testMakeSingleSortKeyAccessor_OtherBuiltInUserColunms(self): |
| 70 """Sorting a built-in user column should create a user accessor.""" |
| 71 self.mox.StubOutWithMock(sorting, '_UserEditNameAccessor') |
| 72 users_by_id = {111L: 'fake user'} |
| 73 sorting._UserEditNameAccessor(users_by_id, 'owner accessor') |
| 74 self.mox.ReplayAll() |
| 75 |
| 76 sorting._MakeSingleSortKeyAccessor( |
| 77 'owner', self.config, {'owner': 'owner accessor'}, |
| 78 ['owner'], users_by_id, []) |
| 79 self.mox.VerifyAll() |
| 80 |
| 81 def testIndexOrLexical(self): |
| 82 well_known_values = ['x-a', 'x-b', 'x-c', 'x-d'] |
| 83 art = 'this is a fake artifact' |
| 84 |
| 85 # Case 1: accessor generates no values. |
| 86 base_accessor = lambda art: None |
| 87 accessor = sorting._IndexOrLexical(well_known_values, base_accessor) |
| 88 self.assertEqual(sorting.MAX_STRING, accessor(art)) |
| 89 neg_accessor = MakeDescending(accessor) |
| 90 self.assertEqual(sorting.DescendingValue(sorting.MAX_STRING), |
| 91 neg_accessor(art)) |
| 92 |
| 93 # Case 2: accessor generates a value, but it is an empty value. |
| 94 base_accessor = lambda art: '' |
| 95 accessor = sorting._IndexOrLexical(well_known_values, base_accessor) |
| 96 self.assertEqual(sorting.MAX_STRING, accessor(art)) |
| 97 neg_accessor = MakeDescending(accessor) |
| 98 self.assertEqual(sorting.DescendingValue(sorting.MAX_STRING), |
| 99 neg_accessor(art)) |
| 100 |
| 101 # Case 3: A single well-known value |
| 102 base_accessor = lambda art: 'x-c' |
| 103 accessor = sorting._IndexOrLexical(well_known_values, base_accessor) |
| 104 self.assertEqual(2, accessor(art)) |
| 105 neg_accessor = MakeDescending(accessor) |
| 106 self.assertEqual(-2, neg_accessor(art)) |
| 107 |
| 108 # Case 4: A single odd-ball value |
| 109 base_accessor = lambda art: 'x-zzz' |
| 110 accessor = sorting._IndexOrLexical(well_known_values, base_accessor) |
| 111 self.assertEqual('x-zzz', accessor(art)) |
| 112 neg_accessor = MakeDescending(accessor) |
| 113 self.assertEqual( |
| 114 sorting.DescendingValue('x-zzz'), neg_accessor(art)) |
| 115 |
| 116 def testIndexListAccessor_SomeWellKnownValues(self): |
| 117 """Values sort according to their position in the well-known list.""" |
| 118 well_known_values = [11, 33, 22] # These represent component IDs. |
| 119 art = fake.MakeTestIssue(789, 1, 'sum 1', 'New', 111L) |
| 120 base_accessor = lambda issue: issue.component_ids |
| 121 accessor = sorting._IndexListAccessor(well_known_values, base_accessor) |
| 122 |
| 123 # Case 1: accessor generates no values. |
| 124 self.assertEqual(sorting.MAX_STRING, accessor(art)) |
| 125 neg_accessor = MakeDescending(accessor) |
| 126 self.assertEqual(sorting.MAX_STRING, neg_accessor(art)) |
| 127 |
| 128 # Case 2: A single well-known value |
| 129 art.component_ids = [33] |
| 130 self.assertEqual([1], accessor(art)) |
| 131 neg_accessor = MakeDescending(accessor) |
| 132 self.assertEqual([-1], neg_accessor(art)) |
| 133 |
| 134 # Case 3: Multiple well-known and odd-ball values |
| 135 art.component_ids = [33, 11, 99] |
| 136 self.assertEqual([0, 1, sorting.MAX_STRING], accessor(art)) |
| 137 neg_accessor = MakeDescending(accessor) |
| 138 self.assertEqual([sorting.MAX_STRING, -1, 0], |
| 139 neg_accessor(art)) |
| 140 |
| 141 def testIndexListAccessor_NoWellKnownValues(self): |
| 142 """When there are no well-known values, all values sort last.""" |
| 143 well_known_values = [] # Nothing pre-defined, so everything is oddball |
| 144 art = fake.MakeTestIssue(789, 1, 'sum 1', 'New', 111L) |
| 145 base_accessor = lambda issue: issue.component_ids |
| 146 accessor = sorting._IndexListAccessor(well_known_values, base_accessor) |
| 147 |
| 148 # Case 1: accessor generates no values. |
| 149 self.assertEqual(sorting.MAX_STRING, accessor(art)) |
| 150 neg_accessor = MakeDescending(accessor) |
| 151 self.assertEqual(sorting.MAX_STRING, neg_accessor(art)) |
| 152 |
| 153 # Case 2: A single oddball value |
| 154 art.component_ids = [33] |
| 155 self.assertEqual([sorting.MAX_STRING], accessor(art)) |
| 156 neg_accessor = MakeDescending(accessor) |
| 157 self.assertEqual([sorting.MAX_STRING], neg_accessor(art)) |
| 158 |
| 159 # Case 3: Multiple odd-ball values |
| 160 art.component_ids = [33, 11, 99] |
| 161 self.assertEqual( |
| 162 [sorting.MAX_STRING, sorting.MAX_STRING, sorting.MAX_STRING], |
| 163 accessor(art)) |
| 164 neg_accessor = MakeDescending(accessor) |
| 165 self.assertEqual( |
| 166 [sorting.MAX_STRING, sorting.MAX_STRING, sorting.MAX_STRING], |
| 167 neg_accessor(art)) |
| 168 |
| 169 def testIndexOrLexicalList(self): |
| 170 well_known_values = ['Pri-High', 'Pri-Med', 'Pri-Low'] |
| 171 art = fake.MakeTestIssue(789, 1, 'sum 1', 'New', 111L, merged_into=200001) |
| 172 |
| 173 # Case 1: accessor generates no values. |
| 174 accessor = sorting._IndexOrLexicalList(well_known_values, [], 'pri', {}) |
| 175 self.assertEqual(sorting.MAX_STRING, accessor(art)) |
| 176 neg_accessor = MakeDescending(accessor) |
| 177 self.assertEqual(sorting.MAX_STRING, neg_accessor(art)) |
| 178 |
| 179 # Case 2: A single well-known value |
| 180 art.labels = ['Pri-Med'] |
| 181 accessor = sorting._IndexOrLexicalList(well_known_values, [], 'pri', {}) |
| 182 self.assertEqual([1], accessor(art)) |
| 183 neg_accessor = MakeDescending(accessor) |
| 184 self.assertEqual([-1], neg_accessor(art)) |
| 185 |
| 186 # Case 3: Multiple well-known and odd-ball values |
| 187 art.labels = ['Pri-zzz', 'Pri-Med', 'yyy', 'Pri-High'] |
| 188 accessor = sorting._IndexOrLexicalList(well_known_values, [], 'pri', {}) |
| 189 self.assertEqual([0, 1, 'zzz'], accessor(art)) |
| 190 neg_accessor = MakeDescending(accessor) |
| 191 self.assertEqual([sorting.DescendingValue('zzz'), -1, 0], |
| 192 neg_accessor(art)) |
| 193 |
| 194 def testComputeSortDirectives(self): |
| 195 config = tracker_pb2.ProjectIssueConfig() |
| 196 mr = testing_helpers.MakeMonorailRequest( |
| 197 path='/p/proj/issues/detail?id=123') |
| 198 self.assertEquals(['project', 'id'], |
| 199 sorting.ComputeSortDirectives(mr, config)) |
| 200 |
| 201 mr = testing_helpers.MakeMonorailRequest( |
| 202 path='/p/proj/issues/detail?id=123&sort=a b C') |
| 203 self.assertEquals(['a', 'b', 'c', 'project', 'id'], |
| 204 sorting.ComputeSortDirectives(mr, config)) |
| 205 |
| 206 config.default_sort_spec = 'id -reporter Owner' |
| 207 mr = testing_helpers.MakeMonorailRequest( |
| 208 path='/p/proj/issues/detail?id=123') |
| 209 self.assertEquals(['id', '-reporter', 'owner', 'project'], |
| 210 sorting.ComputeSortDirectives(mr, config)) |
| 211 |
| 212 mr = testing_helpers.MakeMonorailRequest( |
| 213 path='/p/proj/issues/detail?id=123&sort=A -b c -owner') |
| 214 self.assertEquals( |
| 215 ['a', '-b', 'c', '-owner', 'id', '-reporter', 'project'], |
| 216 sorting.ComputeSortDirectives(mr, config)) |
| 217 |
| 218 |
| 219 if __name__ == '__main__': |
| 220 unittest.main() |
OLD | NEW |