OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Unit tests for owners.py.""" | 6 """Unit tests for owners.py.""" |
7 | 7 |
8 import os | 8 import os |
9 import sys | 9 import sys |
10 import unittest | 10 import unittest |
(...skipping 12 matching lines...) Expand all Loading... |
23 peter = 'peter@example.com' | 23 peter = 'peter@example.com' |
24 tom = 'tom@example.com' | 24 tom = 'tom@example.com' |
25 | 25 |
26 | 26 |
27 def owners_file(*email_addresses, **kwargs): | 27 def owners_file(*email_addresses, **kwargs): |
28 s = '' | 28 s = '' |
29 if kwargs.get('comment'): | 29 if kwargs.get('comment'): |
30 s += '# %s\n' % kwargs.get('comment') | 30 s += '# %s\n' % kwargs.get('comment') |
31 if kwargs.get('noparent'): | 31 if kwargs.get('noparent'): |
32 s += 'set noparent\n' | 32 s += 'set noparent\n' |
| 33 if kwargs.get('file'): |
| 34 s += 'file:%s\n' % kwargs.get('file') |
33 s += '\n'.join(kwargs.get('lines', [])) + '\n' | 35 s += '\n'.join(kwargs.get('lines', [])) + '\n' |
34 return s + '\n'.join(email_addresses) + '\n' | 36 return s + '\n'.join(email_addresses) + '\n' |
35 | 37 |
36 | 38 |
37 def test_repo(): | 39 def test_repo(): |
38 return filesystem_mock.MockFileSystem(files={ | 40 return filesystem_mock.MockFileSystem(files={ |
39 '/DEPS' : '', | 41 '/DEPS' : '', |
40 '/OWNERS': owners_file(owners.EVERYONE), | 42 '/OWNERS': owners_file(owners.EVERYONE), |
41 '/base/vlog.h': '', | 43 '/base/vlog.h': '', |
42 '/chrome/OWNERS': owners_file(ben, brett), | 44 '/chrome/OWNERS': owners_file(ben, brett), |
43 '/chrome/browser/OWNERS': owners_file(brett), | 45 '/chrome/browser/OWNERS': owners_file(brett), |
44 '/chrome/browser/defaults.h': '', | 46 '/chrome/browser/defaults.h': '', |
45 '/chrome/gpu/OWNERS': owners_file(ken), | 47 '/chrome/gpu/OWNERS': owners_file(ken), |
46 '/chrome/gpu/gpu_channel.h': '', | 48 '/chrome/gpu/gpu_channel.h': '', |
47 '/chrome/renderer/OWNERS': owners_file(peter), | 49 '/chrome/renderer/OWNERS': owners_file(peter), |
48 '/chrome/renderer/gpu/gpu_channel_host.h': '', | 50 '/chrome/renderer/gpu/gpu_channel_host.h': '', |
49 '/chrome/renderer/safe_browsing/scorer.h': '', | 51 '/chrome/renderer/safe_browsing/scorer.h': '', |
50 '/content/OWNERS': owners_file(john, darin, comment='foo', noparent=True), | 52 '/content/OWNERS': owners_file(john, darin, comment='foo', noparent=True), |
51 '/content/content.gyp': '', | 53 '/content/content.gyp': '', |
52 '/content/bar/foo.cc': '', | 54 '/content/bar/foo.cc': '', |
53 '/content/baz/OWNERS': owners_file(brett), | 55 '/content/baz/OWNERS': owners_file(brett), |
54 '/content/baz/froboz.h': '', | 56 '/content/baz/froboz.h': '', |
55 '/content/baz/ugly.cc': '', | 57 '/content/baz/ugly.cc': '', |
56 '/content/baz/ugly.h': '', | 58 '/content/baz/ugly.h': '', |
| 59 '/content/garply/OWNERS': owners_file(file='test/OWNERS'), |
| 60 '/content/garply/foo.cc': '', |
| 61 '/content/garply/test/OWNERS': owners_file(peter), |
| 62 '/content/qux/OWNERS': owners_file(peter, file='//content/baz/OWNERS'), |
| 63 '/content/qux/foo.cc': '', |
57 '/content/views/OWNERS': owners_file(ben, john, owners.EVERYONE, | 64 '/content/views/OWNERS': owners_file(ben, john, owners.EVERYONE, |
58 noparent=True), | 65 noparent=True), |
59 '/content/views/pie.h': '', | 66 '/content/views/pie.h': '', |
60 }) | 67 }) |
61 | 68 |
62 | 69 |
63 class _BaseTestCase(unittest.TestCase): | 70 class _BaseTestCase(unittest.TestCase): |
64 def setUp(self): | 71 def setUp(self): |
65 self.repo = test_repo() | 72 self.repo = test_repo() |
66 self.files = self.repo.files | 73 self.files = self.repo.files |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 # This test ensures the mock relpath has the arguments in the right | 209 # This test ensures the mock relpath has the arguments in the right |
203 # order; this should probably live someplace else. | 210 # order; this should probably live someplace else. |
204 self.assertEquals(self.repo.relpath('foo/bar.c', 'foo/'), 'bar.c') | 211 self.assertEquals(self.repo.relpath('foo/bar.c', 'foo/'), 'bar.c') |
205 self.assertEquals(self.repo.relpath('/bar.c', '/'), 'bar.c') | 212 self.assertEquals(self.repo.relpath('/bar.c', '/'), 'bar.c') |
206 | 213 |
207 def test_per_file_glob_across_dirs_not_allowed(self): | 214 def test_per_file_glob_across_dirs_not_allowed(self): |
208 self.files['/OWNERS'] = 'per-file content/*=john@example.org\n' | 215 self.files['/OWNERS'] = 'per-file content/*=john@example.org\n' |
209 self.assertRaises(owners.SyntaxErrorInOwnersFile, | 216 self.assertRaises(owners.SyntaxErrorInOwnersFile, |
210 self.db().files_not_covered_by, ['DEPS'], [brett]) | 217 self.db().files_not_covered_by, ['DEPS'], [brett]) |
211 | 218 |
| 219 def test_file_include_absolute_path(self): |
| 220 self.assert_files_not_covered_by(['content/qux/foo.cc'], [brett], []) |
| 221 self.assert_files_not_covered_by(['content/qux/bar.cc'], [peter], []) |
| 222 self.assert_files_not_covered_by(['content/qux/baz.cc'], |
| 223 [tom], ['content/qux/baz.cc']) |
| 224 |
| 225 def test_file_include_relative_path(self): |
| 226 self.assert_files_not_covered_by(['content/garply/foo.cc'], [peter], []) |
| 227 self.assert_files_not_covered_by(['content/garply/bar.cc'], [darin], []) |
| 228 self.assert_files_not_covered_by(['content/garply/baz.cc'], |
| 229 [tom], ['content/garply/baz.cc']) |
| 230 |
| 231 def test_file_include_per_file_absolute_path(self): |
| 232 self.files['/content/qux/OWNERS'] = owners_file(peter, |
| 233 lines=['per-file foo.*=file://content/baz/OWNERS']) |
| 234 |
| 235 self.assert_files_not_covered_by(['content/qux/foo.cc'], [brett], []) |
| 236 self.assert_files_not_covered_by(['content/qux/baz.cc'], |
| 237 [brett], ['content/qux/baz.cc']) |
| 238 |
| 239 def test_file_include_per_file_relative_path(self): |
| 240 self.files['/content/garply/OWNERS'] = owners_file(brett, |
| 241 lines=['per-file foo.*=file:test/OWNERS']) |
| 242 |
| 243 self.assert_files_not_covered_by(['content/garply/foo.cc'], [peter], []) |
| 244 self.assert_files_not_covered_by(['content/garply/baz.cc'], |
| 245 [peter], ['content/garply/baz.cc']) |
| 246 |
| 247 def test_file_include_recursive(self): |
| 248 self.files['/content/baz/OWNERS'] = owners_file(file='//chrome/gpu/OWNERS') |
| 249 self.assert_files_not_covered_by(['content/qux/foo.cc'], [ken], []) |
| 250 |
| 251 def test_file_include_recursive_loop(self): |
| 252 self.files['/content/baz/OWNERS'] = owners_file(brett, |
| 253 file='//content/qux/OWNERS') |
| 254 self.test_file_include_absolute_path() |
| 255 |
| 256 def test_file_include_different_filename(self): |
| 257 self.files['/owners/garply'] = owners_file(peter) |
| 258 self.files['/content/garply/OWNERS'] = owners_file(john, |
| 259 lines=['per-file foo.*=file://owners/garply']) |
| 260 |
| 261 self.assert_files_not_covered_by(['content/garply/foo.cc'], [peter], []) |
| 262 |
212 def assert_syntax_error(self, owners_file_contents): | 263 def assert_syntax_error(self, owners_file_contents): |
213 db = self.db() | 264 db = self.db() |
214 self.files['/foo/OWNERS'] = owners_file_contents | 265 self.files['/foo/OWNERS'] = owners_file_contents |
215 self.files['/foo/DEPS'] = '' | 266 self.files['/foo/DEPS'] = '' |
216 try: | 267 try: |
217 db.reviewers_for(['foo/DEPS'], None) | 268 db.reviewers_for(['foo/DEPS'], None) |
218 self.fail() # pragma: no cover | 269 self.fail() # pragma: no cover |
219 except owners.SyntaxErrorInOwnersFile, e: | 270 except owners.SyntaxErrorInOwnersFile, e: |
220 self.assertTrue(str(e).startswith('/foo/OWNERS:1')) | 271 self.assertTrue(str(e).startswith('/foo/OWNERS:1')) |
221 | 272 |
222 def test_syntax_error__unknown_token(self): | 273 def test_syntax_error__unknown_token(self): |
223 self.assert_syntax_error('{}\n') | 274 self.assert_syntax_error('{}\n') |
224 | 275 |
225 def test_syntax_error__unknown_set(self): | 276 def test_syntax_error__unknown_set(self): |
226 self.assert_syntax_error('set myfatherisbillgates\n') | 277 self.assert_syntax_error('set myfatherisbillgates\n') |
227 | 278 |
228 def test_syntax_error__bad_email(self): | 279 def test_syntax_error__bad_email(self): |
229 self.assert_syntax_error('ben\n') | 280 self.assert_syntax_error('ben\n') |
230 | 281 |
| 282 def test_syntax_error__invalid_absolute_file(self): |
| 283 self.assert_syntax_error('file://foo/bar/baz\n') |
| 284 |
| 285 def test_syntax_error__invalid_relative_file(self): |
| 286 self.assert_syntax_error('file:foo/bar/baz\n') |
| 287 |
231 | 288 |
232 class ReviewersForTest(_BaseTestCase): | 289 class ReviewersForTest(_BaseTestCase): |
233 def assert_reviewers_for(self, files, potential_suggested_reviewers, | 290 def assert_reviewers_for(self, files, potential_suggested_reviewers, |
234 author=None): | 291 author=None): |
235 db = self.db() | 292 db = self.db() |
236 suggested_reviewers = db.reviewers_for(set(files), author) | 293 suggested_reviewers = db.reviewers_for(set(files), author) |
237 self.assertTrue(suggested_reviewers in | 294 self.assertTrue(suggested_reviewers in |
238 [set(suggestion) for suggestion in potential_suggested_reviewers]) | 295 [set(suggestion) for suggestion in potential_suggested_reviewers]) |
239 | 296 |
240 def test_reviewers_for__basic_functionality(self): | 297 def test_reviewers_for__basic_functionality(self): |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 self.assert_reviewers_for(['chrome/OWNERS', | 372 self.assert_reviewers_for(['chrome/OWNERS', |
316 'chrome/renderer/gpu/gpu_channel_host.h'], | 373 'chrome/renderer/gpu/gpu_channel_host.h'], |
317 [[ben, ken], | 374 [[ben, ken], |
318 [brett, ken]]) | 375 [brett, ken]]) |
319 | 376 |
320 def test_reviewers_for__author_is_known(self): | 377 def test_reviewers_for__author_is_known(self): |
321 # We should never suggest ken as a reviewer for his own changes. | 378 # We should never suggest ken as a reviewer for his own changes. |
322 self.assert_reviewers_for(['chrome/gpu/gpu_channel.h'], | 379 self.assert_reviewers_for(['chrome/gpu/gpu_channel.h'], |
323 [[ben], [brett]], author=ken) | 380 [[ben], [brett]], author=ken) |
324 | 381 |
| 382 def test_reviewers_file_includes__absolute(self): |
| 383 self.assert_reviewers_for(['content/qux/foo.cc'], |
| 384 [[peter], [brett], [john], [darin]]) |
| 385 |
| 386 def test_reviewers_file_includes__relative(self): |
| 387 self.assert_reviewers_for(['content/garply/foo.cc'], |
| 388 [[peter], [john], [darin]]) |
| 389 |
| 390 def test_reviewers_file_includes__per_file(self): |
| 391 self.files['/content/garply/OWNERS'] = owners_file(brett, |
| 392 lines=['per-file foo.*=file:test/OWNERS']) |
| 393 |
| 394 self.assert_reviewers_for(['content/garply/foo.cc'], |
| 395 [[brett], [peter]]) |
| 396 self.assert_reviewers_for(['content/garply/bar.cc'], |
| 397 [[brett]]) |
| 398 |
| 399 def test_reviewers_file_includes__per_file_noparent(self): |
| 400 self.files['/content/garply/OWNERS'] = owners_file(brett, |
| 401 lines=['per-file foo.*=set noparent', |
| 402 'per-file foo.*=file:test/OWNERS']) |
| 403 |
| 404 self.assert_reviewers_for(['content/garply/foo.cc'], |
| 405 [[peter]]) |
| 406 self.assert_reviewers_for(['content/garply/bar.cc'], |
| 407 [[brett]]) |
| 408 |
325 | 409 |
326 class LowestCostOwnersTest(_BaseTestCase): | 410 class LowestCostOwnersTest(_BaseTestCase): |
327 # Keep the data in the test_lowest_cost_owner* methods as consistent with | 411 # Keep the data in the test_lowest_cost_owner* methods as consistent with |
328 # test_repo() where possible to minimize confusion. | 412 # test_repo() where possible to minimize confusion. |
329 | 413 |
330 def check(self, possible_owners, dirs, *possible_lowest_cost_owners): | 414 def check(self, possible_owners, dirs, *possible_lowest_cost_owners): |
331 suggested_owner = owners.Database.lowest_cost_owner(possible_owners, dirs) | 415 suggested_owner = owners.Database.lowest_cost_owner(possible_owners, dirs) |
332 self.assertTrue(suggested_owner in possible_lowest_cost_owners) | 416 self.assertTrue(suggested_owner in possible_lowest_cost_owners) |
333 | 417 |
334 def test_one_dir_with_owner(self): | 418 def test_one_dir_with_owner(self): |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 ('chrome/browser', 2)], | 476 ('chrome/browser', 2)], |
393 ken: [('chrome/gpu', 1)], | 477 ken: [('chrome/gpu', 1)], |
394 peter: [('chrome/renderer', 1)], | 478 peter: [('chrome/renderer', 1)], |
395 brett: [('chrome/browser', 1)]}, | 479 brett: [('chrome/browser', 1)]}, |
396 ['chrome/gpu', 'chrome/renderer', | 480 ['chrome/gpu', 'chrome/renderer', |
397 'chrome/browser'], | 481 'chrome/browser'], |
398 ben) | 482 ben) |
399 | 483 |
400 if __name__ == '__main__': | 484 if __name__ == '__main__': |
401 unittest.main() | 485 unittest.main() |
OLD | NEW |