#!/bin/bash set -euo pipefail if [[ $# -ne 1 ]]; then echo "$0 {run_zoltraak.pl}" exit 1 fi SCRIPT=$1 TEST_DIR=$(mktemp -d) # Delete temporary directory and exit with nonzero status. function die { echo "$1" rm -rf "$TEST_DIR" exit 1 } # Run code and compare against expected output. function run_test { cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > "$TEST_DIR/actual.txt" \ || die "$1: runtime error" diff -q "$TEST_DIR/expected.txt" "$TEST_DIR/actual.txt" \ || die "$1: output mismatched" cat "$TEST_DIR/header.txt" "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > "$TEST_DIR/actual.txt" \ || die "$1: runtime error (double header)" diff -q "$TEST_DIR/expected.txt" "$TEST_DIR/actual.txt" \ || die "$1: output mismatched (double header)" cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > "$TEST_DIR/actual.txt" \ || die "$1: runtime error (double content)" cat "$TEST_DIR/expected.txt" "$TEST_DIR/expected.txt" \ | diff -q - "$TEST_DIR/actual.txt" \ || die "$1: output mismatched (double content)" cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ "$TEST_DIR/code.txt" "$TEST_DIR/header.txt" \ "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > "$TEST_DIR/actual.txt" \ || die "$1: runtime error (quad content)" cat "$TEST_DIR/expected.txt" "$TEST_DIR/expected.txt" \ "$TEST_DIR/expected.txt" "$TEST_DIR/expected.txt" \ | diff -q - "$TEST_DIR/actual.txt" \ || die "$1: output mismatched (quad content)" } # Check that missing header is flagged. perl "$SCRIPT" < /dev/null > /dev/null 2>&1 && die "$LINENO: empty file" echo "zoltraak" | perl "$SCRIPT" > /dev/null 2>&1 && die "$LINENO: bad header" echo "#ifndef zoltraak" > "$TEST_DIR/header.txt" echo "#endif" >> "$TEST_DIR/header.txt" # Check that incomplete code is flagged. echo -n "" > "$TEST_DIR/code.txt" for i in $(seq 8); do echo "zoltraak" >> "$TEST_DIR/code.txt" cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > /dev/null 2>&1 \ && die "$LINENO: incomplete output instruction $i" done echo "" >> "$TEST_DIR/code.txt" for i in $(seq 9); do echo "" >> "$TEST_DIR/code.txt" cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > /dev/null 2>&1 \ && die "$LINENO: incomplete branch instruction $i" done # Check that branch out of bounds is detected. echo -n "" > "$TEST_DIR/code.txt" for i in $(seq 17); do echo "" >> "$TEST_DIR/code.txt" done echo "zoltraak" >> "$TEST_DIR/code.txt" cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > /dev/null 2>&1 \ && die "$LINENO: branch out of bounds (empty)" cat < "$TEST_DIR/code.txt" // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 zoltraak // 9 // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 zoltraak // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 EOT cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > /dev/null 2>&1 \ && die "$LINENO: branch out of bounds (nonempty)" # Check for branch into incomplete instruction. cat < "$TEST_DIR/code.txt" zoltraak // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 zoltraak // 9 // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 EOT cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > /dev/null 2>&1 \ && die "$LINENO: branch into incomplete instruction" # Check that stack overflow is detected. cat < "$TEST_DIR/code.txt" // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 zoltraak // 9 EOT for i in $(seq 250); do cat <> "$TEST_DIR/code.txt" zoltraak // 1 zoltraak // 2 zoltraak // 3 zoltraak // 4 zoltraak // 5 zoltraak // 6 zoltraak // 7 zoltraak // 8 // 9 zoltraak // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 EOT done cat "$TEST_DIR/header.txt" "$TEST_DIR/code.txt" \ | perl "$SCRIPT" > /dev/null 2>&1 \ && die "$LINENO: stack overflow" # Empty input. cp /dev/null "$TEST_DIR/code.txt" cp /dev/null "$TEST_DIR/expected.txt" run_test "$LINENO: empty code" # Output a single byte. cat < "$TEST_DIR/code.txt" zoltraak // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 zoltraak // 9 EOT echo -n "!" > "$TEST_DIR/expected.txt" run_test "$LINENO: one byte (text)" # Check binary output. cat < "$TEST_DIR/code.txt" zoltraak // 1 zoltraak // 2 zoltraak // 3 zoltraak // 4 zoltraak // 5 // 6 zoltraak // 7 zoltraak // 8 zoltraak // 9 EOT perl -e 'print chr(0xff)' > "$TEST_DIR/expected.txt" run_test "$LINENO: one byte (binary)" # Check simple repeat command. cat < "$TEST_DIR/code.txt" zoltraak // 1 // 2 // 3 // 4 // 5 // 6 zoltraak // 7 // 8 zoltraak // 9 // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 EOT echo -n "aaaa" > "$TEST_DIR/expected.txt" run_test "$LINENO: repeat one byte" # Check repeating multiple bytes. cat < "$TEST_DIR/code.txt" // 1 [0] // 2 // 3 zoltraak // 4 zoltraak // 5 // 6 zoltraak // 7 // 8 zoltraak // 9 zoltraak // 1 [1] // 2 // 3 zoltraak // 4 zoltraak // 5 // 6 zoltraak // 7 // 8 zoltraak // 9 // 1 [2] zoltraak // 2 // 3 zoltraak // 4 zoltraak // 5 // 6 zoltraak // 7 // 8 zoltraak // 9 zoltraak // 1 [3] // 2 // 3 zoltraak // 4 // 5 // 6 // 7 // 8 // 9 // 10 [4] zoltraak // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 EOT echo -n "xyzxyzxyzxyzxyz" > "$TEST_DIR/expected.txt" run_test "$LINENO: repeat two bytes" # Check nested repeat groups. cat < "$TEST_DIR/code.txt" zoltraak // 1 [0] // 2 // 3 // 4 zoltraak // 5 // 6 // 7 // 8 zoltraak // 9 // 1 [1] // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 [2] // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 // 1 [3] zoltraak // 2 // 3 // 4 zoltraak // 5 // 6 // 7 // 8 zoltraak // 9 zoltraak // 1 [4] zoltraak // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 [5] // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 zoltraak // 1 [6] zoltraak // 2 // 3 // 4 zoltraak // 5 // 6 // 7 // 8 zoltraak // 9 zoltraak // 1 [7] // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 [8] // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 // 1 [9] // 2 zoltraak // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10 [10] // 11 // 12 zoltraak // 13 // 14 // 15 // 16 // 17 zoltraak // 18 zoltraak // 1 [11] // 2 // 3 // 4 zoltraak // 5 // 6 // 7 // 8 // 9 zoltraak // 10 [12] zoltraak // 11 // 12 // 13 // 14 // 15 // 16 // 17 zoltraak // 18 EOT echo -n "1111222222233333111122233331111222333311112" > "$TEST_DIR/expected.txt" run_test "$LINENO: nested repeat" rm -rf "$TEST_DIR" exit 0