Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 1 | #! /bin/bash |
Gavin Howard | 64f113c | 2018-09-25 09:38:57 -0600 | [diff] [blame] | 2 | # |
| 3 | # Copyright 2018 Gavin D. Howard |
| 4 | # |
| 5 | # Permission to use, copy, modify, and/or distribute this software for any |
| 6 | # purpose with or without fee is hereby granted. |
| 7 | # |
| 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
| 9 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
| 10 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
| 11 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
| 12 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
| 13 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 14 | # PERFORMANCE OF THIS SOFTWARE. |
| 15 | # |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 16 | |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 17 | # This script uses a technique to use a keypress to get |
| 18 | # out of an infinite loop. The technique was found here: |
| 19 | # https://stackoverflow.com/questions/5297638/bash-how-to-end-infinite-loop-with-any-key-pressed |
| 20 | |
| 21 | finish() { |
| 22 | rm -rf "$out1" "$out2" "$math" "$results" "$opfile" |
| 23 | } |
| 24 | trap finish EXIT |
| 25 | |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 26 | gen() |
| 27 | { |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 28 | limit="$1" |
| 29 | shift |
| 30 | |
| 31 | result=$(dd if=/dev/urandom bs="$limit" count=1 2>/dev/null | od -t u4 | awk 'NR==1 {print $2}') |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 32 | echo -n "$result" |
| 33 | } |
| 34 | |
| 35 | neg() |
| 36 | { |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 37 | result=$(gen 1) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 38 | result="$((result & 1))" |
| 39 | echo -n "$result" |
| 40 | } |
| 41 | |
| 42 | zero() |
| 43 | { |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 44 | result=$(gen 1) |
| 45 | echo -n "$result" |
| 46 | } |
| 47 | |
| 48 | limit() |
| 49 | { |
| 50 | max="$1" |
| 51 | shift |
| 52 | |
| 53 | result=$(gen 1) |
| 54 | result=$(expr "$result" % "$max") |
| 55 | echo -n $(expr "$result" + 1) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | num() |
| 59 | { |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 60 | n="" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 61 | |
| 62 | neg=$1 |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 63 | shift |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 64 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 65 | real=$1 |
| 66 | shift |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 67 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 68 | zero=$1 |
| 69 | shift |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 70 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 71 | if [ "$#" -gt 0 ]; then |
| 72 | limit="$1" |
| 73 | shift |
| 74 | else |
| 75 | limit="$(limit 4)" |
| 76 | fi |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 77 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 78 | if [ "$zero" -ne 0 ]; then |
| 79 | z=$(zero) |
| 80 | else |
| 81 | z=1 |
| 82 | fi |
| 83 | |
| 84 | if [ "$z" -eq 0 ]; then |
| 85 | n="0" |
| 86 | else |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 87 | |
| 88 | if [ "$neg" -ne 0 ]; then |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 89 | |
| 90 | neg=$(neg) |
| 91 | |
| 92 | if [ "$neg" -eq 0 ]; then |
| 93 | n="-" |
| 94 | fi |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 95 | fi |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 96 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 97 | g=$(gen $limit) |
| 98 | n="${n}${g}" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 99 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 100 | if [ "$real" -ne 0 ]; then |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 101 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 102 | z=$(neg) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 103 | |
| 104 | if [ "$z" -ne 0 ]; then |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 105 | |
| 106 | limit=$(limit 25) |
| 107 | g=$(gen $limit) |
| 108 | n="$n.$g" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 109 | fi |
| 110 | fi |
| 111 | fi |
| 112 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 113 | echo -n "$n" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 114 | } |
| 115 | |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 116 | ops=( '+' '-' '*' '/' '%' '^' ) |
Gavin Howard | 19a3f0d | 2018-09-06 18:14:18 -0600 | [diff] [blame] | 117 | files=( "add" "subtract" "multiply" "divide" "modulus" "power" "sqrt" "exponent" |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 118 | "log" "arctangent" "sine" "cosine" "bessel" ) |
| 119 | funcs=( "sqrt" "e" "l" "a" "s" "c" "j" ) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 120 | |
| 121 | script="$0" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 122 | testdir=$(dirname "$script") |
| 123 | |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 124 | if [ "$#" -gt 0 ]; then |
| 125 | bc="$1" |
| 126 | shift |
| 127 | else |
| 128 | bc="$testdir/../bc" |
| 129 | fi |
| 130 | |
Gavin Howard | d43ae75 | 2018-09-06 19:36:18 -0600 | [diff] [blame] | 131 | out1="$testdir/../.log_bc.txt" |
| 132 | out2="$testdir/../.log_test.txt" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 133 | |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 134 | # Files to output failed tests to. |
| 135 | math="$testdir/../.math.txt" |
| 136 | results="$testdir/../.results.txt" |
| 137 | opfile="$testdir/../.ops.txt" |
Gavin Howard | b809c3a | 2018-09-07 12:17:49 -0600 | [diff] [blame] | 138 | |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 139 | rm -rf "$math" "$results" "$opfile" |
Gavin Howard | 8ceb651 | 2018-09-06 14:34:46 -0600 | [diff] [blame] | 140 | |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 141 | # Set it so we can exit the loop on keypress. |
| 142 | if [ -t 0 ]; then |
| 143 | stty -echo -icanon -icrnl time 0 min 0 |
| 144 | fi |
| 145 | |
| 146 | it=0 |
| 147 | keypress='' |
| 148 | |
| 149 | while [ "x$keypress" = "x" ]; do |
| 150 | |
| 151 | t="$it" |
| 152 | it=$(expr "$it" + "1") |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 153 | |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 154 | line="" |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 155 | operator=$(gen 1) |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 156 | op=$(expr "$operator" % 13) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 157 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 158 | if [ "$op" -lt 6 ]; then |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 159 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 160 | line="$(num 1 1 1) ${ops[$op]}" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 161 | |
Gavin Howard | 7de9076 | 2018-09-06 11:49:08 -0600 | [diff] [blame] | 162 | if [ "$op" -eq 3 -o "$op" -eq 4 ]; then |
Gavin Howard | fc66b86 | 2018-09-06 12:04:30 -0600 | [diff] [blame] | 163 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 164 | number=$(num 1 1 0) |
Gavin Howard | fc66b86 | 2018-09-06 12:04:30 -0600 | [diff] [blame] | 165 | |
| 166 | scale=$(num 0 0 1 1) |
| 167 | scale=$(echo "s = $scale % 25; s /= 1; s" | bc) |
| 168 | |
| 169 | line="scale = $scale; $line" |
| 170 | |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 171 | elif [ "$op" -eq 5 ]; then |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 172 | number=$(num 1 0 1 1) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 173 | else |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 174 | number=$(num 1 1 1) |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 175 | fi |
| 176 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 177 | line="$line $number" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 178 | |
| 179 | else |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 180 | |
| 181 | if [ "$op" -eq 6 ]; then |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 182 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 183 | number=$(num 0 1 1) |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 184 | |
Gavin Howard | 9e28c10 | 2018-09-08 19:36:39 -0600 | [diff] [blame] | 185 | # GNU bc gets "sqrt(1)" wrong, so skip it. |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 186 | if [ "$number" == "1" ]; then |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 187 | keypress=$(cat -v) |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 188 | continue |
| 189 | fi |
| 190 | |
Gavin Howard | 7de9076 | 2018-09-06 11:49:08 -0600 | [diff] [blame] | 191 | elif [ "$op" -eq 7 -o "$op" -eq 12 ]; then |
| 192 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 193 | number=$(num 1 1 1 1) |
Gavin Howard | 7de9076 | 2018-09-06 11:49:08 -0600 | [diff] [blame] | 194 | |
| 195 | if [ "$op" -eq 12 ]; then |
| 196 | number=$(echo "n = $number % 100; scale = 8; n /= 1; n" | bc) |
| 197 | fi |
| 198 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 199 | else |
| 200 | number=$(num 1 1 1) |
| 201 | fi |
| 202 | |
| 203 | func=$(expr "$op" - 6) |
| 204 | line="${funcs[$func]}($number" |
| 205 | |
| 206 | if [ "$op" -ne 12 ]; then |
| 207 | line="$line)" |
| 208 | else |
| 209 | n=$(num 1 1 1) |
Gavin Howard | 7de9076 | 2018-09-06 11:49:08 -0600 | [diff] [blame] | 210 | n=$(echo "n = $n % 100; scale = 8; n /= 1; n" | bc) |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 211 | line="$line, $n)" |
| 212 | fi |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 213 | fi |
| 214 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 215 | echo "Test $t: $line" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 216 | |
Gavin Howard | abe8c00 | 2018-09-06 11:30:04 -0600 | [diff] [blame] | 217 | echo "$line; halt" | bc -lq > "$out1" |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 218 | |
| 219 | content=$(cat "$out1") |
| 220 | |
| 221 | if [ "$content" == "" ]; then |
| 222 | echo " other bc returned an error ($error); continuing..." |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 223 | keypress=$(cat -v) |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 224 | continue |
Gavin Howard | d43ae75 | 2018-09-06 19:36:18 -0600 | [diff] [blame] | 225 | elif [ "$content" == "-0" ]; then |
| 226 | echo "0" > "$out1" |
Gavin Howard | 741077a | 2018-09-06 16:34:15 -0600 | [diff] [blame] | 227 | fi |
| 228 | |
Gavin Howard | d43ae75 | 2018-09-06 19:36:18 -0600 | [diff] [blame] | 229 | echo "$line; halt" | "$bc" "$@" -lq > "$out2" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 230 | |
| 231 | error="$?" |
| 232 | |
| 233 | if [ "$error" -ne 0 ]; then |
Gavin Howard | a7eabfc | 2018-09-08 20:10:08 -0600 | [diff] [blame] | 234 | echo " bc returned an error ($error); adding \"$line\" to checklist..." |
Gavin Howard | 1784229 | 2018-09-10 09:56:54 -0600 | [diff] [blame] | 235 | echo "$line" >> "$math" |
| 236 | cat "$out1" >> "$results" |
| 237 | echo "$op" >> "$opfile" |
Gavin Howard | a7eabfc | 2018-09-08 20:10:08 -0600 | [diff] [blame] | 238 | keypress=$(cat -v) |
| 239 | continue |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 240 | fi |
| 241 | |
Gavin Howard | 7de9076 | 2018-09-06 11:49:08 -0600 | [diff] [blame] | 242 | diff "$out1" "$out2" > /dev/null |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 243 | error="$?" |
| 244 | |
| 245 | if [ "$error" -ne 0 ]; then |
Gavin Howard | e97309c | 2018-09-07 12:18:20 -0600 | [diff] [blame] | 246 | |
| 247 | # This works around a bug in GNU bc that gets some |
| 248 | # transcendental functions slightly wrong. |
| 249 | if [ "$op" -ge 7 ]; then |
| 250 | |
| 251 | # Have GNU bc calculate to one more decimal place and truncate by 1. |
| 252 | content=$(echo "scale += 10; $line; halt" | bc -lq) |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 253 | content2=${content%??????????} |
| 254 | echo "$content2" > "$out1" |
Gavin Howard | e97309c | 2018-09-07 12:18:20 -0600 | [diff] [blame] | 255 | |
| 256 | # Compare the truncated. |
| 257 | diff "$out1" "$out2" > /dev/null |
| 258 | error="$?" |
| 259 | |
| 260 | # GNU bc got it wrong. |
| 261 | if [ "$error" -eq 0 ]; then |
| 262 | echo " failed because of bug in other bc; continuing..." |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 263 | keypress=$(cat -v) |
Gavin Howard | dccaf6f | 2018-09-07 14:42:23 -0600 | [diff] [blame] | 264 | continue |
| 265 | fi |
Gavin Howard | e97309c | 2018-09-07 12:18:20 -0600 | [diff] [blame] | 266 | fi |
| 267 | |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 268 | echo " failed; adding \"$line\" to checklist..." |
Gavin Howard | 1784229 | 2018-09-10 09:56:54 -0600 | [diff] [blame] | 269 | echo "$line" >> "$math" |
| 270 | cat "$out1" >> "$results" |
| 271 | echo "$op" >> "$opfile" |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 272 | fi |
| 273 | |
Gavin Howard | 9409a87 | 2018-09-08 19:29:29 -0600 | [diff] [blame] | 274 | keypress=$(cat -v) |
| 275 | |
| 276 | done |
| 277 | |
| 278 | # Reset the input. |
| 279 | if [ -t 0 ]; then |
| 280 | stty sane |
| 281 | fi |
| 282 | |
| 283 | if [ ! -f "$math" ]; then |
| 284 | echo -e "\nNo items in checklist." |
| 285 | echo "Exiting..." |
| 286 | exit 0 |
| 287 | fi |
| 288 | |
| 289 | echo -e "\nGoing through the checklist...\n" |
| 290 | |
| 291 | paste "$math" "$results" "$opfile" | while read line result curop; do |
| 292 | |
| 293 | echo -e "\n$line" |
| 294 | |
| 295 | echo "$line; halt" | bc -lq > "$out1" |
| 296 | echo "$line; halt" | "$bc" "$@" -lq > "$out2" |
| 297 | |
| 298 | diff "$out1" "$out2" |
| 299 | |
| 300 | echo -en "\nAdd test to test suite? [y/N] " |
| 301 | read answer </dev/tty |
| 302 | |
| 303 | if [ "$answer" != "${answer#[Yy]}" ] ;then |
| 304 | echo Yes |
| 305 | echo "$line" >> "$testdir/${files[$curop]}.txt" |
| 306 | cat "$result" >> "$testdir/${files[$curop]}_results.txt" |
| 307 | else |
| 308 | echo No |
| 309 | fi |
Gavin Howard | 8ceb651 | 2018-09-06 14:34:46 -0600 | [diff] [blame] | 310 | |
Gavin Howard | ea7bea6 | 2018-02-22 18:55:03 -0700 | [diff] [blame] | 311 | done |