44# For a copy, see <https://opensource.org/license/bsd-3-clause>.
55
66import json
7- from collections .abc import Generator
7+ from collections .abc import Generator , Mapping
88from contextlib import contextmanager
9+ from dataclasses import dataclass
910from pathlib import Path
1011from textwrap import dedent
1112
13+ from cpp_dev .common .types import CppStandard
1214from cpp_dev .common .utils import ensure_dir_exists
1315from cpp_dev .dependency .conan .command_wrapper import conan_create , conan_upload
1416from cpp_dev .dependency .conan .setup import CONAN_REMOTE , initialize_conan
1517from cpp_dev .dependency .conan .types import ConanPackageReference
1618from cpp_dev .dependency .conan .utils import conan_env
19+ from tests .cpp_dev .dependency .conan .utils .server import (
20+ ConanServer , launch_conan_test_server )
1721
1822###############################################################################
1923# Public API ###
2024###############################################################################
2125
26+ FileSpec = Mapping [Path , str ]
27+
28+ @dataclass
29+ class ConanTestPackage :
30+ ref : ConanPackageReference
31+ dependencies : list [ConanPackageReference ]
32+ cpp_standard : CppStandard
33+ bin_files : FileSpec | None = None
34+ lib_files : FileSpec | None = None
35+ include_files : FileSpec | None = None
36+
37+
2238class ConanTestEnv :
2339 """A Conan environment for testing."""
2440
25- def __init__ (self , conan_dir : Path , profile : str ) -> None :
26- self ._conan_dir = conan_dir
27- self ._package_dir = conan_dir / ".conan_test_env "
41+ def __init__ (self , conan_home_dir : Path , profile : str , server : ConanServer ) -> None :
42+ self ._conan_home_dir = conan_home_dir
43+ self ._package_dir = conan_home_dir / ".conan_package_creation "
2844 ensure_dir_exists (self ._package_dir )
2945 self ._profile = profile
46+ self ._server = server
3047
31- def create_and_upload_package (self , ref : ConanPackageReference , dependencies : list [ConanPackageReference ]) -> None :
48+ def create_and_upload_packages (self , packages : list [ConanTestPackage ]) -> None :
3249 """Create and upload a Conan package for testing."""
33- _create_and_upload_conan_package (self ._package_dir , ref , dependencies , self ._profile )
50+ for package in packages :
51+ _create_and_upload_conan_package (self ._package_dir , package , self ._profile )
3452
3553 @property
36- def conan_dir (self ) -> Path :
54+ def conan_home_dir (self ) -> Path :
3755 """Return the base directory of the Conan environment."""
38- return self ._conan_dir
56+ return self ._conan_home_dir
3957
4058 @property
4159 def profile (self ) -> str :
4260 """Return the profile used for testing."""
4361 return self ._profile
62+
63+ @property
64+ def server (self ) -> ConanServer :
65+ """Return the server used for testing."""
66+ return self ._server
4467
4568
4669@contextmanager
47- def create_conan_env ( conan_dir : Path , server_http_port : int ) -> Generator [ConanTestEnv ]:
70+ def create_conan_test_env ( base_dir : Path , server_http_port : int , packages : list [ ConanTestPackage ] ) -> Generator [ConanTestEnv ]:
4871 """Create a Conan environment for testing."""
49- ensure_dir_exists (conan_dir )
50- source_config_path , profile = _create_conan_source_config (conan_dir , server_http_port )
51- initialize_conan (conan_dir , source_config_path )
52- with conan_env (conan_dir ):
53- yield ConanTestEnv (conan_dir , profile )
72+
73+ # create the home for the conan server
74+ conan_server_dir = base_dir / "server"
75+ ensure_dir_exists (conan_server_dir )
76+ with launch_conan_test_server (conan_server_dir , server_http_port ) as server :
77+ # create the home for the conan client
78+ conan_home_dir = base_dir / "conan_home"
79+ ensure_dir_exists (conan_home_dir )
80+ source_config_path , profile = _create_conan_source_config (conan_home_dir , server_http_port )
81+ initialize_conan (conan_home_dir , source_config_path )
82+
83+ with conan_env (conan_home_dir ):
84+ conan_test_env = ConanTestEnv (conan_home_dir , profile , server )
85+ conan_test_env .create_and_upload_packages (packages )
86+ yield conan_test_env
5487
5588
5689###############################################################################
@@ -101,13 +134,13 @@ def _create_conan_source_config(conan_dir: Path, server_http_port: int) -> tuple
101134 return source_config_path , PROFILE_NAME
102135
103136
104- def _create_and_upload_conan_package (base_dir : Path , ref : ConanPackageReference , dependencies : list [ ConanPackageReference ] , profile : str ) -> None :
105- package_dir = base_dir / f"{ ref .name } _{ ref .version } "
137+ def _create_and_upload_conan_package (base_dir : Path , package : ConanTestPackage , profile : str ) -> None :
138+ package_dir = base_dir / f"{ package . ref .name } _{ package . ref .version } "
106139 ensure_dir_exists (package_dir )
107140
108141 conanfile_path = package_dir / "conanfile.py"
109142
110- requirements = "," .join ([f"\" { dep } \" " for dep in dependencies ])
143+ requirements = "," .join ([f"\" { dep } \" " for dep in package . dependencies ])
111144 conanfile_path .write_text (dedent (
112145 """
113146 from conan import ConanFile
@@ -120,11 +153,11 @@ class TestConan(ConanFile):
120153
121154 {requirements}
122155 """ .format (
123- name = ref .name ,
124- user = ref .user ,
125- version = ref .version ,
126- requirements = f"requires = { requirements } " if dependencies else ""
156+ name = package . ref .name ,
157+ user = package . ref .user ,
158+ version = package . ref .version ,
159+ requirements = f"requires = { requirements } " if package . dependencies else ""
127160 )
128161 ))
129162 conan_create (package_dir , profile )
130- conan_upload (ref , CONAN_REMOTE )
163+ conan_upload (package . ref , CONAN_REMOTE )
0 commit comments