#!/usr/bin/env bash set -o pipefail TESTCASE_ITERATIONS=100 TESTCASE_TIMEOUT=5 LOGFILE="log_tests.txt" RAND_STATES=18 RAND_DENSITY="2.5" RAND_ALPHABET=4 EXECUTABLES="arand aepsilon atrim adeterminize aminimize anormalize adiff.automaton aconversion" TESTS_DIR="../examples/automaton" # ---------------------------- for FILE in $EXECUTABLES; do if [ ! -f bin/$FILE ]; then echo "Executable" $FILE "is required for testing. Make sure it is in bin folder." exit 1 fi done cd bin/ rm -f $LOGFILE # ---------------------------- function mDFA { echo "$1" | ./aepsilon | ./atrim | ./adeterminize -t FSM | ./aminimize | ./anormalize } function compare { echo "$1" > tmp1.xml echo "$2" > tmp2.xml # relies on ret code by adiff.automaton ./adiff.automaton tmp1.xml tmp2.xml RET=$? rm tmp1.xml tmp2.xml return $RET } function generateNFA { ./arand -d $RAND_DENSITY -n $(( $RANDOM % $RAND_STATES + 1 )) -a $(( $RANDOM % $RAND_ALPHABET + 1 )) 2>/dev/null } # $1 = command for conversion. Output of such command must be (eps-)NFA !! # $2 = automaton function runTest2 { TMPNFA="nfa.xml" echo "$2" > $TMPNFA TMP=$(timeout $TESTCASE_TIMEOUT bash -c "cat $TMPNFA | $1" 2>/dev/null) RETTMP=$? # segfault if [ $RETTMP -eq 134 ]; then return 3 fi # timeout if [ $RETTMP -ge 123 ]; then return 2 fi mDFA1=$(mDFA "$(cat $TMPNFA)") mDFA2=$(mDFA "$TMP") # as pipefail bash option is turned on, first non-zero exit value of any program in pipe sequence is return code of whole sequence CMP=$(compare "$mDFA1" "$mDFA2") if [ $? == 0 ]; then rm $TMPNFA return 0 else echo "-----------------------------------------" >> $LOGFILE echo "$1" >> $LOGFILE echo "$CMP" >> $LOGFILE echo $(cat $TMPNFA) >> $LOGFILE rm $TMPNFA return 1 fi } # $1 - aconversion sequence function runTest { RES_GOOD=0 RES_FAIL=0 RES_TIMEOUT=0 RES_SIGSEGV=0 echo $1 echo -ne "\t" # predefined tests first for FILE in `ls $TESTS_DIR/aconversion.test*`; do AUTOMATON=$(cat $FILE) runTest2 "$1" "$AUTOMATON" TEST_EXITVALUE=$? if [ $TEST_EXITVALUE == 0 ]; then echo -n "." RES_GOOD=$((RES_GOOD + 1)) elif [ $TEST_EXITVALUE == 1 ]; then echo -n "x" RES_FAIL=$((RES_FAIL + 1)) elif [ $TEST_EXITVALUE == 2 ]; then echo -n "T" RES_TIMEOUT=$((RES_TIMEOUT + 1)) elif [ $TEST_EXITVALUE == 3 ]; then echo -n "F" RES_SIGSEGV=$((RES_SIGSEGV + 1)) else echo -n "?" fi done echo -n " | " # random tests for i in $(seq 1 $TESTCASE_ITERATIONS ); do RAND_AUTOMATON=$(generateNFA) if [ $? -eq 139 ]; then echo -n "F" RES_SIGSEGV=$((RES_SIGSEGV + 1)) continue fi runTest2 "$1" "$RAND_AUTOMATON" TEST_EXITVALUE=$? if [ $TEST_EXITVALUE == 0 ]; then echo -n "." RES_GOOD=$((RES_GOOD + 1)) elif [ $TEST_EXITVALUE == 1 ]; then echo -n "x" RES_FAIL=$((RES_FAIL + 1)) elif [ $TEST_EXITVALUE == 2 ]; then echo -n "T" RES_TIMEOUT=$((RES_TIMEOUT + 1)) elif [ $TEST_EXITVALUE == 3 ]; then echo -n "F" RES_SIGSEGV=$((RES_SIGSEGV + 1)) else echo -n "?" fi done # summary echo -ne "\n\t" echo "RES: GOOD:" $RES_GOOD ", BAD:" $RES_FAIL ", TIMEOUT:" $RES_TIMEOUT ", SIGSEGV:" $RES_SIGSEGV echo "" } # FA -> RG -> FA # covers: FA -> LRG, FA -> RRG, RRG <-> LRG, RRG -> FA, LRG -> FA runTest "./aconversion -t RRG | ./aconversion -t LRG | ./aconversion -t FA" runTest "./aconversion -t LRG | ./aconversion -t RRG | ./aconversion -t FA" # FA -> RE -> FA # covers: FA -> RE (Brzozowski algebraic, elimination), RE -> FA (Brzozowski derivation, Thompson, Glushkov) runTest "./aconversion -t RE -a algebraic | ./aconversion -t FA -a brzozowski" runTest "./aconversion -t RE -a algebraic | ./aconversion -t FA -a thompson" runTest "./aconversion -t RE -a algebraic | ./aconversion -t FA -a glushkov " runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a brzozowski" runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a thompson" runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a glushkov" # FA -> RE -> RRG -> LRG -> FA # covers: FA -> RE (Brz. algebraic, elimination), RE -> RRG ( Brz. derivation, Glushkov), RRG -> LRG, LRG -> FA runTest "./aconversion -t RE -a algebraic | ./aconversion -t RRG -a brzozowski | ./aconversion -t LRG | ./aconversion -t FA" runTest "./aconversion -t RE -a algebraic | ./aconversion -t RRG -a glushkov | ./aconversion -t LRG | ./aconversion -t FA" runTest "./aconversion -t RE -a elimination | ./aconversion -t RRG -a brzozowski | ./aconversion -t LRG | ./aconversion -t FA" runTest "./aconversion -t RE -a elimination | ./aconversion -t RRG -a glushkov | ./aconversion -t LRG | ./aconversion -t FA" # FA -> RRG -> RE -> FA # covers: FA -> RRG, FA -> LRG, RRG -> RE, LRG -> RE, RE -> FA (Brz. derivation, Thompson, Glushkov) runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA -a brzozowski" runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA -a brzozowski" runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA -a thompson" runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA -a thompson" runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA -a glushkov" runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA -a glushkov"