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 presubmit_support.py and presubmit_canned_checks.py.""" | 6 """Unit tests for presubmit_support.py and presubmit_canned_checks.py.""" |
7 | 7 |
8 # pylint: disable=E1101,E1103 | 8 # pylint: disable=E1101,E1103 |
9 | 9 |
10 import functools | 10 import functools |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 ('M ', 'foo/TestExpectations')] | 499 ('M ', 'foo/TestExpectations')] |
500 | 500 |
501 for op, path in files: | 501 for op, path in files: |
502 full_path = presubmit.os.path.join(self.fake_root_dir, *path.split('/')) | 502 full_path = presubmit.os.path.join(self.fake_root_dir, *path.split('/')) |
503 if op.startswith('D'): | 503 if op.startswith('D'): |
504 os.path.exists(full_path).AndReturn(False) | 504 os.path.exists(full_path).AndReturn(False) |
505 else: | 505 else: |
506 os.path.exists(full_path).AndReturn(False) | 506 os.path.exists(full_path).AndReturn(False) |
507 os.path.isfile(full_path).AndReturn(True) | 507 os.path.isfile(full_path).AndReturn(True) |
508 | 508 |
509 presubmit.scm.GIT.GenerateDiff(self.fake_root_dir, files=[], full_move=True | 509 presubmit.scm.GIT.GenerateDiff( |
| 510 self.fake_root_dir, files=[], full_move=True, branch=None |
510 ).AndReturn('\n'.join(unified_diff)) | 511 ).AndReturn('\n'.join(unified_diff)) |
511 | 512 |
512 self.mox.ReplayAll() | 513 self.mox.ReplayAll() |
513 | 514 |
514 change = presubmit.GitChange( | 515 change = presubmit.GitChange( |
515 'mychange', | 516 'mychange', |
516 '\n'.join(description_lines), | 517 '\n'.join(description_lines), |
517 self.fake_root_dir, | 518 self.fake_root_dir, |
518 files, | 519 files, |
519 0, | 520 0, |
520 0, | 521 0, |
521 None) | 522 None, |
| 523 upstream=None) |
522 self.failUnless(change.Name() == 'mychange') | 524 self.failUnless(change.Name() == 'mychange') |
523 self.failUnless(change.DescriptionText() == | 525 self.failUnless(change.DescriptionText() == |
524 'Hello there\nthis is a change\nand some more regular text') | 526 'Hello there\nthis is a change\nand some more regular text') |
525 self.failUnless(change.FullDescriptionText() == | 527 self.failUnless(change.FullDescriptionText() == |
526 '\n'.join(description_lines)) | 528 '\n'.join(description_lines)) |
527 | 529 |
528 self.failUnless(change.BUG == '123') | 530 self.failUnless(change.BUG == '123') |
529 self.failUnless(change.STORY == 'http://foo/') | 531 self.failUnless(change.STORY == 'http://foo/') |
530 self.failUnless(change.BLEH == None) | 532 self.failUnless(change.BLEH == None) |
531 | 533 |
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1335 presubmit.normpath(files[0][1])) | 1337 presubmit.normpath(files[0][1])) |
1336 self.assertEqual(rhs_lines[3][0].LocalPath(), | 1338 self.assertEqual(rhs_lines[3][0].LocalPath(), |
1337 presubmit.normpath(files[0][1])) | 1339 presubmit.normpath(files[0][1])) |
1338 self.assertEqual(rhs_lines[7][0].LocalPath(), | 1340 self.assertEqual(rhs_lines[7][0].LocalPath(), |
1339 presubmit.normpath(files[4][1])) | 1341 presubmit.normpath(files[4][1])) |
1340 self.assertEqual(rhs_lines[13][0].LocalPath(), | 1342 self.assertEqual(rhs_lines[13][0].LocalPath(), |
1341 presubmit.normpath(files[4][1])) | 1343 presubmit.normpath(files[4][1])) |
1342 | 1344 |
1343 def testDefaultWhiteListBlackListFilters(self): | 1345 def testDefaultWhiteListBlackListFilters(self): |
1344 def f(x): | 1346 def f(x): |
1345 return presubmit.AffectedFile(x, 'M', self.fake_root_dir) | 1347 return presubmit.AffectedFile(x, 'M', self.fake_root_dir, None) |
1346 files = [ | 1348 files = [ |
1347 ( | 1349 ( |
1348 [ | 1350 [ |
1349 # To be tested. | 1351 # To be tested. |
1350 f('testing_support/google_appengine/b'), | 1352 f('testing_support/google_appengine/b'), |
1351 f('testing_support/not_google_appengine/foo.cc'), | 1353 f('testing_support/not_google_appengine/foo.cc'), |
1352 ], | 1354 ], |
1353 [ | 1355 [ |
1354 # Expected. | 1356 # Expected. |
1355 'testing_support/not_google_appengine/foo.cc', | 1357 'testing_support/not_google_appengine/foo.cc', |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 class AffectedFileUnittest(PresubmitTestsBase): | 1667 class AffectedFileUnittest(PresubmitTestsBase): |
1666 def testMembersChanged(self): | 1668 def testMembersChanged(self): |
1667 self.mox.ReplayAll() | 1669 self.mox.ReplayAll() |
1668 members = [ | 1670 members = [ |
1669 'AbsoluteLocalPath', 'Action', 'ChangedContents', 'DIFF_CACHE', | 1671 'AbsoluteLocalPath', 'Action', 'ChangedContents', 'DIFF_CACHE', |
1670 'GenerateScmDiff', 'IsDirectory', 'IsTextFile', 'LocalPath', | 1672 'GenerateScmDiff', 'IsDirectory', 'IsTextFile', 'LocalPath', |
1671 'NewContents', 'Property', 'ServerPath', | 1673 'NewContents', 'Property', 'ServerPath', |
1672 ] | 1674 ] |
1673 # If this test fails, you should add the relevant test. | 1675 # If this test fails, you should add the relevant test. |
1674 self.compareMembers( | 1676 self.compareMembers( |
1675 presubmit.AffectedFile('a', 'b', self.fake_root_dir), members) | 1677 presubmit.AffectedFile('a', 'b', self.fake_root_dir, None), members) |
1676 self.compareMembers( | 1678 self.compareMembers( |
1677 presubmit.SvnAffectedFile('a', 'b', self.fake_root_dir), members) | 1679 presubmit.SvnAffectedFile('a', 'b', self.fake_root_dir, None), members) |
1678 self.compareMembers( | 1680 self.compareMembers( |
1679 presubmit.GitAffectedFile('a', 'b', self.fake_root_dir), members) | 1681 presubmit.GitAffectedFile('a', 'b', self.fake_root_dir, None), members) |
1680 | 1682 |
1681 def testAffectedFile(self): | 1683 def testAffectedFile(self): |
1682 path = presubmit.os.path.join('foo', 'blat.cc') | 1684 path = presubmit.os.path.join('foo', 'blat.cc') |
1683 f_path = presubmit.os.path.join(self.fake_root_dir, path) | 1685 f_path = presubmit.os.path.join(self.fake_root_dir, path) |
1684 presubmit.os.path.exists(f_path).AndReturn(True) | 1686 presubmit.os.path.exists(f_path).AndReturn(True) |
1685 presubmit.os.path.isdir(f_path).AndReturn(False) | 1687 presubmit.os.path.isdir(f_path).AndReturn(False) |
1686 presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie') | 1688 presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie') |
1687 presubmit.scm.SVN._CaptureInfo([path], self.fake_root_dir).AndReturn( | 1689 presubmit.scm.SVN._CaptureInfo([path], self.fake_root_dir).AndReturn( |
1688 {'URL': 'svn:/foo/foo/blat.cc'}) | 1690 {'URL': 'svn:/foo/foo/blat.cc'}) |
1689 self.mox.ReplayAll() | 1691 self.mox.ReplayAll() |
1690 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M', self.fake_root_dir) | 1692 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M', self.fake_root_dir, None) |
1691 self.assertEquals('svn:/foo/foo/blat.cc', af.ServerPath()) | 1693 self.assertEquals('svn:/foo/foo/blat.cc', af.ServerPath()) |
1692 self.assertEquals(presubmit.normpath('foo/blat.cc'), af.LocalPath()) | 1694 self.assertEquals(presubmit.normpath('foo/blat.cc'), af.LocalPath()) |
1693 self.assertEquals('M', af.Action()) | 1695 self.assertEquals('M', af.Action()) |
1694 self.assertEquals(['whatever', 'cookie'], af.NewContents()) | 1696 self.assertEquals(['whatever', 'cookie'], af.NewContents()) |
1695 | 1697 |
1696 def testAffectedFileNotExists(self): | 1698 def testAffectedFileNotExists(self): |
1697 notfound = 'notfound.cc' | 1699 notfound = 'notfound.cc' |
1698 f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound) | 1700 f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound) |
1699 presubmit.os.path.exists(f_notfound).AndReturn(False) | 1701 presubmit.os.path.exists(f_notfound).AndReturn(False) |
1700 presubmit.gclient_utils.FileRead(f_notfound, 'rU').AndRaise(IOError) | 1702 presubmit.gclient_utils.FileRead(f_notfound, 'rU').AndRaise(IOError) |
1701 self.mox.ReplayAll() | 1703 self.mox.ReplayAll() |
1702 af = presubmit.AffectedFile(notfound, 'A', self.fake_root_dir) | 1704 af = presubmit.AffectedFile(notfound, 'A', self.fake_root_dir, None) |
1703 self.assertEquals('', af.ServerPath()) | 1705 self.assertEquals('', af.ServerPath()) |
1704 self.assertEquals([], af.NewContents()) | 1706 self.assertEquals([], af.NewContents()) |
1705 | 1707 |
1706 def testProperty(self): | 1708 def testProperty(self): |
1707 presubmit.scm.SVN.GetFileProperty( | 1709 presubmit.scm.SVN.GetFileProperty( |
1708 'foo.cc', 'svn:secret-property', self.fake_root_dir | 1710 'foo.cc', 'svn:secret-property', self.fake_root_dir |
1709 ).AndReturn('secret-property-value') | 1711 ).AndReturn('secret-property-value') |
1710 self.mox.ReplayAll() | 1712 self.mox.ReplayAll() |
1711 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A', self.fake_root_dir) | 1713 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A', self.fake_root_dir, |
| 1714 None) |
1712 # Verify cache coherency. | 1715 # Verify cache coherency. |
1713 self.assertEquals('secret-property-value', | 1716 self.assertEquals('secret-property-value', |
1714 affected_file.Property('svn:secret-property')) | 1717 affected_file.Property('svn:secret-property')) |
1715 self.assertEquals('secret-property-value', | 1718 self.assertEquals('secret-property-value', |
1716 affected_file.Property('svn:secret-property')) | 1719 affected_file.Property('svn:secret-property')) |
1717 | 1720 |
1718 def testIsDirectoryNotExists(self): | 1721 def testIsDirectoryNotExists(self): |
1719 filename = 'foo.cc' | 1722 filename = 'foo.cc' |
1720 f_filename = presubmit.os.path.join(self.fake_root_dir, filename) | 1723 f_filename = presubmit.os.path.join(self.fake_root_dir, filename) |
1721 presubmit.os.path.exists(f_filename).AndReturn(False) | 1724 presubmit.os.path.exists(f_filename).AndReturn(False) |
1722 presubmit.scm.SVN._CaptureInfo([filename], self.fake_root_dir).AndReturn({}) | 1725 presubmit.scm.SVN._CaptureInfo([filename], self.fake_root_dir).AndReturn({}) |
1723 self.mox.ReplayAll() | 1726 self.mox.ReplayAll() |
1724 affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir) | 1727 affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir, |
| 1728 None) |
1725 # Verify cache coherency. | 1729 # Verify cache coherency. |
1726 self.failIf(affected_file.IsDirectory()) | 1730 self.failIf(affected_file.IsDirectory()) |
1727 self.failIf(affected_file.IsDirectory()) | 1731 self.failIf(affected_file.IsDirectory()) |
1728 | 1732 |
1729 def testIsDirectory(self): | 1733 def testIsDirectory(self): |
1730 filename = 'foo.cc' | 1734 filename = 'foo.cc' |
1731 f_filename = presubmit.os.path.join(self.fake_root_dir, filename) | 1735 f_filename = presubmit.os.path.join(self.fake_root_dir, filename) |
1732 presubmit.os.path.exists(f_filename).AndReturn(True) | 1736 presubmit.os.path.exists(f_filename).AndReturn(True) |
1733 presubmit.os.path.isdir(f_filename).AndReturn(True) | 1737 presubmit.os.path.isdir(f_filename).AndReturn(True) |
1734 self.mox.ReplayAll() | 1738 self.mox.ReplayAll() |
1735 affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir) | 1739 affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir, |
| 1740 None) |
1736 # Verify cache coherency. | 1741 # Verify cache coherency. |
1737 self.failUnless(affected_file.IsDirectory()) | 1742 self.failUnless(affected_file.IsDirectory()) |
1738 self.failUnless(affected_file.IsDirectory()) | 1743 self.failUnless(affected_file.IsDirectory()) |
1739 | 1744 |
1740 def testIsTextFile(self): | 1745 def testIsTextFile(self): |
1741 files = [ | 1746 files = [ |
1742 presubmit.SvnAffectedFile('foo/blat.txt', 'M', self.fake_root_dir), | 1747 presubmit.SvnAffectedFile('foo/blat.txt', 'M', self.fake_root_dir, |
1743 presubmit.SvnAffectedFile('foo/binary.blob', 'M', self.fake_root_dir), | 1748 None), |
1744 presubmit.SvnAffectedFile('blat/flop.txt', 'D', self.fake_root_dir) | 1749 presubmit.SvnAffectedFile('foo/binary.blob', 'M', self.fake_root_dir, |
| 1750 None), |
| 1751 presubmit.SvnAffectedFile('blat/flop.txt', 'D', self.fake_root_dir, |
| 1752 None) |
1745 ] | 1753 ] |
1746 blat = presubmit.os.path.join('foo', 'blat.txt') | 1754 blat = presubmit.os.path.join('foo', 'blat.txt') |
1747 blob = presubmit.os.path.join('foo', 'binary.blob') | 1755 blob = presubmit.os.path.join('foo', 'binary.blob') |
1748 f_blat = presubmit.os.path.join(self.fake_root_dir, blat) | 1756 f_blat = presubmit.os.path.join(self.fake_root_dir, blat) |
1749 f_blob = presubmit.os.path.join(self.fake_root_dir, blob) | 1757 f_blob = presubmit.os.path.join(self.fake_root_dir, blob) |
1750 presubmit.os.path.exists(f_blat).AndReturn(True) | 1758 presubmit.os.path.exists(f_blat).AndReturn(True) |
1751 presubmit.os.path.isdir(f_blat).AndReturn(False) | 1759 presubmit.os.path.isdir(f_blat).AndReturn(False) |
1752 presubmit.os.path.exists(f_blob).AndReturn(True) | 1760 presubmit.os.path.exists(f_blob).AndReturn(True) |
1753 presubmit.os.path.isdir(f_blob).AndReturn(False) | 1761 presubmit.os.path.isdir(f_blob).AndReturn(False) |
1754 presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type', self.fake_root_dir | 1762 presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type', self.fake_root_dir |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1977 results2 = check(input_api2, presubmit.OutputApi) | 1985 results2 = check(input_api2, presubmit.OutputApi) |
1978 self.assertEquals(len(results2), 1) | 1986 self.assertEquals(len(results2), 1) |
1979 self.assertEquals(results2[0].__class__, error_type) | 1987 self.assertEquals(results2[0].__class__, error_type) |
1980 | 1988 |
1981 def SvnPropertyTest(self, check, property_name, value1, value2, committing, | 1989 def SvnPropertyTest(self, check, property_name, value1, value2, committing, |
1982 error_type, use_source_file): | 1990 error_type, use_source_file): |
1983 change1 = presubmit.SvnChange( | 1991 change1 = presubmit.SvnChange( |
1984 'mychange', '', self.fake_root_dir, [], 0, 0, None) | 1992 'mychange', '', self.fake_root_dir, [], 0, 0, None) |
1985 input_api1 = self.MockInputApi(change1, committing) | 1993 input_api1 = self.MockInputApi(change1, committing) |
1986 files1 = [ | 1994 files1 = [ |
1987 presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir), | 1995 presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir, None), |
1988 presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir), | 1996 presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir, None), |
1989 ] | 1997 ] |
1990 if use_source_file: | 1998 if use_source_file: |
1991 input_api1.AffectedSourceFiles(None).AndReturn(files1) | 1999 input_api1.AffectedSourceFiles(None).AndReturn(files1) |
1992 else: | 2000 else: |
1993 input_api1.AffectedFiles(include_deleted=False).AndReturn(files1) | 2001 input_api1.AffectedFiles(include_deleted=False).AndReturn(files1) |
1994 presubmit.scm.SVN.GetFileProperty( | 2002 presubmit.scm.SVN.GetFileProperty( |
1995 presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir | 2003 presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir |
1996 ).AndReturn(value1) | 2004 ).AndReturn(value1) |
1997 presubmit.scm.SVN.GetFileProperty( | 2005 presubmit.scm.SVN.GetFileProperty( |
1998 presubmit.normpath('foo.cc'), property_name, self.fake_root_dir | 2006 presubmit.normpath('foo.cc'), property_name, self.fake_root_dir |
1999 ).AndReturn(value1) | 2007 ).AndReturn(value1) |
2000 change2 = presubmit.SvnChange( | 2008 change2 = presubmit.SvnChange( |
2001 'mychange', '', self.fake_root_dir, [], 0, 0, None) | 2009 'mychange', '', self.fake_root_dir, [], 0, 0, None) |
2002 input_api2 = self.MockInputApi(change2, committing) | 2010 input_api2 = self.MockInputApi(change2, committing) |
2003 files2 = [ | 2011 files2 = [ |
2004 presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir), | 2012 presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir, None), |
2005 presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir), | 2013 presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir, None), |
2006 ] | 2014 ] |
2007 if use_source_file: | 2015 if use_source_file: |
2008 input_api2.AffectedSourceFiles(None).AndReturn(files2) | 2016 input_api2.AffectedSourceFiles(None).AndReturn(files2) |
2009 else: | 2017 else: |
2010 input_api2.AffectedFiles(include_deleted=False).AndReturn(files2) | 2018 input_api2.AffectedFiles(include_deleted=False).AndReturn(files2) |
2011 | 2019 |
2012 presubmit.scm.SVN.GetFileProperty( | 2020 presubmit.scm.SVN.GetFileProperty( |
2013 presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir | 2021 presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir |
2014 ).AndReturn(value2) | 2022 ).AndReturn(value2) |
2015 presubmit.scm.SVN.GetFileProperty( | 2023 presubmit.scm.SVN.GetFileProperty( |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 check = presubmit_canned_checks.CheckSvnModifiedDirectories | 2369 check = presubmit_canned_checks.CheckSvnModifiedDirectories |
2362 results = check(input_api, presubmit.OutputApi, None) | 2370 results = check(input_api, presubmit.OutputApi, None) |
2363 self.assertEquals(len(results), 1) | 2371 self.assertEquals(len(results), 1) |
2364 self.assertEquals(results[0].__class__, | 2372 self.assertEquals(results[0].__class__, |
2365 presubmit.OutputApi.PresubmitPromptWarning) | 2373 presubmit.OutputApi.PresubmitPromptWarning) |
2366 | 2374 |
2367 def testCheckSvnForCommonMimeTypes(self): | 2375 def testCheckSvnForCommonMimeTypes(self): |
2368 self.mox.StubOutWithMock(presubmit_canned_checks, 'CheckSvnProperty') | 2376 self.mox.StubOutWithMock(presubmit_canned_checks, 'CheckSvnProperty') |
2369 input_api = self.MockInputApi(None, False) | 2377 input_api = self.MockInputApi(None, False) |
2370 output_api = presubmit.OutputApi(False) | 2378 output_api = presubmit.OutputApi(False) |
2371 A = lambda x: presubmit.AffectedFile(x, 'M', self.fake_root_dir) | 2379 A = lambda x: presubmit.AffectedFile(x, 'M', self.fake_root_dir, None) |
2372 files = [ | 2380 files = [ |
2373 A('a.pdf'), A('b.bmp'), A('c.gif'), A('d.png'), A('e.jpg'), A('f.jpe'), | 2381 A('a.pdf'), A('b.bmp'), A('c.gif'), A('d.png'), A('e.jpg'), A('f.jpe'), |
2374 A('random'), A('g.jpeg'), A('h.ico'), | 2382 A('random'), A('g.jpeg'), A('h.ico'), |
2375 ] | 2383 ] |
2376 input_api.AffectedFiles(include_deletes=False).AndReturn(files) | 2384 input_api.AffectedFiles(include_deletes=False).AndReturn(files) |
2377 presubmit_canned_checks.CheckSvnProperty( | 2385 presubmit_canned_checks.CheckSvnProperty( |
2378 input_api, output_api, 'svn:mime-type', 'application/pdf', [files[0]] | 2386 input_api, output_api, 'svn:mime-type', 'application/pdf', [files[0]] |
2379 ).AndReturn([1]) | 2387 ).AndReturn([1]) |
2380 presubmit_canned_checks.CheckSvnProperty( | 2388 presubmit_canned_checks.CheckSvnProperty( |
2381 input_api, output_api, 'svn:mime-type', 'image/bmp', [files[1]] | 2389 input_api, output_api, 'svn:mime-type', 'image/bmp', [files[1]] |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2901 owners_check=False) | 2909 owners_check=False) |
2902 self.assertEqual(1, len(results)) | 2910 self.assertEqual(1, len(results)) |
2903 self.assertEqual( | 2911 self.assertEqual( |
2904 'Found line ending with white spaces in:', results[0]._message) | 2912 'Found line ending with white spaces in:', results[0]._message) |
2905 self.checkstdout('') | 2913 self.checkstdout('') |
2906 | 2914 |
2907 | 2915 |
2908 if __name__ == '__main__': | 2916 if __name__ == '__main__': |
2909 import unittest | 2917 import unittest |
2910 unittest.main() | 2918 unittest.main() |
OLD | NEW |