Chromium Code Reviews| Index: tests/owners_unittest.py |
| diff --git a/tests/owners_unittest.py b/tests/owners_unittest.py |
| index 34272a1337da077c57ab3ff285f7e219b4ab572b..f9a5d2c690995b8ef4ae521211e04d34edf35004 100755 |
| --- a/tests/owners_unittest.py |
| +++ b/tests/owners_unittest.py |
| @@ -58,7 +58,7 @@ def test_repo(): |
| }) |
| -class OwnersDatabaseTest(unittest.TestCase): |
| +class _BaseTestCase(unittest.TestCase): |
| def setUp(self): |
| self.repo = test_repo() |
| self.files = self.repo.files |
| @@ -73,6 +73,8 @@ class OwnersDatabaseTest(unittest.TestCase): |
| glob = glob or self.glob |
| return owners.Database(root, fopen, os_path, glob) |
| + |
| +class OwnersDatabaseTest(_BaseTestCase): |
| def test_constructor(self): |
| self.assertNotEquals(self.db(), None) |
| @@ -205,16 +207,42 @@ class OwnersDatabaseTest(unittest.TestCase): |
| self.assertRaises(owners.SyntaxErrorInOwnersFile, |
| self.db().directories_not_covered_by, ['DEPS'], [brett]) |
| - def assert_reviewers_for(self, files, expected_reviewers): |
| + |
|
M-A Ruel
2012/12/17 22:27:19
remove extra line
|
| + def assert_syntax_error(self, owners_file_contents): |
| + db = self.db() |
| + self.files['/foo/OWNERS'] = owners_file_contents |
| + self.files['/foo/DEPS'] = '' |
| + try: |
| + db.reviewers_for(['foo/DEPS']) |
| + self.fail() # pragma: no cover |
| + except owners.SyntaxErrorInOwnersFile, e: |
| + self.assertTrue(str(e).startswith('/foo/OWNERS:1')) |
| + |
| + def test_syntax_error__unknown_token(self): |
| + self.assert_syntax_error('{}\n') |
| + |
| + def test_syntax_error__unknown_set(self): |
| + self.assert_syntax_error('set myfatherisbillgates\n') |
| + |
| + def test_syntax_error__bad_email(self): |
| + self.assert_syntax_error('ben\n') |
| + |
| + |
| +class ReviewersForTest(_BaseTestCase): |
| + def assert_reviewers_for(self, files, *potential_suggested_reviewers): |
| db = self.db() |
| - self.assertEquals(db.reviewers_for(set(files)), set(expected_reviewers)) |
| + suggested_reviewers = db.reviewers_for(set(files)) |
| + self.assertTrue(suggested_reviewers in |
| + [set(suggestion) for suggestion in potential_suggested_reviewers]) |
| def test_reviewers_for__basic_functionality(self): |
| self.assert_reviewers_for(['chrome/gpu/gpu_channel.h'], |
| - [brett]) |
| + [ken]) |
| def test_reviewers_for__set_noparent_works(self): |
| - self.assert_reviewers_for(['content/content.gyp'], [darin]) |
| + self.assert_reviewers_for(['content/content.gyp'], |
| + [john], |
| + [darin]) |
| def test_reviewers_for__valid_inputs(self): |
| db = self.db() |
| @@ -236,15 +264,16 @@ class OwnersDatabaseTest(unittest.TestCase): |
| self.assert_reviewers_for([ |
| 'chrome/gpu/gpu_channel.h', |
| 'content/baz/froboz.h', |
| - 'chrome/renderer/gpu/gpu_channel_host.h'], [brett]) |
| + 'chrome/renderer/gpu/gpu_channel_host.h'], |
| + [brett]) |
| def test_reviewers_for__two_owners(self): |
| self.assert_reviewers_for([ |
| 'chrome/gpu/gpu_channel.h', |
| 'content/content.gyp', |
| 'content/baz/froboz.h', |
| - 'content/views/pie.h' |
| - ], [john, brett]) |
| + 'content/views/pie.h'], |
| + [ken, john]) |
| def test_reviewers_for__all_files(self): |
| self.assert_reviewers_for([ |
| @@ -254,32 +283,96 @@ class OwnersDatabaseTest(unittest.TestCase): |
| 'content/content.gyp', |
| 'content/bar/foo.cc', |
| 'content/baz/froboz.h', |
| - 'content/views/pie.h'], [john, brett]) |
| + 'content/views/pie.h'], |
| + [peter, ken, john]) |
| def test_reviewers_for__per_file_owners_file(self): |
| self.files['/content/baz/OWNERS'] = owners_file(lines=[ |
| 'per-file ugly.*=tom@example.com']) |
| - self.assert_reviewers_for(['content/baz/OWNERS'], [darin]) |
| - |
| - def assert_syntax_error(self, owners_file_contents): |
| - db = self.db() |
| - self.files['/foo/OWNERS'] = owners_file_contents |
| - self.files['/foo/DEPS'] = '' |
| - try: |
| - db.reviewers_for(['foo/DEPS']) |
| - self.fail() # pragma: no cover |
| - except owners.SyntaxErrorInOwnersFile, e: |
| - self.assertTrue(str(e).startswith('/foo/OWNERS:1')) |
| - |
| - def test_syntax_error__unknown_token(self): |
| - self.assert_syntax_error('{}\n') |
| - |
| - def test_syntax_error__unknown_set(self): |
| - self.assert_syntax_error('set myfatherisbillgates\n') |
| - |
| - def test_syntax_error__bad_email(self): |
| - self.assert_syntax_error('ben\n') |
| + self.assert_reviewers_for(['content/baz/OWNERS'], |
| + [john], |
| + [darin]) |
| + def test_reviewers_for__per_file(self): |
| + self.files['/content/baz/OWNERS'] = owners_file(lines=[ |
| + 'per-file ugly.*=tom@example.com']) |
| + self.assert_reviewers_for(['content/baz/ugly.cc'], |
| + [tom]) |
| + |
| + |
| +class LowestCostOwnersTest(_BaseTestCase): |
| + # Keep the data in the test_lowest_cost_owner* methods as consistent with |
| + # test_repo() where possible to minimize confusion. |
| + |
| + def check(self, possible_owners, dirs, *possible_lowest_cost_owners): |
| + suggested_owner = owners.Database.lowest_cost_owner(possible_owners, dirs) |
| + self.assertTrue(suggested_owner in possible_lowest_cost_owners) |
| + |
| + def test_one_dir_with_owner(self): |
| + # brett is the only immediate owner for stuff in baz; john is also |
| + # an owner, but further removed. We should always get brett. |
| + self.check({brett: [('content/baz', 1)], |
| + john: [('content/baz', 2)]}, |
| + ['content/baz'], |
| + brett) |
| + |
| + # john and darin are owners for content; the suggestion could be either. |
| + def test_one_dir_with_two_owners(self): |
| + self.check({john: [('content', 1)], |
| + darin: [('content', 1)]}, |
| + ['content'], |
| + john, darin) |
| + |
| + def test_one_dir_with_two_owners_in_parent(self): |
| + # As long as the distance is the same, it shouldn't matter (brett isn't |
| + # listed in this case). |
| + self.check({john: [('content/baz', 2)], |
| + darin: [('content/baz', 2)]}, |
| + ['content/baz'], |
| + john, darin) |
| + |
| + def test_two_dirs_two_owners(self): |
| + # If they both match both dirs, they should be treated equally. |
| + self.check({john: [('content/baz', 2), ('content/bar', 2)], |
| + darin: [('content/baz', 2), ('content/bar', 2)]}, |
| + ['content/baz', 'content/bar'], |
| + john, darin) |
| + |
| + # Here brett is better since he's closer for one of the two dirs. |
| + self.check({brett: [('content/baz', 1), ('content/views', 1)], |
| + darin: [('content/baz', 2), ('content/views', 1)]}, |
| + ['content/baz', 'content/views'], |
| + brett) |
| + |
| + def test_hierarchy(self): |
| + # the choices in these tests are more arbitrary value judgements; |
| + # also, here we drift away from test_repo() to cover more cases. |
| + |
| + # Here ben isn't picked, even though he can review both; we prefer |
| + # closer reviewers. |
| + self.check({ben: [('chrome/gpu', 2), ('chrome/renderer', 2)], |
| + ken: [('chrome/gpu', 1)], |
| + peter: [('chrome/renderer', 1)]}, |
| + ['chrome/gpu', 'chrome/renderer'], |
| + ken, peter) |
| + |
| + # Here we always pick ben since he can review either dir as well as |
| + # the others but can review both (giving us fewer total reviewers). |
| + self.check({ben: [('chrome/gpu', 1), ('chrome/renderer', 1)], |
| + ken: [('chrome/gpu', 1)], |
| + peter: [('chrome/renderer', 1)]}, |
| + ['chrome/gpu', 'chrome/renderer'], |
| + ben) |
| + |
| + # However, three reviewers is too many, so ben gets this one. |
| + self.check({ben: [('chrome/gpu', 2), ('chrome/renderer', 2), |
| + ('chrome/browser', 2)], |
| + ken: [('chrome/gpu', 1)], |
| + peter: [('chrome/renderer', 1)], |
| + brett: [('chrome/browser', 1)]}, |
| + ['chrome/gpu', 'chrome/renderer', |
| + 'chrome/browser'], |
| + ben) |
| if __name__ == '__main__': |
| unittest.main() |