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 import glob |
| 7 import json |
6 import os | 8 import os |
7 import re | 9 import re |
| 10 import subprocess |
| 11 import sys |
8 import unittest | 12 import unittest |
9 | 13 |
10 import PRESUBMIT | 14 import PRESUBMIT |
11 | 15 |
12 | 16 |
| 17 _TEST_DATA_DIR = 'base/test/data/presubmit' |
| 18 |
| 19 |
13 class MockInputApi(object): | 20 class MockInputApi(object): |
14 def __init__(self): | 21 def __init__(self): |
| 22 self.json = json |
15 self.re = re | 23 self.re = re |
16 self.os_path = os.path | 24 self.os_path = os.path |
| 25 self.python_executable = sys.executable |
| 26 self.subprocess = subprocess |
17 self.files = [] | 27 self.files = [] |
18 self.is_committing = False | 28 self.is_committing = False |
19 | 29 |
20 def AffectedFiles(self): | 30 def AffectedFiles(self): |
21 return self.files | 31 return self.files |
22 | 32 |
| 33 def PresubmitLocalPath(self): |
| 34 return os.path.dirname(__file__) |
| 35 |
| 36 def ReadFile(self, filename, mode='rU'): |
| 37 for file_ in self.files: |
| 38 if file_.LocalPath() == filename: |
| 39 return '\n'.join(file_.NewContents()) |
| 40 # Otherwise, file is not in our mock API. |
| 41 raise IOError, "No such file or directory: '%s'" % filename |
| 42 |
23 | 43 |
24 class MockOutputApi(object): | 44 class MockOutputApi(object): |
25 class PresubmitResult(object): | 45 class PresubmitResult(object): |
26 def __init__(self, message, items=None, long_text=''): | 46 def __init__(self, message, items=None, long_text=''): |
27 self.message = message | 47 self.message = message |
28 self.items = items | 48 self.items = items |
29 self.long_text = long_text | 49 self.long_text = long_text |
30 | 50 |
31 class PresubmitError(PresubmitResult): | 51 class PresubmitError(PresubmitResult): |
32 def __init__(self, message, items, long_text=''): | 52 def __init__(self, message, items, long_text=''): |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 'components/nacl/common/DEPS', | 444 'components/nacl/common/DEPS', |
425 'content/public/browser/render_process_host.h', | 445 'content/public/browser/render_process_host.h', |
426 'policy/DEPS', | 446 'policy/DEPS', |
427 'sandbox/DEPS', | 447 'sandbox/DEPS', |
428 'tools/memory_watcher/DEPS', | 448 'tools/memory_watcher/DEPS', |
429 'third_party/lss/linux_syscall_support.h', | 449 'third_party/lss/linux_syscall_support.h', |
430 ]) | 450 ]) |
431 self.assertEqual(expected, files_to_check); | 451 self.assertEqual(expected, files_to_check); |
432 | 452 |
433 | 453 |
| 454 class JSONParsingTest(unittest.TestCase): |
| 455 def testSuccess(self): |
| 456 input_api = MockInputApi() |
| 457 filename = 'valid_json.json' |
| 458 contents = ['// This is a comment.', |
| 459 '{', |
| 460 ' "key1": ["value1", "value2"],', |
| 461 ' "key2": 3 // This is an inline comment.', |
| 462 '}' |
| 463 ] |
| 464 input_api.files = [MockFile(filename, contents)] |
| 465 self.assertEqual(None, |
| 466 PRESUBMIT._GetJSONParseError(input_api, filename)) |
| 467 |
| 468 def testFailure(self): |
| 469 input_api = MockInputApi() |
| 470 test_data = [ |
| 471 ('invalid_json_1.json', |
| 472 ['{ x }'], |
| 473 'Expecting property name: line 1 column 2 (char 2)'), |
| 474 ('invalid_json_2.json', |
| 475 ['// Hello world!', |
| 476 '{ "hello": "world }'], |
| 477 'Unterminated string starting at: line 2 column 12 (char 12)'), |
| 478 ('invalid_json_3.json', |
| 479 ['{ "a": "b", "c": "d", }'], |
| 480 'Expecting property name: line 1 column 22 (char 22)'), |
| 481 ('invalid_json_4.json', |
| 482 ['{ "a": "b" "c": "d" }'], |
| 483 'Expecting , delimiter: line 1 column 11 (char 11)'), |
| 484 ] |
| 485 |
| 486 input_api.files = [MockFile(filename, contents) |
| 487 for (filename, contents, _) in test_data] |
| 488 |
| 489 for (filename, _, expected_error) in test_data: |
| 490 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename) |
| 491 self.assertEqual(expected_error, str(actual_error)) |
| 492 |
| 493 def testNoEatComments(self): |
| 494 input_api = MockInputApi() |
| 495 file_with_comments = 'file_with_comments.json' |
| 496 contents_with_comments = ['// This is a comment.', |
| 497 '{', |
| 498 ' "key1": ["value1", "value2"],', |
| 499 ' "key2": 3 // This is an inline comment.', |
| 500 '}' |
| 501 ] |
| 502 file_without_comments = 'file_without_comments.json' |
| 503 contents_without_comments = ['{', |
| 504 ' "key1": ["value1", "value2"],', |
| 505 ' "key2": 3', |
| 506 '}' |
| 507 ] |
| 508 input_api.files = [MockFile(file_with_comments, contents_with_comments), |
| 509 MockFile(file_without_comments, |
| 510 contents_without_comments)] |
| 511 |
| 512 self.assertEqual('No JSON object could be decoded', |
| 513 str(PRESUBMIT._GetJSONParseError(input_api, |
| 514 file_with_comments, |
| 515 eat_comments=False))) |
| 516 self.assertEqual(None, |
| 517 PRESUBMIT._GetJSONParseError(input_api, |
| 518 file_without_comments, |
| 519 eat_comments=False)) |
| 520 |
| 521 |
| 522 class IDLParsingTest(unittest.TestCase): |
| 523 def testSuccess(self): |
| 524 input_api = MockInputApi() |
| 525 filename = 'valid_idl_basics.idl' |
| 526 contents = ['// Tests a valid IDL file.', |
| 527 'namespace idl_basics {', |
| 528 ' enum EnumType {', |
| 529 ' name1,', |
| 530 ' name2', |
| 531 ' };', |
| 532 '', |
| 533 ' dictionary MyType1 {', |
| 534 ' DOMString a;', |
| 535 ' };', |
| 536 '', |
| 537 ' callback Callback1 = void();', |
| 538 ' callback Callback2 = void(long x);', |
| 539 ' callback Callback3 = void(MyType1 arg);', |
| 540 ' callback Callback4 = void(EnumType type);', |
| 541 '', |
| 542 ' interface Functions {', |
| 543 ' static void function1();', |
| 544 ' static void function2(long x);', |
| 545 ' static void function3(MyType1 arg);', |
| 546 ' static void function4(Callback1 cb);', |
| 547 ' static void function5(Callback2 cb);', |
| 548 ' static void function6(Callback3 cb);', |
| 549 ' static void function7(Callback4 cb);', |
| 550 ' };', |
| 551 '', |
| 552 ' interface Events {', |
| 553 ' static void onFoo1();', |
| 554 ' static void onFoo2(long x);', |
| 555 ' static void onFoo2(MyType1 arg);', |
| 556 ' static void onFoo3(EnumType type);', |
| 557 ' };', |
| 558 '};' |
| 559 ] |
| 560 input_api.files = [MockFile(filename, contents)] |
| 561 self.assertEqual(None, |
| 562 PRESUBMIT._GetIDLParseError(input_api, filename)) |
| 563 |
| 564 def testFailure(self): |
| 565 input_api = MockInputApi() |
| 566 test_data = [ |
| 567 ('invalid_idl_1.idl', |
| 568 ['//', |
| 569 'namespace test {', |
| 570 ' dictionary {', |
| 571 ' DOMString s;', |
| 572 ' };', |
| 573 '};'], |
| 574 'Unexpected "{" after keyword "dictionary".\n'), |
| 575 # TODO(yoz): Disabled because it causes the IDL parser to hang. |
| 576 # See crbug.com/363830. |
| 577 # ('invalid_idl_2.idl', |
| 578 # (['namespace test {', |
| 579 # ' dictionary MissingSemicolon {', |
| 580 # ' DOMString a', |
| 581 # ' DOMString b;', |
| 582 # ' };', |
| 583 # '};'], |
| 584 # 'Unexpected symbol DOMString after symbol a.'), |
| 585 ('invalid_idl_3.idl', |
| 586 ['//', |
| 587 'namespace test {', |
| 588 ' enum MissingComma {', |
| 589 ' name1', |
| 590 ' name2', |
| 591 ' };', |
| 592 '};'], |
| 593 'Unexpected symbol name2 after symbol name1.'), |
| 594 ('invalid_idl_4.idl', |
| 595 ['//', |
| 596 'namespace test {', |
| 597 ' enum TrailingComma {', |
| 598 ' name1,', |
| 599 ' name2,', |
| 600 ' };', |
| 601 '};'], |
| 602 'Trailing comma in block.'), |
| 603 ('invalid_idl_5.idl', |
| 604 ['//', |
| 605 'namespace test {', |
| 606 ' callback Callback1 = void(;', |
| 607 '};'], |
| 608 'Unexpected ";" after "(".'), |
| 609 ('invalid_idl_6.idl', |
| 610 ['//', |
| 611 'namespace test {', |
| 612 ' callback Callback1 = void(long );', |
| 613 '};'], |
| 614 'Unexpected ")" after symbol long.'), |
| 615 ('invalid_idl_7.idl', |
| 616 ['//', |
| 617 'namespace test {', |
| 618 ' interace Events {', |
| 619 ' static void onFoo1();', |
| 620 ' };', |
| 621 '};'], |
| 622 'Unexpected symbol Events after symbol interace.'), |
| 623 ('invalid_idl_8.idl', |
| 624 ['//', |
| 625 'namespace test {', |
| 626 ' interface NotEvent {', |
| 627 ' static void onFoo1();', |
| 628 ' };', |
| 629 '};'], |
| 630 'Did not process Interface Interface(NotEvent)'), |
| 631 ('invalid_idl_9.idl', |
| 632 ['//', |
| 633 'namespace test {', |
| 634 ' interface {', |
| 635 ' static void function1();', |
| 636 ' };', |
| 637 '};'], |
| 638 'Interface missing name.'), |
| 639 ] |
| 640 |
| 641 input_api.files = [MockFile(filename, contents) |
| 642 for (filename, contents, _) in test_data] |
| 643 |
| 644 for (filename, _, expected_error) in test_data: |
| 645 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename) |
| 646 self.assertTrue(expected_error in str(actual_error), |
| 647 "'%s' not found in '%s'" % (expected_error, actual_error)) |
| 648 |
| 649 |
434 if __name__ == '__main__': | 650 if __name__ == '__main__': |
435 unittest.main() | 651 unittest.main() |
OLD | NEW |