| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 is too confused. | 8 # pylint is too confused. |
| 9 # pylint: disable=E1101,E1103,R0201,W0212,W0403 | 9 # pylint: disable=E1101,E1103,R0201,W0212,W0403 |
| 10 | 10 |
| 11 import StringIO | 11 import StringIO |
| 12 import sys | 12 import sys |
| 13 | 13 |
| 14 # Fixes include path. | 14 # Fixes include path. |
| 15 from super_mox import mox, SuperMoxTestBase | 15 from super_mox import mox, SuperMoxTestBase |
| 16 | 16 |
| 17 import owners | 17 import owners |
| 18 import presubmit_support as presubmit | 18 import presubmit_support as presubmit |
| 19 import rietveld |
| 19 # Shortcut. | 20 # Shortcut. |
| 20 presubmit_canned_checks = presubmit.presubmit_canned_checks | 21 presubmit_canned_checks = presubmit.presubmit_canned_checks |
| 21 | 22 |
| 22 | 23 |
| 23 class PresubmitTestsBase(SuperMoxTestBase): | 24 class PresubmitTestsBase(SuperMoxTestBase): |
| 24 """Setups and tear downs the mocks but doesn't test anything as-is.""" | 25 """Setups and tear downs the mocks but doesn't test anything as-is.""" |
| 25 presubmit_text = """ | 26 presubmit_text = """ |
| 26 def CheckChangeOnUpload(input_api, output_api): | 27 def CheckChangeOnUpload(input_api, output_api): |
| 27 if not input_api.change.NOSUCHKEY: | 28 if not input_api.change.NOSUCHKEY: |
| 28 return [output_api.PresubmitError("!!")] | 29 return [output_api.PresubmitError("!!")] |
| (...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 | 1332 |
| 1332 class CannedChecksUnittest(PresubmitTestsBase): | 1333 class CannedChecksUnittest(PresubmitTestsBase): |
| 1333 """Tests presubmit_canned_checks.py.""" | 1334 """Tests presubmit_canned_checks.py.""" |
| 1334 | 1335 |
| 1335 def setUp(self): | 1336 def setUp(self): |
| 1336 PresubmitTestsBase.setUp(self) | 1337 PresubmitTestsBase.setUp(self) |
| 1337 | 1338 |
| 1338 def MockInputApi(self, change, committing): | 1339 def MockInputApi(self, change, committing): |
| 1339 input_api = self.mox.CreateMock(presubmit.InputApi) | 1340 input_api = self.mox.CreateMock(presubmit.InputApi) |
| 1340 input_api.cStringIO = presubmit.cStringIO | 1341 input_api.cStringIO = presubmit.cStringIO |
| 1342 input_api.json = presubmit.json |
| 1341 input_api.os_listdir = self.mox.CreateMockAnything() | 1343 input_api.os_listdir = self.mox.CreateMockAnything() |
| 1342 input_api.os_walk = self.mox.CreateMockAnything() | 1344 input_api.os_walk = self.mox.CreateMockAnything() |
| 1343 input_api.os_path = presubmit.os.path | 1345 input_api.os_path = presubmit.os.path |
| 1344 input_api.re = presubmit.re | 1346 input_api.re = presubmit.re |
| 1347 input_api.rietveld = self.mox.CreateMock(rietveld.Rietveld) |
| 1345 input_api.traceback = presubmit.traceback | 1348 input_api.traceback = presubmit.traceback |
| 1346 input_api.urllib2 = self.mox.CreateMock(presubmit.urllib2) | 1349 input_api.urllib2 = self.mox.CreateMock(presubmit.urllib2) |
| 1347 input_api.unittest = unittest | 1350 input_api.unittest = unittest |
| 1348 input_api.subprocess = self.mox.CreateMock(presubmit.subprocess) | 1351 input_api.subprocess = self.mox.CreateMock(presubmit.subprocess) |
| 1349 class fake_CalledProcessError(Exception): | 1352 class fake_CalledProcessError(Exception): |
| 1350 def __str__(self): | 1353 def __str__(self): |
| 1351 return 'foo' | 1354 return 'foo' |
| 1352 input_api.subprocess.CalledProcessError = fake_CalledProcessError | 1355 input_api.subprocess.CalledProcessError = fake_CalledProcessError |
| 1353 | 1356 |
| 1354 input_api.change = change | 1357 input_api.change = change |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1808 self.mox.ReplayAll() | 1811 self.mox.ReplayAll() |
| 1809 results = presubmit_canned_checks.CheckTreeIsOpen( | 1812 results = presubmit_canned_checks.CheckTreeIsOpen( |
| 1810 input_api, presubmit.OutputApi, | 1813 input_api, presubmit.OutputApi, |
| 1811 url='url_to_closed', closed='.*closed.*') | 1814 url='url_to_closed', closed='.*closed.*') |
| 1812 self.assertEquals(len(results), 1) | 1815 self.assertEquals(len(results), 1) |
| 1813 self.assertEquals(results[0].__class__, | 1816 self.assertEquals(results[0].__class__, |
| 1814 presubmit.OutputApi.PresubmitError) | 1817 presubmit.OutputApi.PresubmitError) |
| 1815 | 1818 |
| 1816 def testCannedCheckJsonTreeIsOpenOpen(self): | 1819 def testCannedCheckJsonTreeIsOpenOpen(self): |
| 1817 input_api = self.MockInputApi(None, True) | 1820 input_api = self.MockInputApi(None, True) |
| 1818 input_api.json = presubmit.json | |
| 1819 connection = self.mox.CreateMockAnything() | 1821 connection = self.mox.CreateMockAnything() |
| 1820 input_api.urllib2.urlopen('url_to_open').AndReturn(connection) | 1822 input_api.urllib2.urlopen('url_to_open').AndReturn(connection) |
| 1821 status = { | 1823 status = { |
| 1822 'can_commit_freely': True, | 1824 'can_commit_freely': True, |
| 1823 'general_state': 'open', | 1825 'general_state': 'open', |
| 1824 'message': 'The tree is open' | 1826 'message': 'The tree is open' |
| 1825 } | 1827 } |
| 1826 connection.read().AndReturn(input_api.json.dumps(status)) | 1828 connection.read().AndReturn(input_api.json.dumps(status)) |
| 1827 connection.close() | 1829 connection.close() |
| 1828 self.mox.ReplayAll() | 1830 self.mox.ReplayAll() |
| 1829 results = presubmit_canned_checks.CheckTreeIsOpen( | 1831 results = presubmit_canned_checks.CheckTreeIsOpen( |
| 1830 input_api, presubmit.OutputApi, json_url='url_to_open') | 1832 input_api, presubmit.OutputApi, json_url='url_to_open') |
| 1831 self.assertEquals(results, []) | 1833 self.assertEquals(results, []) |
| 1832 | 1834 |
| 1833 def testCannedCheckJsonTreeIsOpenClosed(self): | 1835 def testCannedCheckJsonTreeIsOpenClosed(self): |
| 1834 input_api = self.MockInputApi(None, True) | 1836 input_api = self.MockInputApi(None, True) |
| 1835 input_api.json = presubmit.json | |
| 1836 connection = self.mox.CreateMockAnything() | 1837 connection = self.mox.CreateMockAnything() |
| 1837 input_api.urllib2.urlopen('url_to_closed').AndReturn(connection) | 1838 input_api.urllib2.urlopen('url_to_closed').AndReturn(connection) |
| 1838 status = { | 1839 status = { |
| 1839 'can_commit_freely': False, | 1840 'can_commit_freely': False, |
| 1840 'general_state': 'closed', | 1841 'general_state': 'closed', |
| 1841 'message': 'The tree is close', | 1842 'message': 'The tree is close', |
| 1842 } | 1843 } |
| 1843 connection.read().AndReturn(input_api.json.dumps(status)) | 1844 connection.read().AndReturn(input_api.json.dumps(status)) |
| 1844 connection.close() | 1845 connection.close() |
| 1845 self.mox.ReplayAll() | 1846 self.mox.ReplayAll() |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1961 | 1962 |
| 1962 results = presubmit_canned_checks.CheckRietveldTryJobExecution( | 1963 results = presubmit_canned_checks.CheckRietveldTryJobExecution( |
| 1963 input_api, presubmit.OutputApi, 'uurl', ('mac', 'linux', 'amiga'), | 1964 input_api, presubmit.OutputApi, 'uurl', ('mac', 'linux', 'amiga'), |
| 1964 'georges') | 1965 'georges') |
| 1965 self.assertEquals(len(results), 1) | 1966 self.assertEquals(len(results), 1) |
| 1966 self.assertEquals(results[0].__class__, | 1967 self.assertEquals(results[0].__class__, |
| 1967 presubmit.OutputApi.PresubmitPromptWarning) | 1968 presubmit.OutputApi.PresubmitPromptWarning) |
| 1968 | 1969 |
| 1969 def testCheckBuildbotPendingBuildsBad(self): | 1970 def testCheckBuildbotPendingBuildsBad(self): |
| 1970 input_api = self.MockInputApi(None, True) | 1971 input_api = self.MockInputApi(None, True) |
| 1971 input_api.json = presubmit.json | |
| 1972 connection = self.mox.CreateMockAnything() | 1972 connection = self.mox.CreateMockAnything() |
| 1973 input_api.urllib2.urlopen('uurl').AndReturn(connection) | 1973 input_api.urllib2.urlopen('uurl').AndReturn(connection) |
| 1974 connection.read().AndReturn('foo') | 1974 connection.read().AndReturn('foo') |
| 1975 connection.close() | 1975 connection.close() |
| 1976 self.mox.ReplayAll() | 1976 self.mox.ReplayAll() |
| 1977 | 1977 |
| 1978 results = presubmit_canned_checks.CheckBuildbotPendingBuilds( | 1978 results = presubmit_canned_checks.CheckBuildbotPendingBuilds( |
| 1979 input_api, presubmit.OutputApi, 'uurl', 2, ('foo')) | 1979 input_api, presubmit.OutputApi, 'uurl', 2, ('foo')) |
| 1980 self.assertEquals(len(results), 1) | 1980 self.assertEquals(len(results), 1) |
| 1981 self.assertEquals(results[0].__class__, | 1981 self.assertEquals(results[0].__class__, |
| 1982 presubmit.OutputApi.PresubmitNotifyResult) | 1982 presubmit.OutputApi.PresubmitNotifyResult) |
| 1983 | 1983 |
| 1984 def testCheckBuildbotPendingBuildsGood(self): | 1984 def testCheckBuildbotPendingBuildsGood(self): |
| 1985 input_api = self.MockInputApi(None, True) | 1985 input_api = self.MockInputApi(None, True) |
| 1986 input_api.json = presubmit.json | |
| 1987 connection = self.mox.CreateMockAnything() | 1986 connection = self.mox.CreateMockAnything() |
| 1988 input_api.urllib2.urlopen('uurl').AndReturn(connection) | 1987 input_api.urllib2.urlopen('uurl').AndReturn(connection) |
| 1989 connection.read().AndReturn(""" | 1988 connection.read().AndReturn(""" |
| 1990 { | 1989 { |
| 1991 'b1': { 'pending_builds': [0, 1, 2, 3, 4, 5, 6, 7] }, | 1990 'b1': { 'pending_builds': [0, 1, 2, 3, 4, 5, 6, 7] }, |
| 1992 'foo': { 'pending_builds': [0, 1, 2, 3, 4, 5, 6, 7] }, | 1991 'foo': { 'pending_builds': [0, 1, 2, 3, 4, 5, 6, 7] }, |
| 1993 'b2': { 'pending_builds': [0] } | 1992 'b2': { 'pending_builds': [0] } |
| 1994 }""") | 1993 }""") |
| 1995 connection.close() | 1994 connection.close() |
| 1996 self.mox.ReplayAll() | 1995 self.mox.ReplayAll() |
| 1997 | 1996 |
| 1998 results = presubmit_canned_checks.CheckBuildbotPendingBuilds( | 1997 results = presubmit_canned_checks.CheckBuildbotPendingBuilds( |
| 1999 input_api, presubmit.OutputApi, 'uurl', 2, ('foo')) | 1998 input_api, presubmit.OutputApi, 'uurl', 2, ('foo')) |
| 2000 self.assertEquals(len(results), 1) | 1999 self.assertEquals(len(results), 1) |
| 2001 self.assertEquals(results[0].__class__, | 2000 self.assertEquals(results[0].__class__, |
| 2002 presubmit.OutputApi.PresubmitNotifyResult) | 2001 presubmit.OutputApi.PresubmitNotifyResult) |
| 2003 | 2002 |
| 2004 def AssertOwnersWorks(self, tbr=False, issue='1', approvers=None, | 2003 def AssertOwnersWorks(self, tbr=False, issue='1', approvers=None, |
| 2005 rietveld_response=None, host_url=None, | 2004 rietveld_response=None, uncovered_files=None, expected_output=''): |
| 2006 uncovered_files=None, expected_output=''): | |
| 2007 if approvers is None: | 2005 if approvers is None: |
| 2008 approvers = set() | 2006 approvers = set() |
| 2009 if uncovered_files is None: | 2007 if uncovered_files is None: |
| 2010 uncovered_files = set() | 2008 uncovered_files = set() |
| 2011 | 2009 |
| 2012 change = self.mox.CreateMock(presubmit.Change) | 2010 change = self.mox.CreateMock(presubmit.Change) |
| 2013 change.issue = issue | 2011 change.issue = issue |
| 2014 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) | 2012 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) |
| 2015 input_api = self.MockInputApi(change, False) | 2013 input_api = self.MockInputApi(change, False) |
| 2016 fake_db = self.mox.CreateMock(owners.Database) | 2014 fake_db = self.mox.CreateMock(owners.Database) |
| 2017 fake_db.email_regexp = input_api.re.compile(owners.BASIC_EMAIL_REGEXP) | 2015 fake_db.email_regexp = input_api.re.compile(owners.BASIC_EMAIL_REGEXP) |
| 2018 input_api.owners_db = fake_db | 2016 input_api.owners_db = fake_db |
| 2019 input_api.is_committing = True | 2017 input_api.is_committing = True |
| 2020 input_api.tbr = tbr | 2018 input_api.tbr = tbr |
| 2021 | 2019 |
| 2022 if not tbr and issue: | 2020 if not tbr and issue: |
| 2023 affected_file.LocalPath().AndReturn('foo.cc') | 2021 affected_file.LocalPath().AndReturn('foo.cc') |
| 2024 change.AffectedFiles(file_filter=None).AndReturn([affected_file]) | 2022 change.AffectedFiles(file_filter=None).AndReturn([affected_file]) |
| 2025 | |
| 2026 expected_host = 'http://localhost' | |
| 2027 if host_url: | |
| 2028 input_api.host_url = host_url | |
| 2029 if host_url.startswith('https'): | |
| 2030 expected_host = host_url | |
| 2031 | |
| 2032 owner_email = 'john@example.com' | 2023 owner_email = 'john@example.com' |
| 2033 if not rietveld_response: | 2024 if not rietveld_response: |
| 2034 messages = ( | 2025 rietveld_response = { |
| 2035 '{"sender": "%s", "text": "I approve", "approval": true}' % a | 2026 "owner_email": owner_email, |
| 2036 for a in approvers) | 2027 "messages": [ |
| 2037 rietveld_response = '{"owner_email": "%s", "messages": [%s]}' % ( | 2028 {"sender": a, "text": "I approve", "approval": True} |
| 2038 owner_email, ','.join(messages)) | 2029 for a in approvers |
| 2039 input_api.urllib2.urlopen( | 2030 ], |
| 2040 expected_host + '/api/1?messages=true').AndReturn( | 2031 } |
| 2041 StringIO.StringIO(rietveld_response)) | 2032 input_api.rietveld.get_issue_properties( |
| 2042 input_api.json = presubmit.json | 2033 int(input_api.change.issue), True).AndReturn(rietveld_response) |
| 2043 fake_db.files_not_covered_by(set(['foo.cc']), | 2034 fake_db.files_not_covered_by(set(['foo.cc']), |
| 2044 approvers.union(set([owner_email]))).AndReturn(uncovered_files) | 2035 approvers.union(set([owner_email]))).AndReturn(uncovered_files) |
| 2045 | 2036 |
| 2046 self.mox.ReplayAll() | 2037 self.mox.ReplayAll() |
| 2047 output = presubmit.PresubmitOutput() | 2038 output = presubmit.PresubmitOutput() |
| 2048 results = presubmit_canned_checks.CheckOwners(input_api, | 2039 results = presubmit_canned_checks.CheckOwners(input_api, |
| 2049 presubmit.OutputApi) | 2040 presubmit.OutputApi) |
| 2050 if results: | 2041 if results: |
| 2051 results[0].handle(output) | 2042 results[0].handle(output) |
| 2052 self.assertEquals(output.getvalue(), expected_output) | 2043 self.assertEquals(output.getvalue(), expected_output) |
| 2053 | 2044 |
| 2054 def testCannedCheckOwners_LGTMPhrases(self): | 2045 def testCannedCheckOwners_Approved(self): |
| 2055 def phrase_test(approval, approvers=None, expected_output=''): | 2046 response = { |
| 2056 if approvers is None: | 2047 "owner_email": "john@example.com", |
| 2057 approvers = set(['ben@example.com']) | 2048 "messages": [ |
| 2058 self.AssertOwnersWorks(approvers=approvers, | 2049 { |
| 2059 rietveld_response=( | 2050 "sender": "ben@example.com", "text": "foo", "approval": True, |
| 2060 '{"owner_email": "john@example.com",' | 2051 }, |
| 2061 '"messages": [{"sender": "ben@example.com",' | 2052 ], |
| 2062 ' "text": "foo", "approval": %s}]}') % approval, | 2053 } |
| 2063 expected_output=expected_output) | 2054 self.AssertOwnersWorks(approvers=set(['ben@example.com']), |
| 2055 rietveld_response=response, |
| 2056 expected_output='') |
| 2064 | 2057 |
| 2065 phrase_test('true') | 2058 def testCannedCheckOwners_NotApproved(self): |
| 2066 phrase_test('false', approvers=set(), | 2059 response = { |
| 2067 expected_output='Missing LGTM from someone other than ' | 2060 "owner_email": "john@example.com", |
| 2068 'john@example.com\n') | 2061 "messages": [ |
| 2069 | 2062 { |
| 2070 def testCannedCheckOwners_HTTPS_HostURL(self): | 2063 "sender": "ben@example.com", "text": "foo", "approval": False, |
| 2071 self.AssertOwnersWorks(approvers=set(['ben@example.com']), | 2064 }, |
| 2072 host_url='https://localhost') | 2065 ], |
| 2073 | 2066 } |
| 2074 def testCannedCheckOwners_MissingSchemeInHostURL(self): | 2067 self.AssertOwnersWorks( |
| 2075 self.AssertOwnersWorks(approvers=set(['ben@example.com']), | 2068 approvers=set(), |
| 2076 host_url='localhost') | 2069 rietveld_response=response, |
| 2070 expected_output= |
| 2071 'Missing LGTM from someone other than john@example.com\n') |
| 2077 | 2072 |
| 2078 def testCannedCheckOwners_NoIssue(self): | 2073 def testCannedCheckOwners_NoIssue(self): |
| 2079 self.AssertOwnersWorks(issue=None, | 2074 self.AssertOwnersWorks(issue=None, |
| 2080 expected_output="OWNERS check failed: this change has no Rietveld " | 2075 expected_output="OWNERS check failed: this change has no Rietveld " |
| 2081 "issue number, so we can't check it for approvals.\n") | 2076 "issue number, so we can't check it for approvals.\n") |
| 2082 | 2077 |
| 2083 def testCannedCheckOwners_NoLGTM(self): | 2078 def testCannedCheckOwners_NoLGTM(self): |
| 2084 self.AssertOwnersWorks(expected_output='Missing LGTM from someone ' | 2079 self.AssertOwnersWorks(expected_output='Missing LGTM from someone ' |
| 2085 'other than john@example.com\n') | 2080 'other than john@example.com\n') |
| 2086 | 2081 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2158 whitelist=['^a$', '^b$'], | 2153 whitelist=['^a$', '^b$'], |
| 2159 blacklist=['a']) | 2154 blacklist=['a']) |
| 2160 self.assertEqual(results, []) | 2155 self.assertEqual(results, []) |
| 2161 self.checkstdout( | 2156 self.checkstdout( |
| 2162 'Running %s\n' % presubmit.os.path.join('random_directory', 'b')) | 2157 'Running %s\n' % presubmit.os.path.join('random_directory', 'b')) |
| 2163 | 2158 |
| 2164 | 2159 |
| 2165 if __name__ == '__main__': | 2160 if __name__ == '__main__': |
| 2166 import unittest | 2161 import unittest |
| 2167 unittest.main() | 2162 unittest.main() |
| OLD | NEW |