forked from synodic/cppython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_install.py
More file actions
174 lines (139 loc) · 6.48 KB
/
test_install.py
File metadata and controls
174 lines (139 loc) · 6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
"""Unit tests for the conan plugin install functionality"""
from pathlib import Path
from typing import Any
from unittest.mock import Mock
import pytest
from packaging.requirements import Requirement
from pytest_mock import MockerFixture
from cppython.plugins.conan.plugin import ConanProvider
from cppython.plugins.conan.schema import ConanDependency
from cppython.test.pytest.mixins import ProviderPluginTestMixin
from cppython.utility.exception import ProviderInstallationError
# Constants for test assertions
EXPECTED_PROFILE_CALLS = 2
EXPECTED_GET_PROFILE_CALLS = 2
# Use shared fixtures
pytest_plugins = ['tests.fixtures.conan']
# Constants for test verification
EXPECTED_DEPENDENCY_COUNT = 2
class TestConanInstall(ProviderPluginTestMixin[ConanProvider]):
"""Tests for the Conan provider install functionality"""
@staticmethod
@pytest.fixture(name='plugin_data', scope='session')
def fixture_plugin_data() -> dict[str, Any]:
"""A required testing hook that allows data generation
Returns:
The constructed plugin data
"""
return {
'remotes': [],
}
@staticmethod
@pytest.fixture(name='plugin_type', scope='session')
def fixture_plugin_type() -> type[ConanProvider]:
"""A required testing hook that allows type generation
Returns:
The type of the Provider
"""
return ConanProvider
def test_with_dependencies(
self,
plugin: ConanProvider,
conan_temp_conanfile: Path,
conan_mock_dependencies: list[Requirement],
conan_setup_mocks: dict[str, Mock],
) -> None:
"""Test install method with dependencies and existing conanfile
Args:
plugin: The plugin instance
conan_temp_conanfile: Path to temporary conanfile.py
conan_mock_dependencies: List of mock dependencies
conan_setup_mocks: Dictionary containing all mocks
"""
# Setup dependencies
plugin.core_data.cppython_data.dependencies = conan_mock_dependencies
# Execute
plugin.install()
# Verify builder was called
conan_setup_mocks['builder'].generate_conanfile.assert_called_once()
assert (
conan_setup_mocks['builder'].generate_conanfile.call_args[0][0]
== plugin.core_data.project_data.project_root
)
assert len(conan_setup_mocks['builder'].generate_conanfile.call_args[0][1]) == EXPECTED_DEPENDENCY_COUNT
# Verify dependency resolution was called
assert conan_setup_mocks['resolve_conan_dependency'].call_count == EXPECTED_DEPENDENCY_COUNT
# Verify build path was created
assert plugin.core_data.cppython_data.build_path.exists()
# Verify ConanAPI constructor was called
conan_setup_mocks['conan_api_constructor'].assert_called_once()
def test_conan_command_failure(
self,
plugin: ConanProvider,
conan_temp_conanfile: Path,
conan_mock_dependencies: list[Requirement],
conan_mock_api: Mock,
mocker: MockerFixture,
) -> None:
"""Test install method when conan API operations fail
Args:
plugin: The plugin instance
conan_temp_conanfile: Path to temporary conanfile.py
conan_mock_dependencies: List of mock dependencies
conan_mock_api: Mock ConanAPI instance
mocker: Pytest mocker fixture
"""
# Mock builder
mock_builder = mocker.Mock()
mock_builder.generate_conanfile = mocker.Mock()
plugin.builder = mock_builder # type: ignore[attr-defined]
# Configure the API mock to fail on graph loading
conan_mock_api.graph.load_graph_consumer.side_effect = Exception('Conan API error: package not found')
# Mock ConanAPI constructor to return our configured mock
mock_conan_api_constructor = mocker.patch('cppython.plugins.conan.plugin.ConanAPI', return_value=conan_mock_api)
# Mock resolve_conan_dependency
def mock_resolve(requirement: Requirement) -> ConanDependency:
return ConanDependency(name=requirement.name)
mocker.patch('cppython.plugins.conan.plugin.resolve_conan_dependency', side_effect=mock_resolve)
# Add a dependency
plugin.core_data.cppython_data.dependencies = [conan_mock_dependencies[0]]
# Execute and verify exception is raised
with pytest.raises(
ProviderInstallationError,
match='Failed to load dependency graph: Conan API error: package not found',
):
plugin.install()
# Verify builder was still called
mock_builder.generate_conanfile.assert_called_once()
# Verify Conan API was attempted
mock_conan_api_constructor.assert_called_once()
def test_with_default_profiles(
self,
plugin: ConanProvider,
conan_temp_conanfile: Path,
conan_mock_dependencies: list[Requirement],
conan_setup_mocks: dict[str, Mock],
conan_mock_api: Mock,
) -> None:
"""Test install method uses pre-resolved profiles from plugin construction
Args:
plugin: The plugin instance
conan_temp_conanfile: Path to temporary conanfile.py
conan_mock_dependencies: List of mock dependencies
conan_setup_mocks: Dictionary containing all mocks
conan_mock_api: Mock ConanAPI instance
"""
# Setup dependencies
plugin.core_data.cppython_data.dependencies = conan_mock_dependencies
# Execute - should use the profiles resolved during plugin construction
plugin.install()
# Verify that the API was used for installation
conan_setup_mocks['conan_api_constructor'].assert_called_once()
# Verify the rest of the process continued with resolved profiles
conan_mock_api.graph.load_graph_consumer.assert_called_once()
conan_mock_api.install.install_binaries.assert_called_once()
conan_mock_api.install.install_consumer.assert_called_once()
# Verify that the resolved profiles were used in the graph loading
call_args = conan_mock_api.graph.load_graph_consumer.call_args
assert call_args.kwargs['profile_host'] == plugin.data.host_profile
assert call_args.kwargs['profile_build'] == plugin.data.build_profile