diff options
author | Salud Lemus <saludlemus@google.com> | 2019-07-25 17:34:50 -0700 |
---|---|---|
committer | Salud Lemus <saludlemus@google.com> | 2019-08-01 22:44:27 +0000 |
commit | 8231d4fd7797571fd5c04c9c37c0411995e99061 (patch) | |
tree | 4034a1b08aaab10f9c52b376c143c0f5a8251d19 /llvm_tools | |
parent | d8845f46c5613ec0fd9f982e5de9982dc7ed5f79 (diff) | |
download | toolchain-utils-8231d4fd7797571fd5c04c9c37c0411995e99061.tar.gz |
LLVM tools: Unittests for update_chromeos_llvm_next_hash.py
Updated and added unittests for the script now that the script calls a
script that setups up the arguments for the patch manager.
BUG=None
TEST='./update_chromeos_llvm_next_hash_unittest.py' passes
Change-Id: If16797725818d9f3c08c9e030e870e6bdbc3c83b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1719774
Reviewed-by: George Burgess <gbiv@chromium.org>
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
Tested-by: Salud Lemus <saludlemus@google.com>
Diffstat (limited to 'llvm_tools')
-rwxr-xr-x | llvm_tools/update_chromeos_llvm_next_hash_unittest.py | 478 |
1 files changed, 341 insertions, 137 deletions
diff --git a/llvm_tools/update_chromeos_llvm_next_hash_unittest.py b/llvm_tools/update_chromeos_llvm_next_hash_unittest.py index 1b5ed455..7397857b 100755 --- a/llvm_tools/update_chromeos_llvm_next_hash_unittest.py +++ b/llvm_tools/update_chromeos_llvm_next_hash_unittest.py @@ -8,6 +8,7 @@ from __future__ import print_function +from collections import namedtuple from pipes import quote from tempfile import mkstemp import mock @@ -15,34 +16,12 @@ import os import unittest from cros_utils import command_executer +from failure_modes import FailureModes +from test_helpers import CallCountsToMockFunctions +import llvm_patch_management import update_chromeos_llvm_next_hash -def CallCountsToMockFunctions(mock_function): - """A decorator that passes a call count to the function it decorates. - - Examples: - @CallCountsToMockFunctions - def foo(call_count): - return call_count - ... - ... - [foo(), foo(), foo()] - [0, 1, 2] - - NOTE: This decorator will not handle recursive functions properly. - """ - - counter = [0] - - def Result(*args, **kwargs): - ret_value = mock_function(counter[0], *args, **kwargs) - counter[0] += 1 - return ret_value - - return Result - - class UpdateLLVMNextHashTest(unittest.TestCase): """Test class for updating 'LLVM_NEXT_HASH' of packages.""" @@ -108,11 +87,9 @@ class UpdateLLVMNextHashTest(unittest.TestCase): '/path/to/chroot', ['/mnt/host/source/src/package.ebuild']), ['/path/to/chroot/src/package.ebuild']) - @mock.patch.object(os.path, 'islink') + # Simulate 'os.path.islink' when a path is not a symbolic link. + @mock.patch.object(os.path, 'islink', return_value=False) def testFailedToGetEbuildPathFromInvalidSymlink(self, mock_islink): - # Simulate 'os.path.islink' when a path is not a symbolic link. - mock_islink.return_value = False - # Verify the exception is raised when the argument is not a symbolic link. with self.assertRaises(ValueError) as err: update_chromeos_llvm_next_hash.GetEbuildPathsFromSymLinkPaths( @@ -125,7 +102,8 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_islink.assert_called_once_with( '/symlink/path/src/to/package-r1.ebuild') - @mock.patch.object(os.path, 'islink') + # Simulate 'os.path.islink' when a path is a symbolic link. + @mock.patch.object(os.path, 'islink', return_value=True) @mock.patch.object(os.path, 'realpath') def testSucceedsToGetEbuildPathFromValidSymlink(self, mock_realpath, mock_islink): @@ -133,9 +111,6 @@ class UpdateLLVMNextHashTest(unittest.TestCase): # Simulate 'os.path.realpath' when a valid path is passed in. mock_realpath.return_value = '/abs/path/to/src/package.ebuild' - # Simulate 'os.path.islink' when a path is a symbolic link. - mock_islink.return_value = True - self.assertEqual( update_chromeos_llvm_next_hash.GetEbuildPathsFromSymLinkPaths( ['/path/to/chroot/src/package-r1.ebuild']), { @@ -148,7 +123,10 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_islink.assert_called_once_with('/path/to/chroot/src/package-r1.ebuild') - def testFailedToUpdateLLVMNextHashForInvalidEbuildPath(self): + # Simulate behavior of 'os.path.isfile()' when the ebuild path to a package + # does not exist. + @mock.patch.object(os.path, 'isfile', return_value=False) + def testFailedToUpdateLLVMNextHashForInvalidEbuildPath(self, mock_isfile): # Verify the exception is raised when the ebuild path does not exist. with self.assertRaises(ValueError) as err: update_chromeos_llvm_next_hash.UpdateBuildLLVMNextHash( @@ -158,11 +136,11 @@ class UpdateLLVMNextHashTest(unittest.TestCase): err.exception.message, 'Invalid ebuild path provided: /some/path/to/package.ebuild') - @mock.patch.object(os.path, 'isfile') - def testFailedToUpdateLLVMNextHash(self, mock_isfile): - # Simulate 'os.path.isfile' behavior on a valid ebuild path. - mock_isfile.return_value = True + mock_isfile.assert_called_once() + # Simulate 'os.path.isfile' behavior on a valid ebuild path. + @mock.patch.object(os.path, 'isfile', return_value=True) + def testFailedToUpdateLLVMNextHash(self, mock_isfile): # Create a temporary file to simulate an ebuild file of a package. ebuild_file, file_path = mkstemp() @@ -187,14 +165,12 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_isfile.assert_called_once() - @mock.patch.object(os.path, 'isfile') + # Simulate 'os.path.isfile' behavior on a valid ebuild path. + @mock.patch.object(os.path, 'isfile', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testFailedToStageTheEbuildForCommitForLLVMNextHashUpdate( self, mock_stage_commit_command, mock_isfile): - # Simulate 'os.path.isfile' behavior on a valid ebuild path. - mock_isfile.return_value = True - # Simulate 'RunCommandWOutput' when failed to stage the ebuild file for # commit. # @@ -241,14 +217,12 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_isfile.assert_called_once() mock_stage_commit_command.assert_called_once() - @mock.patch.object(os.path, 'isfile') + # Simulate 'os.path.isfile' behavior on a valid ebuild path. + @mock.patch.object(os.path, 'isfile', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testSuccessfullyStageTheEbuildForCommitForLLVMNextHashUpdate( self, mock_stage_commit_command, mock_isfile): - # Simulate 'os.path.isfile' behavior on a valid ebuild path. - mock_isfile.return_value = True - # Simulate 'RunCommandWOutput' when successfully staged the ebuild file for # commit. # @@ -289,7 +263,10 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_isfile.assert_called_once() mock_stage_commit_command.assert_called_once() - def testFailedToUprevEbuildForInvalidSymlink(self): + # Simulate behavior of 'os.path.islink()' when the argument passed in is not a + # symbolic link. + @mock.patch.object(os.path, 'islink', return_value=False) + def testFailedToUprevEbuildForInvalidSymlink(self, mock_islink): # Verify the exception is raised when a symbolic link is not passed in. with self.assertRaises(ValueError) as err: update_chromeos_llvm_next_hash.UprevEbuild('/symlink/to/package.ebuild') @@ -297,11 +274,11 @@ class UpdateLLVMNextHashTest(unittest.TestCase): self.assertEqual(err.exception.message, 'Invalid symlink provided: /symlink/to/package.ebuild') - @mock.patch.object(os.path, 'islink') - def testFailedToUprevEbuild(self, mock_islink): - # Simulate 'os.path.islink' when a symbolic link is passed in. - mock_islink.return_value = True + mock_islink.assert_called_once() + # Simulate 'os.path.islink' when a symbolic link is passed in. + @mock.patch.object(os.path, 'islink', return_value=True) + def testFailedToUprevEbuild(self, mock_islink): # Verify the exception is raised when the symlink does not have a revision # number. with self.assertRaises(ValueError) as err: @@ -311,19 +288,15 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_islink.assert_called_once_with('/symlink/to/package.ebuild') - @mock.patch.object(os.path, 'islink') - @mock.patch.object(os.path, 'dirname') + # Simulate 'os.path.islink' when a valid symbolic link is passed in. + @mock.patch.object(os.path, 'islink', return_value=True) + # Simulate 'os.path.dirname' when returning a path to the directory of a + # valid symbolic link. + @mock.patch.object(os.path, 'dirname', return_value='/symlink/to') @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testSuccessfullyUprevEbuild(self, mock_command_output, mock_dirname, mock_islink): - # Simulate 'os.path.islink' when a valid symbolic link is passed in. - mock_islink.return_value = True - - # Simulate 'os.path.dirname' when returning a path to the directory of a - # valid symbolic link. - mock_dirname.return_value = '/symlink/to' - # Simulate 'RunCommandWOutput' when the symbolic link was incremented by 1 # and staged for commit. # @@ -341,7 +314,10 @@ class UpdateLLVMNextHashTest(unittest.TestCase): '/symlink/to/package-r1.ebuild /symlink/to/package-r2.ebuild', print_to_console=False) - def testFailedToCreateRepoForInvalidDirectoryPath(self): + # Simulate behavior of 'os.path.isdir()' when the path to the repo is not a + # directory. + @mock.patch.object(os.path, 'isdir', return_value=False) + def testFailedToCreateRepoForInvalidDirectoryPath(self, mock_isdir): # Verify the exception is raised when provided an invalid directory path. with self.assertRaises(ValueError) as err: update_chromeos_llvm_next_hash._CreateRepo('/path/to/repo', @@ -350,12 +326,12 @@ class UpdateLLVMNextHashTest(unittest.TestCase): self.assertEqual(err.exception.message, 'Invalid directory path provided: /path/to/repo') - @mock.patch.object(os.path, 'isdir') + mock_isdir.assert_called_once() + + # Simulate 'os.path.isdir' when the path to the repo is valid. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testFailedToCreateRepo(self, mock_command_output, mock_isdir): - # Simulate 'os.path.isdir' when the path to the repo is valid. - mock_isdir.return_value = True - # Simulate 'RunCommandWOutput' when 'repo start' fails. # # Returns shell error code, stdout, stderr. @@ -375,7 +351,8 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_command_output.assert_called_once() - @mock.patch.object(os.path, 'isdir') + # Simulate 'os.path.isdir' when a valid repo path is provided. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testSuccessfullyCreatedRepo(self, mock_command_output, mock_isdir): # Test function to simulate 'RunCommandWOutput' when 'repo start' succeeds. @@ -386,9 +363,6 @@ class UpdateLLVMNextHashTest(unittest.TestCase): # Returns shell error code, stdout, stderr. return 0, None, 0 - # Simulate 'os.path.isdir' when a valid repo path is provided. - mock_isdir.return_value = True - # Use test function to simulate 'RunCommandWOutput' behavior. mock_command_output.side_effect = GoodRepoStart @@ -398,7 +372,10 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_command_output.assert_called_once() - def testFailedToDeleteRepoForInvalidDirectoryPath(self): + # Simulate behavior of 'os.path.isdir()' when the path to the repo is not a + # directory. + @mock.patch.object(os.path, 'isdir', return_value=False) + def testFailedToDeleteRepoForInvalidDirectoryPath(self, mock_isdir): # Verify the exception is raised on an invalid repo path. with self.assertRaises(ValueError) as err: update_chromeos_llvm_next_hash._DeleteRepo('/some/path/to/repo', @@ -407,12 +384,12 @@ class UpdateLLVMNextHashTest(unittest.TestCase): self.assertEqual(err.exception.message, 'Invalid directory path provided: /some/path/to/repo') - @mock.patch.object(os.path, 'isdir') + mock_isdir.assert_called_once() + + # Simulate 'os.path.isdir' on a valid directory. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testFailedToDeleteRepo(self, mock_command_output, mock_isdir): - # Simulate 'os.path.isdir' on a valid directory. - mock_isdir.return_value = True - # Simulate 'RunCommandWOutput' when failed to delete a branch. # # Returns shell error code, stdout, stderr. @@ -432,7 +409,8 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_command_output.assert_called_once() - @mock.patch.object(os.path, 'isdir') + # Simulate 'os.path.isdir' on valid directory path. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testSuccessfullyDeletedRepo(self, mock_command_output, mock_isdir): # Test function to simulate 'RunCommandWOutput' when successfully deleted a @@ -444,9 +422,6 @@ class UpdateLLVMNextHashTest(unittest.TestCase): # Returns shell error code, stdout, stderr. return 0, None, 0 - # Simulate 'os.path.isdir' on valid directory path. - mock_isdir.return_value = True - # Use test function to simulate 'RunCommandWOutput' behavior. mock_command_output.side_effect = GoodRepoDelete @@ -457,7 +432,10 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_command_output.assert_called_once() - def testFailedToUploadChangesForInvalidPathDirectory(self): + # Simulate behavior of 'os.path.isdir()' when the path to the repo is not a + # directory. + @mock.patch.object(os.path, 'isdir', return_value=False) + def testFailedToUploadChangesForInvalidPathDirectory(self, mock_isdir): # Verify exception is raised when on an invalid repo path. with self.assertRaises(ValueError) as err: update_chromeos_llvm_next_hash.UploadChanges( @@ -466,14 +444,14 @@ class UpdateLLVMNextHashTest(unittest.TestCase): self.assertEqual(err.exception.message, 'Invalid directory path provided: /some/path/to/repo') - @mock.patch.object(os.path, 'isdir') + mock_isdir.assert_called_once() + + # Simulate 'os.path.isdir' on a valid repo directory. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testFailedToCreateACommitForTheChanges(self, mock_command_output, mock_isdir): - # Simulate 'os.path.isdir' on a valid repo directory. - mock_isdir.return_value = True - # Simulate 'RunCommandWOutput' when failed to create a commit for the # changes. # @@ -495,7 +473,8 @@ class UpdateLLVMNextHashTest(unittest.TestCase): 'cd /some/path/to/repo && git commit -m \"Test message\"', print_to_console=False) - @mock.patch.object(os.path, 'isdir') + # Simulate 'os.path.isdir' on a valid repo path. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testFailedToUploadChangesForReview(self, mock_command_output, mock_isdir): # Test function to simulate 'RunCommandWOutput' when attempting to create @@ -521,9 +500,6 @@ class UpdateLLVMNextHashTest(unittest.TestCase): # Testing function was called more times than expected (2 times). assert False, 'RunCommandWOutput was called more than 2 times.' - # Simulate 'os.path.isdir' on a valid repo path. - mock_isdir.return_value = True - # Use test function to simulate 'RunCommandWOutput' behavior. mock_command_output.side_effect = MultipleCallsToUploadACommit @@ -540,7 +516,8 @@ class UpdateLLVMNextHashTest(unittest.TestCase): self.assertEqual(mock_command_output.call_count, 2) - @mock.patch.object(os.path, 'isdir') + # Simulate 'os.path.isdir' when a valid repo path is passed in. + @mock.patch.object(os.path, 'isdir', return_value=True) @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') def testSuccessfullyUploadedChangesForReview(self, mock_command_output, mock_isdir): @@ -567,9 +544,6 @@ class UpdateLLVMNextHashTest(unittest.TestCase): # Testing function was called more times than expected (2 times). assert False, 'RunCommandWOutput was called more than 2 times.' - # Simulate 'os.path.isdir' when a valid repo path is passed in. - mock_isdir.return_value = True - # Use test function to simulate 'RunCommandWOutput' behavior. mock_command_output.side_effect = MultipleCallsToUploadACommit @@ -671,6 +645,220 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_ebuild_paths_from_symlink_paths.assert_called_once_with( ['/some/path/to/chroot/src/path/to/package-r1.ebuild']) + @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') + def testFailedToRemovePatchFromFilesDir(self, mock_run_cmd): + # Simulate the behavior of 'RunCommandWOutput()' when failed to remove a + # patch whose absolute path does not exist. + # + # Returns shell error code, stdout, stderr. + mock_run_cmd.return_value = (1, None, 'Patch does not exist.') + + # Verify the exception is raised when the patch does not exist and the + # command executer attempts to remove the patch. + with self.assertRaises(ValueError) as err: + update_chromeos_llvm_next_hash.RemovePatchesFromFilesDir([ + '/abs/path/to/filesdir/display_results.patch', + '/abs/path/to/filesdir/cherry/fix_output.patch' + ]) + + self.assertEqual( + err.exception.message, 'Failed to remove patch display_results.patch: ' + 'Patch does not exist.') + + self.assertEqual(mock_run_cmd.call_count, 1) + + mock_run_cmd.assert_called_once_with( + 'git -C /abs/path/to/filesdir rm -f ' + '/abs/path/to/filesdir/display_results.patch', + print_to_console=False) + + @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') + def testSuccessfullyRemovedPatchesFromFilesDir(self, mock_run_cmd): + # Simulate the behavior of 'RunCommandWOutput()' when all patches exist and + # were removed from $FILESDIR. + @CallCountsToMockFunctions + def MultipleCallsToRemovePatches(call_count, rm_cmd, print_to_console): + # First patch to remove from $FILESDIR. + if call_count == 0: + self.assertEqual( + rm_cmd, 'git -C /abs/path/to/filesdir/cherry rm -f ' + '/abs/path/to/filesdir/cherry/fix_output.patch') + self.assertFalse(print_to_console) + + # Returns shell error code, stdout, stderr. + return 0, None, 0 + + # Second (and last patch) to remove from $FILESDIR. + if call_count == 1: + self.assertEqual( + rm_cmd, 'git -C /abs/path/to/filesdir rm -f ' + '/abs/path/to/filesdir/display_results.patch') + self.assertFalse(print_to_console) + + # Returns shell error code, stdout, stderr. + return 0, None, 0 + + # 'RunCommandWOutput()' called more than times than expected (2 times). + assert False, 'Unexpectedly called more than 2 times.' + + # Use test function to simulate 'RunCommandWOutput()' behavior. + mock_run_cmd.side_effect = MultipleCallsToRemovePatches + + update_chromeos_llvm_next_hash.RemovePatchesFromFilesDir([ + '/abs/path/to/filesdir/cherry/fix_output.patch', + '/abs/path/to/filesdir/display_results.patch' + ]) + + self.assertEqual(mock_run_cmd.call_count, 2) + + # Simulate behavior of 'os.path.isfile()' when the absolute path to the patch + # metadata file does not exist. + @mock.patch.object(os.path, 'isfile', return_value=False) + def testInvalidPatchMetadataFileStagedForCommit(self, mock_isfile): + # Verify the exception is raised when the absolute path to the patch + # metadata file does not exist or is not a file. + with self.assertRaises(ValueError) as err: + update_chromeos_llvm_next_hash.StagePatchMetadataFileForCommit( + '/abs/path/to/filesdir/PATCHES') + + self.assertEqual( + err.exception.message, 'Invalid patch metadata file provided: ' + '/abs/path/to/filesdir/PATCHES') + + mock_isfile.assert_called_once() + + # Simulate the behavior of 'os.path.isfile()' when the absolute path to the + # patch metadata file exists. + @mock.patch.object(os.path, 'isfile', return_value=True) + @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') + def testFailedToStagePatchMetadataFileForCommit(self, mock_run_cmd, + mock_isfile): + + # Simulate the behavior of 'RunCommandWOutput()' when failed to stage the + # patch metadata file for commit. + # + # Returns shell error code, stdout, stderr. + mock_run_cmd.return_value = (1, None, 'No changes made to the file.') + + # Verify the exception is raised when no changes were made to the patch + # metadata file when attempting to stage the file for commit. + with self.assertRaises(ValueError) as err: + update_chromeos_llvm_next_hash.StagePatchMetadataFileForCommit( + '/abs/path/to/filesdir/PATCHES.json') + + self.assertEqual( + err.exception.message, + 'Failed to stage patch metadata file PATCHES.json for ' + 'commit: No changes made to the file.') + + mock_run_cmd.assert_called_once_with( + 'git -C /abs/path/to/filesdir add /abs/path/to/filesdir/PATCHES.json', + print_to_console=False) + + # Simulate the behavior of 'os.path.isfile()' when the absolute path to the + # patch metadata file exists. + @mock.patch.object(os.path, 'isfile', return_value=True) + @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') + def testSuccessfullyStagedPatchMetadataFileForCommit(self, mock_run_cmd, + mock_isfile): + + # Simulate the behavior of 'RunCommandWOutput()' when successfully staged + # the patch metadata file for commit. + # + # Returns shell error code, stdout, stderr. + mock_run_cmd.return_value = (0, None, 0) + + update_chromeos_llvm_next_hash.StagePatchMetadataFileForCommit( + '/abs/path/to/filesdir/PATCHES.json') + + mock_run_cmd.assert_called_once_with( + 'git -C /abs/path/to/filesdir add /abs/path/to/filesdir/PATCHES.json', + print_to_console=False) + + def testNoPatchResultsForCommit(self): + package_1_patch_info_dict = { + 'applied_patches': ['display_results.patch'], + 'failed_patches': ['fixes_output.patch'], + 'non_applicable_patches': [], + 'disabled_patches': [], + 'removed_patches': [], + 'modified_metadata': None + } + + package_2_patch_info_dict = { + 'applied_patches': ['redirects_stdout.patch', 'fix_display.patch'], + 'failed_patches': [], + 'non_applicable_patches': [], + 'disabled_patches': [], + 'removed_patches': [], + 'modified_metadata': None + } + + test_package_info_dict = { + 'test-packages/package1': package_1_patch_info_dict, + 'test-packages/package2': package_2_patch_info_dict + } + + test_commit_message = ['-m %s' % quote('Updated packages')] + + self.assertListEqual( + update_chromeos_llvm_next_hash.StagePackagesPatchResultsForCommit( + test_package_info_dict, test_commit_message), test_commit_message) + + @mock.patch.object(update_chromeos_llvm_next_hash, + 'StagePatchMetadataFileForCommit') + @mock.patch.object(update_chromeos_llvm_next_hash, + 'RemovePatchesFromFilesDir') + def testAddedPatchResultsForCommit(self, mock_remove_patches, + mock_stage_patches_for_commit): + + package_1_patch_info_dict = { + 'applied_patches': [], + 'failed_patches': [], + 'non_applicable_patches': [], + 'disabled_patches': ['fixes_output.patch'], + 'removed_patches': [], + 'modified_metadata': '/abs/path/to/filesdir/PATCHES.json' + } + + package_2_patch_info_dict = { + 'applied_patches': ['fix_display.patch'], + 'failed_patches': [], + 'non_applicable_patches': [], + 'disabled_patches': [], + 'removed_patches': ['/abs/path/to/filesdir/redirect_stdout.patch'], + 'modified_metadata': '/abs/path/to/filesdir/PATCHES.json' + } + + test_package_info_dict = { + 'test-packages/package1': package_1_patch_info_dict, + 'test-packages/package2': package_2_patch_info_dict + } + + test_commit_message = ['-m %s' % quote('Updated packages')] + + expected_commit_messages = [ + '-m %s' % quote('Updated packages'), + '-m %s' % quote('For the package test-packages/package2:'), + '-m %s' % quote('The patch metadata file PATCHES.json was modified'), + '-m %s' % quote('The following patches were removed:'), + '-m %s' % quote('redirect_stdout.patch'), + '-m %s' % quote('For the package test-packages/package1:'), + '-m %s' % quote('The patch metadata file PATCHES.json was modified'), + '-m %s' % quote('The following patches were disabled:'), + '-m %s' % quote('fixes_output.patch') + ] + + self.assertListEqual( + update_chromeos_llvm_next_hash.StagePackagesPatchResultsForCommit( + test_package_info_dict, test_commit_message), + expected_commit_messages) + + mock_remove_patches.assert_called_once_with( + ['/abs/path/to/filesdir/redirect_stdout.patch']) + + self.assertEqual(mock_stage_patches_for_commit.call_count, 2) + @mock.patch.object(os.path, 'dirname') @mock.patch.object(update_chromeos_llvm_next_hash, '_CreateRepo') @mock.patch.object(update_chromeos_llvm_next_hash, 'UpdateBuildLLVMNextHash') @@ -732,13 +920,17 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_uprev_ebuild.side_effect = FailedToUprevEbuild mock_upload_changes.side_effect = ShouldNotExecuteUploadChanges + test_ebuild_dict = { + '/some/path/to/chroot/src/path/to/package-r1.ebuild': + '/some/path/to/chroot/src/path/to/package.ebuild' + } + # Verify exception is raised when an exception is thrown within # the 'try' block by UprevEbuild function. with self.assertRaises(ValueError) as err: - update_chromeos_llvm_next_hash.UpdatePackages({ - '/some/path/to/chroot/src/path/to/package-r1.ebuild': - '/some/path/to/chroot/src/path/to/package.ebuild' - }, 'a123testhash4', 1000) + update_chromeos_llvm_next_hash.UpdatePackages( + test_ebuild_dict, 'a123testhash4', 1000, '/some/path/to/chroot', + '/abs/path/to/filesdir/PATCHES.json', FailureModes.FAIL) self.assertEqual(err.exception.message, 'Failed to uprev the ebuild.') @@ -759,30 +951,18 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_delete_repo.assert_called_once_with('/some/path/to/chroot/src/path/to', 'a123testhash4') - @mock.patch.object(os.path, 'dirname') @mock.patch.object(update_chromeos_llvm_next_hash, '_CreateRepo') @mock.patch.object(update_chromeos_llvm_next_hash, 'UpdateBuildLLVMNextHash') @mock.patch.object(update_chromeos_llvm_next_hash, 'UprevEbuild') - @mock.patch.object(os.path, 'basename') @mock.patch.object(update_chromeos_llvm_next_hash, 'UploadChanges') @mock.patch.object(update_chromeos_llvm_next_hash, '_DeleteRepo') + @mock.patch.object(llvm_patch_management, 'UpdatePackagesPatchMetadataFile') + @mock.patch.object(update_chromeos_llvm_next_hash, + 'StagePatchMetadataFileForCommit') def testSuccessfullyUpdatedPackages( - self, mock_delete_repo, mock_upload_changes, mock_basename, - mock_uprev_ebuild, mock_update_llvm_next, mock_create_repo, mock_dirname): - - # Test function to simulate 'os.path.dirname' on a valid ebuild path. - @CallCountsToMockFunctions - def SuccessfullyGetDirectoryPath(call_count, ebuild_path): - # Returns the absolute path to the directory of the ebuild file. - # - # 'os.path.dirname()' is expected to be called 3 times. - if call_count == 0 or call_count == 1: - return '/some/path/to/chroot/src/path/to' - if call_count == 2: - return '/some/path/to/chroot/src/path' - - # 'os.path.dirname()' was called more than 3 times. - assert False, 'os.path.dirname() was called more than 3 times.' + self, mock_stage_patch_file, mock_update_package_metadata_file, + mock_delete_repo, mock_upload_changes, mock_uprev_ebuild, + mock_update_llvm_next, mock_create_repo): # Test function to simulate '_CreateRepo' when successfully created the repo # for the changes to be made to the ebuild files. @@ -790,22 +970,6 @@ class UpdateLLVMNextHashTest(unittest.TestCase): self.assertEqual(llvm_hash, 'a123testhash5') return - # Test function to simulate 'os.path.basename' when called on the ebuild - # path. - @CallCountsToMockFunctions - def SuccessfullyGetBaseNameOfDirectory(call_count, path_to_ebuild_dir): - if call_count == 0: - self.assertEqual(path_to_ebuild_dir, '/some/path/to/chroot/src/path/to') - - return 'to' - if call_count == 1: - self.assertEqual(path_to_ebuild_dir, '/some/path/to/chroot/src/path') - - return 'path' - - # Test function was called more times than expected (2 times). - assert False, 'os.path.basename() was called more than 2 times.' - # Test function to simulate 'UploadChanges' after a successfull update of # 'LLVM_NEXT_HASH" of the ebuild file. def SuccessfullyUpdatedLLVMNextHash(ebuild_path, llvm_hash, llvm_version): @@ -823,19 +987,52 @@ class UpdateLLVMNextHashTest(unittest.TestCase): return + # Test function to simulate 'UpdatePackagesPatchMetadataFile()' when the + # patch results contains a disabled patch in 'disable_patches' mode. + def RetrievedPatchResults(chroot_path, llvm_version, patch_metadata_file, + packages, mode): + + self.assertEqual(chroot_path, '/some/path/to/chroot') + self.assertEqual(llvm_version, 1000) + self.assertEqual(patch_metadata_file, + '/abs/path/to/filesdir/PATCHES.json') + self.assertListEqual(packages, ['path/to']) + self.assertEqual(mode, FailureModes.DISABLE_PATCHES) + + PatchInfo = namedtuple('PatchInfo', [ + 'applied_patches', 'failed_patches', 'non_applicable_patches', + 'disabled_patches', 'removed_patches', 'modified_metadata' + ]) + + package_patch_info = PatchInfo( + applied_patches=['fix_display.patch'], + failed_patches=['fix_stdout.patch'], + non_applicable_patches=[], + disabled_patches=['fix_stdout.patch'], + removed_patches=[], + modified_metadata=patch_metadata_file) + + package_info_dict = {'path/to': package_patch_info._asdict()} + + # Returns a dictionary where the key is the package and the value is a + # dictionary that contains information about the package's patch results + # produced by the patch manager. + return package_info_dict + # Use test function to simulate behavior. - mock_dirname.side_effect = SuccessfullyGetDirectoryPath mock_create_repo.side_effect = SuccessfullyCreateRepoForChanges mock_update_llvm_next.side_effect = SuccessfullyUpdatedLLVMNextHash mock_uprev_ebuild.side_effect = SuccessfullyUprevedEbuild - mock_basename.side_effect = SuccessfullyGetBaseNameOfDirectory + mock_update_package_metadata_file.side_effect = RetrievedPatchResults - update_chromeos_llvm_next_hash.UpdatePackages({ + test_ebuild_dict = { '/some/path/to/chroot/src/path/to/package-r1.ebuild': '/some/path/to/chroot/src/path/to/package.ebuild' - }, 'a123testhash5', 1000) + } - self.assertEqual(mock_dirname.call_count, 3) + update_chromeos_llvm_next_hash.UpdatePackages( + test_ebuild_dict, 'a123testhash5', 1000, '/some/path/to/chroot', + '/abs/path/to/filesdir/PATCHES.json', FailureModes.DISABLE_PATCHES) mock_create_repo.assert_called_once_with('/some/path/to/chroot/src/path/to', 'a123testhash5') @@ -847,14 +1044,21 @@ class UpdateLLVMNextHashTest(unittest.TestCase): mock_uprev_ebuild.assert_called_once_with( '/some/path/to/chroot/src/path/to/package-r1.ebuild') - self.assertEqual(mock_basename.call_count, 2) - expected_commit_messages = ' '.join([ '-m %s' % quote('llvm-next: Update packages to r1000'), '-m %s' % quote('Following packages have been updated:'), - '-m %s' % quote('path/to') + '-m %s' % quote('path/to'), + '-m %s' % quote('For the package path/to:'), + '-m %s' % quote('The patch metadata file PATCHES.json was modified'), + '-m %s' % quote('The following patches were disabled:'), + '-m %s' % quote('fix_stdout.patch') ]) + mock_update_package_metadata_file.assert_called_once() + + mock_stage_patch_file.assert_called_once_with( + '/abs/path/to/filesdir/PATCHES.json') + mock_upload_changes.assert_called_once_with( '/some/path/to/chroot/src/path/to', 'a123testhash5', expected_commit_messages) |