all repos — xyw @ ed455f994f4497b3b389df581489c0bf91ec0b0a

A minimal virtual machine and assembler for terminals.

test.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
#!/usr/bin/env bash
set -euo pipefail

### Test cases
TEST_CASES=(
  "run_test helloworld.xyw assert_output_equals \$'Hello, World!\\n'"
  "run_test d6.xyw assert_output_in_range 1 6"
)

### Helper functions

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
EXAMPLES_DIR="$ROOT_DIR/examples"

fail() {
  echo "ERROR: $*" >&2
  exit 1
}

need_file() {
  local path="$1"
  [[ -f "$path" ]] || fail "Missing file: $path"
}

build_xyw() {
  if command -v make >/dev/null 2>&1; then
    (cd "$ROOT_DIR" && make xyw)
  else
    echo "WARN: 'make' not found; using existing xyw binary if present." >&2
  fi
}

find_xyw_bin() {
  if [[ -x "$ROOT_DIR/xyw" ]]; then
    echo "$ROOT_DIR/xyw"
    return 0
  fi
  if [[ -x "$ROOT_DIR/xyw.exe" ]]; then
    echo "$ROOT_DIR/xyw.exe"
    return 0
  fi
  fail "Could not find executable xyw binary (expected $ROOT_DIR/xyw or $ROOT_DIR/xyw.exe)."
}

assemble_in_examples_dir() {
  local xyw_bin="$1"
  local src_basename="$2" # e.g. helloworld.xyw

  need_file "$EXAMPLES_DIR/$src_basename"

  (cd "$EXAMPLES_DIR" && "$xyw_bin" "$src_basename" >/dev/null)

  local img_basename="${src_basename%.xyw}.xim"
  need_file "$EXAMPLES_DIR/$img_basename"
  echo "$img_basename"
}

run_image_capture_stdout() {
  local xyw_bin="$1"
  local img_basename="$2" # e.g. helloworld.xim
  local out_file="$3"

  need_file "$EXAMPLES_DIR/$img_basename"

  (cd "$EXAMPLES_DIR" && "$xyw_bin" "$img_basename" >"$out_file")
}

normalize_crlf() {
  local in_file="$1"
  local out_file="$2"

  tr -d '\r' <"$in_file" >"$out_file"
}

### Assertion functions

assert_file_equals() {
  local actual_file="$1"
  local expected_file="$2"

  if ! cmp -s "$actual_file" "$expected_file"; then
    echo "--- Expected (cat -v) ---" >&2
    cat -v "$expected_file" >&2 || true
    echo "--- Actual (cat -v) ---" >&2
    cat -v "$actual_file" >&2 || true
    fail "Output did not match expectation."
  fi
}

assert_output_equals() {
  local stdout_file="$1"
  local expected_string="$2"

  local expected_file
  expected_file="$TMPDIR/expected.$$.${RANDOM}.txt"
  printf '%s' "$expected_string" >"$expected_file"
  assert_file_equals "$stdout_file" "$expected_file"
  rm -f "$expected_file"
}

assert_output_in_range() {
  local stdout_file="$1"
  local min_value="$2"
  local max_value="$3"

  local value
  value="$(tr -d '\n\t ' <"$stdout_file")"

  if [[ ! "$value" =~ ^-?[0-9]+$ ]]; then
    echo "--- Actual (cat -v) ---" >&2
    cat -v "$stdout_file" >&2 || true
    fail "Output is not an integer: '$value'"
  fi

  if (( value < min_value || value > max_value )); then
    echo "--- Actual (cat -v) ---" >&2
    cat -v "$stdout_file" >&2 || true
    fail "Output out of range (expected ${min_value}..${max_value}): $value"
  fi
}

### Test runner

run_test() {
  local src_basename="$1"
  local assert_fn="$2"
  shift 2

  if ! declare -F "$assert_fn" >/dev/null 2>&1; then
    fail "Assertion function not found: $assert_fn"
  fi

  need_file "$EXAMPLES_DIR/$src_basename"

  local img_basename
  img_basename="$(assemble_in_examples_dir "$XYW_BIN" "$src_basename")"

  local raw_out="$TMPDIR/${src_basename%.xyw}.raw"
  local norm_out="$TMPDIR/${src_basename%.xyw}.norm"

  run_image_capture_stdout "$XYW_BIN" "$img_basename" "$raw_out"
  normalize_crlf "$raw_out" "$norm_out"

  "$assert_fn" "$norm_out" "$@"
  echo "PASS: $src_basename"
}

### Main

main() {
  need_file "$ROOT_DIR/Makefile"

  build_xyw

  TMPDIR="$(mktemp -d 2>/dev/null || mktemp -d -t xywtest)"
  trap "rm -rf \"$TMPDIR\"" EXIT

  XYW_BIN="$(find_xyw_bin)"

  for tc in "${TEST_CASES[@]}"; do
    eval "$tc"
  done

  echo "All tests passed."
}

main "$@"