Skip to content

Commit ab846ff

Browse files
committed
Add Profile Tests
1 parent fc67ca2 commit ab846ff

File tree

3 files changed

+138
-43
lines changed

3 files changed

+138
-43
lines changed

cppython/plugins/conan/plugin.py

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -109,27 +109,7 @@ def _install_dependencies(self, *, update: bool = False) -> None:
109109
logger.debug('Available remotes: %s', [remote.name for remote in all_remotes])
110110

111111
# Get default profiles, handle case when no default profile exists
112-
try:
113-
profile_host_path = conan_api.profiles.get_default_host()
114-
profile_build_path = conan_api.profiles.get_default_build()
115-
116-
# Ensure we have valid profile paths
117-
if profile_host_path is None:
118-
# Create a minimal default profile with basic settings if none exists
119-
profile_host = conan_api.profiles.detect()
120-
else:
121-
profile_host = conan_api.profiles.get_profile([profile_host_path])
122-
123-
if profile_build_path is None:
124-
# Create a minimal default profile with basic settings if none exists
125-
profile_build = conan_api.profiles.detect()
126-
else:
127-
profile_build = conan_api.profiles.get_profile([profile_build_path])
128-
129-
except Exception:
130-
# If profile operations fail, create minimal default profiles with basic settings
131-
profile_host = conan_api.profiles.detect()
132-
profile_build = conan_api.profiles.detect()
112+
profile_host, profile_build = self._resolve_profiles(conan_api)
133113

134114
logger.debug('Using profiles: host=%s, build=%s', profile_host, profile_build)
135115

@@ -267,27 +247,7 @@ def publish(self) -> None:
267247
)
268248

269249
# Step 2: Get default profiles, handle case when no default profile exists
270-
try:
271-
profile_host_path = conan_api.profiles.get_default_host()
272-
profile_build_path = conan_api.profiles.get_default_build()
273-
274-
# Ensure we have valid profile paths
275-
if profile_host_path is None:
276-
# Create a minimal default profile with basic settings if none exists
277-
profile_host = conan_api.profiles.detect()
278-
else:
279-
profile_host = conan_api.profiles.get_profile([profile_host_path])
280-
281-
if profile_build_path is None:
282-
# Create a minimal default profile with basic settings if none exists
283-
profile_build = conan_api.profiles.detect()
284-
else:
285-
profile_build = conan_api.profiles.get_profile([profile_build_path])
286-
287-
except Exception:
288-
# If profile operations fail, create minimal default profiles with basic settings
289-
profile_host = conan_api.profiles.detect()
290-
profile_build = conan_api.profiles.detect()
250+
profile_host, profile_build = self._resolve_profiles(conan_api)
291251

292252
# Step 3: Build dependency graph for the package
293253
deps_graph = conan_api.graph.load_graph_consumer(
@@ -339,3 +299,40 @@ def publish(self) -> None:
339299
)
340300
else:
341301
raise ProviderInstallationError('conan', 'No packages found to upload')
302+
303+
def _resolve_profiles(self, conan_api) -> tuple:
304+
"""Resolve host and build profiles with fallback to detect().
305+
306+
Args:
307+
conan_api: The Conan API instance
308+
309+
Returns:
310+
Tuple of (profile_host, profile_build)
311+
"""
312+
try:
313+
profile_host_path = conan_api.profiles.get_default_host()
314+
profile_build_path = conan_api.profiles.get_default_build()
315+
316+
# Resolve host profile
317+
if profile_host_path is None:
318+
profile_host = conan_api.profiles.detect()
319+
else:
320+
profile_host = conan_api.profiles.get_profile([profile_host_path])
321+
if profile_host is None:
322+
profile_host = conan_api.profiles.detect()
323+
324+
# Resolve build profile
325+
if profile_build_path is None:
326+
profile_build = conan_api.profiles.detect()
327+
else:
328+
profile_build = conan_api.profiles.get_profile([profile_build_path])
329+
if profile_build is None:
330+
profile_build = conan_api.profiles.detect()
331+
332+
return profile_host, profile_build
333+
334+
except Exception:
335+
# If profile operations fail, create minimal default profiles with basic settings
336+
profile_host = conan_api.profiles.detect()
337+
profile_build = conan_api.profiles.detect()
338+
return profile_host, profile_build

tests/unit/plugins/conan/test_install.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
from cppython.test.pytest.mixins import ProviderPluginTestMixin
1414
from cppython.utility.exception import ProviderInstallationError
1515

16+
# Constants for test assertions
17+
EXPECTED_PROFILE_CALLS = 2
18+
EXPECTED_GET_PROFILE_CALLS = 2
19+
1620
# Use shared fixtures
1721
pytest_plugins = ['tests.fixtures.conan']
1822

1923
# Constants for test verification
2024
EXPECTED_DEPENDENCY_COUNT = 2
21-
EXPECTED_PROFILE_CALLS = 2
2225

2326

