|
4 | 4 | import subprocess |
5 | 5 | import tempfile |
6 | 6 | import textwrap |
| 7 | +import tomllib |
7 | 8 | import unittest |
8 | 9 | from pathlib import Path |
9 | 10 | import re |
@@ -172,6 +173,141 @@ def test_repo_validates_managed_plugins_layout(self) -> None: |
172 | 173 | result = run_catalog("validate", str(REPO_ROOT)) |
173 | 174 | self.assertEqual(result.returncode, 0, result.stderr) |
174 | 175 |
|
| 176 | + def test_repo_centralizes_shared_cargo_dependencies(self) -> None: |
| 177 | + cargo = tomllib.loads((REPO_ROOT / "Cargo.toml").read_text()) |
| 178 | + workspace_deps = cargo["workspace"]["dependencies"] |
| 179 | + |
| 180 | + self.assertEqual( |
| 181 | + workspace_deps["cpex_framework_bridge"], |
| 182 | + {"path": "crates/framework_bridge"}, |
| 183 | + ) |
| 184 | + self.assertEqual( |
| 185 | + workspace_deps["criterion"], |
| 186 | + {"version": "0.8", "features": ["html_reports"]}, |
| 187 | + ) |
| 188 | + self.assertEqual(workspace_deps["log"], "0.4") |
| 189 | + self.assertEqual( |
| 190 | + workspace_deps["pyo3-async-runtimes"], |
| 191 | + {"version": "0.28", "features": ["tokio-runtime"]}, |
| 192 | + ) |
| 193 | + self.assertEqual( |
| 194 | + workspace_deps["pyo3"], |
| 195 | + {"version": "0.28.2", "features": ["abi3-py311"]}, |
| 196 | + ) |
| 197 | + self.assertEqual(workspace_deps["pyo3-log"], "0.13") |
| 198 | + self.assertEqual(workspace_deps["pyo3-stub-gen"], "0.20.0") |
| 199 | + self.assertEqual(workspace_deps["rand"], "0.8") |
| 200 | + self.assertEqual(workspace_deps["regex"], "1.12") |
| 201 | + self.assertEqual(workspace_deps["serde_json"], "1.0") |
| 202 | + self.assertEqual(workspace_deps["thiserror"], "2.0") |
| 203 | + self.assertEqual( |
| 204 | + workspace_deps["tokio"], |
| 205 | + {"version": "1", "features": ["full"]}, |
| 206 | + ) |
| 207 | + |
| 208 | + expected_plugin_deps = { |
| 209 | + "encoded_exfil_detection": { |
| 210 | + "dependencies": { |
| 211 | + "cpex_framework_bridge": {"workspace": True}, |
| 212 | + "log": {"workspace": True}, |
| 213 | + "pyo3": {"workspace": True}, |
| 214 | + "pyo3-log": {"workspace": True}, |
| 215 | + "pyo3-stub-gen": {"workspace": True}, |
| 216 | + "regex": {"workspace": True}, |
| 217 | + "serde_json": {"workspace": True}, |
| 218 | + }, |
| 219 | + "dev-dependencies": { |
| 220 | + "criterion": {"workspace": True}, |
| 221 | + }, |
| 222 | + }, |
| 223 | + "pii_filter": { |
| 224 | + "dependencies": { |
| 225 | + "cpex_framework_bridge": {"workspace": True}, |
| 226 | + "log": {"workspace": True}, |
| 227 | + "pyo3": {"workspace": True}, |
| 228 | + "pyo3-log": {"workspace": True}, |
| 229 | + "pyo3-stub-gen": {"workspace": True}, |
| 230 | + "regex": {"workspace": True}, |
| 231 | + "serde_json": {"workspace": True}, |
| 232 | + "thiserror": {"workspace": True}, |
| 233 | + }, |
| 234 | + "dev-dependencies": { |
| 235 | + "criterion": {"workspace": True}, |
| 236 | + }, |
| 237 | + }, |
| 238 | + "rate_limiter": { |
| 239 | + "dependencies": { |
| 240 | + "cpex_framework_bridge": {"workspace": True}, |
| 241 | + "log": {"workspace": True}, |
| 242 | + "pyo3": {"workspace": True}, |
| 243 | + "pyo3-async-runtimes": {"workspace": True}, |
| 244 | + "pyo3-log": {"workspace": True}, |
| 245 | + "pyo3-stub-gen": {"workspace": True}, |
| 246 | + "thiserror": {"workspace": True}, |
| 247 | + "tokio": {"workspace": True}, |
| 248 | + }, |
| 249 | + "dev-dependencies": { |
| 250 | + "criterion": {"workspace": True}, |
| 251 | + }, |
| 252 | + }, |
| 253 | + "retry_with_backoff": { |
| 254 | + "dependencies": { |
| 255 | + "log": {"workspace": True}, |
| 256 | + "pyo3": {"workspace": True}, |
| 257 | + "pyo3-log": {"workspace": True}, |
| 258 | + "pyo3-stub-gen": {"workspace": True}, |
| 259 | + "rand": {"workspace": True}, |
| 260 | + }, |
| 261 | + "dev-dependencies": {}, |
| 262 | + }, |
| 263 | + "secrets_detection": { |
| 264 | + "dependencies": { |
| 265 | + "cpex_framework_bridge": {"workspace": True}, |
| 266 | + "log": {"workspace": True}, |
| 267 | + "pyo3": {"workspace": True}, |
| 268 | + "pyo3-log": {"workspace": True}, |
| 269 | + "pyo3-stub-gen": {"workspace": True}, |
| 270 | + "regex": {"workspace": True}, |
| 271 | + "serde_json": {"workspace": True}, |
| 272 | + }, |
| 273 | + "dev-dependencies": { |
| 274 | + "criterion": {"workspace": True}, |
| 275 | + }, |
| 276 | + }, |
| 277 | + "url_reputation": { |
| 278 | + "dependencies": { |
| 279 | + "log": {"workspace": True}, |
| 280 | + "pyo3": {"workspace": True}, |
| 281 | + "pyo3-log": {"workspace": True}, |
| 282 | + "regex": {"workspace": True}, |
| 283 | + }, |
| 284 | + "dev-dependencies": { |
| 285 | + "criterion": {"workspace": True}, |
| 286 | + }, |
| 287 | + }, |
| 288 | + } |
| 289 | + |
| 290 | + for slug, expected_sections in expected_plugin_deps.items(): |
| 291 | + plugin_cargo = tomllib.loads( |
| 292 | + ( |
| 293 | + REPO_ROOT |
| 294 | + / "plugins" |
| 295 | + / "rust" |
| 296 | + / "python-package" |
| 297 | + / slug |
| 298 | + / "Cargo.toml" |
| 299 | + ).read_text() |
| 300 | + ) |
| 301 | + for section_name, expected_deps in expected_sections.items(): |
| 302 | + actual_section = plugin_cargo.get(section_name, {}) |
| 303 | + self.assertIsInstance(actual_section, dict) |
| 304 | + for dependency_name, expected_value in expected_deps.items(): |
| 305 | + self.assertEqual( |
| 306 | + actual_section.get(dependency_name), |
| 307 | + expected_value, |
| 308 | + f"{slug} should source {dependency_name} from workspace {section_name}", |
| 309 | + ) |
| 310 | + |
175 | 311 | def test_repo_lists_all_managed_plugins(self) -> None: |
176 | 312 | result = run_catalog("list", str(REPO_ROOT)) |
177 | 313 | self.assertEqual(result.returncode, 0, result.stderr) |
|
0 commit comments