blob: 97dd12782360834f0ac730e3733671923454c580 [file] [log] [blame]
#!/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()