From 383ed9cb09559f14e85491f022f706687c42cad2 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Fri, 16 May 2008 22:01:11 +0000 Subject: [PATCH] * Add statistical analysis to the testsuite to check our random number generator. --- .gitignore | 1 + test/Makefile.am | 5 +- test/testsuite.sh | 154 +++++++++++++++++++++++++++++++++------------- test/zzero.c | 36 +++++++++++ 4 files changed, 153 insertions(+), 43 deletions(-) create mode 100644 test/zzero.c diff --git a/.gitignore b/.gitignore index 3be968b..2bfbab1 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ stamp-* *-stamp src/zzuf test/zzcat +test/zzero diff --git a/test/Makefile.am b/test/Makefile.am index bb7bd45..f8402b9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,9 @@ EXTRA_DIST = testsuite.sh file-00 file-ff file-random file-text -noinst_PROGRAMS = zzcat +noinst_PROGRAMS = zzcat zzero + zzcat_SOURCES = zzcat.c +zzero_SOURCES = zzero.c + diff --git a/test/testsuite.sh b/test/testsuite.sh index b327444..edd870d 100755 --- a/test/testsuite.sh +++ b/test/testsuite.sh @@ -2,52 +2,43 @@ set -e -check() +checkflip() { - ZZOPTS="$1" - CMD="$2" - ALIAS="$3" - CHECK="$4" - echo -n " $(echo "$ALIAS .............." | cut -b1-18) " - MD5="$(eval "$ZZUF -m $ZZOPTS $CMD" 2>/dev/null | cut -f2 -d' ')" - if [ -n "$CHECK" ]; then - REFMD5="$CHECK" - fi - if [ -z "$REFMD5" ]; then - REFMD5="$MD5" - echo "$MD5" + r=$1 + expect=$2 + s2=$seed + mib=20 + echo "*** $mib MiB of zeroes, ratio $r ***" + echo " expected ....... $expect" + rmax=-1 + rmin=-1 + rtot=0 + for x in 0 1 2 3 4 5 6 7 8 9; do + ret=`dd if=/dev/zero bs=1048576 count=$mib 2>/dev/null | "$ZZUF" -s $s2 -r $r | "$ZZERO"` + if [ "$rmax" = -1 -o "$ret" -gt "$rmax" ]; then rmax=$ret; fi + if [ "$rmin" = -1 -o "$ret" -lt "$rmin" ]; then rmin=$ret; fi + rtot=`expr $rtot + $ret || true` + echo " try $x .......... $ret" + s2=`expr $s2 + 1` + done + rmean=`expr '(' $rtot + 5 ')' / 10 || true` + delta=`expr $rmean - $expect || true` + if [ "$delta" -gt -5 -a "$delta" -lt 5 ]; then + result="ok" + elif [ $(($rmean * 8)) -lt $(($expect * 7)) \ + -o $(($rmean * 7)) -gt $(($expect * 8)) ]; then + result="FAILED" + FAILED=$(($FAILED + 1)) else - TESTED=$(($TESTED + 1)) - if [ "$MD5" != "$REFMD5" ]; then - FAILED=$(($FAILED + 1)) - echo "$MD5 FAILED" - else - echo 'ok' - fi + result="ok" fi + TESTED=$(($TESTED + 1)) + echo " min/avg/max $rmin/$rmean/$rmax .......... $result" } -seed=$((0+0$1)) -DIR="$(dirname "$0")" -ZZUF="$DIR/../src/zzuf" -ZZCAT="$DIR/zzcat" -if [ ! -f "$ZZCAT" ]; then - echo "error: test/zzcat is missing" - exit 1 -fi -if file /bin/cat | grep -q 'statically linked'; then - STATIC_CAT=1 -fi -if file /bin/dd | grep -q 'statically linked'; then - STATIC_DD=1 -fi -FAILED=0 -TESTED=0 - -echo "*** running zzuf test suite ***" -echo "*** using seed $seed ***" - -for r in 0.0 0.00001 0.001 0.1 10.0; do +checkutils() +{ + r=$1 for type in 00 ff text random; do file="$DIR/file-$type" ZZOPTS="-s $seed -r $r" @@ -96,8 +87,87 @@ for r in 0.0 0.00001 0.001 0.1 10.0; do ;; esac done -done +} +check() +{ + ZZOPTS="$1" + CMD="$2" + ALIAS="$3" + CHECK="$4" + echo -n " $(echo "$ALIAS .............." | cut -b1-18) " + MD5="$(eval "$ZZUF -m $ZZOPTS $CMD" 2>/dev/null | cut -f2 -d' ')" + if [ -n "$CHECK" ]; then + REFMD5="$CHECK" + fi + if [ -z "$REFMD5" ]; then + REFMD5="$MD5" + echo "$MD5" + else + TESTED=$(($TESTED + 1)) + if [ "$MD5" != "$REFMD5" ]; then + FAILED=$(($FAILED + 1)) + echo "$MD5 FAILED" + else + echo 'ok' + fi + fi +} + +DIR="$(dirname "$0")" +ZZUF="$DIR/../src/zzuf" +ZZCAT="$DIR/zzcat" +if [ ! -f "$ZZCAT" ]; then + echo "error: test/zzcat is missing" + exit 1 +fi +ZZERO="$DIR/zzero" +if [ ! -f "$ZZERO" ]; then + echo "error: test/zzero is missing" + exit 1 +fi +if file /bin/cat | grep -q 'statically linked'; then + STATIC_CAT=1 +fi +if file /bin/dd | grep -q 'statically linked'; then + STATIC_DD=1 +fi +FAILED=0 +TESTED=0 + +if [ -z "$1" ]; then + seed=$(date | $ZZUF -m 2>/dev/null | cut -f2 -d' ' | tr -d abcdef | cut -b1-8) +else + seed="$1" +fi + +echo "*** running zzuf test suite with seed $seed ***" + +echo "" +echo "*** check #1: random number generator ***" +# if X flips are performed on N bits set to 0, the average number of bits +# set to 1 is: N / 2 * (1 - pow(1 - 2 / N, X) +checkflip 0.000000001 0 +checkflip 0.00000001 1 +checkflip 0.0000001 16 +checkflip 0.000001 167 +checkflip 0.00001 1677 +checkflip 0.0001 16775 +checkflip 0.001 167604 +checkflip 0.01 1661055 +checkflip 0.1 15205967 + +echo "" +echo "*** check #2: libc functions coverage ***" +checkutils 0.0 +checkutils 0.000000001 +checkutils 0.0000001 +checkutils 0.00001 +checkutils 0.001 +checkutils 0.1 +checkutils 10.0 + +echo "" if [ "$FAILED" != 0 ]; then echo "*** $FAILED tests failed out of $TESTED ***" exit 1 diff --git a/test/zzero.c b/test/zzero.c new file mode 100644 index 0000000..b0ffee7 --- /dev/null +++ b/test/zzero.c @@ -0,0 +1,36 @@ +/* + * zzero - check how many bits zzuf changes in a stream of zeroes + * Copyright (c) 2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This program is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +#include "config.h" + +#include +#include + +int main(void) +{ + static const int lut[16] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 + }; + + int ones = 0, ch; + + while((ch = getc(stdin)) != EOF) + ones += lut[ch & 0xf] + lut[(ch >> 4) & 0xf]; + + printf("%i\n", ones); + + return EXIT_SUCCESS; +} +