Test harness & some refactoring

This commit is contained in:
2026-04-10 14:06:08 +01:00
parent 363446821e
commit 5df8d6aeb9
46 changed files with 478 additions and 305 deletions

View File

@@ -0,0 +1,8 @@
Using BDD-based Bounded Model Checking
Formula (((EF(E< proc0.allowed >X(proc0.in)) AND EF(E< proc1.allowed >X(proc1.in))) AND EF(E< proc2.allowed >X(proc2.in))) AND EF(E< proc3.allowed >X(proc3.in))) holds
Using BDD-based Bounded Model Checking
Formula EF((((proc0.approach AND proc1.approach) AND proc2.approach) AND proc3.approach)) holds
Using BDD-based Bounded Model Checking
Formula AG((proc0.in IMPLIES K[proc0](((~proc1.in AND ~proc2.in) AND ~proc3.in)))) holds
Using BDD-based Bounded Model Checking
Formula AG((proc0.in IMPLIES C[proc0 proc1 proc2 proc3](((~proc1.in AND ~proc2.in) AND ~proc3.in)))) holds

View File

@@ -0,0 +1,58 @@
# Context entities: out allowed
# Reactions:
. proc = "proc0":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc1":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc2":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc3":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
# Context Automaton States:
= Init state: init
* init
* green
* red
* T
# Context Automaton Transitions:
* [init -> green]: { proc0={ out } proc1={ out } proc2={ out } proc3={ out } }
* [green -> red]: { proc0={ allowed } } proc0.req
* [green -> red]: { proc1={ allowed } } proc1.req
* [green -> red]: { proc2={ allowed } } proc2.req
* [green -> red]: { proc3={ allowed } } proc3.req
* [green -> green]: { proc0={ } } (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)
* [green -> green]: { proc1={ } } (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)
* [green -> green]: { proc2={ } } (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)
* [green -> green]: { proc3={ } } (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)
* [red -> green]: { proc0={ } } proc0.leave
* [red -> green]: { proc1={ } } proc1.leave
* [red -> green]: { proc2={ } } proc2.leave
* [red -> green]: { proc3={ } } proc3.leave
* [red -> red]: { proc0={ } } (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)
* [red -> red]: { proc1={ } } (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)
* [red -> red]: { proc2={ } } (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)
* [red -> red]: { proc3={ } } (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)
* [green -> T]: { } ~((((((((true OR proc0.req) OR proc1.req) OR proc2.req) OR proc3.req) OR (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)) OR (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)) OR (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req)) OR (((~proc0.req AND ~proc1.req) AND ~proc2.req) AND ~proc3.req))
* [red -> T]: { } ~((((((((true OR proc0.leave) OR proc1.leave) OR proc2.leave) OR proc3.leave) OR (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)) OR (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)) OR (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave)) OR (((~proc0.leave AND ~proc1.leave) AND ~proc2.leave) AND ~proc3.leave))
* [T -> T]: { }

View File

