Metastatic.Test.AdapterHelper
(Metastatic v0.10.4)
View Source
Testing utilities for language adapters (M1 ↔ M2 transformations).
Provides macros and helper functions to test adapter round-trip fidelity, validate conformance, and measure transformation quality.
M1 ↔ M2 Round-Trip Testing
A round-trip test validates the following pipeline:
Source → M1 → M2 → M1 → SourceWhere:
- Source → M1:
adapter.parse/1 - M1 → M2:
adapter.to_meta/1 - M2 → M1:
adapter.from_meta/2 - M1 → Source:
adapter.unparse/1
Fidelity Metrics
- Exact match: Source output matches input exactly
- Semantic match: ASTs match even if formatting differs
- Partial match: Core structure preserved but details lost
Usage
defmodule MyAdapterTest do
use ExUnit.Case
import Metastatic.Test.AdapterHelper
test "round-trip simple arithmetic" do
source = "x + 5"
assert_round_trip(MyAdapter, source)
end
test "validates M2 conformance" do
source = "x + 5"
assert_valid_meta_ast(MyAdapter, source)
end
end
Summary
Functions
Assert that source code round-trips successfully through the adapter.
Assert that source code produces a valid MetaAST.
Assert that MetaAST can be reified back to source.
Calculate round-trip fidelity score.
Load test fixtures from a directory.
Measure adapter performance.
Functions
Assert that source code round-trips successfully through the adapter.
Validates: Source → M1 → M2 → M1 → Source
Options
:exact- Require exact source match (default:false):semantic- Allow formatting differences (default:true)
Examples
assert_round_trip(MyAdapter, "x + 5")
assert_round_trip(MyAdapter, "x + 5", exact: true)
@spec assert_valid_meta_ast(module(), String.t(), keyword()) :: Metastatic.Document.t()
Assert that source code produces a valid MetaAST.
Validates: Source → M1 → M2 and checks M2 conformance.
Options
:mode- Validation mode (:strict,:standard,:permissive):max_depth- Maximum allowed AST depth:max_nodes- Maximum allowed node count
Examples
assert_valid_meta_ast(MyAdapter, "x + 5")
assert_valid_meta_ast(MyAdapter, "x + 5", mode: :strict)
@spec assert_valid_reification(module(), Metastatic.AST.meta_ast(), map()) :: String.t()
Assert that MetaAST can be reified back to source.
Validates: M2 → M1 → Source
Examples
ast = {:binary_op, :arithmetic, :+, {:variable, "x"}, {:literal, :integer, 5}}
assert_valid_reification(MyAdapter, ast, %{})
Calculate round-trip fidelity score.
Returns a percentage (0.0 to 100.0) representing how closely the round-trip output matches the input.
Examples
fidelity = calculate_fidelity(original, round_trip_result)
# => 95.5
Load test fixtures from a directory.
Expects a directory structure like:
fixtures/
├── python/
│ ├── simple_arithmetic.py
│ ├── list_comprehension.py
│ └── expected/
│ ├── simple_arithmetic.exs
│ └── list_comprehension.exsReturns a list of {source_file, source_code, expected_meta_ast} tuples.
Examples
fixtures = load_fixtures("test/fixtures/python")
Measure adapter performance.
Returns timing information for each stage of the transformation pipeline.
Examples
metrics = measure_performance(MyAdapter, source)
# => %{
# parse_time_us: 150,
# to_meta_time_us: 200,
# from_meta_time_us: 180,
# unparse_time_us: 120,
# total_time_us: 650
# }