import pattern_core
def test_para_atomic_pattern():
atomic = pattern_core.Pattern.point(5)
result = atomic.para(lambda p, rs: p.value + sum(rs))
assert result == 5, f"Expected 5, got {result}"
def test_para_simple_pattern():
pattern = pattern_core.Pattern.pattern(1, [
pattern_core.Pattern.point(2),
pattern_core.Pattern.point(3)
])
result = pattern.para(lambda p, rs: p.value + sum(rs))
assert result == 6, f"Expected 6, got {result}"
def test_para_nested_pattern():
pattern = pattern_core.Pattern.pattern(1, [
pattern_core.Pattern.point(2),
pattern_core.Pattern.pattern(3, [
pattern_core.Pattern.point(4)
])
])
result = pattern.para(lambda p, rs: p.value + sum(rs))
assert result == 10, f"Expected 10, got {result}"
def test_para_fold_parity():
pattern = pattern_core.Pattern.pattern(10, [
pattern_core.Pattern.point(20),
pattern_core.Pattern.point(30),
pattern_core.Pattern.pattern(40, [
pattern_core.Pattern.point(50)
])
])
para_result = pattern.para(lambda p, rs: p.value + sum(rs))
fold_result = pattern.fold(0, lambda acc, v: acc + v)
assert para_result == fold_result, f"Para {para_result} != Fold {fold_result}"
assert para_result == 150, f"Expected 150, got {para_result}"
def test_para_multi_statistics():
pattern = pattern_core.Pattern.pattern(1, [
pattern_core.Pattern.point(2),
pattern_core.Pattern.pattern(3, [
pattern_core.Pattern.point(4)
])
])
def compute_stats(p, element_stats):
if not element_stats:
return (p.value, 1, 0)
elem_sum = sum(s[0] for s in element_stats)
elem_count = sum(s[1] for s in element_stats)
elem_max_depth = max(s[2] for s in element_stats)
total_sum = p.value + elem_sum
total_count = 1 + elem_count
max_depth = 1 + elem_max_depth
return (total_sum, total_count, max_depth)
result = pattern.para(compute_stats)
assert result == (10, 4, 2), f"Expected (10, 4, 2), got {result}"
def test_para_structure_preserving_transformation():
pattern = pattern_core.Pattern.pattern(1, [
pattern_core.Pattern.point(2),
pattern_core.Pattern.pattern(3, [
pattern_core.Pattern.point(4)
])
])
def double_values(p, transformed_elements):
new_value = p.value * 2
if not transformed_elements:
return pattern_core.Pattern.point(new_value)
else:
return pattern_core.Pattern.pattern(new_value, transformed_elements)
transformed = pattern.para(double_values)
assert transformed.value == 2, f"Root value should be 2, got {transformed.value}"
assert len(transformed.elements) == 2, "Root should have 2 elements"
assert transformed.elements[0].value == 4
assert transformed.elements[0].is_atomic()
assert transformed.elements[1].value == 6
assert len(transformed.elements[1].elements) == 1
assert transformed.elements[1].elements[0].value == 8
def test_para_access_to_pattern_structure():
pattern = pattern_core.Pattern.pattern("root", [
pattern_core.Pattern.point("a"),
pattern_core.Pattern.point("b")
])
def check_structure(p, rs):
assert hasattr(p, 'value')
assert hasattr(p, 'elements')
assert hasattr(p, 'is_atomic')
assert hasattr(p, 'length')
if p.value == "root":
assert not p.is_atomic()
assert p.length() == 2
else:
assert p.is_atomic()
assert p.length() == 0
return 1
result = pattern.para(check_structure)
assert result == 1
def test_para_with_subject_values():
alice = pattern_core.Subject(
identity="alice",
labels={"Person"},
properties={"age": pattern_core.Value.int(30)}
)
bob = pattern_core.Subject(
identity="bob",
labels={"Person"},
properties={"age": pattern_core.Value.int(25)}
)
pattern = pattern_core.Pattern.pattern(alice, [
pattern_core.Pattern.point(bob)
])
def count_people(p, counts):
count = 1 if p.value.has_label("Person") else 0
return count + sum(counts)
result = pattern.para(count_people)
assert result == 2, f"Expected 2 people, got {result}"
if __name__ == "__main__":
test_para_atomic_pattern()
test_para_simple_pattern()
test_para_nested_pattern()
test_para_fold_parity()
test_para_multi_statistics()
test_para_structure_preserving_transformation()
test_para_access_to_pattern_structure()
test_para_with_subject_values()
print("✓ All paramorphism tests passed!")