@@ -0,0 +1,80 @@
{ proc0={ req } proc1={ approach } proc2={ req } proc3={ out leave } }
{ proc0={ req } proc1={ req } proc2={ approach } proc3={ out leave } }
{ proc0={ req } proc1={ req } proc2={ req } proc3={ out leave } }
{ proc0={ approach } proc1={ approach } proc2={ req } proc3={ out leave } }
{ proc0={ approach } proc1={ req } proc2={ req } proc3={ out leave } }
{ proc0={ approach } proc1={ approach } proc2={ req in } proc3={ approach } }
{ proc0={ approach } proc1={ req } proc2={ out leave } proc3={ req } }
{ proc0={ approach } proc1={ req } proc2={ req in } proc3={ approach } }
{ proc0={ req } proc1={ approach } proc2={ approach } proc3={ out leave } }
{ proc0={ approach } proc1={ approach } proc2={ approach } proc3={ out leave } }
{ proc0={ req } proc1={ approach } proc2={ req in } proc3={ req } }
{ proc0={ approach } proc1={ req } proc2={ approach } proc3={ out leave } }
{ proc0={ req } proc1={ approach } proc2={ req } proc3={ req in } }
{ proc0={ approach } proc1={ req } proc2={ req in } proc3={ req } }
{ proc0={ req } proc1={ approach } proc2={ out leave } proc3={ approach } }
{ proc0={ req in } proc1={ approach } proc2={ req } proc3={ req } }
{ proc0={ approach } proc1={ approach } proc2={ approach } proc3={ req in } }
{ proc0={ req } proc1={ req } proc2={ out leave } proc3={ req } }
{ proc0={ req } proc1={ approach } proc2={ out leave } proc3={ req } }
{ proc0={ req } proc1={ req } proc2={ req in } proc3={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ out leave } proc3={ req } }
{ proc0={ req } proc1={ req } proc2={ req in } proc3={ req } }
{ proc0={ req } proc1={ approach } proc2={ req in } proc3={ approach } }
{ proc0={ approach } proc1={ req } proc2={ out leave } proc3={ approach } }
{ proc0={ req } proc1={ req } proc2={ out leave } proc3={ approach } }
{ proc0={ } proc1={ } proc2={ } proc3={ } }
{ proc0={ approach } proc1={ approach } proc2={ out leave } proc3={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ req in } proc3={ req } }
{ proc0={ req } proc1={ approach } proc2={ approach } proc3={ req in } }
{ proc0={ req in } proc1={ req } proc2={ approach } proc3={ req } }
{ proc0={ req in } proc1={ approach } proc2={ approach } proc3={ approach } }
{ proc0={ req } proc1={ req in } proc2={ req } proc3={ req } }
{ proc0={ req in } proc1={ req } proc2={ approach } proc3={ approach } }
{ proc0={ req } proc1={ req } proc2={ req } proc3={ req in } }
{ proc0={ approach } proc1={ req } proc2={ req } proc3={ req in } }
{ proc0={ approach } proc1={ approach } proc2={ req } proc3={ req in } }
{ proc0={ out leave } proc1={ req } proc2={ approach } proc3={ approach } }
{ proc0={ req in } proc1={ req } proc2={ req } proc3={ req } }
{ proc0={ out leave } proc1={ req } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ req } proc2={ approach } proc3={ req in } }
{ proc0={ req in } proc1={ approach } proc2={ approach } proc3={ req } }
{ proc0={ req } proc1={ approach } proc2={ approach } proc3={ req } }
{ proc0={ req in } proc1={ approach } proc2={ req } proc3={ approach } }
{ proc0={ out leave } proc1={ approach } proc2={ req } proc3={ req } }
{ proc0={ approach } proc1={ req } proc2={ approach } proc3={ req in } }
{ proc0={ out leave } proc1={ req } proc2={ approach } proc3={ req } }
{ proc0={ req } proc1={ out leave } proc2={ req } proc3={ req } }
{ proc0={ req } proc1={ approach } proc2={ req } proc3={ req } }
{ proc0={ out leave } proc1={ req } proc2={ req } proc3={ req } }
{ proc0={ approach } proc1={ req in } proc2={ approach } proc3={ approach } }
{ proc0={ out leave } proc1={ approach } proc2={ approach } proc3={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ approach } proc3={ approach } }
{ proc0={ approach } proc1={ req } proc2={ req } proc3={ req } }
{ proc0={ approach } proc1={ out leave } proc2={ approach } proc3={ approach } }
{ proc0={ approach } proc1={ req } proc2={ approach } proc3={ approach } }
{ proc0={ approach } proc1={ out leave } proc2={ req } proc3={ req } }
{ proc0={ req } proc1={ out leave } proc2={ approach } proc3={ req } }
{ proc0={ approach } proc1={ out leave } proc2={ approach } proc3={ req } }
{ proc0={ approach } proc1={ req in } proc2={ req } proc3={ req } }
{ proc0={ out leave } proc1={ approach } proc2={ req } proc3={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ req } proc3={ req } }
{ proc0={ out leave } proc1={ approach } proc2={ approach } proc3={ req } }
{ proc0={ req in } proc1={ req } proc2={ req } proc3={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ approach } proc3={ req } }
{ proc0={ req } proc1={ req } proc2={ approach } proc3={ req } }
{ proc0={ approach } proc1={ req } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ approach } proc2={ approach } proc3={ approach } }
{ proc0={ approach } proc1={ req in } proc2={ approach } proc3={ req } }
{ proc0={ approach } proc1={ approach } proc2={ req } proc3={ approach } }
{ proc0={ approach } proc1={ req in } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ approach } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ req in } proc2={ approach } proc3={ req } }
{ proc0={ approach } proc1={ req } proc2={ approach } proc3={ req } }
{ proc0={ req } proc1={ req in } proc2={ approach } proc3={ approach } }
{ proc0={ req } proc1={ out leave } proc2={ approach } proc3={ approach } }
{ proc0={ req } proc1={ req } proc2={ approach } proc3={ approach } }
{ proc0={ approach } proc1={ out leave } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ out leave } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ req in } proc2={ req } proc3={ approach } }
{ proc0={ req } proc1={ req } proc2={ req } proc3={ approach } }

View File

