"""Shared pytest configuration for OpsBridge tests. Registers capability and access_mode marks, and provides the collect_capability_coverage() helper used by the cross-mode meta-test. """ from __future__ import annotations import textwrap from typing import Iterable import pytest # --------------------------------------------------------------------------- # Shared fixtures # --------------------------------------------------------------------------- VALID_CONFIG = textwrap.dedent("""\ tunnels: test-tunnel: host: host.local remote_port: 18000 local_port: 8000 ssh_user: ubuntu ssh_key: ~/.ssh/id_ops actor: adm-bernd actors: adm-bernd: class: adm description: Bernd """) VALID_CONFIG_WITH_CATALOG = textwrap.dedent("""\ tunnels: test-tunnel: host: host.local remote_port: 18000 local_port: 8000 ssh_user: ubuntu ssh_key: ~/.ssh/id_ops actor: adm-bernd actors: adm-bernd: class: adm description: Bernd catalog_path: {catalog_path} """) @pytest.fixture def config_file(tmp_path): f = tmp_path / "tunnels.yaml" f.write_text(VALID_CONFIG) return f @pytest.fixture def state_dir(tmp_path): d = tmp_path / "state" d.mkdir() return d @pytest.fixture def catalog_dir(tmp_path): """Minimal catalog directory with one domain, target, and bridge.""" cat = tmp_path / "catalog" domain_dir = cat / "domains" / "coulombcore" domain_dir.mkdir(parents=True) (domain_dir / "domain.yaml").write_text(textwrap.dedent("""\ type: domain id: coulombcore name: CoulombCore Infrastructure description: Core infrastructure domain environment: production """)) targets_dir = domain_dir / "targets" targets_dir.mkdir() (targets_dir / "state-hub.yaml").write_text(textwrap.dedent("""\ type: target id: state-hub domain: coulombcore kind: service description: Infrastructure state coordination service reachable_via: - state-hub-coulombcore """)) bridges_dir = domain_dir / "bridges" bridges_dir.mkdir() (bridges_dir / "state-hub-coulombcore.yaml").write_text(textwrap.dedent("""\ type: bridge id: state-hub-coulombcore domain: coulombcore target: state-hub description: Bridge to state hub access_method: ssh-reverse host: coulombcore.local remote_port: 18000 local_port: 8000 ssh_user: ubuntu ssh_key: ~/.ssh/id_ops actor: agent.claude-coulombcore reconnect: max_attempts: 0 backoff_initial: 5 backoff_max: 60 """)) actors_dir = cat / "actors" actors_dir.mkdir() (actors_dir / "agent.yaml").write_text(textwrap.dedent("""\ type: actor id: agent.claude-coulombcore class: automation description: Claude Code agent on CoulombCore """)) return cat @pytest.fixture def config_file_with_catalog(tmp_path, catalog_dir): f = tmp_path / "tunnels.yaml" f.write_text(VALID_CONFIG_WITH_CATALOG.format(catalog_path=str(catalog_dir))) return f # --------------------------------------------------------------------------- # Coverage collector helper # --------------------------------------------------------------------------- def collect_capability_coverage(items: Iterable) -> set[tuple[str, str]]: """Walk pytest items and return set of (capability_name, access_mode) pairs. Each test item is inspected for `capability` and `access_mode` markers. A pair is added for every combination of capability × access_mode marks found on a single item. Args: items: Iterable of pytest.Item objects (from session.items or similar). Returns: Set of (capability_name, access_mode) tuples found across all items. """ covered: set[tuple[str, str]] = set() for item in items: capabilities = [ m.args[0] for m in item.iter_markers("capability") if m.args ] modes = [ m.args[0] for m in item.iter_markers("access_mode") if m.args ] for cap in capabilities: for mode in modes: covered.add((cap, mode)) return covered