| #!/usr/bin/env python2 |
| # -*- coding: utf-8 -*- |
| # Copyright 2019 The Chromium OS 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 retrieving the LLVM hash.""" |
| |
| from __future__ import print_function |
| |
| import mock |
| import tempfile |
| import unittest |
| |
| from cros_utils import command_executer |
| from get_google3_llvm_version import LLVMVersion |
| from get_llvm_hash import LLVMHash |
| |
| |
| class TestGetLLVMHash(unittest.TestCase): |
| """The LLVMHash test class.""" |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| def testCloneRepoSucceeds(self, mock_run_commmand_output): |
| # Test function to emulate RunCommandWOutput behavior in succeeds case. |
| def GoodCloneRepo(clone_cmd, print_to_console): |
| # Expected argument to RunCommandWOutput. |
| self.assertEqual(clone_cmd.split()[-1], '/tmp/tmpTest') |
| |
| # Returns shell error code, stdout, stderr. |
| return 0, None, 0 |
| |
| # Use the test function to simulate RunCommandWOutput behavior. |
| mock_run_commmand_output.side_effect = GoodCloneRepo |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Test the call to _CloneLLVMRepo function. |
| TestLLVMHash._CloneLLVMRepo('/tmp/tmpTest') |
| |
| mock_run_commmand_output.assert_called_once() |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| def testCloneRepoFails(self, mock_run_command_output): |
| # Test function to simulate RunCommandWOutput behavior in a failed case. |
| def BadCloneRepo(clone_cmd, print_to_console): |
| # Make sure an invalid argument is passed in. |
| self.assertNotEqual(clone_cmd.split()[-1], '/tmp/tmpTest') |
| |
| # Returns shell error code, stdout, stderr. |
| return 1, None, 'Invalid path provided' |
| |
| # Use the test function to simulate RunCommandWOutput behavior. |
| mock_run_command_output.side_effect = BadCloneRepo |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Verify the exception is raised when cloning the repo fails. |
| with self.assertRaises(ValueError) as err: |
| TestLLVMHash._CloneLLVMRepo('/tmp/tmp1') |
| |
| self.assertEqual(err.exception.message, 'Failed to clone the llvm repo: ' \ |
| 'Invalid path provided') |
| |
| mock_run_command_output.assert_called_once() |
| |
| @mock.patch.object(tempfile, 'mkdtemp') |
| def testCreateTempDirectory(self, mock_create_temp_dir): |
| # Test function to simulate mkdtemp behavior. |
| def FakeMakeDir(): |
| # Returns a directory in '/tmp/'. |
| return '/tmp/tmpTest' |
| |
| # Use the test function to simulate mkdtemp behavior. |
| mock_create_temp_dir.side_effect = FakeMakeDir |
| |
| TestLLVMHash = LLVMHash() |
| |
| self.assertEqual(TestLLVMHash._CreateTempDirectory(), '/tmp/tmpTest') |
| |
| mock_create_temp_dir.assert_called_once() |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| def testFailToParseCommitMessage(self, mock_commit_message): |
| # Test function to simulate RunCommandWOutput behavior. |
| def FakeCommitMessageOutput(find_llvm_cmd, print_to_console): |
| # Returns shell error code, stdout, stderr. |
| return 1, None, 'Unable to find the llvm version' |
| |
| # Use the test function to simulate RunCommandWOutput behavior. |
| mock_commit_message.side_effect = FakeCommitMessageOutput |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Verify the exception is raised when failed to parse a commit message. |
| with self.assertRaises(ValueError) as err: |
| TestLLVMHash._ParseCommitMessages('/tmp/tmpTest', |
| 'a13testhash2 This is a test', 100) |
| |
| self.assertEqual(err.exception.message, 'Failed to parse commit message: ' \ |
| 'Unable to find the llvm version') |
| |
| mock_commit_message.assert_called_once() |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| def testUnableToFindCommitHash(self, mock_commit_message): |
| # Test function to simulate RunCommandWOutput when parsing a |
| # commit message body. |
| def CustomCommitMessage(find_llvm_cmd, print_to_console): |
| commit_message = ('[Test] Test sentence.\n\n' |
| 'A change was made.\n\n' |
| 'llvm-svn: 1000') |
| |
| # Returns shell error code, stdout, stderr. |
| return 0, commit_message, 0 |
| |
| # Use test function to simulate RunCommandWOutput behavior. |
| mock_commit_message.side_effect = CustomCommitMessage |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Verify the exception is raised when failed to find the commit hash. |
| with self.assertRaises(ValueError) as err: |
| TestLLVMHash._ParseCommitMessages('/tmp/tmpTest', |
| 'a13testhash2 This is a test', 100) |
| |
| self.assertEqual(err.exception.message, 'Could not find commit hash.') |
| |
| mock_commit_message.assert_called_once() |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| def testFindCommitHashSuccessfully(self, mock_commit_message): |
| # Test function will be called 3 times, so |
| # 'loop_counter' determines which commit message to return |
| loop_counter = [0] |
| |
| # Test function to simulate RunCommandWOutput when |
| # returning a commit message. |
| def MultipleCommitMessages(find_llvm_cmd, print_to_console): |
| if loop_counter[0] == 0: # first iteration |
| commit_message_1 = ('[Test] Test sentence.\n\n' |
| 'A change was made.\n\n' |
| 'llvm-svn: 1001') |
| |
| loop_counter[0] += 1 |
| |
| # Returns shell error code, stdout, stderr. |
| return 0, commit_message_1, 0 |
| if loop_counter[0] == 1: # second iteration |
| # nested commit message containing two 'llvm-svn' |
| commit_message_2 = ('[Revert] Reverted commit.\n\n' |
| 'This reverts r1000:\n\n' |
| ' [Test2] Update.\n\n' |
| ' This updates stuff.\n\n' |
| ' llvm-svn: 1000\n\n' |
| 'llvm-svn: 58') |
| |
| loop_counter[0] += 1 |
| |
| # Returns shell error code, stdout, stderr. |
| return 0, commit_message_2, 0 |
| if loop_counter[0] == 2: # third iteration |
| # nested commit message containing two 'llvm-svn' |
| commit_message_3 = ('[Revert] Reverted commit.\n\n' |
| 'This reverts r958:\n\n' |
| ' [Test2] Update.\n\n' |
| ' This updates stuff.\n\n' |
| ' llvm-svn: 958\n\n' |
| 'llvm-svn: 1000') |
| |
| # Returns shell error code, stdout, stderr. |
| return 0, commit_message_3, 0 |
| |
| # Testing function was called more times than expected (3 times) |
| assert False, 'RunCommandWOutput was called more than 3 times.' |
| |
| # Use test function to simulate RunCommandWOutput behavior. |
| mock_commit_message.side_effect = MultipleCommitMessages |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Test hashes used for parsing. |
| # |
| # Format: |
| # [Hash] [Commit Summary] |
| hash_vals = ('a13testhash2 [Test] Test sentence.\n' |
| 'a13testhash3 [Revert] Reverted commit.\n' |
| 'a13testhash4 [Revert] Reverted commit.') |
| |
| self.assertEqual( |
| TestLLVMHash._ParseCommitMessages('/tmp/tmpTest', hash_vals, 1000), |
| 'a13testhash4') |
| |
| self.assertEqual(mock_commit_message.call_count, 3) |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| def testUnableToGetGitHash(self, mock_hash_val_output): |
| # Test function to simulate RunCommandWOuput when unable to |
| # find the 'llvm-svn' passed in. |
| def FailedHashValOutput(hash_cmd, print_to_console): |
| # Returns shell error code, stdout, stderr. |
| return 1, None, 'Failed to find specific llvm-svn' |
| |
| # Use test function to simulate RunCommandWOutput behavior. |
| mock_hash_val_output.side_effect = FailedHashValOutput |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Verify the exception is raised when unable to get the hash for the llvm |
| # version. |
| with self.assertRaises(ValueError) as err: |
| TestLLVMHash.GetGitHashForVersion('/tmp/tmpTest', 100) |
| |
| self.assertEqual(err.exception.message, |
| 'Hash not found: Failed to find specific llvm-svn') |
| |
| mock_hash_val_output.assert_called_once() |
| |
| @mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput') |
| @mock.patch.object(LLVMHash, '_ParseCommitMessages') |
| def testGetGitHashSuccess(self, mock_return_hash_val, mock_hash_val_output): |
| # Test function to simulate RunCommandWOutput when parsing the git log |
| # history. |
| # |
| # Format: |
| # [Hash] [Commit Summary] |
| def CustomHashValsOutput(hash_cmd, print_to_console): |
| hash_val = 'a13testhash2 [Test] Test sentence.' |
| |
| # Returns shell error code, stdout, stderr. |
| return 0, hash_val, 0 |
| |
| # Test function to simulate _ParseCommitMessages when a commit hash is |
| # returned. |
| def CustomReturnHash(subdir, hash_vals, llvm_version): |
| return 'a13testhash2' |
| |
| # Use test functions to simulate behavior. |
| mock_hash_val_output.side_effect = CustomHashValsOutput |
| mock_return_hash_val.side_effect = CustomReturnHash |
| |
| TestLLVMHash = LLVMHash() |
| |
| self.assertEqual( |
| TestLLVMHash.GetGitHashForVersion('/tmp/tmpTest', 100), 'a13testhash2') |
| |
| mock_return_hash_val.assert_called_once_with( |
| '/tmp/tmpTest/llvm', 'a13testhash2 [Test] Test sentence.', 100) |
| mock_hash_val_output.assert_called_once() |
| |
| @mock.patch.object(LLVMHash, '_CloneLLVMRepo') |
| @mock.patch.object(LLVMHash, '_DeleteTempDirectory') |
| @mock.patch.object(LLVMHash, '_CreateTempDirectory') |
| def testExceptionWhenGetLLVMHash(self, mock_create_temp_dir, |
| mock_del_temp_dir, mock_clone_repo): |
| |
| # Test function to simulate _CloneLLVMRepo when exception is thrown. |
| def FailedCloneRepo(llvm_git_dir): |
| raise ValueError('Failed to clone LLVM repo.') |
| |
| # Test function to simulate _DeleteTempDirectory when successfully |
| # deleted the temp directory. |
| def DeletedTempDirectory(llvm_git_dir): |
| return True |
| |
| # Test function to simulate _CreateTempDirectory when temp directory |
| # is returned. |
| def CreatedTempDirectory(): |
| return '/tmp/tmpTest' |
| |
| # Use test functions to simulate the behavior. |
| mock_clone_repo.side_effect = FailedCloneRepo |
| mock_del_temp_dir.side_effect = DeletedTempDirectory |
| mock_create_temp_dir.side_effect = CreatedTempDirectory |
| |
| TestLLVMHash = LLVMHash() |
| |
| # Verify the exception is raised when an exception is thrown |
| # within the 'try' block |
| # |
| # Cloning the repo will raise the exception. |
| with self.assertRaises(ValueError) as err: |
| TestLLVMHash.GetLLVMHash(100) |
| |
| self.assertEqual(err.exception.message, 'Failed to clone LLVM repo.') |
| |
| mock_del_temp_dir.assert_called_once_with('/tmp/tmpTest') |
| mock_clone_repo.assert_called_once() |
| mock_create_temp_dir.assert_called_once() |
| |
| @mock.patch.object(LLVMHash, '_CloneLLVMRepo') |
| @mock.patch.object(LLVMHash, '_DeleteTempDirectory') |
| @mock.patch.object(LLVMHash, '_CreateTempDirectory') |
| @mock.patch.object(LLVMHash, 'GetGitHashForVersion') |
| def testReturnWhenGetLLVMHash(self, mock_get_git_hash, mock_create_temp_dir, |
| mock_del_temp_dir, mock_clone_repo): |
| |
| # Test function to simulate _CloneLLVMRepo when successfully cloned the |
| # repo. |
| def ClonedRepo(llvm_git_dir): |
| return True |
| |
| # Test function to simulate _DeleteTempDirectory when successfully |
| # deleted the temp directory. |
| def DeletedTempDirectory(llvm_git_dir): |
| return True |
| |
| # Test function to simulate _CreateTempDirectory when successfully |
| # created the temp directory. |
| def CreatedTempDirectory(): |
| return '/tmp/tmpTest' |
| |
| # Test function to simulate GetGitHashForVersion when a hash is returned |
| # of its llvm version. |
| def ReturnGitHashForVersion(llvm_git_dir, llvm_version): |
| return 'a13testhash2' |
| |
| # Use test functions to simulate behavior. |
| mock_clone_repo.side_effect = ClonedRepo |
| mock_del_temp_dir.side_effect = DeletedTempDirectory |
| mock_create_temp_dir.side_effect = CreatedTempDirectory |
| mock_get_git_hash.side_effect = ReturnGitHashForVersion |
| |
| TestLLVMHash = LLVMHash() |
| |
| self.assertEqual(TestLLVMHash.GetLLVMHash(100), 'a13testhash2') |
| |
| mock_create_temp_dir.assert_called_once() |
| mock_clone_repo.assert_called_once_with('/tmp/tmpTest') |
| mock_get_git_hash.assert_called_once_with('/tmp/tmpTest', 100) |
| mock_del_temp_dir.assert_called_once() |
| |
| @mock.patch.object(LLVMHash, 'GetLLVMHash') |
| @mock.patch.object(LLVMVersion, 'GetGoogle3LLVMVersion') |
| def testReturnGoogle3LLVMHash(self, mock_google3_llvm_version, |
| mock_get_llvm_hash): |
| |
| # Test function to simulate GetLLVMHash that returns |
| # the hash of the google3 llvm version. |
| def ReturnGoogle3LLVMHash(google3_llvm_version): |
| return 'a13testhash3' |
| |
| # Test function to simulate GetGoogle3LLVMVersion that returns |
| # the google3 llvm version. |
| def ReturnGoogle3LLVMVersion(): |
| return 1000 |
| |
| # Use test functions to simulate behavior. |
| mock_get_llvm_hash.side_effect = ReturnGoogle3LLVMHash |
| mock_google3_llvm_version.side_effect = ReturnGoogle3LLVMVersion |
| |
| TestLLVMHash = LLVMHash() |
| |
| self.assertEqual(TestLLVMHash.GetGoogle3LLVMHash(), 'a13testhash3') |
| |
| mock_get_llvm_hash.assert_called_once_with(1000) |
| mock_google3_llvm_version.assert_called_once() |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |