xref: /aosp_15_r20/external/toolchain-utils/llvm_tools/git_unittest.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
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