1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# Copyright 2020 The ChromiumOS Authors 3*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 4*760c253cSXin Li# found in the LICENSE file. 5*760c253cSXin Li 6*760c253cSXin Li"""Unit tests for git helper functions.""" 7*760c253cSXin Li 8*760c253cSXin Liimport os 9*760c253cSXin Liimport subprocess 10*760c253cSXin Liimport tempfile 11*760c253cSXin Liimport unittest 12*760c253cSXin Lifrom unittest import mock 13*760c253cSXin Li 14*760c253cSXin Liimport git 15*760c253cSXin Li 16*760c253cSXin Li 17*760c253cSXin Li# These are unittests; protected access is OK to a point. 18*760c253cSXin Li# pylint: disable=protected-access 19*760c253cSXin Li 20*760c253cSXin LiEXAMPLE_GIT_SHA = "d46d9c1a23118e3943f43fe2dfc9f9c9c0b4aefe" 21*760c253cSXin Li 22*760c253cSXin Li 23*760c253cSXin Liclass HelperFunctionsTest(unittest.TestCase): 24*760c253cSXin Li """Test class for updating LLVM hashes of packages.""" 25*760c253cSXin Li 26*760c253cSXin Li def testIsFullGitSHASuccessCases(self): 27*760c253cSXin Li shas = ("a" * 40, EXAMPLE_GIT_SHA) 28*760c253cSXin Li for s in shas: 29*760c253cSXin Li self.assertTrue(git.IsFullGitSHA(s), s) 30*760c253cSXin Li 31*760c253cSXin Li def testIsFullGitSHAFailureCases(self): 32*760c253cSXin Li shas = ( 33*760c253cSXin Li "", 34*760c253cSXin Li "A" * 40, 35*760c253cSXin Li "g" * 40, 36*760c253cSXin Li EXAMPLE_GIT_SHA[1:], 37*760c253cSXin Li EXAMPLE_GIT_SHA + "a", 38*760c253cSXin Li ) 39*760c253cSXin Li for s in shas: 40*760c253cSXin Li self.assertFalse(git.IsFullGitSHA(s), s) 41*760c253cSXin Li 42*760c253cSXin Li @mock.patch.object(os.path, "isdir", return_value=False) 43*760c253cSXin Li def testFailedToCreateBranchForInvalidDirectoryPath(self, mock_isdir): 44*760c253cSXin Li path_to_repo = "/invalid/path/to/repo" 45*760c253cSXin Li branch = "branch-name" 46*760c253cSXin Li 47*760c253cSXin Li # Verify the exception is raised when provided an invalid directory 48*760c253cSXin Li # path. 49*760c253cSXin Li with self.assertRaises(ValueError) as err: 50*760c253cSXin Li git.CreateBranch(path_to_repo, branch) 51*760c253cSXin Li 52*760c253cSXin Li self.assertEqual( 53*760c253cSXin Li str(err.exception), 54*760c253cSXin Li "Invalid directory path provided: %s" % path_to_repo, 55*760c253cSXin Li ) 56*760c253cSXin Li 57*760c253cSXin Li mock_isdir.assert_called_once() 58*760c253cSXin Li 59*760c253cSXin Li @mock.patch.object(os.path, "isdir", return_value=True) 60*760c253cSXin Li @mock.patch.object(subprocess, "check_output", return_value=None) 61*760c253cSXin Li def testSuccessfullyCreatedBranch(self, mock_command_output, mock_isdir): 62*760c253cSXin Li path_to_repo = "/path/to/repo" 63*760c253cSXin Li branch = "branch-name" 64*760c253cSXin Li 65*760c253cSXin Li git.CreateBranch(path_to_repo, branch) 66*760c253cSXin Li 67*760c253cSXin Li mock_isdir.assert_called_once_with(path_to_repo) 68*760c253cSXin Li 69*760c253cSXin Li self.assertEqual(mock_command_output.call_count, 2) 70*760c253cSXin Li 71*760c253cSXin Li @mock.patch.object(os.path, "isdir", return_value=False) 72*760c253cSXin Li def testFailedToDeleteBranchForInvalidDirectoryPath(self, mock_isdir): 73*760c253cSXin Li path_to_repo = "/invalid/path/to/repo" 74*760c253cSXin Li branch = "branch-name" 75*760c253cSXin Li 76*760c253cSXin Li # Verify the exception is raised on an invalid repo path. 77*760c253cSXin Li with self.assertRaises(ValueError) as err: 78*760c253cSXin Li git.DeleteBranch(path_to_repo, branch) 79*760c253cSXin Li 80*760c253cSXin Li self.assertEqual( 81*760c253cSXin Li str(err.exception), 82*760c253cSXin Li "Invalid directory path provided: %s" % path_to_repo, 83*760c253cSXin Li ) 84*760c253cSXin Li 85*760c253cSXin Li mock_isdir.assert_called_once() 86*760c253cSXin Li 87*760c253cSXin Li @mock.patch.object(os.path, "isdir", return_value=True) 88*760c253cSXin Li @mock.patch.object(subprocess, "run", return_value=None) 89*760c253cSXin Li def testSuccessfullyDeletedBranch(self, mock_command_output, mock_isdir): 90*760c253cSXin Li path_to_repo = "/valid/path/to/repo" 91*760c253cSXin Li branch = "branch-name" 92*760c253cSXin Li 93*760c253cSXin Li git.DeleteBranch(path_to_repo, branch) 94*760c253cSXin Li 95*760c253cSXin Li mock_isdir.assert_called_once_with(path_to_repo) 96*760c253cSXin Li 97*760c253cSXin Li self.assertEqual(mock_command_output.call_count, 3) 98*760c253cSXin Li 99*760c253cSXin Li @mock.patch.object(os.path, "isdir", return_value=False) 100*760c253cSXin Li def testFailedToUploadChangesForInvalidDirectoryPath(self, mock_isdir): 101*760c253cSXin Li path_to_repo = "/some/path/to/repo" 102*760c253cSXin Li branch = "update-LLVM_NEXT_HASH-a123testhash3" 103*760c253cSXin Li 104*760c253cSXin Li # Verify exception is raised when on an invalid repo path. 105*760c253cSXin Li with self.assertRaises(ValueError) as err: 106*760c253cSXin Li git.UploadChanges(path_to_repo, branch) 107*760c253cSXin Li 108*760c253cSXin Li self.assertEqual( 109*760c253cSXin Li str(err.exception), "Invalid path provided: %s" % path_to_repo 110*760c253cSXin Li ) 111*760c253cSXin Li 112*760c253cSXin Li mock_isdir.assert_called_once() 113*760c253cSXin Li 114*760c253cSXin Li @mock.patch.object(os.path, "isdir", return_value=True) 115*760c253cSXin Li @mock.patch.object(subprocess, "check_output") 116*760c253cSXin Li @mock.patch.object(tempfile, "NamedTemporaryFile") 117*760c253cSXin Li def testSuccessfullyUploadedChangesForReview( 118*760c253cSXin Li self, mock_tempfile, mock_commands, mock_isdir 119*760c253cSXin Li ): 120*760c253cSXin Li path_to_repo = "/some/path/to/repo" 121*760c253cSXin Li branch = "branch-name" 122*760c253cSXin Li commit_messages = ["Test message"] 123*760c253cSXin Li mock_tempfile.return_value.__enter__.return_value.name = "tmp" 124*760c253cSXin Li 125*760c253cSXin Li # A test CL generated by `repo upload`. 126*760c253cSXin Li mock_commands.side_effect = [ 127*760c253cSXin Li None, 128*760c253cSXin Li ( 129*760c253cSXin Li "remote: https://chromium-review.googlesource." 130*760c253cSXin Li "com/c/chromiumos/overlays/chromiumos-overlay/" 131*760c253cSXin Li "+/193147 Fix stdout" 132*760c253cSXin Li ), 133*760c253cSXin Li ] 134*760c253cSXin Li git.CommitChanges(path_to_repo, commit_messages) 135*760c253cSXin Li change_list = git.UploadChanges(path_to_repo, branch) 136*760c253cSXin Li 137*760c253cSXin Li self.assertEqual(change_list.cl_number, 193147) 138*760c253cSXin Li 139*760c253cSXin Li mock_isdir.assert_called_with(path_to_repo) 140*760c253cSXin Li 141*760c253cSXin Li expected_command = [ 142*760c253cSXin Li "git", 143*760c253cSXin Li "commit", 144*760c253cSXin Li "-F", 145*760c253cSXin Li mock_tempfile.return_value.__enter__.return_value.name, 146*760c253cSXin Li ] 147*760c253cSXin Li self.assertEqual( 148*760c253cSXin Li mock_commands.call_args_list[0], 149*760c253cSXin Li mock.call(expected_command, cwd=path_to_repo), 150*760c253cSXin Li ) 151*760c253cSXin Li 152*760c253cSXin Li expected_cmd = [ 153*760c253cSXin Li "repo", 154*760c253cSXin Li "upload", 155*760c253cSXin Li "--yes", 156*760c253cSXin Li "--ne", 157*760c253cSXin Li "--no-verify", 158*760c253cSXin Li "--br=%s" % branch, 159*760c253cSXin Li ] 160*760c253cSXin Li self.assertEqual( 161*760c253cSXin Li mock_commands.call_args_list[1], 162*760c253cSXin Li mock.call( 163*760c253cSXin Li expected_cmd, 164*760c253cSXin Li stderr=subprocess.STDOUT, 165*760c253cSXin Li cwd=path_to_repo, 166*760c253cSXin Li encoding="utf-8", 167*760c253cSXin Li ), 168*760c253cSXin Li ) 169*760c253cSXin Li 170*760c253cSXin Li self.assertEqual( 171*760c253cSXin Li change_list.url, 172*760c253cSXin Li "https://chromium-review.googlesource.com/c/chromiumos/overlays/" 173*760c253cSXin Li "chromiumos-overlay/+/193147", 174*760c253cSXin Li ) 175*760c253cSXin Li 176*760c253cSXin Li 177*760c253cSXin Liif __name__ == "__main__": 178*760c253cSXin Li unittest.main() 179