plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
scripts/test-examples.sh
| 408b9c0 | 1 | #!/usr/bin/env bash |
| 408b9c0 | 2 | # |
| 408b9c0 | 3 | # Integration test: compiles and runs every examples/*.plum file through the |
| 408b9c0 | 4 | # REAL toolchain — the `plum` CLI binary (which resolves `import`s against |
| 408b9c0 | 5 | # --lib-path, unlike plum-checker/plum-wasm-codegen's unit tests, which parse |
| 408b9c0 | 6 | # and compile a single file directly) and, if available, an external |
| 408b9c0 | 7 | # `wasmtime` runtime. |
| 408b9c0 | 8 | # |
| 408b9c0 | 9 | # This exists because the unit tests alone missed a real bug: examples/basics.plum |
| 408b9c0 | 10 | # had an `import std/io` where libs/std/io.plum doesn't exist. The unit tests |
| 408b9c0 | 11 | # never noticed since they don't touch plum-core's loader/import resolution at |
| 408b9c0 | 12 | # all — only compiling and running through the actual CLI catches that class |
| 408b9c0 | 13 | # of problem. |
| 408b9c0 | 14 | # |
| 408b9c0 | 15 | # Usage: scripts/test-examples.sh |
| 408b9c0 | 16 | # Exit code is 0 if every example compiled (and, where checked, ran) correctly. |
| 408b9c0 | 17 | |
| 408b9c0 | 18 | set -uo pipefail |
| 408b9c0 | 19 | |
| 408b9c0 | 20 | cd "$(dirname "${BASH_SOURCE[0]}")/.." |
| 408b9c0 | 21 | |
| 408b9c0 | 22 | WORKDIR=$(mktemp -d) |
| 408b9c0 | 23 | trap 'rm -rf "$WORKDIR"' EXIT |
| 408b9c0 | 24 | |
| 408b9c0 | 25 | echo "Building plum-cli..." |
| 408b9c0 | 26 | if ! cargo build -p plum-cli --quiet 2>"$WORKDIR/build.log"; then |
| 408b9c0 | 27 | echo "FAIL: plum-cli failed to build" >&2 |
| 408b9c0 | 28 | cat "$WORKDIR/build.log" >&2 |
| 408b9c0 | 29 | exit 1 |
| 408b9c0 | 30 | fi |
| 408b9c0 | 31 | PLUM_BIN="target/debug/plum" |
| 408b9c0 | 32 | |
| 408b9c0 | 33 | HAVE_WASMTIME=0 |
| 408b9c0 | 34 | if command -v wasmtime >/dev/null 2>&1; then |
| 408b9c0 | 35 | HAVE_WASMTIME=1 |
| 408b9c0 | 36 | else |
| 408b9c0 | 37 | echo "note: wasmtime CLI not found on PATH — will compile every example but skip running them" >&2 |
| 408b9c0 | 38 | fi |
| 408b9c0 | 39 | |
| 408b9c0 | 40 | # Examples that export `main` and are expected to run without trapping. Kept |
| 408b9c0 | 41 | # in sync with plum-wasm-codegen/tests/examples_test.rs. |
| 408b9c0 | 42 | has_main() { |
| 408b9c0 | 43 | case "$1" in |
| 408b9c0 | 44 | basics|closures|match|methods) return 0 ;; |
| 408b9c0 | 45 | *) return 1 ;; |
| 408b9c0 | 46 | esac |
| 408b9c0 | 47 | } |
| 408b9c0 | 48 | |
| 408b9c0 | 49 | # Expected `main` return value for examples whose result is asserted in |
| 408b9c0 | 50 | # plum-wasm-codegen/tests/examples_test.rs. Empty means "just don't trap" |
| 408b9c0 | 51 | # (e.g. basics.plum's main returns Unit, not a value to compare). |
| 408b9c0 | 52 | expected_value() { |
| 408b9c0 | 53 | case "$1" in |
| 408b9c0 | 54 | closures) echo 120 ;; |
| 408b9c0 | 55 | match) echo 5 ;; |
| 408b9c0 | 56 | methods) echo 10 ;; |
| 408b9c0 | 57 | *) echo "" ;; |
| 408b9c0 | 58 | esac |
| 408b9c0 | 59 | } |
| 408b9c0 | 60 | |
| 408b9c0 | 61 | failed=0 |
| 408b9c0 | 62 | passed=0 |
| 408b9c0 | 63 | |
| 408b9c0 | 64 | for src in examples/*.plum; do |
| 408b9c0 | 65 | name=$(basename "$src" .plum) |
| 408b9c0 | 66 | wasm="$WORKDIR/$name.wasm" |
| 408b9c0 | 67 | |
| 408b9c0 | 68 | printf '%-14s compile ... ' "$name" |
| 408b9c0 | 69 | if ! "$PLUM_BIN" compile "$src" -o "$wasm" >"$WORKDIR/$name.compile.log" 2>&1; then |
| 408b9c0 | 70 | echo "FAIL" |
| 408b9c0 | 71 | sed 's/^/ /' "$WORKDIR/$name.compile.log" |
| 408b9c0 | 72 | failed=$((failed + 1)) |
| 408b9c0 | 73 | continue |
| 408b9c0 | 74 | fi |
| 408b9c0 | 75 | echo "ok" |
| 408b9c0 | 76 | |
| 408b9c0 | 77 | if [ "$HAVE_WASMTIME" -eq 1 ] && has_main "$name"; then |
| 408b9c0 | 78 | printf '%-14s run ... ' "$name" |
| 408b9c0 | 79 | if output=$(wasmtime run --invoke main "$wasm" 2>"$WORKDIR/$name.run.log"); then |
| 408b9c0 | 80 | expected=$(expected_value "$name") |
| 408b9c0 | 81 | if [ -n "$expected" ] && [ "$output" != "$expected" ]; then |
| 408b9c0 | 82 | echo "FAIL (expected $expected, got '$output')" |
| 408b9c0 | 83 | failed=$((failed + 1)) |
| 408b9c0 | 84 | continue |
| 408b9c0 | 85 | fi |
| 408b9c0 | 86 | if [ -n "$output" ]; then |
| 408b9c0 | 87 | echo "ok (-> $output)" |
| 408b9c0 | 88 | else |
| 408b9c0 | 89 | echo "ok" |
| 408b9c0 | 90 | fi |
| 408b9c0 | 91 | else |
| 408b9c0 | 92 | echo "FAIL (trapped)" |
| 408b9c0 | 93 | sed 's/^/ /' "$WORKDIR/$name.run.log" |
| 408b9c0 | 94 | failed=$((failed + 1)) |
| 408b9c0 | 95 | continue |
| 408b9c0 | 96 | fi |
| 408b9c0 | 97 | fi |
| 408b9c0 | 98 | |
| 408b9c0 | 99 | passed=$((passed + 1)) |
| 408b9c0 | 100 | done |
| 408b9c0 | 101 | |
| 408b9c0 | 102 | echo |
| 408b9c0 | 103 | echo "$passed passed, $failed failed" |
| 408b9c0 | 104 | [ "$failed" -eq 0 ] |