2427
class TestConanInstall(ProviderPluginTestMixin[ConanProvider]):
@@ -255,3 +258,47 @@ def test_install_with_second_profile_exception_fallback(
255258
conan_mock_api.graph.load_graph_consumer.assert_called_once()
256259
conan_mock_api.install.install_binaries.assert_called_once()
257260
conan_mock_api.install.install_consumer.assert_called_once()
261+
262+
def test_install_with_get_profile_returning_none_fallback(
263+
self,
264+
plugin: ConanProvider,
265+
conan_temp_conanfile: Path,
266+
conan_mock_dependencies: list[Requirement],
267+
conan_setup_mocks: dict[str, Mock],
268+
conan_mock_api: Mock,
269+
) -> None:
270+
"""Test install method when get_profile returns None (profile file corrupted/invalid)
271+
272+
Args:
273+
plugin: The plugin instance
274+
conan_temp_conanfile: Path to temporary conanfile.py
275+
conan_mock_dependencies: List of mock dependencies
276+
conan_setup_mocks: Dictionary containing all mocks
277+
conan_mock_api: Mock ConanAPI instance
278+
"""
279+
# Configure profiles to exist but get_profile returns None (corrupted/invalid profile)
280+
conan_mock_api.profiles.get_default_host.return_value = '/path/to/host/profile'
281+
conan_mock_api.profiles.get_default_build.return_value = '/path/to/build/profile'
282+
conan_mock_api.profiles.get_profile.return_value = None # Profile file exists but is corrupted
283+
284+
# Setup dependencies
285+
plugin.core_data.cppython_data.dependencies = conan_mock_dependencies
286+
287+
# Execute - should not throw an exception despite get_profile returning None
288+
plugin.install()
289+
290+
# Verify that despite get_profile returning None, the fallback was used
291+
conan_setup_mocks['conan_api_constructor'].assert_called_once()
292+
conan_mock_api.profiles.get_default_host.assert_called_once()
293+
conan_mock_api.profiles.get_default_build.assert_called_once()
294+
295+
# Should call get_profile twice (once for host, once for build)
296+
assert conan_mock_api.profiles.get_profile.call_count == EXPECTED_GET_PROFILE_CALLS
297+
298+
# Verify fallback profile creation was called (should be called twice for detect)
299+
assert conan_mock_api.profiles.detect.call_count >= EXPECTED_PROFILE_CALLS
300+
301+
# Verify the rest of the process continued
302+
conan_mock_api.graph.load_graph_consumer.assert_called_once()
303+
conan_mock_api.install.install_binaries.assert_called_once()
304+
conan_mock_api.install.install_consumer.assert_called_once()

tests/unit/plugins/conan/test_publish.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Unit tests for the conan plugin publish functionality"""
22

3+
from pathlib import Path
34
from typing import Any
45
from unittest.mock import MagicMock, Mock
56

@@ -13,6 +14,9 @@
1314
# Use shared fixtures
1415
pytest_plugins = ['tests.fixtures.conan']
1516

17+
# Constants for test assertions
18+
EXPECTED_PROFILE_CALLS = 2
19+
1620

1721
class TestConanPublish(ProviderPluginTestMixin[ConanProvider]):
1822
"""Tests for the Conan provider publish functionality"""
@@ -282,3 +286,50 @@ def test_publish_list_pattern_creation(
282286

283287
# Verify ListPattern was created with correct reference pattern
284288
mock_list_pattern.assert_called_once_with(f'{ref.name}/*', package_id='*', only_recipe=False)
289+
290+
def test_publish_with_get_profile_returning_none_fallback(
291+
self,
292+
plugin: ConanProvider,
293+
conan_temp_conanfile: Path,
294+
conan_mock_api_publish: Mock,
295+
mocker: MockerFixture,
296+
) -> None:
297+
"""Test publish method when get_profile returns None (profile file corrupted/invalid)
298+
299+
Args:
300+
plugin: The plugin instance
301+
conan_temp_conanfile: Path to temporary conanfile.py
302+
conan_mock_api_publish: Mock ConanAPI instance configured for publish
303+
mocker: Pytest mocker fixture
304+
"""
305+
# Set plugin to local mode to avoid remote upload complications
306+
plugin.data = plugin.data.__class__(
307+
remotes=[],
308+
)
309+
310+
# Configure profiles to exist but get_profile returns None (corrupted/invalid profile)
311+
conan_mock_api_publish.profiles.get_default_host.return_value = '/path/to/host/profile'
312+
conan_mock_api_publish.profiles.get_default_build.return_value = '/path/to/build/profile'
313+
conan_mock_api_publish.profiles.get_profile.return_value = None # Profile file exists but is corrupted
314+
315+
# Mock ConanAPI constructor to return our configured mock
316+
mock_conan_api_constructor = mocker.patch(
317+
'cppython.plugins.conan.plugin.ConanAPI', return_value=conan_mock_api_publish
318+
)
319+
320+
# Execute - should not throw an exception despite get_profile returning None
321+
plugin.publish()
322+
323+
# Verify that despite get_profile returning None, the fallback was used
324+
mock_conan_api_constructor.assert_called_once()
325+
conan_mock_api_publish.profiles.get_default_host.assert_called_once()
326+
conan_mock_api_publish.profiles.get_default_build.assert_called_once()
327+
328+
# Should call get_profile twice (once for host, once for build)
329+
assert conan_mock_api_publish.profiles.get_profile.call_count == EXPECTED_PROFILE_CALLS
330+
331+
# Verify fallback profile creation was called (should be called twice for detect)
332+
assert conan_mock_api_publish.profiles.detect.call_count >= EXPECTED_PROFILE_CALLS
333+
334+
# Verify the rest of the process continued
335+
conan_mock_api_publish.export.export.assert_called_once()

0 commit comments

Comments
 (0)