]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
fuzz
authorRudolf Polzer <divverent@xonotic.org>
Tue, 7 Jan 2014 10:39:02 +0000 (11:39 +0100)
committerRudolf Polzer <divverent@xonotic.org>
Tue, 7 Jan 2014 10:54:40 +0000 (11:54 +0100)
fuzzer.sh [new file with mode: 0755]

diff --git a/fuzzer.sh b/fuzzer.sh
new file mode 100755 (executable)
index 0000000..4a6c566
--- /dev/null
+++ b/fuzzer.sh
@@ -0,0 +1,240 @@
+#!/bin/bash
+
+expression_depth=5
+
+randomselect_init() {
+       randomselect_choice=
+       randomselect_count=0
+}
+randomselect() {
+       randomselect_count=$((randomselect_count + 1))
+       if [ $((RANDOM % randomselect_count)) -eq 0 ]; then
+               randomselect_choice=$*
+       fi
+}
+
+# runtime expression:
+# 1. variables section (needs whitespace)
+# float var0;
+# vector var1;
+# ...
+# 2. function creation (no whitespace)
+# var0="a";var1=(!var0);
+# ...
+# 3.
+# VARIABLES
+# float is_ok() {
+#   STATEMENTS
+#   return varN == EXPRESSION
+# }
+
+# Thus we return:
+# EXPRESSION STATEMENTS VARIABLES...
+# a constant is:
+# 42 var0=42; float var0
+# 23 var1=23; float var1
+# (42)+(23) var0=42;var1=23;var2=(var0+var1); float var0; float var1; float var2
+
+NL="
+"
+TAB="  "
+
+newvars() {
+       varidx=0
+}
+nextvar() {
+       varidx=$((varidx + 1))
+       var=var$varidx
+}
+build_constant() {
+       randomselect_init
+       case "$1" in
+               float)
+                       randomselect 0
+                       randomselect 1
+                       randomselect -1
+                       randomselect 3
+                       randomselect -1073741824
+                       randomselect 'f'
+                       ;;
+               vector)
+                       randomselect "'0 0 0'"
+                       randomselect "'0 1 0'"
+                       randomselect "'-1 0 0'"
+                       randomselect "'2 2 2'"
+                       randomselect "'3 2 -1'"
+                       randomselect "'16777216 -1073741824 0.0625'"
+                       randomselect 'v'
+                       ;;
+               string)
+                       randomselect '""'
+                       randomselect '"42"'
+                       randomselect 'string_null'
+                       randomselect 's'
+                       ;;
+       esac
+       nextvar
+       compiletime=$randomselect_choice
+       runtime="$var=$randomselect_choice"
+       vars="$1 $var"
+}
+
+# Format: "compiletime runtime"
+build_random_expression() {
+       local depth type op expr1_runtime expr2_runtime expr1_compiletime expr2_compiletime expr1_vars expr2_vars
+       depth=$1
+       type=$2
+       case "$depth" in
+               0)
+                       build_constant "$type"
+                       return
+                       ;;
+       esac
+       while :; do
+               randomselect_init
+               #randomselect "float ** float float"
+               randomselect "float ! float"
+               randomselect "float ~ float"
+               randomselect "float + float"
+               randomselect "float - float"
+               randomselect "float ! vector"
+               randomselect "vector ~ vector"
+               randomselect "vector + vector"
+               randomselect "vector - vector"
+               randomselect "float ! string"
+               randomselect "float * float float"
+               for binop in '+' '-' '&' '^' '|'; do
+                       randomselect "float $binop float float"
+                       randomselect "vector $binop vector vector"
+               done
+               for binop in '*'; do
+                       randomselect "vector $binop vector float"
+                       randomselect "vector $binop float vector"
+               done
+               randomselect "float / float float"
+               randomselect "vector / vector float"
+               #randomselect "float % float float"
+               randomselect "vector >< vector vector"
+               randomselect "float >> float float"
+               randomselect "float << float float"
+               randomselect "float < float float"
+               randomselect "float > float float"
+               randomselect "float <=> float float"
+               randomselect "float <= float float"
+               randomselect "float >= float float"
+               for type1 in float vector string; do
+                       randomselect "float == $type1 $type1"
+               done
+               for type1 in float vector string; do
+                       for type2 in float vector string; do
+                               randomselect "float || $type1 $type2"
+                               randomselect "float && $type1 $type2"
+                       done
+               done
+               thistype=${randomselect_choice%% *}
+               if [ x"$type" = x"$thistype" ]; then
+                       case "$depth" in
+                               0)
+                                       break
+                                       ;;
+                               *)
+                                       case "$randomselect_choice" in
+                                               *string*)
+                                                       ;;
+                                               *)
+                                                       break
+                                                       ;;
+                                       esac
+                                       ;;
+                       esac
+               fi
+       done
+       randomselect_choice=${randomselect_choice#* }
+       op=${randomselect_choice%% *}
+       randomselect_choice=${randomselect_choice#* }
+       case "$randomselect_choice" in
+               *' '*)
+                       set -- $randomselect_choice
+                       build_random_expression "$((depth - 1))" "$1"
+                       expr1_compiletime=$compiletime
+                       expr1_runtime=$runtime
+                       expr1_vars=$vars
+                       build_random_expression "$((depth - 1))" "$2"
+                       expr2_compiletime=$compiletime
+                       expr2_runtime=$runtime
+                       expr2_vars=$vars
+                       nextvar
+                       case "$op" in
+                               '/'|'%')
+                                       check="if(!${expr2_vars##* }) { print(\"DIVISION BY ZERO\\n\"); return 1; }$NL$TAB"
+                                       ;;
+                               *)
+                                       check=
+                                       ;;
+                       esac
+                       compiletime="($expr1_compiletime)$op($expr2_compiletime)"
+                       runtime="$expr1_runtime;$NL$TAB$expr2_runtime;$NL$TAB$check$var=(${expr1_vars##* }$op${expr2_vars##* })"
+                       vars="$expr1_vars;$NL$expr2_vars;$NL$type $var"
+                       ;;
+               *)
+                       build_random_expression "$((depth - 1))" "$randomselect_choice"
+                       nextvar
+                       compiletime="$op($compiletime)"
+                       runtime="$runtime;$NL$TAB$var=($op${vars##* })"
+                       vars="$vars;$NL$type $var"
+                       ;;
+       esac
+}
+
+while :; do
+       case "$((RANDOM % 2))" in
+               0)
+                       conv=ftos
+                       type=float
+                       ;;
+               1)
+                       conv=vtos
+                       type=vector
+                       ;;
+       esac
+       newvars
+       build_random_expression 2 "$type"
+       cat <<EOF >foo.qc
+void print(...) = #1;
+string ftos(float) = #2;
+string vtos(vector) = #5;
+float sqrt(float) = #13;
+float floor(float) = #14;
+noref string string_null;
+var string s = "s";
+var float f = 134217728;
+var vector v = '-134217728 17 0.03125';
+$vars;
+float check() {
+       $runtime;
+       $type result = ($compiletime);
+       print("Runtime: ", $conv(${vars##* }), "\\n");
+       print("Compile-time: ", $conv(result), "\\n");
+       return ${vars##* } == result;
+}
+void main() {
+       if (check()) {
+               print("OK\\n");
+       } else {
+               print("FAIL\\n");
+       }
+}
+EOF
+       if ./gmqcc -std=gmqcc -Wall foo.qc; then
+               if ./qcvm progs.dat | tee /dev/stderr | grep FAIL >/dev/null; then
+                       nl foo.qc
+                       echo "Compiler is broken AGAIN."
+                       break
+               fi
+       else
+               nl foo.qc
+               echo "Compile fail. Maybe this script is broken?"
+               break
+       fi
+done
+