grammar-inference-engine/tests/test_decompose.py

128 lines
3.7 KiB
Python
Raw Normal View History

"""Tests for decomposition forest."""
import pytest
from bex.decompose import (
decompose_sequence,
decompose_all,
decompose_with_coverage,
get_decomposition_stats,
)
class TestDecomposeSequence:
"""Test sequence decomposition."""
def test_short_sequence(self):
seq = ["if", "return"]
result = decompose_sequence(seq, max_length=5)
# Short sequences returned as-is
assert result == [seq]
def test_empty_sequence(self):
result = decompose_sequence([], max_length=5)
assert result == []
def test_long_sequence(self):
seq = ["if", "return", "if", "return", "if", "return"]
result = decompose_sequence(seq, max_length=3)
# Should have prefixes, suffixes, and windows
assert len(result) > 0
# All fragments should be <= max_length
for frag in result:
assert len(frag) <= 3
def test_prefixes(self):
seq = ["a", "b", "c", "d"]
result = decompose_sequence(seq, max_length=2)
# Should include prefixes: [a], [a,b]
assert ["a"] in result
assert ["a", "b"] in result
def test_suffixes(self):
seq = ["a", "b", "c", "d"]
result = decompose_sequence(seq, max_length=2)
# Should include suffixes: [d], [c,d]
assert ["d"] in result
assert ["c", "d"] in result
def test_windows(self):
seq = ["a", "b", "c", "d", "e"]
result = decompose_sequence(seq, max_length=3)
# Should include windows: [a,b,c], [b,c,d], [c,d,e]
assert ["a", "b", "c"] in result
assert ["b", "c", "d"] in result
assert ["c", "d", "e"] in result
class TestDecomposeAll:
"""Test decomposing multiple sequences."""
def test_basic(self):
seqs = [
["if", "return", "if"],
["while", "return"],
]
result = decompose_all(seqs, max_length=2)
# Should have fragments from both sequences
assert len(result) > len(seqs)
def test_empty(self):
result = decompose_all([], max_length=5)
assert result == []
class TestDecomposeWithCoverage:
"""Test decomposition with coverage filtering."""
def test_filter_rare(self):
seqs = [
["if", "return", "if", "return"],
["if", "return", "if", "return"],
["if", "return", "if", "return"],
["rare", "other", "rare", "other"], # Only 1/4 have "rare"
]
result = decompose_with_coverage(seqs, max_length=2, min_coverage=0.5)
# "rare" fragments should be filtered out
result_strs = [str(f) for f in result]
assert not any("rare" in s for s in result_strs)
def test_keep_common(self):
seqs = [
["if", "return", "if"],
["if", "return", "if"],
["if", "return", "if"],
]
result = decompose_with_coverage(seqs, max_length=2, min_coverage=0.5)
# "if" and "return" fragments should be kept
result_strs = [str(f) for f in result]
assert any("if" in s for s in result_strs)
assert any("return" in s for s in result_strs)
class TestDecompositionStats:
"""Test decomposition statistics."""
def test_basic(self):
seqs = [
["if", "return", "if", "return"],
["while", "return"],
]
stats = get_decomposition_stats(seqs, max_length=2)
assert stats['n_original'] == 2
assert stats['n_fragments'] > 2
assert stats['expansion_ratio'] > 1
def test_empty(self):
stats = get_decomposition_stats([], max_length=5)
assert stats['n_original'] == 0
assert stats['n_fragments'] == 0