blob: 70922bdaba9d4c0e53bfd8a89f4722f66c237b11 [file] [log] [blame]
Trent Apted7d2777b2023-06-29 13:35:03 +10001# Copyright 2023 The ChromiumOS Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Unit tests for build_sdk_subtools."""
6
Trent Apted7d2777b2023-06-29 13:35:03 +10007from pathlib import Path
8from unittest import mock
9
10import pytest
11
12from chromite.lib import commandline
13from chromite.lib import cros_build_lib
14from chromite.scripts import build_sdk_subtools
15
16
17@pytest.fixture(name="outside_chroot")
18def outside_chroot_fixture():
19 """Mocks IsInsideChroot to be False."""
20 with mock.patch.object(
21 cros_build_lib, "IsInsideChroot", return_value=False
22 ) as outside_chroot:
23 yield outside_chroot
24
25
26@pytest.fixture(name="mock_emerge")
27def mock_emerge_fixture():
28 """Stubs the build_sdk_subtools emerge helper and sets it up to run."""
29 with mock.patch.multiple(
30 "chromite.scripts.build_sdk_subtools",
31 _run_system_emerge=mock.DEFAULT,
32 _is_inside_subtools_chroot=mock.DEFAULT,
33 ) as mocks:
34 mocks["_is_inside_subtools_chroot"].return_value = True
35 yield mocks["_run_system_emerge"]
36
37
38def test_must_run_outside_sdk(caplog) -> None:
39 """Tests build_sdk_subtools complains if run in the chroot."""
40 with pytest.raises(cros_build_lib.DieSystemExit) as error_info:
41 build_sdk_subtools.main()
42 assert error_info.value.code == 1
43 assert "build_sdk_subtools must be run outside the chroot" in caplog.text
44
45
46def test_cros_sdk(run_mock, outside_chroot) -> None:
47 """Tests the steps leading up to the cros_sdk invocation."""
48 # Fake a failure from cros_sdk to ensure it propagates.
49 run_mock.SetDefaultCmdResult(returncode=42)
50
51 assert build_sdk_subtools.main() == 42
52 assert outside_chroot.called
53 assert run_mock.call_count == 1
54 assert run_mock.call_args_list[0].args[0] == [
55 "cros_sdk",
56 "--chroot",
57 "/mnt/host/source/chroot/build/amd64-subtools-host",
58 "--create",
59 "--skip-chroot-upgrade",
60 ]
61
62
63def test_cros_sdk_clean(run_mock, outside_chroot) -> None:
64 """Tests steps leading up to the cros_sdk invocation with --clean."""
65 run_mock.SetDefaultCmdResult(returncode=42)
66
67 assert build_sdk_subtools.main(["--clean"]) == 42
68 assert outside_chroot.called
69 assert run_mock.call_count == 1
70 cros_sdk_cmd = run_mock.call_args_list[0].args[0]
71 assert cros_sdk_cmd[0] == "cros_sdk"
72 assert "--delete" in cros_sdk_cmd
73
74
75def test_cros_sdk_output_dir(run_mock, outside_chroot) -> None:
76 """Tests steps leading up to the cros_sdk invocation with --output-dir."""
77 run_mock.SetDefaultCmdResult(returncode=42)
78
79 assert build_sdk_subtools.main(["--output-dir", "/foo"]) == 42
80 assert outside_chroot.called
81 cros_sdk_cmd = run_mock.call_args_list[0].args[0]
82 chroot_arg_index = cros_sdk_cmd.index("/mnt/host/source/chroot/foo")
83 assert cros_sdk_cmd[0] == "cros_sdk"
84 assert cros_sdk_cmd[chroot_arg_index - 1] == "--chroot"
85
86
87def test_chroot_required_after_cros_sdk(run_mock, outside_chroot) -> None:
88 """Tests that build_sdk_subtools will ask for chroot when setup."""
89 with pytest.raises(commandline.ChrootRequiredError) as error_info:
90 build_sdk_subtools.main(["--no-setup-chroot"])
91
92 assert run_mock.call_count == 0
93 assert outside_chroot.called
94 assert error_info.value.cmd == ["build_sdk_subtools", "--no-setup-chroot"]
95 assert error_info.value.chroot_args == [
96 "--chroot",
97 "/mnt/host/source/chroot/build/amd64-subtools-host",
98 ]
99
100
101def test_chroots_into_output_dir(run_mock, outside_chroot) -> None:
102 """Tests that --output-dir is consumed properly after setup."""
103 with pytest.raises(commandline.ChrootRequiredError) as error_info:
104 build_sdk_subtools.main(["--no-setup-chroot", "--output-dir", "/foo"])
105
106 assert run_mock.call_count == 0
107 assert outside_chroot.called
108 assert error_info.value.chroot_args == [
109 "--chroot",
110 "/mnt/host/source/chroot/foo",
111 ]
112
113
114def test_setup_sdk_invocation(run_mock, outside_chroot) -> None:
115 """Tests the SDK setup invocation, before it becomes a subtools chroot."""
116 # Fake success from cros_sdk, failure from _setup_base_sdk().
117 run_mock.SetDefaultCmdResult(returncode=0)
118 run_mock.AddCmdResult(
119 ["sudo", "--", "build_sdk_subtools", "--relaunch-for-setup"],
120 returncode=42,
121 )
122
Trent Apted2d9111b2023-08-04 16:20:35 +1000123 assert build_sdk_subtools.main() == 42
Trent Apted7d2777b2023-06-29 13:35:03 +1000124 assert run_mock.call_count == 2
125 assert outside_chroot.called
126
127 sudo_run_cmd = run_mock.call_args_list[1]
128
129 assert sudo_run_cmd.args[0] == [
130 "sudo",
131 "--",
132 "build_sdk_subtools",
133 "--relaunch-for-setup",
134 ]
135 assert sudo_run_cmd.kwargs["enter_chroot"] is True
136 assert sudo_run_cmd.kwargs["chroot_args"] == [
137 "--chroot",
138 "/mnt/host/source/chroot/build/amd64-subtools-host",
139 ]
140 # Stop here: Actually running `--relaunch-for-setup` principally wants to
141 # mutate the SDK state as root, which is too messy as a unit test.
142
143
144def test_default_package(mock_emerge) -> None:
145 """Tests a default virtual package is provided to update packages."""
146 assert build_sdk_subtools.main() == 0
147 assert mock_emerge.call_count == 1
148 emerge_cmd = mock_emerge.call_args.args[0]
149 assert Path("/mnt/host/source/chromite/bin/parallel_emerge") in emerge_cmd
150 assert emerge_cmd[-1] == "virtual/target-sdk-subtools"
151
152
153def test_provided_package(mock_emerge) -> None:
154 """Tests the default package can be passed in from command line."""
155 assert build_sdk_subtools.main(["vim"]) == 0
156 assert mock_emerge.call_args.args[0][-1] == "vim"
157
158
159def test_skip_package_update(mock_emerge) -> None:
160 """Tests --skip-package-update will not try to emerge anything."""
161 assert build_sdk_subtools.main(["--no-update-packages"]) == 0
162 assert mock_emerge.call_count == 0