#!/bin/bash set -e echo "=== MetaCA Studio Test Suite ===" python3 -c " from metaca import CARule, CAGrid, TournamentSelector # Test 1: CARule creation and fingerprinting print('Test 1: CARule fingerprint...') rule = CARule( rule_id='test-rule', neighborhood='moore', states=2, transition_table={'0:3': 1, '1:2': 1, '1:3': 1}, origin_agent='test-agent' ) fp = rule.fingerprint() assert len(fp) == 16, f'Expected 16-char fingerprint, got {len(fp)}' assert fp == rule.fingerprint(), 'Fingerprint must be deterministic' print(f' PASS (fingerprint={fp})') # Test 2: CAGrid initialization print('Test 2: Grid initialization...') grid = CAGrid(10, 10, states=2) assert grid.population() == 0, 'Empty grid should have 0 population' assert grid.density() == 0.0, 'Empty grid should have 0 density' print(' PASS') # Test 3: Cell operations with wrapping print('Test 3: Cell set/get with toroidal wrapping...') grid.set_cell(0, 0, 1) assert grid.get_cell(0, 0) == 1 assert grid.get_cell(10, 10) == 1, 'Toroidal wrap failed' assert grid.population() == 1 print(' PASS') # Test 4: Moore neighborhood print('Test 4: Moore neighborhood...') neighbors = grid.get_moore_neighbors(1, 1) assert len(neighbors) == 8, f'Moore should return 8 neighbors, got {len(neighbors)}' print(' PASS') # Test 5: Von Neumann neighborhood print('Test 5: Von Neumann neighborhood...') neighbors = grid.get_vonneumann_neighbors(1, 1) assert len(neighbors) == 4, f'VN should return 4 neighbors, got {len(neighbors)}' print(' PASS') # Test 6: Game of Life step (B3/S23) print('Test 6: Game of Life simulation step...') life_rule = CARule( rule_id='game-of-life', neighborhood='moore', states=2, transition_table={'0:3': 1, '1:2': 1, '1:3': 1} ) grid2 = CAGrid(5, 5) # Blinker pattern grid2.set_cell(1, 2, 1) grid2.set_cell(2, 2, 1) grid2.set_cell(3, 2, 1) assert grid2.population() == 3 next_gen = grid2.step(life_rule) assert next_gen.population() == 3, f'Blinker should preserve population, got {next_gen.population()}' assert next_gen.get_cell(2, 1) == 1, 'Blinker should rotate' assert next_gen.get_cell(2, 3) == 1, 'Blinker should rotate' print(' PASS') # Test 7: Tournament selector print('Test 7: Tournament selection...') selector = TournamentSelector(tournament_size=2) for i in range(5): r = CARule(rule_id=f'r{i}', neighborhood='moore', states=2, transition_table={'0:3': 1}, fitness=float(i)) selector.add_rule(r) top = selector.top_k(3) assert len(top) == 3 assert top[0].fitness == 4.0, 'Top rule should have highest fitness' print(' PASS') # Test 8: Merge remote rules with dedup print('Test 8: Federated merge with dedup...') remote = [CARule(rule_id='r0-dup', neighborhood='moore', states=2, transition_table={'0:3': 1}, fitness=10.0)] before = len(selector.population) selector.merge_remote(remote) after = len(selector.population) assert after == before, f'Duplicate rule should not increase population ({before} -> {after})' print(' PASS') # Test 9: Serialization roundtrip print('Test 9: Serialization roundtrip...') d = rule.to_dict() restored = CARule.from_dict(d) assert restored.fingerprint() == rule.fingerprint() print(' PASS') print() print('All 9 tests passed!') " echo "=== All tests passed ==="