diff --git a/PRESUBMIT.py b/PRESUBMIT.py new file mode 100755 index 000000000..4694a2861 --- /dev/null +++ b/PRESUBMIT.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Top-level presubmit script for depot tools. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for +details on the presubmit API built into gcl. +""" + + +def CheckChangeOnUpload(input_api, output_api): + return RunUnitTests(input_api, output_api) + + +def CheckChangeOnCommit(input_api, output_api): + return (RunUnitTests(input_api, output_api) + + input_api.canned_checks.CheckDoNotSubmit(input_api, output_api)) + + +def RunUnitTests(input_api, output_api): + import unittest + tests_suite = [] + test_loader = unittest.TestLoader() + def LoadTests(module_name): + module = __import__(module_name) + for part in module_name.split('.')[1:]: + module = getattr(module, part) + tests_suite.extend(test_loader.loadTestsFromModule(module)._tests) + # List all the test modules to test here: + LoadTests('tests.gcl_unittest') + LoadTests('tests.gclient_test') + LoadTests('tests.presubmit_unittest') + LoadTests('tests.trychange_unittest') + unittest.TextTestRunner(verbosity=0).run(unittest.TestSuite(tests_suite)) + # TODO(maruel): Find a way to block the check-in. + return [] diff --git a/presubmit_support.py b/presubmit_support.py index fbd0e0bba..7c73ab05a 100755 --- a/presubmit_support.py +++ b/presubmit_support.py @@ -181,7 +181,7 @@ class InputApi(object): self.platform = sys.platform # The local path of the currently-being-processed presubmit script. - self.current_presubmit_path = presubmit_path + self._current_presubmit_path = os.path.dirname(presubmit_path) # We carry the canned checks so presubmit scripts can easily use them. self.canned_checks = presubmit_canned_checks @@ -194,7 +194,7 @@ class InputApi(object): relative to the PRESUBMIT.py script, so the whole tree can be branched and the presubmit script still works, without editing its content. """ - return self.current_presubmit_path + return self._current_presubmit_path @staticmethod def DepotToLocalPath(depot_path): @@ -258,8 +258,7 @@ class InputApi(object): script, or subdirectories thereof. """ output_files = [] - dir_with_slash = normpath( - "%s/" % os.path.dirname(self.current_presubmit_path)) + dir_with_slash = normpath("%s/" % self.PresubmitLocalPath()) if len(dir_with_slash) == 1: dir_with_slash = '' for af in self.change.AffectedFiles(include_dirs, include_deletes): @@ -630,6 +629,7 @@ def DoPresubmitChecks(change_info, results = [] executer = PresubmitExecuter(change_info, committing) for filename in presubmit_files: + filename = os.path.abspath(filename) if verbose: print "Running %s" % filename # Accept CRLF presubmit script. diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..ea9de4b42 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/python +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Unit tests for depot_tools.""" + +pass diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py index 68760ee76..2eb1ec428 100755 --- a/tests/presubmit_unittest.py +++ b/tests/presubmit_unittest.py @@ -7,6 +7,7 @@ import os import StringIO +import sys import unittest # Local imports @@ -79,6 +80,8 @@ class PresubmitTestsBase(unittest.TestCase): def MockGetRepositoryRoot(): return '' gcl.GetRepositoryRoot = MockGetRepositoryRoot + self._sys_stdout = sys.stdout + sys.stdout = StringIO.StringIO() def tearDown(self): os.path.isfile = self.original_IsFile @@ -86,6 +89,7 @@ class PresubmitTestsBase(unittest.TestCase): gcl.GetSVNFileProperty = self.original_GetSVNFileProperty gcl.ReadFile = self.original_ReadFile gcl.GetRepositoryRoot = self.original_GetRepositoryRoot + sys.stdout = self._sys_stdout @staticmethod def MakeBasicChange(name, description): @@ -299,7 +303,7 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO('y\n') - self.failIf(presubmit.DoPresubmitChecks(ci, False, False, output, input)) + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input)) self.failUnless(output.getvalue().count('!!')) def testDoPresubmitChecksPromptsAfterWarnings(self): @@ -316,7 +320,7 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO('n\n') # say no to the warning - self.failIf(presubmit.DoPresubmitChecks(ci, False, False, output, input)) + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input)) self.failUnless(output.getvalue().count('??')) output = StringIO.StringIO() @@ -324,7 +328,7 @@ class PresubmitUnittest(PresubmitTestsBase): self.failUnless(presubmit.DoPresubmitChecks(ci, False, - False, + True, output, input)) self.failUnless(output.getvalue().count('??')) @@ -344,7 +348,7 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO() # should be unused - self.failIf(presubmit.DoPresubmitChecks(ci, False, False, output, input)) + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input)) self.failUnless(output.getvalue().count('??')) self.failUnless(output.getvalue().count('XX!!XX')) self.failIf(output.getvalue().count('(y/N)')) @@ -380,11 +384,11 @@ class InputApiUnittest(PresubmitTestsBase): 'DepotToLocalPath', 'FilterTextFiles', 'LocalPaths', 'LocalToDepotPath', 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', - 'current_presubmit_path', 'marshal', 'os_path', 'pickle', 'platform', + 'marshal', 'os_path', 'pickle', 'platform', 're', 'subprocess', 'tempfile', 'urllib2', ] # If this test fails, you should add the relevant test. - self.compareMembers(presubmit.InputApi(None, None), members) + self.compareMembers(presubmit.InputApi(None, './.'), members) def testDepotToLocalPath(self): path = presubmit.InputApi.DepotToLocalPath('svn:/foo/smurf') @@ -400,7 +404,7 @@ class InputApiUnittest(PresubmitTestsBase): def testInputApiConstruction(self): # Fudge the change object, it's not used during construction anyway - api = presubmit.InputApi(change=42, presubmit_path='foo/path') + api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') self.failUnless(api.PresubmitLocalPath() == 'foo/path') self.failUnless(api.change == 42) @@ -450,13 +454,13 @@ class InputApiUnittest(PresubmitTestsBase): api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') affected_files = api.AffectedFiles() - self.failUnless(len(affected_files) == 3) - self.failUnless(affected_files[0].LocalPath() == - presubmit.normpath('foo/blat.cc')) - self.failUnless(affected_files[1].LocalPath() == - presubmit.normpath('foo/blat/binary.dll')) - self.failUnless(affected_files[2].LocalPath() == - presubmit.normpath('foo/mat/beingdeleted.txt')) + self.assertEquals(len(affected_files), 3) + self.assertEquals(affected_files[0].LocalPath(), + presubmit.normpath('foo/blat.cc')) + self.assertEquals(affected_files[1].LocalPath(), + presubmit.normpath('foo/blat/binary.dll')) + self.assertEquals(affected_files[2].LocalPath(), + presubmit.normpath('foo/mat/beingdeleted.txt')) rhs_lines = [] for line in api.RightHandSideLines(): @@ -596,64 +600,64 @@ class CannedChecksUnittest(PresubmitTestsBase): def testCannedCheckChangeHasBugField(self): change = self.MakeBasicChange('foo', 'Foo\nBUG=1234') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failIf(presubmit_canned_checks.CheckChangeHasBugField( api, presubmit.OutputApi)) change = self.MakeBasicChange('foo', 'Foo\nNEVERTESTED=did some stuff') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failUnless(presubmit_canned_checks.CheckChangeHasBugField( api, presubmit.OutputApi)) def testCannedCheckChangeHasTestField(self): change = self.MakeBasicChange('foo', 'Foo\nTEST=did some stuff') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failIf(presubmit_canned_checks.CheckChangeHasTestField( api, presubmit.OutputApi)) change = self.MakeBasicChange('foo', 'Foo\nNOTEST=did some stuff') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failUnless(presubmit_canned_checks.CheckChangeHasTestField( api, presubmit.OutputApi)) def testCannedCheckChangeHasTestedField(self): change = self.MakeBasicChange('foo', 'Foo\nTESTED=did some stuff') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failIf(presubmit_canned_checks.CheckChangeHasTestedField( api, presubmit.OutputApi)) change = self.MakeBasicChange('foo', 'Foo\nNEVERTESTED=did some stuff') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failUnless(presubmit_canned_checks.CheckChangeHasTestedField( api, presubmit.OutputApi)) def testCannedCheckChangeHasQAField(self): change = self.MakeBasicChange('foo', 'Foo\nQA=test floop feature very well') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failIf(presubmit_canned_checks.CheckChangeHasQaField( api, presubmit.OutputApi)) change = self.MakeBasicChange('foo', 'Foo\nNOTFORQA=test floop feature very well') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failUnless(presubmit_canned_checks.CheckChangeHasQaField( api, presubmit.OutputApi)) def testCannedCheckDoNotSubmitInDescription(self): change = self.MakeBasicChange('foo', 'hello') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failIf(presubmit_canned_checks.CheckDoNotSubmitInDescription( api, presubmit.OutputApi)) change = self.MakeBasicChange('foo', 'DO NOT ' + 'SUBMIT') - api = presubmit.InputApi(change, 'PRESUBMIT.py') + api = presubmit.InputApi(change, './PRESUBMIT.py') self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInDescription( api, presubmit.OutputApi))