"""Core conformance runner — detects capabilities, runs test suites, builds report.""" from __future__ import annotations from langgraph.checkpoint.conformance.capabilities import ( Capability, DetectedCapabilities, ) from langgraph.checkpoint.conformance.initializer import RegisteredCheckpointer from langgraph.checkpoint.conformance.report import ( CapabilityReport, CapabilityResult, ProgressCallbacks, ) from langgraph.checkpoint.conformance.spec.test_copy_thread import run_copy_thread_tests from langgraph.checkpoint.conformance.spec.test_delete_for_runs import ( run_delete_for_runs_tests, ) from langgraph.checkpoint.conformance.spec.test_delete_thread import ( run_delete_thread_tests, ) from langgraph.checkpoint.conformance.spec.test_delta_channel_history import ( run_delta_channel_history_tests, ) from langgraph.checkpoint.conformance.spec.test_get_tuple import run_get_tuple_tests from langgraph.checkpoint.conformance.spec.test_list import run_list_tests from langgraph.checkpoint.conformance.spec.test_prune import run_prune_tests from langgraph.checkpoint.conformance.spec.test_put import run_put_tests from langgraph.checkpoint.conformance.spec.test_put_writes import run_put_writes_tests # Maps capability to its runner function. _RUNNERS = { Capability.PUT: run_put_tests, Capability.PUT_WRITES: run_put_writes_tests, Capability.GET_TUPLE: run_get_tuple_tests, Capability.LIST: run_list_tests, Capability.DELETE_THREAD: run_delete_thread_tests, Capability.DELETE_FOR_RUNS: run_delete_for_runs_tests, Capability.COPY_THREAD: run_copy_thread_tests, Capability.PRUNE: run_prune_tests, Capability.DELTA_CHANNEL_HISTORY: run_delta_channel_history_tests, } async def validate( registered: RegisteredCheckpointer, *, capabilities: set[str] | None = None, progress: ProgressCallbacks | None = None, ) -> CapabilityReport: """Run the validation suite against a registered checkpointer. Args: registered: A RegisteredCheckpointer (from @checkpointer_test decorator). capabilities: If given, only run tests for these capability names. Otherwise, auto-detect and run all applicable tests. progress: Optional progress callbacks for incremental output. Use ``ProgressCallbacks.default()`` for dot-style, ``ProgressCallbacks.verbose()`` for per-test output, or ``None`` / ``ProgressCallbacks.quiet()`` for silent mode. Returns: A CapabilityReport with per-capability results. """ report = CapabilityReport(checkpointer_name=registered.name) # Determine which capabilities to test. caps_to_test: set[Capability] if capabilities is not None: caps_to_test = {Capability(c) for c in capabilities} else: caps_to_test = set(Capability) async with registered.enter_lifespan(): for cap in Capability: if cap in caps_to_test and cap.value not in registered.skip_capabilities: # Create a fresh checkpointer for each capability suite. async with registered.create() as saver: detected = DetectedCapabilities.from_instance(saver) is_detected = cap in detected.detected if not is_detected: if progress and progress.on_capability_start: progress.on_capability_start(cap.value, False) report.results[cap.value] = CapabilityResult( detected=False, passed=None, tests_skipped=1, ) continue runner = _RUNNERS.get(cap) if runner is None: report.results[cap.value] = CapabilityResult( detected=True, passed=None, tests_skipped=1, ) continue if progress and progress.on_capability_start: progress.on_capability_start(cap.value, True) passed, failed, failures = await runner( saver, on_test_result=progress.on_test_result if progress else None, ) if progress and progress.on_capability_end: progress.on_capability_end(cap.value) report.results[cap.value] = CapabilityResult( detected=True, passed=failed == 0, tests_passed=passed, tests_failed=failed, failures=failures, ) else: if progress and progress.on_capability_start: progress.on_capability_start(cap.value, False) report.results[cap.value] = CapabilityResult( detected=False, passed=None, tests_skipped=1, ) return report