From 17f59f2dd92a65c71af6f03f6418e7322526b730 Mon Sep 17 00:00:00 2001 From: "maruel@chromium.org" Date: Fri, 12 Jun 2009 13:27:24 +0000 Subject: [PATCH] A step closer to make presubmit SCM independent. Stop presubmit_support.py from calling gcl.GetRepositoryRoot(). Instead, save the repository root in ChangeInfo and name it GetLocalRoot() to make it less confusing. Add GetFileList() and GetFileNames() to ChangeInfo to make it less confusing and more "interface-like". TEST=updated unit tests with a lot of pain BUG=none Review URL: http://codereview.chromium.org/119442 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@18266 0039d316-1c4b-4281-b951-d872f2087c98 --- gcl.py | 69 ++++---- presubmit_support.py | 21 ++- tests/gcl_unittest.py | 89 ++++++---- tests/presubmit_unittest.py | 331 +++++++++++++++++++++--------------- 4 files changed, 303 insertions(+), 207 deletions(-) diff --git a/gcl.py b/gcl.py index 7feb68a64..9aee26812 100755 --- a/gcl.py +++ b/gcl.py @@ -286,26 +286,36 @@ class ChangeInfo(object): self.description = description if files is None: files = [] - self.files = files + self._files = files self.patch = None + self._local_root = GetRepositoryRoot() - def FileList(self): - """Returns a list of files.""" - return [file[1] for file in self.files] + def GetFileNames(self): + """Returns the list of file names included in this change.""" + return [file[1] for file in self._files] + + def GetFiles(self): + """Returns the list of files included in this change with their status.""" + return self._files + + def GetLocalRoot(self): + """Returns the local repository checkout root directory.""" + return self._local_root def _NonDeletedFileList(self): """Returns a list of files in this change, not including deleted files.""" - return [file[1] for file in self.files if not file[0].startswith("D")] + return [file[1] for file in self.GetFiles() + if not file[0].startswith("D")] def _AddedFileList(self): """Returns a list of files added in this change.""" - return [file[1] for file in self.files if file[0].startswith("A")] + return [file[1] for file in self.GetFiles() if file[0].startswith("A")] def Save(self): """Writes the changelist information to disk.""" data = ChangeInfo._SEPARATOR.join([ "%d, %d" % (self.issue, self.patchset), - "\n".join([f[0] + f[1] for f in self.files]), + "\n".join([f[0] + f[1] for f in self.GetFiles()]), self.description]) WriteFile(GetChangelistInfoFile(self.name), data) @@ -377,7 +387,7 @@ class ChangeInfo(object): # apart from source and headers; besides, we'll want them all if we're # uploading anyway. if self.patch is None: - self.patch = GenerateDiff(self.FileList()) + self.patch = GenerateDiff(self.GetFileNames()) definition = "" for line in self.patch.splitlines(): @@ -475,8 +485,8 @@ def LoadChangelistInfoForMultiple(changenames, fail_on_not_found=True, changes = changenames.split(',') aggregate_change_info = ChangeInfo(changenames, 0, 0, '', None) for change in changes: - aggregate_change_info.files += ChangeInfo.Load(change, fail_on_not_found, - update_status).files + aggregate_change_info._files += ChangeInfo.Load(change, fail_on_not_found, + update_status).GetFiles() return aggregate_change_info @@ -519,7 +529,7 @@ def GetModifiedFiles(): files_in_cl = {} for cl in GetCLs(): change_info = ChangeInfo.Load(cl) - for status, filename in change_info.files: + for status, filename in change_info.GetFiles(): files_in_cl[filename] = change_info.name # Get all the modified files. @@ -587,7 +597,7 @@ def Opened(): for cl_name in cl_keys: if cl_name: note = "" - if len(ChangeInfo.Load(cl_name).files) != len(files[cl_name]): + if len(ChangeInfo.Load(cl_name).GetFiles()) != len(files[cl_name]): note = " (Note: this changelist contains files outside this directory)" print "\n--- Changelist " + cl_name + note + ":" for file in files[cl_name]: @@ -733,7 +743,7 @@ def OptionallyDoPresubmitChecks(change_info, committing, args): def UploadCL(change_info, args): - if not change_info.FileList(): + if not change_info.GetFiles(): print "Nothing to upload, changelist is empty." return if not OptionallyDoPresubmitChecks(change_info, False, args): @@ -782,7 +792,7 @@ def UploadCL(change_info, args): # http://dev.chromium.org/developers/contributing-code/watchlists if not no_watchlists: import watchlists - watchlist = watchlists.Watchlists(GetRepositoryRoot()) + watchlist = watchlists.Watchlists(change_info.GetLocalRoot()) watchers = watchlist.GetWatchersForPaths(change_info.FileList()) cc_list = GetCodeReviewSetting("CC_LIST") @@ -805,13 +815,13 @@ def UploadCL(change_info, args): # Change the current working directory before calling upload.py so that it # shows the correct base. previous_cwd = os.getcwd() - os.chdir(GetRepositoryRoot()) + os.chdir(change_info.GetLocalRoot()) # If we have a lot of files with long paths, then we won't be able to fit # the command to "svn diff". Instead, we generate the diff manually for # each file and concatenate them before passing it to upload.py. if change_info.patch is None: - change_info.patch = GenerateDiff(change_info.FileList()) + change_info.patch = GenerateDiff(change_info.GetFileNames()) issue, patchset = upload.RealMain(upload_arg, change_info.patch) if issue and patchset: change_info.issue = int(issue) @@ -839,7 +849,7 @@ def UploadCL(change_info, args): def PresubmitCL(change_info): """Reports what presubmit checks on the change would report.""" - if not change_info.FileList(): + if not change_info.GetFiles(): print "Nothing to presubmit check, changelist is empty." return @@ -867,7 +877,7 @@ def TryChange(change_info, args, swallow_exception): trychange_args.extend(["--patchset", str(change_info.patchset)]) trychange_args.extend(args) trychange.TryChange(trychange_args, - file_list=change_info.FileList(), + file_list=change_info.GetFileNames(), swallow_exception=swallow_exception, prog='gcl try') else: @@ -878,7 +888,7 @@ def TryChange(change_info, args, swallow_exception): def Commit(change_info, args): - if not change_info.FileList(): + if not change_info.GetFiles(): print "Nothing to commit, changelist is empty." return if not OptionallyDoPresubmitChecks(change_info, True, args): @@ -908,14 +918,14 @@ def Commit(change_info, args): os.close(handle) handle, targets_filename = tempfile.mkstemp(text=True) - os.write(handle, "\n".join(change_info.FileList())) + os.write(handle, "\n".join(change_info.GetFileNames())) os.close(handle) commit_cmd += ['--file=' + commit_filename] commit_cmd += ['--targets=' + targets_filename] # Change the current working directory before calling commit. previous_cwd = os.getcwd() - os.chdir(GetRepositoryRoot()) + os.chdir(change_info.GetLocalRoot()) output = RunShell(commit_cmd, True) os.remove(commit_filename) os.remove(targets_filename) @@ -961,11 +971,12 @@ def Change(change_info, override_description): unaffected_files = filter(lambda x: not file_re.match(x[0]), other_files) separator1 = ("\n---All lines above this line become the description.\n" - "---Repository Root: " + GetRepositoryRoot() + "\n" + "---Repository Root: " + change_info.GetLocalRoot() + "\n" "---Paths in this changelist (" + change_info.name + "):\n") separator2 = "\n\n---Paths modified but not in any changelist:\n\n" text = (description + separator1 + '\n' + - '\n'.join([f[0] + f[1] for f in change_info.files]) + separator2 + + '\n'.join([f[0] + f[1] for f in change_info.GetFiles()]) + + separator2 + '\n'.join([f[0] + f[1] for f in affected_files]) + '\n' + '\n'.join([f[0] + f[1] for f in unaffected_files]) + '\n') @@ -1002,7 +1013,7 @@ def Change(change_info, override_description): status = line[:7] file = line[7:] new_cl_files.append((status, file)) - change_info.files = new_cl_files + change_info._files = new_cl_files change_info.Save() print change_info.name + " changelist saved." @@ -1025,10 +1036,10 @@ def Lint(change_info, args): # Change the current working directory before calling lint so that it # shows the correct base. previous_cwd = os.getcwd() - os.chdir(GetRepositoryRoot()) + os.chdir(change_info.GetLocalRoot()) # Process cpplints arguments if any. - filenames = cpplint.ParseArguments(args + change_info.FileList()) + filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) for file in filenames: if len([file for suffix in CPP_EXTENSIONS if file.endswith(suffix)]): @@ -1063,7 +1074,7 @@ def Changes(): for cl in GetCLs(): change_info = ChangeInfo.Load(cl, True, True) print "\n--- Changelist " + change_info.name + ":" - for file in change_info.files: + for file in change_info.GetFiles(): print "".join(file) @@ -1161,7 +1172,7 @@ def main(argv=None): elif command == "try": # When the change contains no file, send the "changename" positional # argument to trychange.py. - if change_info.files: + if change_info.GetFiles(): args = argv[3:] else: change_info = None @@ -1172,7 +1183,7 @@ def main(argv=None): # the files. This allows commands such as 'gcl diff xxx' to work. args =["svn", command] root = GetRepositoryRoot() - args.extend([os.path.join(root, x) for x in change_info.FileList()]) + args.extend([os.path.join(root, x) for x in change_info.GetFileNames()]) RunShell(args, True) return 0 diff --git a/presubmit_support.py b/presubmit_support.py index 3cc68182f..9275dbc98 100755 --- a/presubmit_support.py +++ b/presubmit_support.py @@ -504,11 +504,11 @@ class GclChange(object): _tag_line_re = re.compile( '^\s*(?P[A-Z][A-Z_0-9]*)\s*=\s*(?P.*?)\s*$') - def __init__(self, change_info, repository_root=''): + def __init__(self, change_info): # Do not keep a reference to the original change_info. self._name = change_info.name self._full_description = change_info.description - self._repository_root = repository_root + self._repository_root = change_info.GetLocalRoot() self.issue = change_info.issue self.patchset = change_info.patchset @@ -528,8 +528,8 @@ class GclChange(object): self._description_without_tags = self._description_without_tags.rstrip() self._affected_files = [ - SvnAffectedFile(info[1], info[0].strip(), repository_root) - for info in change_info.files + SvnAffectedFile(info[1], info[0].strip(), self._repository_root) + for info in change_info.GetFiles() ] def Name(self): @@ -651,11 +651,11 @@ class PresubmitExecuter(object): def __init__(self, change_info, committing): """ Args: - change_info: The ChangeInfo object for the change. + change_info: The gcl.ChangeInfo object for the change. committing: True if 'gcl commit' is running, False if 'gcl upload' is. """ # TODO(maruel): Determine the SCM. - self.change = GclChange(change_info, gcl.GetRepositoryRoot()) + self.change = GclChange(change_info) self.committing = committing def ExecPresubmitScript(self, script_text, presubmit_path): @@ -714,7 +714,7 @@ def DoPresubmitChecks(change_info, when needed. Args: - change_info: The ChangeInfo object for the change. + change_info: The gcl.ChangeInfo object for the change. committing: True if 'gcl commit' is running, False if 'gcl upload' is. verbose: Prints debug info. output_stream: A stream to write output from presubmit tests to. @@ -725,9 +725,8 @@ def DoPresubmitChecks(change_info, Return: True if execution can continue, False if not. """ - checkout_root = gcl.GetRepositoryRoot() - presubmit_files = ListRelevantPresubmitFiles(change_info.FileList(), - checkout_root) + presubmit_files = ListRelevantPresubmitFiles(change_info.GetFileNames(), + change_info.local_root) if not presubmit_files and verbose: output_stream.write("Warning, no presubmit.py found.\n") results = [] @@ -735,7 +734,7 @@ def DoPresubmitChecks(change_info, if default_presubmit: if verbose: output_stream.write("Running default presubmit script.\n") - fake_path = os.path.join(checkout_root, 'PRESUBMIT.py') + fake_path = os.path.join(change_info.local_root, 'PRESUBMIT.py') results += executer.ExecPresubmitScript(default_presubmit, fake_path) for filename in presubmit_files: filename = os.path.abspath(filename) diff --git a/tests/gcl_unittest.py b/tests/gcl_unittest.py index 4c8382f53..f731bd596 100755 --- a/tests/gcl_unittest.py +++ b/tests/gcl_unittest.py @@ -19,13 +19,25 @@ class GclTestsBase(super_mox.SuperMoxTestBase): super_mox.SuperMoxTestBase.setUp(self) self.mox.StubOutWithMock(gcl, 'RunShell') self.mox.StubOutWithMock(gcl.gclient, 'CaptureSVNInfo') - self.mox.StubOutWithMock(gcl, 'os') self.mox.StubOutWithMock(gcl.os, 'getcwd') + self.mox.StubOutWithMock(gcl.os, 'chdir') + self.mox.StubOutWithMock(gcl.os, 'close') + self.mox.StubOutWithMock(gcl.os, 'remove') + self.mox.StubOutWithMock(gcl.os, 'write') + self.mox.StubOutWithMock(gcl.os.path, 'exists') + self.mox.StubOutWithMock(gcl.os.path, 'isdir') + self.mox.StubOutWithMock(gcl.os.path, 'isfile') + self.mox.StubOutWithMock(gcl, 'tempfile') + self.mox.StubOutWithMock(gcl.upload, 'RealMain') + # These are not tested. + self.mox.StubOutWithMock(gcl, 'ReadFile') + self.mox.StubOutWithMock(gcl, 'WriteFile') class GclUnittest(GclTestsBase): """General gcl.py tests.""" def testMembersChanged(self): + self.mox.ReplayAll() members = [ 'CODEREVIEW_SETTINGS', 'CODEREVIEW_SETTINGS_FILE', 'CPP_EXTENSIONS', 'Change', 'ChangeInfo', 'Changes', 'Commit', 'DoPresubmitChecks', @@ -86,14 +98,15 @@ class ChangeInfoUnittest(GclTestsBase): def setUp(self): GclTestsBase.setUp(self) self.mox.StubOutWithMock(gcl, 'GetChangelistInfoFile') - self.mox.StubOutWithMock(gcl.os.path, 'exists') - self.mox.StubOutWithMock(gcl, 'ReadFile') - self.mox.StubOutWithMock(gcl, 'WriteFile') + self.mox.StubOutWithMock(gcl, 'GetRepositoryRoot') def testChangeInfoMembers(self): + gcl.GetRepositoryRoot().AndReturn('prout') + self.mox.ReplayAll() members = [ - 'CloseIssue', 'Delete', 'FileList', 'Load', 'MissingTests', 'Save', - 'UpdateRietveldDescription', 'description', 'files', 'issue', 'name', + 'CloseIssue', 'Delete', 'GetFiles', 'GetFileNames', 'GetLocalRoot', + 'Load', 'MissingTests', 'Save', 'UpdateRietveldDescription', + 'description', 'issue', 'name', 'patch', 'patchset', ] # If this test fails, you should add the relevant test. @@ -101,15 +114,17 @@ class ChangeInfoUnittest(GclTestsBase): def testChangeInfoBase(self): files = [('M', 'foo'), ('A', 'bar')] + gcl.GetRepositoryRoot().AndReturn('prout') self.mox.ReplayAll() o = gcl.ChangeInfo('name2', '42', '53', 'description2', files) self.assertEquals(o.name, 'name2') self.assertEquals(o.issue, 42) self.assertEquals(o.patchset, 53) self.assertEquals(o.description, 'description2') - self.assertEquals(o.files, files) self.assertEquals(o.patch, None) - self.assertEquals(o.FileList(), ['foo', 'bar']) + self.assertEquals(o.GetFileNames(), ['foo', 'bar']) + self.assertEquals(o.GetFiles(), files) + self.assertEquals(o.GetLocalRoot(), 'prout') def testLoadWithIssue(self): description = ["This is some description.", "force an extra separator."] @@ -117,6 +132,7 @@ class ChangeInfoUnittest(GclTestsBase): gcl.os.path.exists('bleeeh').AndReturn(True) gcl.ReadFile('bleeeh').AndReturn( gcl.ChangeInfo._SEPARATOR.join(["42,53", "G b.cc"] + description)) + gcl.GetRepositoryRoot().AndReturn('prout') self.mox.ReplayAll() change_info = gcl.ChangeInfo.Load('bleh', True, False) @@ -125,13 +141,14 @@ class ChangeInfoUnittest(GclTestsBase): self.assertEquals(change_info.patchset, 53) self.assertEquals(change_info.description, gcl.ChangeInfo._SEPARATOR.join(description)) - self.assertEquals(change_info.files, [('G ', 'b.cc')]) + self.assertEquals(change_info.GetFiles(), [('G ', 'b.cc')]) def testLoadEmpty(self): gcl.GetChangelistInfoFile('bleh').AndReturn('bleeeh') gcl.os.path.exists('bleeeh').AndReturn(True) gcl.ReadFile('bleeeh').AndReturn( gcl.ChangeInfo._SEPARATOR.join(["", "", ""])) + gcl.GetRepositoryRoot().AndReturn('prout') self.mox.ReplayAll() change_info = gcl.ChangeInfo.Load('bleh', True, False) @@ -139,11 +156,12 @@ class ChangeInfoUnittest(GclTestsBase): self.assertEquals(change_info.issue, 0) self.assertEquals(change_info.patchset, 0) self.assertEquals(change_info.description, "") - self.assertEquals(change_info.files, []) + self.assertEquals(change_info.GetFiles(), []) def testSaveEmpty(self): gcl.GetChangelistInfoFile('').AndReturn('foo') gcl.WriteFile('foo', gcl.ChangeInfo._SEPARATOR.join(['0, 0', '', ''])) + gcl.GetRepositoryRoot().AndReturn('prout') self.mox.ReplayAll() change_info = gcl.ChangeInfo('', 0, 0, '', None) change_info.Save() @@ -152,12 +170,6 @@ class ChangeInfoUnittest(GclTestsBase): class UploadCLUnittest(GclTestsBase): def setUp(self): GclTestsBase.setUp(self) - self.mox.StubOutWithMock(gcl.os, 'chdir') - self.mox.StubOutWithMock(gcl.os, 'close') - self.mox.StubOutWithMock(gcl.os, 'remove') - self.mox.StubOutWithMock(gcl.os, 'write') - self.mox.StubOutWithMock(gcl, 'tempfile') - self.mox.StubOutWithMock(gcl.upload, 'RealMain') self.mox.StubOutWithMock(gcl, 'DoPresubmitChecks') self.mox.StubOutWithMock(gcl, 'GenerateDiff') self.mox.StubOutWithMock(gcl, 'GetCodeReviewSetting') @@ -166,16 +178,23 @@ class UploadCLUnittest(GclTestsBase): self.mox.StubOutWithMock(gcl, 'TryChange') def testNew(self): - change_info = gcl.ChangeInfo('naame', 1, 0, 'deescription', - ['aa', 'bb']) - self.mox.StubOutWithMock(change_info, 'Save') + change_info = self.mox.CreateMock(gcl.ChangeInfo) + change_info.name = 'naame' + change_info.issue = 1 + change_info.patchset = 0 + change_info.description = 'deescription', + change_info.files = [('A', 'aa'), ('M', 'bb')] + change_info.patch = None + files = [item[1] for item in change_info.files] args = ['--foo=bar'] - change_info.Save() gcl.DoPresubmitChecks(change_info, False, True).AndReturn(True) gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server') gcl.os.getcwd().AndReturn('somewhere') - gcl.os.chdir(gcl.GetRepositoryRoot().AndReturn(None)) - gcl.GenerateDiff(change_info.FileList()) + change_info.GetFiles().AndReturn(change_info.files) + change_info.GetLocalRoot().AndReturn('proout') + gcl.os.chdir('proout') + change_info.GetFileNames().AndReturn(files) + gcl.GenerateDiff(files) gcl.upload.RealMain(['upload.py', '-y', '--server=my_server', '--foo=bar', "--message=''", '--issue=1'], change_info.patch).AndReturn(("1", "2")) @@ -183,13 +202,15 @@ class UploadCLUnittest(GclTestsBase): gcl.GetCodeReviewSetting('TRY_ON_UPLOAD').AndReturn('True') gcl.TryChange(change_info, [], swallow_exception=True) gcl.os.chdir('somewhere') + change_info.Save() self.mox.ReplayAll() + gcl.UploadCL(change_info, args) def testServerOverride(self): change_info = gcl.ChangeInfo('naame', 0, 0, 'deescription', - ['aa', 'bb']) - change_info.Save = self.mox.CreateMockAnything() + [('A', 'aa'), ('M', 'bb')]) + self.mox.StubOutWithMock(change_info, 'Save') args = ['--server=a', '--no_watchlists'] change_info.Save() gcl.DoPresubmitChecks(change_info, False, True).AndReturn(True) @@ -199,8 +220,8 @@ class UploadCLUnittest(GclTestsBase): gcl.os.close(42) gcl.GetCodeReviewSetting('CC_LIST') gcl.os.getcwd().AndReturn('somewhere') - gcl.os.chdir(gcl.GetRepositoryRoot().AndReturn(None)) - gcl.GenerateDiff(change_info.FileList()) + gcl.os.chdir(change_info.GetLocalRoot()) + gcl.GenerateDiff(change_info.GetFileNames()) gcl.upload.RealMain(['upload.py', '-y', '--server=my_server', '--server=a', "--description_file=descfile", "--message=deescription"], change_info.patch).AndReturn(("1", "2")) @@ -209,11 +230,13 @@ class UploadCLUnittest(GclTestsBase): gcl.os.chdir('somewhere') self.mox.ReplayAll() + # To balance out the call in gcl.ChangeInfo.__init__(). + gcl.GetRepositoryRoot() gcl.UploadCL(change_info, args) def testNoTry(self): change_info = gcl.ChangeInfo('naame', 0, 0, 'deescription', - ['aa', 'bb']) + [('A', 'aa'), ('M', 'bb')]) change_info.Save = self.mox.CreateMockAnything() args = ['--no-try', '--no_watchlists'] change_info.Save() @@ -224,8 +247,8 @@ class UploadCLUnittest(GclTestsBase): gcl.os.close(42) gcl.GetCodeReviewSetting('CC_LIST') gcl.os.getcwd().AndReturn('somewhere') - gcl.os.chdir(gcl.GetRepositoryRoot().AndReturn(None)) - gcl.GenerateDiff(change_info.FileList()) + gcl.os.chdir(change_info.GetLocalRoot()) + gcl.GenerateDiff(change_info.GetFileNames()) gcl.upload.RealMain(['upload.py', '-y', '--server=my_server', "--description_file=descfile", "--message=deescription"], change_info.patch).AndReturn(("1", "2")) @@ -234,6 +257,8 @@ class UploadCLUnittest(GclTestsBase): gcl.os.chdir('somewhere') self.mox.ReplayAll() + # To balance out the call in gcl.ChangeInfo.__init__(). + gcl.GetRepositoryRoot() gcl.UploadCL(change_info, args) def testNormal(self): @@ -249,8 +274,8 @@ class UploadCLUnittest(GclTestsBase): gcl.os.close(42) gcl.GetCodeReviewSetting('CC_LIST') gcl.os.getcwd().AndReturn('somewhere') - gcl.os.chdir(gcl.GetRepositoryRoot().AndReturn(None)) - gcl.GenerateDiff(change_info.FileList()) + gcl.os.chdir(change_info.GetLocalRoot()) + gcl.GenerateDiff(change_info.GetFileNames()) gcl.upload.RealMain(['upload.py', '-y', '--server=my_server', "--description_file=descfile", "--message=deescription"], change_info.patch).AndReturn(("1", "2")) @@ -261,6 +286,8 @@ class UploadCLUnittest(GclTestsBase): gcl.os.chdir('somewhere') self.mox.ReplayAll() + # To balance out the call in gcl.ChangeInfo.__init__(). + gcl.GetRepositoryRoot() gcl.UploadCL(change_info, args) self.assertEquals(change_info.issue, 1) self.assertEquals(change_info.patchset, 2) diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py index b50fbe1aa..03a96ebf8 100755 --- a/tests/presubmit_unittest.py +++ b/tests/presubmit_unittest.py @@ -52,21 +52,21 @@ def CheckChangeOnUpload(input_api, output_api): def MockAbsPath(f): return f presubmit.os.path.abspath = MockAbsPath - self.mox.StubOutWithMock(presubmit.gcl, 'GetRepositoryRoot') - fake_root_dir = self.RootDir() - self.fake_root_dir = fake_root_dir - def MockGetRepositoryRoot(): - return fake_root_dir - presubmit.gcl.GetRepositoryRoot = MockGetRepositoryRoot + self.fake_root_dir = self.RootDir() self.mox.StubOutWithMock(presubmit.gclient, 'CaptureSVNInfo') self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty') self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile') + self.mox.StubOutWithMock(presubmit.gcl, 'ChangeInfo') - def MakeBasicChange(self, name, description, root=None): - ci = presubmit.gcl.ChangeInfo(name, 0, 0, description, None) - if root is None: - root = self.fake_root_dir - return presubmit.GclChange(ci, root) + def MakeChangeInfo(self, name, issue, patchset, description): + ci = self.mox.CreateMock(presubmit.gcl.ChangeInfo) + ci.name = name + ci.issue = issue + ci.patchset = patchset + ci.description = description + ci.patch = None + ci.local_root = self.fake_root_dir + return ci class PresubmitUnittest(PresubmitTestsBase): @@ -76,8 +76,8 @@ class PresubmitUnittest(PresubmitTestsBase): members = [ 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', - 'OutputApi', 'ParseFiles', 'PresubmitExecuter', - 'ScanSubDirs', 'SvnAffectedFile', + 'OutputApi', 'ParseFiles', 'PresubmitExecuter', 'ScanSubDirs', + 'SvnAffectedFile', 'cPickle', 'cStringIO', 'exceptions', 'fnmatch', 'gcl', 'gclient', 'glob', 'logging', 'marshal', 'normpath', 'optparse', @@ -142,15 +142,17 @@ class PresubmitUnittest(PresubmitTestsBase): ['?', 'flop/notfound.txt'], # not found in SVN, still exists locally ['D', 'boo/flap.h'], ] - blat = presubmit.os.path.join('foo', 'blat.cc') - notfound = presubmit.os.path.join('flop', 'notfound.txt') - flap = presubmit.os.path.join('boo', 'flap.h') + blat = presubmit.os.path.join(self.fake_root_dir, 'foo', 'blat.cc') + notfound = presubmit.os.path.join(self.fake_root_dir, 'flop', 'notfound.txt') + flap = presubmit.os.path.join(self.fake_root_dir, 'boo', 'flap.h') + binary = presubmit.os.path.join(self.fake_root_dir, 'binary.dll') + isdir = presubmit.os.path.join(self.fake_root_dir, 'isdir') presubmit.os.path.exists(blat).AndReturn(True) presubmit.os.path.isdir(blat).AndReturn(False) - presubmit.os.path.exists('binary.dll').AndReturn(True) - presubmit.os.path.isdir('binary.dll').AndReturn(False) - presubmit.os.path.exists('isdir').AndReturn(True) - presubmit.os.path.isdir('isdir').AndReturn(True) + presubmit.os.path.exists(binary).AndReturn(True) + presubmit.os.path.isdir(binary).AndReturn(False) + presubmit.os.path.exists(isdir).AndReturn(True) + presubmit.os.path.isdir(isdir).AndReturn(True) presubmit.os.path.exists(notfound).AndReturn(True) presubmit.os.path.isdir(notfound).AndReturn(False) presubmit.os.path.exists(flap).AndReturn(False) @@ -158,23 +160,23 @@ class PresubmitUnittest(PresubmitTestsBase): ).AndReturn({'Node Kind': 'file'}) presubmit.gcl.GetSVNFileProperty(blat, 'svn:mime-type').AndReturn(None) presubmit.gcl.GetSVNFileProperty( - 'binary.dll', 'svn:mime-type').AndReturn('application/octet-stream') + binary, 'svn:mime-type').AndReturn('application/octet-stream') presubmit.gcl.GetSVNFileProperty( notfound, 'svn:mime-type').AndReturn('') presubmit.gclient.CaptureSVNInfo(blat).AndReturn( {'URL': 'svn:/foo/foo/blat.cc'}) - presubmit.gclient.CaptureSVNInfo('binary.dll').AndReturn( + presubmit.gclient.CaptureSVNInfo(binary).AndReturn( {'URL': 'svn:/foo/binary.dll'}) presubmit.gclient.CaptureSVNInfo(notfound).AndReturn({}) presubmit.gclient.CaptureSVNInfo(flap).AndReturn( {'URL': 'svn:/foo/boo/flap.h'}) presubmit.gcl.ReadFile(blat).AndReturn('boo!\nahh?') presubmit.gcl.ReadFile(notfound).AndReturn('look!\nthere?') + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) change = presubmit.GclChange(ci) self.failUnless(change.Name() == 'mychange') @@ -238,12 +240,13 @@ class PresubmitUnittest(PresubmitTestsBase): ['A', 'foo\\blat.cc'], ] fake_presubmit = presubmit.os.path.join(self.fake_root_dir, 'PRESUBMIT.py') + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) - executer = presubmit.PresubmitExecuter(ci, False) self.failIf(executer.ExecPresubmitScript('', fake_presubmit)) # No error if no on-upload entry point @@ -307,12 +310,12 @@ class PresubmitUnittest(PresubmitTestsBase): 'rU').AndReturn(self.presubmit_text) presubmit.gcl.ReadFile(haspresubmit_path, 'rU').AndReturn(self.presubmit_text) + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) + ci.GetFileNames().AndReturn([item[1] for item in files]) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) - output = StringIO.StringIO() input = StringIO.StringIO('y\n') @@ -330,6 +333,7 @@ class PresubmitUnittest(PresubmitTestsBase): ] presubmit_path = join(self.fake_root_dir, 'PRESUBMIT.py') haspresubmit_path = join(self.fake_root_dir, 'haspresubmit', 'PRESUBMIT.py') + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) for i in range(2): presubmit.os.path.isfile(presubmit_path).AndReturn(True) presubmit.os.path.isfile(haspresubmit_path).AndReturn(True) @@ -337,12 +341,11 @@ class PresubmitUnittest(PresubmitTestsBase): ).AndReturn(self.presubmit_text) presubmit.gcl.ReadFile(haspresubmit_path, 'rU' ).AndReturn(self.presubmit_text) + ci.GetFileNames().AndReturn([item[1] for item in files]) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) - output = StringIO.StringIO() input = StringIO.StringIO('n\n') # say no to the warning self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, @@ -351,13 +354,8 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO('y\n') # say yes to the warning - self.failUnless(presubmit.DoPresubmitChecks(ci, - False, - True, - output, - input, - None, - True)) + self.failUnless(presubmit.DoPresubmitChecks(ci, False, True, output, input, + None, True)) self.assertEquals(output.getvalue().count('??'), 2) def testDoPresubmitChecksNoWarningPromptIfErrors(self): @@ -375,13 +373,14 @@ class PresubmitUnittest(PresubmitTestsBase): presubmit.os.path.isfile(presubmit_path).AndReturn(True) presubmit.os.path.isfile(haspresubmit_path).AndReturn(True) presubmit.gcl.ReadFile(presubmit_path, 'rU').AndReturn(self.presubmit_text) - presubmit.gcl.ReadFile(haspresubmit_path, 'rU' - ).AndReturn(self.presubmit_text) + presubmit.gcl.ReadFile(haspresubmit_path, 'rU').AndReturn( + self.presubmit_text) + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) + ci.GetFileNames().AndReturn([item[1] for item in files]) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) output = StringIO.StringIO() input = StringIO.StringIO() # should be unused self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, @@ -409,12 +408,11 @@ def CheckChangeOnCommit(input_api, output_api): presubmit.os.path.isfile(join(self.fake_root_dir, 'haspresubmit', 'PRESUBMIT.py')).AndReturn(False) + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) + ci.GetFileNames().AndReturn([item[1] for item in files]) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) - output = StringIO.StringIO() input = StringIO.StringIO('y\n') @@ -428,17 +426,18 @@ def CheckChangeOnCommit(input_api, output_api): ['A', 'isdir'], ['A', 'isdir\\blat.cc'], ] - presubmit.os.path.exists('isdir').AndReturn(True) - presubmit.os.path.isdir('isdir').AndReturn(True) - presubmit.os.path.exists(presubmit.os.path.join('isdir', 'blat.cc') - ).AndReturn(True) - presubmit.os.path.isdir(presubmit.os.path.join('isdir', 'blat.cc') - ).AndReturn(False) + isdir = presubmit.os.path.join(self.fake_root_dir, 'isdir') + blat = presubmit.os.path.join(isdir, 'blat.cc') + presubmit.os.path.exists(isdir).AndReturn(True) + presubmit.os.path.isdir(isdir).AndReturn(True) + presubmit.os.path.exists(blat).AndReturn(True) + presubmit.os.path.isdir(blat).AndReturn(False) + ci = self.MakeChangeInfo('mychange', 0, 0, 'foo') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='foo', files=files) - change = presubmit.GclChange(ci) + change = presubmit.GclChange(ci) affected_files = change.AffectedFiles(include_dirs=False) self.failUnless(len(affected_files) == 1) self.failUnless(affected_files[0].LocalPath().endswith('blat.cc')) @@ -476,17 +475,16 @@ def CheckChangeOnUpload(input_api, output_api): def CheckChangeOnCommit(input_api, output_api): raise Exception("Test error") """ + ci = self.MakeChangeInfo( + 'foo', 0, 0, "Blah Blah\n\nSTORY=http://tracker.com/42\nBUG=boo\n") + ci.GetFileNames().AndReturn([]) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn([]) self.mox.ReplayAll() - change = presubmit.gcl.ChangeInfo( - name='foo', - issue=0, - patchset=0, - description="Blah Blah\n\nSTORY=http://tracker.com/42\nBUG=boo\n", - files=None) output = StringIO.StringIO() input = StringIO.StringIO('y\n') - self.failUnless(presubmit.DoPresubmitChecks(change, False, True, output, + self.failUnless(presubmit.DoPresubmitChecks(ci, False, True, output, input, DEFAULT_SCRIPT, False)) self.assertEquals(output.getvalue(), ('Warning, no presubmit.py found.\n' @@ -553,27 +551,26 @@ class InputApiUnittest(PresubmitTestsBase): 'BUG=123', ' STORY =http://foo/ \t', 'and some more regular text') - blat = join('foo', 'blat.cc') - readme = join('foo', 'blat', 'READ_ME2') - binary = join('foo', 'blat', 'binary.dll') - weird = join('foo', 'blat', 'weird.xyz') - third_party = join('foo', 'third_party', 'third.cc') - another = join('foo', 'blat', 'another.h') - beingdeleted = join('foo', 'mat', 'beingdeleted.txt') - notfound = join('flop', 'notfound.txt') - flap = join('boo', 'flap.h') files = [ - ['A', blat], - ['M', readme], - ['M', binary], - ['M', weird], - ['M', another], - ['M', third_party], + ['A', join('foo', 'blat.cc')], + ['M', join('foo', 'blat', 'READ_ME2')], + ['M', join('foo', 'blat', 'binary.dll')], + ['M', join('foo', 'blat', 'weird.xyz')], + ['M', join('foo', 'blat', 'another.h')], + ['M', join('foo', 'third_party', 'third.cc')], ['D', 'foo/mat/beingdeleted.txt'], ['M', 'flop/notfound.txt'], ['A', 'boo/flap.h'], ] - + blat = presubmit.normpath(join(self.fake_root_dir, files[0][1])) + readme = presubmit.normpath(join(self.fake_root_dir, files[1][1])) + binary = presubmit.normpath(join(self.fake_root_dir, files[2][1])) + weird = presubmit.normpath(join(self.fake_root_dir, files[3][1])) + another = presubmit.normpath(join(self.fake_root_dir, files[4][1])) + third_party = presubmit.normpath(join(self.fake_root_dir, files[5][1])) + beingdeleted = presubmit.normpath(join(self.fake_root_dir, files[6][1])) + notfound = presubmit.normpath(join(self.fake_root_dir, files[7][1])) + flap = presubmit.normpath(join(self.fake_root_dir, files[8][1])) for i in (blat, readme, binary, weird, another, third_party): presubmit.os.path.exists(i).AndReturn(True) presubmit.os.path.isdir(i).AndReturn(False) @@ -593,33 +590,39 @@ class InputApiUnittest(PresubmitTestsBase): ).AndReturn(None) presubmit.gcl.ReadFile(blat).AndReturn('whatever\ncookie') presubmit.gcl.ReadFile(another).AndReturn('whatever\ncookie2') + ci = self.MakeChangeInfo('mychange', 0, 0, '\n'.join(description_lines)) + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='\n'.join(description_lines), - files=files) change = presubmit.GclChange(ci) - input_api = presubmit.InputApi(change, 'foo/PRESUBMIT.py', False) + input_api = presubmit.InputApi(change, + join(self.fake_root_dir, 'foo', + 'PRESUBMIT.py'), + False) # Doesn't filter much got_files = input_api.AffectedFiles() self.assertEquals(len(got_files), 7) - self.assertEquals(got_files[0].LocalPath(), presubmit.normpath(blat)) - self.assertEquals(got_files[1].LocalPath(), presubmit.normpath(readme)) - self.assertEquals(got_files[2].LocalPath(), presubmit.normpath(binary)) - self.assertEquals(got_files[3].LocalPath(), presubmit.normpath(weird)) - self.assertEquals(got_files[4].LocalPath(), presubmit.normpath(another)) - self.assertEquals(got_files[5].LocalPath(), presubmit.normpath(third_party)) - self.assertEquals(got_files[6].LocalPath(), - presubmit.normpath(beingdeleted)) + self.assertEquals(got_files[0].LocalPath(), presubmit.normpath(files[0][1])) + self.assertEquals(got_files[1].LocalPath(), presubmit.normpath(files[1][1])) + self.assertEquals(got_files[2].LocalPath(), presubmit.normpath(files[2][1])) + self.assertEquals(got_files[3].LocalPath(), presubmit.normpath(files[3][1])) + self.assertEquals(got_files[4].LocalPath(), presubmit.normpath(files[4][1])) + self.assertEquals(got_files[5].LocalPath(), presubmit.normpath(files[5][1])) + self.assertEquals(got_files[6].LocalPath(), presubmit.normpath(files[6][1])) # Ignores weird because of whitelist, third_party because of blacklist, # binary isn't a text file and beingdeleted doesn't exist. The rest is # outside foo/. rhs_lines = [x for x in input_api.RightHandSideLines(None)] self.assertEquals(len(rhs_lines), 4) - self.assertEqual(rhs_lines[0][0].LocalPath(), presubmit.normpath(blat)) - self.assertEqual(rhs_lines[1][0].LocalPath(), presubmit.normpath(blat)) - self.assertEqual(rhs_lines[2][0].LocalPath(), presubmit.normpath(another)) - self.assertEqual(rhs_lines[3][0].LocalPath(), presubmit.normpath(another)) + self.assertEqual(rhs_lines[0][0].LocalPath(), + presubmit.normpath(files[0][1])) + self.assertEqual(rhs_lines[1][0].LocalPath(), + presubmit.normpath(files[0][1])) + self.assertEqual(rhs_lines[2][0].LocalPath(), + presubmit.normpath(files[4][1])) + self.assertEqual(rhs_lines[3][0].LocalPath(), + presubmit.normpath(files[4][1])) def testDefaultWhiteListBlackListFilters(self): def f(x): @@ -697,14 +700,20 @@ class InputApiUnittest(PresubmitTestsBase): return 'a' in affected_file.LocalPath() files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee')] for (action, item) in files: + item = presubmit.os.path.join(self.fake_root_dir, item) presubmit.os.path.exists(item).AndReturn(True) presubmit.os.path.isdir(item).AndReturn(False) presubmit.gcl.GetSVNFileProperty(item, 'svn:mime-type').AndReturn(None) + ci = self.MakeChangeInfo('mychange', 0, 0, '') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo('mychange', 0, 0, '', files) change = presubmit.GclChange(ci) - input_api = presubmit.InputApi(change, './PRESUBMIT.py', False) + input_api = presubmit.InputApi(change, + presubmit.os.path.join(self.fake_root_dir, + 'PRESUBMIT.py'), + False) got_files = input_api.AffectedSourceFiles(FilterSourceFile) self.assertEquals(len(got_files), 2) self.assertEquals(got_files[0].LocalPath(), 'eeaee') @@ -715,12 +724,15 @@ class InputApiUnittest(PresubmitTestsBase): black_list = [r".*?b.*?"] files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee'), ('M', 'eecaee')] for (action, item) in files: + item = presubmit.os.path.join(self.fake_root_dir, item) presubmit.os.path.exists(item).AndReturn(True) presubmit.os.path.isdir(item).AndReturn(False) presubmit.gcl.GetSVNFileProperty(item, 'svn:mime-type').AndReturn(None) + ci = self.MakeChangeInfo('mychange', 0, 0, '') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo('mychange', 0, 0, '', files) change = presubmit.GclChange(ci) input_api = presubmit.InputApi(change, './PRESUBMIT.py', False) # Sample usage of overiding the default white and black lists. @@ -743,13 +755,14 @@ class InputApiUnittest(PresubmitTestsBase): ['A', join('isdir', 'blat.cc')], ['M', join('elsewhere', 'ouf.cc')], ] + ci = self.MakeChangeInfo('mychange', 0, 0, '') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn(files) self.mox.ReplayAll() - ci = presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='', files=files) # It doesn't make sense on non-Windows platform. This is somewhat hacky, # but it is needed since we can't just use os.path.join('c:', 'temp'). - change = presubmit.GclChange(ci, self.fake_root_dir) + change = presubmit.GclChange(ci) affected_files = change.AffectedFiles(include_dirs=True) # Local paths should remain the same self.assertEquals(affected_files[0].LocalPath(), normpath('isdir')) @@ -778,40 +791,65 @@ class InputApiUnittest(PresubmitTestsBase): def testDeprecated(self): presubmit.warnings.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), stacklevel=2) + ci = self.MakeChangeInfo('mychange', 0, 0, 'Bleh\n') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn([]) self.mox.ReplayAll() - change = presubmit.GclChange( - presubmit.gcl.ChangeInfo(name='mychange', issue=0, patchset=0, - description='Bleh\n', files=None)) - api = presubmit.InputApi(change, 'foo/PRESUBMIT.py', True) + + change = presubmit.GclChange(ci) + api = presubmit.InputApi( + change, + presubmit.os.path.join(self.fake_root_dir, 'foo', 'PRESUBMIT.py'), True) api.AffectedTextFiles(include_deletes=False) def testReadFileStringDenied(self): + ci = self.MakeChangeInfo('foo', 0, 0, 'Foo\n') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn([('M', 'AA')]) self.mox.ReplayAll() - input_api = presubmit.InputApi(None, './p', False) - input_api.change = self.MakeBasicChange('foo', 'Foo\n', '/AA') + + input_api = presubmit.InputApi( + None, presubmit.os.path.join(self.fake_root_dir, '/p'), False) + input_api.change = presubmit.GclChange(ci) self.assertRaises(IOError, input_api.ReadFile, 'boo', 'x') def testReadFileStringAccepted(self): - presubmit.gcl.ReadFile('/AA/boo', 'x').AndReturn(None) + ci = self.MakeChangeInfo('foo', 0, 0, 'Foo\n') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + path = presubmit.os.path.join(self.fake_root_dir, 'AA/boo') + ci.GetFiles().AndReturn([('M', 'AA')]) + presubmit.gcl.ReadFile(path, 'x').AndReturn(None) self.mox.ReplayAll() - input_api = presubmit.InputApi(None, './p', False) - input_api.change = self.MakeBasicChange('foo', 'Foo\n', '/AA') - input_api.ReadFile('/AA/boo', 'x') + + input_api = presubmit.InputApi( + None, presubmit.os.path.join(self.fake_root_dir, '/p'), False) + input_api.change = presubmit.GclChange(ci) + input_api.ReadFile(path, 'x') def testReadFileAffectedFileDenied(self): - file = presubmit.AffectedFile('boo', 'M') + ci = self.MakeChangeInfo('foo', 0, 0, 'Foo\n') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn([('M', 'AA')]) + file = presubmit.AffectedFile('boo', 'M', 'Unrelated') self.mox.ReplayAll() - input_api = presubmit.InputApi(None, './p', False) - input_api.change = self.MakeBasicChange('foo', 'Foo\n', '/AA') - self.assertRaises(IOError, input_api.ReadFile, 'boo', 'x') + + input_api = presubmit.InputApi( + None, presubmit.os.path.join(self.fake_root_dir, '/p'), False) + input_api.change = presubmit.GclChange(ci) + self.assertRaises(IOError, input_api.ReadFile, file, 'x') def testReadFileAffectedFileAccepted(self): - file = presubmit.AffectedFile('/AA/boo', 'M') - presubmit.gcl.ReadFile('/AA/boo', 'x').AndReturn(None) + ci = self.MakeChangeInfo('foo', 0, 0, 'Foo\n') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn([('M', 'AA')]) + file = presubmit.AffectedFile('AA/boo', 'M', self.fake_root_dir) + presubmit.gcl.ReadFile(file.AbsoluteLocalPath(), 'x').AndReturn(None) self.mox.ReplayAll() - input_api = presubmit.InputApi(None, './p', False) - input_api.change = self.MakeBasicChange('foo', 'Foo\n', '/AA') - input_api.ReadFile('/AA/boo', 'x') + + input_api = presubmit.InputApi( + None, presubmit.os.path.join(self.fake_root_dir, '/p'), False) + input_api.change = presubmit.GclChange(ci) + input_api.ReadFile(file, 'x') class OuputApiUnittest(PresubmitTestsBase): @@ -950,7 +988,6 @@ class AffectedFileUnittest(PresubmitTestsBase): class GclChangeUnittest(PresubmitTestsBase): def testMembersChanged(self): - self.mox.ReplayAll() members = [ 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', 'DescriptionText', 'FullDescriptionText', 'LocalPaths', 'Name', @@ -958,8 +995,12 @@ class GclChangeUnittest(PresubmitTestsBase): 'issue', 'patchset', 'tags', ] # If this test fails, you should add the relevant test. - ci = presubmit.gcl.ChangeInfo('', 0, 0, '', None) - self.compareMembers(presubmit.GclChange(ci, self.fake_root_dir), members) + ci = self.MakeChangeInfo('', 0, 0, '') + ci.GetLocalRoot().AndReturn(self.fake_root_dir) + ci.GetFiles().AndReturn([]) + self.mox.ReplayAll() + + self.compareMembers(presubmit.GclChange(ci), members) class CannedChecksUnittest(PresubmitTestsBase): @@ -999,12 +1040,18 @@ class CannedChecksUnittest(PresubmitTestsBase): committing): input_api1 = self.MockInputApi() input_api1.is_committing = committing - input_api1.change = self.MakeBasicChange('foo', description1) + ci1 = self.MakeChangeInfo('foo', 0, 0, description1) + ci1.GetLocalRoot().AndReturn(self.fake_root_dir) + ci1.GetFiles().AndReturn([]) input_api2 = self.MockInputApi() input_api2.is_committing = committing - input_api2.change = self.MakeBasicChange('foo', description2) + ci2 = self.MakeChangeInfo('foo', 0, 0, description2) + ci2.GetLocalRoot().AndReturn(self.fake_root_dir) + ci2.GetFiles().AndReturn([]) self.mox.ReplayAll() + input_api1.change = presubmit.GclChange(ci1) + input_api2.change = presubmit.GclChange(ci2) results1 = check(input_api1, presubmit.OutputApi) self.assertEquals(results1, []) results2 = check(input_api2, presubmit.OutputApi) @@ -1013,7 +1060,9 @@ class CannedChecksUnittest(PresubmitTestsBase): def ContentTest(self, check, content1, content2, error_type): input_api1 = self.MockInputApi() - input_api1.change = self.MakeBasicChange('foo', 'Foo\n') + ci1 = self.MakeChangeInfo('foo', 0, 0, 'foo1\n') + ci1.GetLocalRoot().AndReturn(self.fake_root_dir) + ci1.GetFiles().AndReturn([]) affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) affected_file.LocalPath().AndReturn('foo.cc') output1 = [ @@ -1023,7 +1072,9 @@ class CannedChecksUnittest(PresubmitTestsBase): ] input_api1.RightHandSideLines(mox.IgnoreArg()).AndReturn(output1) input_api2 = self.MockInputApi() - input_api2.change = self.MakeBasicChange('foo', 'Foo\n') + ci2 = self.MakeChangeInfo('foo2', 0, 0, 'foo2\n') + ci2.GetLocalRoot().AndReturn(self.fake_root_dir) + ci2.GetFiles().AndReturn([]) output2 = [ (affected_file, 42, 'yo, ' + content2), (affected_file, 43, 'yer'), @@ -1032,6 +1083,8 @@ class CannedChecksUnittest(PresubmitTestsBase): input_api2.RightHandSideLines(mox.IgnoreArg()).AndReturn(output2) self.mox.ReplayAll() + input_api1.change = presubmit.GclChange(ci1) + input_api2.change = presubmit.GclChange(ci2) results1 = check(input_api1, presubmit.OutputApi, None) self.assertEquals(results1, []) results2 = check(input_api2, presubmit.OutputApi, None) @@ -1041,19 +1094,25 @@ class CannedChecksUnittest(PresubmitTestsBase): def ReadFileTest(self, check, content1, content2, error_type): input_api1 = self.MockInputApi() self.mox.StubOutWithMock(input_api1, 'ReadFile') - input_api1.change = self.MakeBasicChange('foo', 'Foo\n') + ci1 = self.MakeChangeInfo('foo', 0, 0, 'foo1\n') + ci1.GetLocalRoot().AndReturn(self.fake_root_dir) + ci1.GetFiles().AndReturn([]) affected_file1 = self.mox.CreateMock(presubmit.SvnAffectedFile) input_api1.AffectedSourceFiles(None).AndReturn([affected_file1]) input_api1.ReadFile(affected_file1, 'rb').AndReturn(content1) input_api2 = self.MockInputApi() self.mox.StubOutWithMock(input_api2, 'ReadFile') - input_api2.change = self.MakeBasicChange('foo', 'Foo\n') + ci2 = self.MakeChangeInfo('foo2', 0, 0, 'foo2\n') + ci2.GetLocalRoot().AndReturn(self.fake_root_dir) + ci2.GetFiles().AndReturn([]) affected_file2 = self.mox.CreateMock(presubmit.SvnAffectedFile) input_api2.AffectedSourceFiles(None).AndReturn([affected_file2]) input_api2.ReadFile(affected_file2, 'rb').AndReturn(content2) affected_file2.LocalPath().AndReturn('bar.cc') self.mox.ReplayAll() + input_api1.change = presubmit.GclChange(ci1) + input_api2.change = presubmit.GclChange(ci2) results = check(input_api1, presubmit.OutputApi) self.assertEquals(results, []) results2 = check(input_api2, presubmit.OutputApi)