blob: 4f2cf39e58ef4af13047571ddad8c9384997fd41 [file] [log] [blame]
Trent Aptedbd3cb412023-08-18 11:37:02 +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 the sdk_subtools api layer."""
6
7import os
8from typing import Dict, Iterator, Optional, Union
9from unittest import mock
10
11import pytest
12
13from chromite.api import api_config
14from chromite.api.controller import sdk_subtools
15from chromite.api.gen.chromite.api import sdk_subtools_pb2
16from chromite.lib import cros_build_lib
17from chromite.lib import sysroot_lib
18from chromite.lib.parser import package_info
19
20
21def make_request(
22 chroot_path: Union[str, os.PathLike, None] = "fake_chroot_path"
23) -> sdk_subtools_pb2.BuildSdkSubtoolsRequest:
24 """Helper to build a request message."""
25 request = sdk_subtools_pb2.BuildSdkSubtoolsRequest()
26 if chroot_path is not None:
27 request.chroot.path = os.fspath(chroot_path)
28 return request
29
30
31def build_sdk_subtools(
32 request: sdk_subtools_pb2.BuildSdkSubtoolsRequest,
33 call_type: Optional[int] = api_config.ApiConfig.CALL_TYPE_EXECUTE,
34) -> sdk_subtools_pb2.BuildSdkSubtoolsResponse:
35 """Invokes sdk_subtools.BuildSdkSubtools and return the response proto."""
36 config = api_config.ApiConfig(call_type)
37 response = sdk_subtools_pb2.BuildSdkSubtoolsResponse()
38 sdk_subtools.BuildSdkSubtools(request, response, config)
39 return response
40
41
42MockService = Dict[str, mock.MagicMock]
43
44
45@pytest.fixture(name="mock_service")
46def mock_service_fixture() -> Iterator[MockService]:
47 """Mocks the sdk_subtools service layer with mocks."""
48 with mock.patch.multiple(
49 "chromite.service.sdk_subtools",
50 setup_base_sdk=mock.DEFAULT,
51 update_packages=mock.DEFAULT,
52 bundle_and_export=mock.DEFAULT,
53 ) as dict_of_mocks:
54 yield dict_of_mocks
55
56
57def test_validate_only(mock_service: MockService) -> None:
58 """Verify a validate-only call does not execute any logic."""
59 build_sdk_subtools(
60 make_request(), api_config.ApiConfig.CALL_TYPE_VALIDATE_ONLY
61 )
62 for f in mock_service.values():
63 f.assert_not_called()
64
65
66def test_mock_call(mock_service: MockService) -> None:
67 """Consistency check that a mock call does not execute any logic."""
68 build_sdk_subtools(
69 make_request(), api_config.ApiConfig.CALL_TYPE_MOCK_SUCCESS
70 )
71 for f in mock_service.values():
72 f.assert_not_called()
73
74
75def test_success(mock_service: MockService) -> None:
76 """Test the successful call output handling."""
77 response = build_sdk_subtools(make_request())
78 mock_service["setup_base_sdk"].assert_called_once()
79 mock_service["update_packages"].assert_called_once()
80 mock_service["bundle_and_export"].assert_called_once()
81 assert not response.failed_package_data
82
83
84def test_package_update_failure(mock_service: MockService) -> None:
85 """Test output handling when package update fails."""
86 mock_service[
87 "update_packages"
88 ].side_effect = sysroot_lib.PackageInstallError(
89 "mock failure",
90 cros_build_lib.CompletedProcess(),
91 packages=[package_info.parse("some-category/some-package-0.42-r43")],
92 )
93 response = build_sdk_subtools(make_request())
94 mock_service["setup_base_sdk"].assert_called_once()
95 mock_service["update_packages"].assert_called_once()
96 mock_service["bundle_and_export"].assert_not_called()
97 assert len(response.failed_package_data) == 1
98 assert response.failed_package_data[0].name.package_name == "some-package"
99 assert response.failed_package_data[0].name.category == "some-category"
100 assert response.failed_package_data[0].name.version == "0.42-r43"