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