@@ -0,0 +1,8 @@
Using BDD-based Bounded Model Checking
Formula ((EF(E< proc0.allowed >X(proc0.in)) AND EF(E< proc1.allowed >X(proc1.in))) AND EF(E< proc2.allowed >X(proc2.in))) holds
Using BDD-based Bounded Model Checking
Formula EF(((proc0.approach AND proc1.approach) AND proc2.approach)) holds
Using BDD-based Bounded Model Checking
Formula AG((proc0.in IMPLIES K[proc0]((~proc1.in AND ~proc2.in)))) holds
Using BDD-based Bounded Model Checking
Formula AG((proc0.in IMPLIES C[proc0 proc1 proc2]((~proc1.in AND ~proc2.in)))) holds

View File

@@ -0,0 +1,47 @@
# Context entities: out allowed
# Reactions:
. proc = "proc0":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc1":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc2":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
# Context Automaton States:
= Init state: init
* init
* green
* red
* T
# Context Automaton Transitions:
* [init -> green]: { proc0={ out } proc1={ out } proc2={ out } }
* [green -> red]: { proc0={ allowed } } proc0.req
* [green -> red]: { proc1={ allowed } } proc1.req
* [green -> red]: { proc2={ allowed } } proc2.req
* [green -> green]: { proc0={ } } ((~proc0.req AND ~proc1.req) AND ~proc2.req)
* [green -> green]: { proc1={ } } ((~proc0.req AND ~proc1.req) AND ~proc2.req)
* [green -> green]: { proc2={ } } ((~proc0.req AND ~proc1.req) AND ~proc2.req)
* [red -> green]: { proc0={ } } proc0.leave
* [red -> green]: { proc1={ } } proc1.leave
* [red -> green]: { proc2={ } } proc2.leave
* [red -> red]: { proc0={ } } ((~proc0.leave AND ~proc1.leave) AND ~proc2.leave)
* [red -> red]: { proc1={ } } ((~proc0.leave AND ~proc1.leave) AND ~proc2.leave)
* [red -> red]: { proc2={ } } ((~proc0.leave AND ~proc1.leave) AND ~proc2.leave)
* [green -> T]: { } ~((((((true OR proc0.req) OR proc1.req) OR proc2.req) OR ((~proc0.req AND ~proc1.req) AND ~proc2.req)) OR ((~proc0.req AND ~proc1.req) AND ~proc2.req)) OR ((~proc0.req AND ~proc1.req) AND ~proc2.req))
* [red -> T]: { } ~((((((true OR proc0.leave) OR proc1.leave) OR proc2.leave) OR ((~proc0.leave AND ~proc1.leave) AND ~proc2.leave)) OR ((~proc0.leave AND ~proc1.leave) AND ~proc2.leave)) OR ((~proc0.leave AND ~proc1.leave) AND ~proc2.leave))
* [T -> T]: { }

View File

@@ -0,0 +1,23 @@
# Reactions:
. proc = "proc0":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc1":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })
. proc = "proc2":
* (R={ out },I={ },P={ approach })
* (R={ approach },I={ req },P={ req })
* (R={ allowed },I={ },P={ in })
* (R={ in },I={ },P={ out leave })
* (R={ req },I={ in },P={ req })

View File

@@ -0,0 +1,32 @@
{ proc0={ req in } proc1={ req } proc2={ req } }
{ proc0={ req in } proc1={ req } proc2={ approach } }
{ proc0={ req } proc1={ req in } proc2={ approach } }
{ proc0={ req in } proc1={ approach } proc2={ req } }
{ proc0={ req in } proc1={ approach } proc2={ approach } }
{ proc0={ req } proc1={ req in } proc2={ req } }
{ proc0={ approach } proc1={ req in } proc2={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ req in } }
{ proc0={ approach } proc1={ req in } proc2={ req } }
{ proc0={ approach } proc1={ out leave } proc2={ req } }
{ proc0={ req } proc1={ approach } proc2={ out leave } }
{ proc0={ req } proc1={ req } proc2={ req in } }
{ proc0={ approach } proc1={ req } proc2={ req } }
{ proc0={ approach } proc1={ req } proc2={ req in } }
{ proc0={ out leave } proc1={ req } proc2={ req } }
{ proc0={ req } proc1={ approach } proc2={ req in } }
{ proc0={ req } proc1={ out leave } proc2={ approach } }
{ proc0={ approach } proc1={ out leave } proc2={ approach } }
{ proc0={ req } proc1={ req } proc2={ out leave } }
{ proc0={ req } proc1={ out leave } proc2={ req } }
{ proc0={ } proc1={ } proc2={ } }
{ proc0={ req } proc1={ approach } proc2={ req } }
{ proc0={ out leave } proc1={ req } proc2={ approach } }
{ proc0={ approach } proc1={ req } proc2={ out leave } }
{ proc0={ approach } proc1={ approach } proc2={ req } }
{ proc0={ req } proc1={ req } proc2={ approach } }
{ proc0={ out leave } proc1={ approach } proc2={ req } }
{ proc0={ approach } proc1={ req } proc2={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ approach } }
{ proc0={ approach } proc1={ approach } proc2={ out leave } }
{ proc0={ out leave } proc1={ approach } proc2={ approach } }
{ proc0={ req } proc1={ approach } proc2={ approach } }

