aboutsummaryrefslogtreecommitdiff
path: root/tests/test.sh
diff options
context:
space:
mode:
authorGravatar Moon Flower <moonflower@elhenney.local> 2026-10-14 08:29:46 +0330
committerGravatar Moon Flower <moonflower@elhenney.local> 2026-10-14 08:29:46 +0330
commit1c53304d03414890af0da7432d1aea87e754a14a (patch)
tree97190d86cf548c9bc63f68c86a4d2a4f09809713 /tests/test.sh
parenta (diff)
feat: grow memory limits, add icon/actor libraries, overhaul LSP diagnostics
Compiler and VM - make every memory map limit dynamic and adjustable at both build time and runtime, including compiler tables, stacks, and every execution region - reserve and grow tables, operand and return stacks, frame segments, and image-building output without relocating live code or globals - rename i/o and string helpers consistently (puts -> put_s, putn -> put_n, scat -> cat_s) across compiler, runtime, examples, tests, and docs - recast and consume values assigned to globals from inside functions - allow fixed and const together, add typed closure returns (fn:t(...)), multi-include syntax (include rt, run, core;), and recurse type inference - never infer string literals as word, anywhere, as argument, variable, or return type - draft docs/BORROW.md: a borrow checker less intrusive than Rust's but more intelligent LSP and editor integration - require explicit includes and give every toolchain area its own namespace (rt, lsp, run, core) - hover for built-in types, inferred types, values known at hover time, array and pointer lifetime/size, library names in include statements, and inferred lifetimes with explanations - honor /* */ comments as documentation for variables and arguments, and stop misattributing section headers or trailing comments as variable hints - stream diagnostics and cancel stale requests on change - jump to definition and references, including cross-file - quick fixes with automatic library import, and namespace completion Hints and diagnostics - render hints as blue squigglies by default, with hints on/small/off per file - suppress magic-number hints via a preceding /* */ comment, and say so - warn on unused arguments; allow multiple _ discards in parameters, pattern matching, and tagged enums, warning if a _ is actually used - rewrite hint and comment prose in professional compiler-doc register Libraries - add icon.zc: run-time self-modification, find/replace syntax, type and block edits, and step-through inspection of locals and globals - add actor.zc: async actors with Actor<I,O>, implicit this, spawn/recv/send, injected into the compiler machinery at include time rather than built in Tooling and docs - reorganize sources, tests, and designs into subdirectories - unify windows entry points in tinyvm.bat and add a matching tinyvm.sh - add --help across the toolchain - polish the learning guide, stdlib docs, and design notes Tests - add accept, reject, and regression coverage across the compiler, LSP, - runtime, icon, actors, threads, formatting, and the toolchain contracts, plus fuzzers and property tests
Diffstat (limited to 'tests/test.sh')
-rwxr-xr-xtests/test.sh135
1 files changed, 114 insertions, 21 deletions
diff --git a/tests/test.sh b/tests/test.sh
index 27d60f7..e7f8f7c 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -20,7 +20,7 @@
cd "$(dirname "$0")/.."; T=$(mktemp -d); trap 'rm -rf $T' EXIT
ok=0; bad=0
chk(){ if [ "$1" = "$2" ]; then echo "ok $3"; ok=$((ok+1)); else echo "FAIL $3: got [$1]"; bad=$((bad+1)); fi; }
-src(){ cat src/runtime/rt.zc src/compiler/compiler.zc; }
+src(){ cat src/runtime/rt.zc src/core/core.zc src/compiler/compiler.zc; }
# -j N runs N sections at a time: j is how many cores to use. each section
# writes its own log, so the output still reads in the order it always did.
JOBS=1; QUICK=0; SELECT=""
@@ -45,7 +45,7 @@ ROOT=$T
# built here rather than inside a section: interp runs the program list on
# it, and the run-only and bare-metal sections read it as the reference.
-gcc -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy || exit 1
+gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy || exit 1
gcc -O2 -w -fwrapv src/tools/genmap.c -Isrc/core -o $T/genmap || exit 1
# the c helper for tests/programs/structval.zc: structs by value, loaded with cload
mkdir -p build && gcc -shared -fPIC -w tests/data/sbv.c -o build/sbv.so || exit 1
@@ -57,9 +57,9 @@ gcc -O1 -w -fwrapv src/tools/zc0.c -Isrc/core -o $T/zc0 && gcc -O1 -w -fwrapv sr
mkdir $T/s0 $T/s1
cp src/core/core.c src/core/io_linux.c src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h $T/s0/; cp src/core/core.c src/core/io_linux.c src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h $T/s1/
src | $T/zc0 > $T/s0/genome.h || exit 1
-gcc -O2 -w -fwrapv -DJTYPE=int $T/s0/core.c $T/s0/io_linux.c -o $T/zy0
+gcc -pthread -O2 -w -fwrapv -DJTYPE=int $T/s0/core.c $T/s0/io_linux.c -o $T/zy0
selfc $T/zy0 $T/g1.bin; $T/mkg < $T/g1.bin > $T/s1/genome.h
-gcc -O2 -w -fwrapv -DJTYPE=int $T/s1/core.c $T/s1/io_linux.c -o $T/zy1
+gcc -pthread -O2 -w -fwrapv -DJTYPE=int $T/s1/core.c $T/s1/io_linux.c -o $T/zy1
selfc $T/zy1 $T/g2.bin
cmp -s $T/g1.bin $T/g2.bin && chk 1 1 "fixpoint: the compiler compiles itself to the same $(($(wc -c < $T/g1.bin) / 8)) words" || chk 0 1 "fixpoint"
cmp -s $T/s1/genome.h src/core/genome.h && chk 1 1 "genome.h is up to date" || chk 0 1 "genome.h is stale (cp the bootstrap output over it)"
@@ -124,7 +124,7 @@ run(){ # $1 = vm command, $2 = label
chk "$($vm < tests/programs/csyn.zc)" "13 0 5 6 0" "$l do/while, enum, and a C cast"
chk "$($vm < tests/programs/use_std.zc)" "42 -7 1" "$l include and the string helpers"
chk "$($vm < tests/programs/stdbuf.zc)" "4 1 266 8" "$l stdlib arena and packed byte buffer"
- chk "$($vm < tests/programs/stdmore.zc)" "$(printf '5 1 0 0 7 copy me 12 -1 0\n9 mixed 123 9 MIXED 123\n11 [padded line]\n42 3 9 10 12 81 9 10 -1 0')" "$l stdlib text and num helpers"
+ chk "$($vm < tests/programs/stdmore.zc)" "$(printf '5 1 0 0 7 copy me 12 -1 0 1 0 1\n9 mixed 123 9 MIXED 123\n11 [padded line]\n42 3 9 10 12 81 9 10 -1 0\n6 1 2 -1 1 0')" "$l stdlib text, byte-string and num helpers"
chk "$(ZC_FILE=tests/data/hi.txt $vm < examples/cli.zc)" "6 h" "$l reading a file named by the environment"
chk "$(ZC_ARG_TEST=ok $vm < tests/programs/args.zc)" "1 <eval> <eval> 1 1" "$l argv and envp from the host, argv[0] is <eval> on stdin"
chk "$(ZC_ARG_TEST=ok $vm < tests/programs/capture.zc)" "0
@@ -155,6 +155,8 @@ ABC" "$l o3 lifts byte loads and stores"
chk "$($vm < tests/programs/strings.zc)" "hi! 3 3 104 i! 1 1 1 -42 42 -42 11 1 -9223372036854775808 0 1 3 10 1 1 1 W ab" "$l byte strings"
chk "$($vm < tests/programs/share.zc)" "1 2 1 4 1 1 1 1 42 1 1 1 6 0" "$l shared cons cells"
chk "$($vm < tests/programs/share_dbg.zc)" "7 1" "$l memdebug accepts a shared cell"
+ chk "$($vm < tests/programs/global_transfer.zc)" "5 9" "$l an m or u owner stored in a global is transferred"
+ chk "$($vm < tests/programs/closure_result.zc)" "8 1.500000" "$l a closure with a declared result type"
chk "$($vm < examples/strings.zc)" "hello, zc
9 42" "$l byte string example"
chk "$(ZC_BSTR=zybyte $vm < tests/programs/bstr_io.zc)" "byte-io 7 7 1 6 122 101" "$l byte-string file and getenv"
@@ -174,7 +176,11 @@ ABC" "$l o3 lifts byte loads and stores"
chk "$($vm < tests/programs/arrays.zc | tr '\n' '/')" "100 128 9801 9801 99 3 4 12 19 8 19 28/0/" "$l growable and fixed arrays"
chk "$($vm < tests/programs/o3.zc)" "3142 42 43 9 57 98781 520625 10192 -18782 1152" "$l o3 regions: loops, calls, recursion, switch, arrays, more vars than registers"
chk "$($vm < tests/programs/o3scopes.zc)" "116" "$l o3 registers shared by scopes, cached fixed arrays"
- chk "$($vm < tests/programs/o3fat.zc)" "node node 3 box node [0]int" "$l o3 data gets fattened on the way out"
+ chk "$($vm < tests/programs/borrow_rules.zc)" "$(cat tests/programs/borrow_rules.expected)" "$l inferred transfers, projections and shared closure cells"
+ chk "$($vm < tests/programs/replace_owner.zc)" "$(cat tests/programs/replace_owner.expected)" "$l replacing a released owner moves ownership and cleans up once"
+ chk "$($vm < tests/programs/temporary_borrows.zc)" "$(cat tests/programs/temporary_borrows.expected)" "$l temporary borrows preserve aliases and release allocations"
+ chk "$($vm < tests/programs/array_values.zc)" "$(cat tests/programs/array_values.expected)" "$l array initializers, designators, zero filling, nested and compound literals"
+ chk "$($vm < tests/programs/o3fat.zc)" "node node 3 box node int[0]" "$l o3 data gets fattened on the way out"
chk "$($vm < tests/programs/o3call.zc)" "0 0 4 23 55 node" "$l o3 calls o3 directly, and new stamps the header"
chk "$($vm < tests/programs/o3direct.zc | md5sum)" "$(md5sum < tests/programs/o3direct.expected)" "$l o3 calls: arguments, results, recursion, floats, pointers, the ways out of a fast call"
chk "$($vm < tests/programs/o3licm.zc)" "3184200 7950 315 50 260 -56" "$l o3 hoists loop invariants and shares values between blocks"
@@ -193,8 +199,14 @@ ABC" "$l o3 lifts byte loads and stores"
}
s_interp() {
T=$ROOT/interp
- gcc -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy
run $T/zy "interp"
+ python3 tests/drivers/array_methods_test.py $T/zy > $T/arrays.out 2>&1; r=$?
+ grep -v '^ok' $T/arrays.out
+ chk $r 0 "native array receiver, algorithm and ownership contracts"
+ python3 tests/drivers/actor_test.py $T/zy > $T/actor.out 2>&1; r=$?
+ grep -v '^ok' $T/actor.out
+ chk $r 0 "native isolated actor acceptance, rejection and regression fixtures"
chk "$(ZC_ARG_TEST=ok $T/zy tests/programs/args.zc alpha beta < tests/programs/args.zc)" "4 <eval> beta 1 1" "interp the command line reaches argv, after <eval>"
chk "$($T/zy < tests/programs/cabi.zc | md5sum)" "$(md5sum < tests/programs/cabi.expected)" "interp native calls and callbacks (extern, cfunc)"
chk "$($T/zy < tests/programs/cabi_o3.zc | md5sum)" "$(md5sum < tests/programs/cabi_o3.expected)" "interp native calls from o3 code, more arguments than registers"
@@ -204,7 +216,7 @@ s_interp() {
chk "$(ZYTRACE=1 $T/zy < tests/programs/o3.zc 2>&1 | grep -c 'micro-ops$')" "8" "every o3 region lifts"
chk "$($T/zy < tests/programs/infer_return.zc)" "3" "an owned return with no .u is inferred from the body"
chk "$($T/zy < tests/programs/discard_m.zc)" "7" "m* discards an unnamed u result"
- chk "$($T/zy < tests/programs/closure.zc | tr '\n' ' ')" "31 35 42 2 7 0 109 30 7 16 33 20 2 " "closures: calls through values, captures, nesting, returns"
+ chk "$($T/zy < tests/programs/closure.zc | tr '\n' ' ')" "31 35 42 2 7 7 109 30 7 16 33 20 101 " "closures: calls through values, captures, nesting, returns"
chk "$($T/zy < tests/programs/decl_undefined.zc 2>&1 | head -1)" "zc: line 1: helper is used but never defined" "a declared function nothing defines fails a build"
if [ "$(uname -s)" = Linux ]; then chk "$($T/zy < tests/programs/rawsys.zc)" "-38" "Host.raw: an unknown syscall number gives -ENOSYS"; else chk "$($T/zy < tests/programs/rawsys.zc)" "-1" "Host.raw: unavailable on this host"; fi
if [ "$(uname -m)" = x86_64 ]; then chk "$($T/zy < tests/programs/rawpid.zc)" "1" "Host.raw: getpid (39 on x86-64) answers"; fi
@@ -212,12 +224,28 @@ s_interp() {
s_micro() {
T=$ROOT/micro
- gcc -O2 -w -fwrapv src/micro/micro.c src/micro/port_linux.c -Isrc/core -Isrc/micro -o $T/zym || exit 1
+ gcc -pthread -DZY_THREADS -O2 -w -fwrapv src/micro/micro.c src/micro/port_linux.c -Isrc/core -Isrc/micro -o $T/zym || exit 1
run $T/zym "micro"
+ python3 tests/drivers/array_methods_test.py $T/zym > $T/arrays.out 2>&1; r=$?
+ grep -v '^ok' $T/arrays.out
+ chk $r 0 "micro array receiver, algorithm and ownership contracts"
+ python3 tests/drivers/actor_test.py $T/zym > $T/actor.out 2>&1; r=$?
+ grep -v '^ok' $T/actor.out
+ chk $r 0 "micro isolated actor acceptance, rejection and regression fixtures"
+ if command -v node >/dev/null; then
+ python3 tests/drivers/fuzz_compiler.py $ROOT/zy $T/zym --js > $T/fuzz.out 2>&1; r=$?
+ else
+ python3 tests/drivers/fuzz_compiler.py $ROOT/zy $T/zym > $T/fuzz.out 2>&1; r=$?
+ fi
+ grep -v '^ok' $T/fuzz.out
+ chk $r 0 "compiler/runtime/stdlib differential fuzz across available hosts"
+ python3 tests/drivers/fuzz_malformed.py $ROOT/zy $T/zym > $T/fuzzmalformed.out 2>&1; r=$?
+ grep -v '^ok' $T/fuzzmalformed.out
+ chk $r 0 "malformed compiler input fuzz and host agreement"
selfc $T/zym $T/gm.bin
cmp -s $T/g1.bin $T/gm.bin && chk 1 1 "microcore self-compile matches" || chk 0 1 "microcore self-compile matches"
gcc -ffreestanding -w -c src/micro/micro.c -Isrc/core -Isrc/micro -o $T/micro.o && gcc -ffreestanding -w -c src/micro/port_stub.c -Isrc/core -Isrc/micro -o $T/stub.o && chk 1 1 "microcore and the stub port compile freestanding" || chk 0 1 "microcore and the stub port compile freestanding"
- gcc -O2 -w -fwrapv -DJTYPE=int -DZY_SOFTFLOAT -DZYINTERP src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zysoft || exit 1
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int -DZY_SOFTFLOAT -DZYINTERP src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zysoft || exit 1
chk "$($T/zysoft < tests/programs/float.zc)" "4.000000 4.500000 3.000000 2.500000 2.500000 0.001500 0.100000 -0.125000 inf -inf nan 1 1 1 0 0 3 -3 3.000000 -2.000000 2" "soft-float fallback matches the hardware line"
chk "$($T/zysoft < tests/programs/ftruth.zc)" "00111000110107" "soft-float negative zero is false"
chk "$($T/zysoft < tests/programs/fo3.zc)" "5997 5997 4.000000 nan 0 3.250000 1 0 0" "soft-float o3 float ops match"
@@ -231,7 +259,7 @@ s_small() {
$T/genmap --preset default --check >/dev/null && chk 1 1 "default map matches the checked-in sources" || chk 0 1 "default map matches the checked-in sources"
$T/genmap --preset small -o $T/small || exit 1
$T/genmap --mode compiler --name small --heap-lo 8192 --heap 20480 --types 8192 \
- --genome 245760 --frame 2048 --return 512 --mark 512 --data 3072 \
+ --genome 393216 --frame 2048 --return 512 --mark 512 --data 3072 \
--snap-cap 1000 --quote-cap 300 -o $T/small-flags || exit 1
cmp -s $T/small/memmap.h $T/small-flags/memmap.h && cmp -s $T/small/rt.zc $T/small-flags/rt.zc \
&& cmp -s $T/small/compiler.zc $T/small-flags/compiler.zc && cmp -s $T/small/map.txt $T/small-flags/map.txt \
@@ -240,8 +268,8 @@ s_small() {
gcc -O1 -w -fwrapv $T/small/zc0.c -o $T/zc0s || exit 1
cat $T/small/rt.zc $T/small/compiler.zc | $T/zc0s > $T/small/genome.h || exit 1
cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h $T/small/
- gcc -O2 -w -fwrapv $T/small/micro.c $T/small/port_linux.c -o $T/zyms || exit 1
- gcc -O2 -w -fwrapv -DJTYPE=int $T/small/core.c $T/small/io_linux.c -o $T/zys || exit 1
+ gcc -pthread -DZY_THREADS -O2 -w -fwrapv $T/small/micro.c $T/small/port_linux.c -o $T/zyms || exit 1
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int $T/small/core.c $T/small/io_linux.c -o $T/zys || exit 1
gcc -ffreestanding -w -c $T/small/micro.c -o $T/micro_s.o && gcc -ffreestanding -w -c $T/small/port_stub.c -o $T/stub_s.o && chk 1 1 "small microcore compiles freestanding" || chk 0 1 "small microcore compiles freestanding"
sameout() { # $1 = other vm, $2 = label, $3 = source file
local a b
@@ -274,6 +302,9 @@ s_small() {
s_runonly() {
T=$ROOT/runonly
+ python3 tests/drivers/runtime_image_test.py --host $T/zy --mkgenome $ROOT/mkg > $T/images.out 2>&1; r=$?
+ grep -v '^ok' $T/images.out
+ chk $r 0 "self-hosted run-only images install enhancements and preserve generic array methods"
# its own run map: the run-only image is built against this one, and the
# small-machine section lays out its own rather than sharing this
$T/genmap --preset run -o $T/run || exit 1
@@ -285,7 +316,7 @@ s_runonly() {
if [ "$1" = gc ]; then input=$T/collector-progress.zc; sed 's/f >= 990/f > 0/' "$2" > "$input"; fi
GENMAP=$T/genmap bash src/tools/automap.sh run $d src/runtime/run.zc "$input" >/dev/null || { chk 0 1 "run $1 builds"; return; }
cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h $d/
- gcc -O2 -w -fwrapv $d/micro.c $d/port_linux.c -o $T/zymr || { chk 0 1 "run $1 links"; return; }
+ gcc -pthread -DZY_THREADS -O2 -w -fwrapv $d/micro.c $d/port_linux.c -o $T/zymr || { chk 0 1 "run $1 links"; return; }
a=$($T/zy < "$input" 2>&1 | tr '\n' '/')
b=$($T/zymr </dev/null 2>&1 | tr '\n' '/')
chk "$b" "$a" "run $1"
@@ -303,7 +334,7 @@ s_runonly() {
runonly strings-ex examples/strings.zc
runonly share tests/programs/share.zc
d=$T/run-echo; GENMAP=$T/genmap bash src/tools/automap.sh run $d src/runtime/run.zc examples/echo.zc >/dev/null && cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h $d/ \
- && gcc -O2 -w -fwrapv $d/micro.c $d/port_linux.c -o $T/zymr \
+ && gcc -pthread -DZY_THREADS -O2 -w -fwrapv $d/micro.c $d/port_linux.c -o $T/zymr \
&& chk "$(printf 'abc\n' | $T/zymr | tr '\n' '/')" "$( (cat examples/echo.zc; printf '`abc\n') | $T/zy | tr '\n' '/')" "run echo" \
|| chk 0 1 "run echo"
# zcc: a program becomes a static binary that runs without stdin and with a held-open pipe
@@ -395,13 +426,13 @@ s_bare() {
s_jit() {
T=$ROOT/jit
if command -v aarch64-linux-gnu-gcc >/dev/null && command -v qemu-aarch64 >/dev/null; then
- aarch64-linux-gnu-gcc -O2 -w -fwrapv -DJTYPE=int -static src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyj || exit 1
+ aarch64-linux-gnu-gcc -pthread -O2 -w -fwrapv -DJTYPE=int -static src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyj || exit 1
printf '#!/bin/sh\nexec qemu-aarch64 %s "$@"\n' $T/zyj > $T/jit; chmod +x $T/jit
run $T/jit "jit"
chk "$(ZYTRACE=1 $T/jit < tests/programs/o3.zc 2>&1 | grep -c 'bytes of arm64')" "8" "jit compiles every o3 region to arm64"
selfc $T/jit $T/gj.bin; cmp -s $T/g1.bin $T/gj.bin && chk 1 1 "jit self-compile matches" || chk 0 1 "jit self-compile matches"
# native calls need a dynamic binary (a static one has no dlsym), run against the aarch64 libc
- if [ -d /usr/aarch64-linux-gnu/lib ] && aarch64-linux-gnu-gcc -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyjd -ldl 2>/dev/null; then
+ if [ -d /usr/aarch64-linux-gnu/lib ] && aarch64-linux-gnu-gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyjd -ldl 2>/dev/null; then
chk "$(qemu-aarch64 -L /usr/aarch64-linux-gnu $T/zyjd < tests/programs/cabi.zc | md5sum)" "$(md5sum < tests/programs/cabi.expected)" "jit native calls and callbacks (extern, cfunc)"
chk "$(qemu-aarch64 -L /usr/aarch64-linux-gnu $T/zyjd < tests/programs/cabi_o3.zc | md5sum)" "$(md5sum < tests/programs/cabi_o3.expected)" "jit native calls from o3 code, stack arguments"
chk "$(qemu-aarch64 -L /usr/aarch64-linux-gnu $T/zyjd < tests/programs/cabi_sized.zc | md5sum)" "$(md5sum < tests/programs/cabi_sized.expected)" "jit native calls with f32 and the sized integers"
@@ -417,7 +448,7 @@ s_llvm() {
T=$ROOT/llvm
# llvm-config can exist without the headers and static libs (a runtime-only install), so the gate is a real build
llvm_ok=0
- if command -v llvm-config >/dev/null && gcc -O2 -w -fwrapv -DJTYPE=int -DZYLLVM $(llvm-config --cflags) src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyl $(llvm-config --ldflags --libs) 2>/dev/null; then llvm_ok=1; fi
+ if command -v llvm-config >/dev/null && gcc -pthread -O2 -w -fwrapv -DJTYPE=int -DZYLLVM $(llvm-config --cflags) src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyl $(llvm-config --ldflags --libs) 2>/dev/null; then llvm_ok=1; fi
if [ $llvm_ok = 1 ]; then
run $T/zyl "llvm"
chk "$(ZYTRACE=1 $T/zyl < tests/programs/o3.zc 2>&1 | grep -c 'compiled by llvm')" "8" "llvm compiles every o3 region"
@@ -460,12 +491,12 @@ s_lsp() {
chk "$($lsp < examples/hello.zc)" "no errors" "lsp: a clean program"
chk "$($lsp < tests/errors/back_to_m.zc | head -1 | cut -d' ' -f2-)" "error: $(head -1 tests/errors/back_to_m.zc | sed 's#^// expect: ##')" "lsp: the compiler's own message"
h=$($lsp < examples/opt_test.zc)
- for w in "is never read" "is never reassigned; make it a const" "is a shift; write << 3" "the number 1234 has no name" "new inside a loop" "stack buffer"; do
+ for w in "is never read" "is never reassigned; make it a const" "is a shift; write << 3" "unannotated numeric literal 1234" "new inside a loop" "stack buffer"; do
case "$h" in *"$w"*) chk 1 1 "lsp hint: $w";; *) chk 0 1 "lsp hint: $w";; esac
done
chk "$($lsp < examples/struct_closure_opt.zc | grep -c error)" "0" "lsp: methods and closures check clean"
# a file of a larger build checks on its own: its bodyless declarations are not errors in check mode
- for f in src/runtime/rt.zc src/runtime/run.zc src/lsp/server.zc; do chk "$($lsp < $f | grep -c ': error:')" "0" "lsp: $f checks alone"; done
+ for f in src/runtime/rt.zc src/runtime/run.zc src/compiler/compiler.zc src/lsp/server.zc; do chk "$($lsp < $f | grep -c ': error:')" "0" "lsp: $f checks alone"; done
chk "$($lsp < tests/programs/decl_undefined.zc)" "no errors" "lsp: a bodyless declaration is not an error in check mode"
chk "$($lsp < tests/programs/undefined_call.zc | grep -c ': error:')" "1" "lsp: a call to a name nothing defines is still an error"
chk "$($lsp --annotate < tests/programs/annotate.zc | md5sum)" "$(md5sum < tests/programs/annotate.expected)" "lsp --annotate writes the types the compiler can see into a program"
@@ -475,9 +506,44 @@ s_lsp() {
printf 'Content-Length: 40\r\n\r\n{"jsonrpc": [2.0", "method": "x"}' | timeout 10 $lsp > /dev/null 2>&1; chk $? 0 "lsp: a stray brace in an array ends the message, and the server exits"
if [ $QUICK = 1 ]; then echo "skip lsp protocol and corpus tests (quick)"
elif command -v node >/dev/null; then
+ node tests/drivers/fuzz_lsp.js $lsp > $T/fuzzlsp.out 2>&1; r=$?
+ grep -v '^ok' $T/fuzzlsp.out
+ chk $r 0 "lsp fuzz: malformed recovery, long-session churn and cache invalidation"
node tests/drivers/storage_analysis_test.js $lsp > $T/storage.out 2>&1; r=$?
grep -v '^ok' $T/storage.out
chk $r 0 "lsp: definite storage warnings and reference lifetime hovers"
+ node tests/drivers/hints_test.js $lsp > $T/hints.out 2>&1; r=$?
+ grep -v '^ok' $T/hints.out
+ chk $r 0 "lsp: hints are information diagnostics and obey hints on, small and off"
+ node tests/drivers/stream_test.js $lsp > $T/stream.out 2>&1; r=$?
+ grep -v '^ok' $T/stream.out
+ chk $r 0 "lsp: large checks stream and a stale check is dropped"
+ node tests/drivers/format_test.js $lsp > $T/format.out 2>&1; r=$?
+ grep -v '^ok' $T/format.out
+ chk $r 0 "lsp: the formatter keeps tokens, is stable and follows its options"
+ node tests/drivers/include_test.js $lsp > $T/include.out 2>&1; r=$?
+ grep -v '^ok' $T/include.out
+ chk $r 0 "lsp: relative includes, string diagnostics and explicit std"
+ for group in quickfix modulehover namespacecompletion navigation inference qualifiers; do
+ CONTRACT_GROUP=$group node tests/drivers/toolchain_lsp_contract_test.js $lsp > $T/contracts-$group.out 2>&1; r=$?
+ grep -v '^ok' $T/contracts-$group.out
+ chk $r 0 "lsp: $group contracts"
+ done
+ node tests/drivers/codeactions_client_test.js > $T/codeactions-client.out 2>&1; r=$?
+ grep -v '^ok' $T/codeactions-client.out
+ chk $r 0 "lsp: versioned import quick-fix edits"
+ node tests/drivers/completion_test.js $lsp > $T/completion.out 2>&1; r=$?
+ grep -v '^ok' $T/completion.out
+ chk $r 0 "lsp: fuzzy completions, signatures, scope and expired lifetimes"
+ node tests/drivers/analysis_cache_test.js $lsp > $T/analysiscache.out 2>&1; r=$?
+ grep -v '^ok' $T/analysiscache.out
+ chk $r 0 "lsp: analysis cache reuse and invalidation"
+ node tests/drivers/hover_surface_test.js $lsp > $T/hoversurface.out 2>&1; r=$?
+ grep -v '^ok' $T/hoversurface.out
+ chk $r 0 "lsp: embedded declarations, constant values, asm and std hovers"
+ node tests/drivers/nav_test.js $lsp > $T/nav.out 2>&1; r=$?
+ grep -v '^ok' $T/nav.out
+ chk $r 0 "lsp: definition and references across includes"
node tests/drivers/lsp_test.js $lsp > $T/lsp.out 2>&1; r=$?
grep -v '^ok' $T/lsp.out
chk $r 0 "lsp: protocol and corpus tests ($(grep -c '^ok' $T/lsp.out) checks)"
@@ -496,6 +562,12 @@ s_lsp() {
chk $r 0 "lsp: the extension's cache, end to end ($(grep -c '^ok' $T/ecache.out) checks)"
# the same server as WebAssembly, through the extension's host (needs clang)
if command -v clang >/dev/null && clang --print-targets 2>/dev/null | grep -q wasm32 && LSP_BUILD_DIR=$T/lsp LSP_REUSE_BUILD=1 bash src/tools/mklspwasm.sh $T/lsp/lsp.wasm >/dev/null 2>&1; then
+ node tests/drivers/hover_surface_test.js --wasm $T/lsp/lsp.wasm > $T/hoversurfacewasm.out 2>&1; r=$?
+ grep -v '^ok' $T/hoversurfacewasm.out
+ chk $r 0 "lsp: embedded and asm hovers through the wasm host"
+ node tests/drivers/completion_test.js --wasm $T/lsp/lsp.wasm > $T/completionwasm.out 2>&1; r=$?
+ grep -v '^ok' $T/completionwasm.out
+ chk $r 0 "lsp: completions through the wasm host"
node tests/drivers/lsp_wasm.js $T/lsp/lsp.wasm > $T/lspw.out 2>&1; r=$?
grep -v '^ok' $T/lspw.out
chk $r 0 "lsp: wasm server through the extension's host ($(grep -c '^ok' $T/lspw.out) checks)"
@@ -503,9 +575,20 @@ s_lsp() {
# the same server run by the javascript vm, the extension's fallback when wasm is not there.
# the vm starts at the image's heap and grows on the heap's request, so a long document is the test
node src/js/extract_lsp.js >/dev/null && mkdir -p $T/vmserver && cp src/js/tinyvm.js src/js/layout.js src/js/lsp.json $T/vmserver/
+ node tests/drivers/hover_surface_test.js --vm $T/vmserver > $T/hoversurfacevm.out 2>&1; r=$?
+ grep -v '^ok' $T/hoversurfacevm.out
+ chk $r 0 "lsp: embedded and asm hovers through the javascript host"
+ node tests/drivers/completion_test.js --vm $T/vmserver > $T/completionvm.out 2>&1; r=$?
+ grep -v '^ok' $T/completionvm.out
+ chk $r 0 "lsp: completions through the javascript host"
node tests/drivers/lsp_vm.js $T/vmserver > $T/lspvm.out 2>&1; r=$?
grep -v '^ok' $T/lspvm.out
chk $r 0 "lsp: the server in the javascript vm, through the extension's host ($(grep -c '^ok' $T/lspvm.out) checks)"
+ if [ -f $T/lsp/lsp.wasm ]; then
+ node tests/drivers/stream_host_test.js $T/lsp/lsp.wasm $T/vmserver > $T/streamhost.out 2>&1; r=$?
+ grep -v '^ok' $T/streamhost.out
+ chk $r 0 "lsp: the wasm and vm servers stream and drop stale checks"
+ fi
else echo "skip lsp protocol tests (no node)"; fi
else chk 0 1 "lsp server builds"; fi
}
@@ -519,10 +602,14 @@ s_js() {
chk "$(node src/js/tinyvm.js examples/fact.zc | tail -1)" "3628800" "js vm: factorial"
chk "$(node src/js/tinyvm.js examples/primes.zc | tail -1)" "widest gap: 72, after 31397" "js vm: primes"
chk "$(node src/js/tinyvm.js tests/programs/growone.zc)" "12 1" "js vm: a block past the initial heap grows the machine"
+ chk "$(node src/js/tinyvm.js tests/programs/replace_owner.zc)" "$(cat tests/programs/replace_owner.expected)" "js vm: replacement ownership and cleanup"
if command -v clang >/dev/null && command -v wasm-ld >/dev/null && clang --print-targets 2>/dev/null | grep -q wasm32; then
bash src/web/build.sh $T/zc.wasm >/dev/null && node tests/drivers/wasm_test.js $T/zc.wasm > $T/wasm.out 2>&1; r=$?
grep -v '^ok' $T/wasm.out
chk $r 0 "wasm: the microcore in webassembly ($(grep -c '^ok' $T/wasm.out) checks)"
+ node tests/drivers/fuzz_wasm.js $T/zc.wasm > $T/fuzzw.out 2>&1; r=$?
+ grep -v '^ok' $T/fuzzw.out
+ chk $r 0 "wasm: compiler/runtime/stdlib differential fuzz"
else echo "skip wasm (no clang with the wasm32 target, or no wasm-ld)"; fi
else echo "skip js and wasm (no node)"; fi
}
@@ -532,6 +619,12 @@ s_make() {
# the makefile builds the programs and the run-only image tool
if command -v make >/dev/null; then
make -s BIN=$T/mbin B=$T/mbuild all >/dev/null 2>&1 && chk "$($T/mbin/zy < examples/hello.zc)" "hello, world!" "make: bin/zy runs a program" || chk 0 1 "make: all builds"
+ python3 tests/drivers/cli_help_test.py --group binaries --bin-dir $T/mbin > $T/help.out 2>&1; r=$?
+ grep -v '^ok' $T/help.out
+ chk $r 0 "command-line help, invalid options and existing lsp source modes"
+ python3 tests/drivers/cli_help_test.py --group scripts > $T/scripthelp.out 2>&1; r=$?
+ grep -v '^ok' $T/scripthelp.out
+ chk $r 0 "build-script help exits without reading input or starting a build"
make -s BIN=$T/mbin B=$T/mbuild run PROG=examples/hello.zc >/dev/null 2>&1 && chk "$($T/mbuild/run/zymr </dev/null)" "hello, world!" "make: run PROG= builds a run-only image" || chk 0 1 "make: run builds"
else echo "skip make (not installed)"; fi
}
@@ -540,7 +633,7 @@ s_make() {
# every block in it is one of those examples (tests/drivers/learn.py)
s_learn() {
T=$ROOT/learn
- gcc -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy
# learn.py prints its own ok and FAIL lines, which the tally below counts
python3 tests/drivers/learn.py $T/zy; true
}