blob: 39316276f9df8e722833524c4af9e821001c3b56 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 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 git helper functions."""
from __future__ import print_function
import os
import subprocess
import unittest
import unittest.mock as mock
import git
# These are unittests; protected access is OK to a point.
# pylint: disable=protected-access
class HelperFunctionsTest(unittest.TestCase):
"""Test class for updating LLVM hashes of packages."""
@mock.patch.object(os.path, 'isdir', return_value=False)
def testFailedToCreateBranchForInvalidDirectoryPath(self, mock_isdir):
path_to_repo = '/invalid/path/to/repo'
branch = 'branch-name'
# Verify the exception is raised when provided an invalid directory path.
with self.assertRaises(ValueError) as err:
git.CreateBranch(path_to_repo, branch)
self.assertEqual(
str(err.exception),
'Invalid directory path provided: %s' % path_to_repo)
mock_isdir.assert_called_once()
@mock.patch.object(os.path, 'isdir', return_value=True)
@mock.patch.object(subprocess, 'check_output', return_value=None)
def testSuccessfullyCreatedBranch(self, mock_command_output, mock_isdir):
path_to_repo = '/path/to/repo'
branch = 'branch-name'
git.CreateBranch(path_to_repo, branch)
mock_isdir.assert_called_once_with(path_to_repo)
self.assertEqual(mock_command_output.call_count, 2)
@mock.patch.object(os.path, 'isdir', return_value=False)
def testFailedToDeleteBranchForInvalidDirectoryPath(self, mock_isdir):
path_to_repo = '/invalid/path/to/repo'
branch = 'branch-name'
# Verify the exception is raised on an invalid repo path.
with self.assertRaises(ValueError) as err:
git.DeleteBranch(path_to_repo, branch)
self.assertEqual(
str(err.exception),
'Invalid directory path provided: %s' % path_to_repo)
mock_isdir.assert_called_once()
@mock.patch.object(os.path, 'isdir', return_value=True)
@mock.patch.object(subprocess, 'check_output', return_value=None)
def testSuccessfullyDeletedBranch(self, mock_command_output, mock_isdir):
path_to_repo = '/valid/path/to/repo'
branch = 'branch-name'
git.DeleteBranch(path_to_repo, branch)
mock_isdir.assert_called_once_with(path_to_repo)
self.assertEqual(mock_command_output.call_count, 3)
@mock.patch.object(os.path, 'isdir', return_value=False)
def testFailedToUploadChangesForInvalidDirectoryPath(self, mock_isdir):
path_to_repo = '/some/path/to/repo'
branch = 'update-LLVM_NEXT_HASH-a123testhash3'
commit_messages = ['Test message']
# Verify exception is raised when on an invalid repo path.
with self.assertRaises(ValueError) as err:
git.UploadChanges(path_to_repo, branch, commit_messages)
self.assertEqual(
str(err.exception), 'Invalid path provided: %s' % path_to_repo)
mock_isdir.assert_called_once()
@mock.patch.object(os.path, 'isdir', return_value=True)
@mock.patch.object(subprocess, 'check_output', return_value=None)
@mock.patch.object(subprocess, 'Popen')
def testFailedToUploadChangesForReview(self, mock_repo_upload,
mock_command_output, mock_isdir):
# Simulate the behavior of 'subprocess.Popen()' when uploading the changes
# for review
#
# `Popen.communicate()` returns a tuple of `stdout` and `stderr`.
mock_repo_upload.return_value.communicate.return_value = (
None, 'Branch does not exist.')
# Exit code of 1 means failed to upload changes for review.
mock_repo_upload.return_value.returncode = 1
path_to_repo = '/some/path/to/repo'
branch = 'invalid-branch-name'
commit_messages = ['Test message']
# Verify exception is raised when failed to upload the changes for review.
with self.assertRaises(ValueError) as err:
git.UploadChanges(path_to_repo, branch, commit_messages)
self.assertEqual(str(err.exception), 'Failed to upload changes for review')
mock_isdir.assert_called_once_with(path_to_repo)
mock_command_output.assert_called_once()
mock_command_output_args = mock_command_output.call_args_list[0][0][0]
expected_mock_command_output_prefix = ['git', 'commit', '-F']
self.assertEqual(
mock_command_output_args[:len(expected_mock_command_output_prefix)],
expected_mock_command_output_prefix)
mock_repo_upload.assert_called_once()
@mock.patch.object(os.path, 'isdir', return_value=True)
@mock.patch.object(subprocess, 'check_output', return_value=None)
@mock.patch.object(subprocess, 'Popen')
def testSuccessfullyUploadedChangesForReview(self, mock_repo_upload,
mock_command_output, mock_isdir):
# A test CL generated by `repo upload`.
repo_upload_contents = ('remote: https://chromium-review.googlesource.'
'com/c/chromiumos/overlays/chromiumos-overlay/'
'+/193147 Fix stdout')
# Simulate the behavior of 'subprocess.Popen()' when uploading the changes
# for review
#
# `Popen.communicate()` returns a tuple of `stdout` and `stderr`.
mock_repo_upload.return_value.communicate.return_value = (
repo_upload_contents, None)
# Exit code of 0 means successfully uploaded changes for review.
mock_repo_upload.return_value.returncode = 0
path_to_repo = '/some/path/to/repo'
branch = 'branch-name'
commit_messages = ['Test message']
change_list = git.UploadChanges(path_to_repo, branch, commit_messages)
self.assertEqual(
change_list.url,
'https://chromium-review.googlesource.com/c/chromiumos/overlays/'
'chromiumos-overlay/+/193147')
self.assertEqual(change_list.cl_number, 193147)
mock_isdir.assert_called_once_with(path_to_repo)
mock_command_output.assert_called_once()
mock_repo_upload.assert_called_once()
if __name__ == '__main__':
unittest.main()