• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2019 The ChromiumOS Authors
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Unit tests for retrieving the LLVM hash."""
8
9
10import subprocess
11import unittest
12import unittest.mock as mock
13
14import get_llvm_hash
15from get_llvm_hash import LLVMHash
16
17
18# We grab protected stuff from get_llvm_hash. That's OK.
19# pylint: disable=protected-access
20
21
22def MakeMockPopen(return_code):
23    def MockPopen(*_args, **_kwargs):
24        result = mock.MagicMock()
25        result.returncode = return_code
26
27        communicate_result = result.communicate.return_value
28        # Communicate returns stdout, stderr.
29        communicate_result.__iter__.return_value = (None, "some stderr")
30        return result
31
32    return MockPopen
33
34
35class TestGetLLVMHash(unittest.TestCase):
36    """The LLVMHash test class."""
37
38    @mock.patch.object(subprocess, "Popen")
39    def testCloneRepoSucceedsWhenGitSucceeds(self, popen_mock):
40        popen_mock.side_effect = MakeMockPopen(return_code=0)
41        llvm_hash = LLVMHash()
42
43        into_tempdir = "/tmp/tmpTest"
44        llvm_hash.CloneLLVMRepo(into_tempdir)
45        popen_mock.assert_called_with(
46            ["git", "clone", get_llvm_hash._LLVM_GIT_URL, into_tempdir],
47            stderr=subprocess.PIPE,
48        )
49
50    @mock.patch.object(subprocess, "Popen")
51    def testCloneRepoFailsWhenGitFails(self, popen_mock):
52        popen_mock.side_effect = MakeMockPopen(return_code=1)
53
54        with self.assertRaises(ValueError) as err:
55            LLVMHash().CloneLLVMRepo("/tmp/tmp1")
56
57        self.assertIn("Failed to clone", str(err.exception.args))
58        self.assertIn("some stderr", str(err.exception.args))
59
60    @mock.patch.object(get_llvm_hash, "GetGitHashFrom")
61    def testGetGitHashWorks(self, mock_get_git_hash):
62        mock_get_git_hash.return_value = "a13testhash2"
63
64        self.assertEqual(
65            get_llvm_hash.GetGitHashFrom("/tmp/tmpTest", 100), "a13testhash2"
66        )
67
68        mock_get_git_hash.assert_called_once()
69
70    @mock.patch.object(LLVMHash, "GetLLVMHash")
71    @mock.patch.object(get_llvm_hash, "GetGoogle3LLVMVersion")
72    def testReturnGoogle3LLVMHash(
73        self, mock_google3_llvm_version, mock_get_llvm_hash
74    ):
75        mock_get_llvm_hash.return_value = "a13testhash3"
76        mock_google3_llvm_version.return_value = 1000
77        self.assertEqual(LLVMHash().GetGoogle3LLVMHash(), "a13testhash3")
78        mock_get_llvm_hash.assert_called_once_with(1000)
79
80    @mock.patch.object(LLVMHash, "GetLLVMHash")
81    @mock.patch.object(get_llvm_hash, "GetGoogle3LLVMVersion")
82    def testReturnGoogle3UnstableLLVMHash(
83        self, mock_google3_llvm_version, mock_get_llvm_hash
84    ):
85        mock_get_llvm_hash.return_value = "a13testhash3"
86        mock_google3_llvm_version.return_value = 1000
87        self.assertEqual(
88            LLVMHash().GetGoogle3UnstableLLVMHash(), "a13testhash3"
89        )
90        mock_get_llvm_hash.assert_called_once_with(1000)
91
92    @mock.patch.object(subprocess, "check_output")
93    def testSuccessfullyGetGitHashFromToTOfLLVM(self, mock_check_output):
94        mock_check_output.return_value = "a123testhash1 path/to/main\n"
95        self.assertEqual(LLVMHash().GetTopOfTrunkGitHash(), "a123testhash1")
96        mock_check_output.assert_called_once()
97
98    @mock.patch.object(subprocess, "Popen")
99    def testCheckoutBranch(self, mock_popen):
100        mock_popen.return_value = mock.MagicMock(
101            communicate=lambda: (None, None), returncode=0
102        )
103        get_llvm_hash.CheckoutBranch("fake/src_dir", "fake_branch")
104        self.assertEqual(
105            mock_popen.call_args_list[0][0],
106            (["git", "-C", "fake/src_dir", "checkout", "fake_branch"],),
107        )
108        self.assertEqual(
109            mock_popen.call_args_list[1][0],
110            (["git", "-C", "fake/src_dir", "pull"],),
111        )
112
113    def testParseLLVMMajorVersion(self):
114        cmakelist_42 = (
115            "set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)\n"
116            "if(NOT DEFINED LLVM_VERSION_MAJOR)\n"
117            "  set(LLVM_VERSION_MAJOR 42)\n"
118            "endif()"
119        )
120        self.assertEqual(
121            get_llvm_hash.ParseLLVMMajorVersion(cmakelist_42), "42"
122        )
123
124    def testParseLLVMMajorVersionInvalid(self):
125        invalid_cmakelist = "invalid cmakelist.txt contents"
126        with self.assertRaises(ValueError):
127            get_llvm_hash.ParseLLVMMajorVersion(invalid_cmakelist)
128
129    @mock.patch.object(get_llvm_hash, "GetAndUpdateLLVMProjectInLLVMTools")
130    @mock.patch.object(get_llvm_hash, "ParseLLVMMajorVersion")
131    @mock.patch.object(get_llvm_hash, "CheckCommand")
132    @mock.patch.object(get_llvm_hash, "CheckoutBranch")
133    @mock.patch(
134        "get_llvm_hash.open",
135        mock.mock_open(read_data="mock contents"),
136        create=True,
137    )
138    def testGetLLVMMajorVersion(
139        self,
140        mock_checkout_branch,
141        mock_git_checkout,
142        mock_major_version,
143        mock_llvm_project_path,
144    ):
145        mock_llvm_project_path.return_value = "path/to/llvm-project"
146        mock_major_version.return_value = "1234"
147        self.assertEqual(get_llvm_hash.GetLLVMMajorVersion("314159265"), "1234")
148        # Second call should be memoized
149        self.assertEqual(get_llvm_hash.GetLLVMMajorVersion("314159265"), "1234")
150        mock_llvm_project_path.assert_called_once()
151        mock_major_version.assert_called_with("mock contents")
152        mock_git_checkout.assert_called_once_with(
153            ["git", "-C", "path/to/llvm-project", "checkout", "314159265"]
154        )
155        mock_checkout_branch.assert_called_once_with(
156            "path/to/llvm-project", "main"
157        )
158
159
160if __name__ == "__main__":
161    unittest.main()
162