View File

@@ -0,0 +1,17 @@
# Context entities: e1 e4
# Reactions:
. proc = "m":
* (R={ e1 e4 },I={ e2 },P={ e1 e2 })
* (R={ e2 },I={ e4 },P={ e1 e4 e3 })
* (R={ e1 e3 },I={ e2 },P={ e1 e2 })
* (R={ e3 },I={ e2 },P={ e1 })
# Context Automaton States:
= Init state: s0
* s0
* s1
# Context Automaton Transitions:
* [s0 -> s1]: { m={ e1 e4 } }
* [s1 -> s1]: { m={ } }
* [s1 -> s1]: { m={ e4 } }

View File

@@ -0,0 +1,8 @@
# Reactions:
. proc = "m":
* (R={ e1 e4 },I={ e2 },P={ e1 e2 })
* (R={ e2 },I={ e4 },P={ e1 e4 e3 })
* (R={ e1 e3 },I={ e2 },P={ e1 e2 })
* (R={ e3 },I={ e2 },P={ e1 })

View File

@@ -0,0 +1,3 @@
{ m={ e1 e4 e3 } }
{ m={ e1 e2 } }
{ m={ } }

69
tests/run_tests.sh Executable file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Regression test harness for ReactICS BDD module
# Compares current output against saved expected output
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
REACTICS="$ROOT_DIR/reactics-bdd/reactics"
EXPECTED_DIR="$SCRIPT_DIR/expected"
PASS=0
FAIL=0
ERRORS=""
run_test() {
local name="$1"
local expected_file="$2"
shift 2
local actual
actual=$("$@" 2>&1) || true
local expected
expected=$(cat "$expected_file")
if [[ "$actual" == "$expected" ]]; then
echo " PASS: $name"
((PASS++))
else
echo " FAIL: $name"
diff <(echo "$expected") <(echo "$actual") | head -20
((FAIL++))
ERRORS="$ERRORS\n - $name"
fi
}
echo "Running ReactICS regression tests..."
echo
# --- tgc.drs tests ---
echo "[tgc]"
run_test "tgc print" "$EXPECTED_DIR/tgc_print.txt" "$REACTICS" -P examples/bdd/tgc.drs
run_test "tgc reactions" "$EXPECTED_DIR/tgc_reactions.txt" "$REACTICS" -r examples/bdd/tgc.drs
run_test "tgc states" "$EXPECTED_DIR/tgc_states.txt" "$REACTICS" -s examples/bdd/tgc.drs
run_test "tgc mc (f1-f4)" "$EXPECTED_DIR/tgc_mc.txt" \
bash -c 'for f in f1 f2 f3 f4; do '"$REACTICS"' -c $f examples/bdd/tgc.drs 2>&1; done'
echo
echo "[trivial]"
run_test "trivial print" "$EXPECTED_DIR/trivial_print.txt" "$REACTICS" -P reactics-bdd/in/trivial.drs
run_test "trivial reactions" "$EXPECTED_DIR/trivial_reactions.txt" "$REACTICS" -r reactics-bdd/in/trivial.drs
run_test "trivial states" "$EXPECTED_DIR/trivial_states.txt" "$REACTICS" -s reactics-bdd/in/trivial.drs
echo
echo "[tgc4]"
run_test "tgc4 print" "$EXPECTED_DIR/tgc4_print.txt" "$REACTICS" -P examples/bdd/tgc4.drs
run_test "tgc4 states" "$EXPECTED_DIR/tgc4_states.txt" "$REACTICS" -s examples/bdd/tgc4.drs
run_test "tgc4 mc (f1-f4)" "$EXPECTED_DIR/tgc4_mc.txt" \
bash -c 'for f in f1 f2 f3 f4; do '"$REACTICS"' -c $f examples/bdd/tgc4.drs 2>&1; done'
echo
echo "================================"
echo "Results: $PASS passed, $FAIL failed"
if [[ $FAIL -gt 0 ]]; then
echo -e "Failures:$ERRORS"
exit 1
else
echo "All tests passed."
fi