67 lines
4.8 KiB
Nu
67 lines
4.8 KiB
Nu
#!/usr/bin/env nu
|
|
# Real service acceptance tests. Every created box is removed, including failures.
|
|
def check [condition: bool, message: string] {
|
|
if not $condition { error make {msg: $message} }
|
|
print $'ok - ($message)'
|
|
}
|
|
def call [component: path, root: path, args: list<string>] {
|
|
^wasmtime run -S http -S cli-exit-with-code=y --dir $'($root)::/' $component ...$args | complete
|
|
}
|
|
def require [] {
|
|
let result = $in
|
|
if $result.exit_code != 0 { error make {msg: $'box failed: ($result.stderr)'} }
|
|
$result
|
|
}
|
|
def main [component: path = '/home/surma/src/gitea.surma.technology/surma/sausage/target/p1-tools/wasm32-wasip2/release/box.wasm'] {
|
|
let component = ($component | path expand)
|
|
let root = (^mktemp -d /tmp/box-test-XXXXXXXX | str trim)
|
|
mkdir ($root | path join project sub)
|
|
'{"scripts":{"test":"node sub/test.js"}}' | save ($root | path join project package.json)
|
|
'const fs = require("node:fs"); require("node:assert/strict").equal(2 + 2, 4); fs.writeFileSync("result.txt", "npm test passed\n");' | save ($root | path join project sub test.js)
|
|
'binary-safe file payload' | save ($root | path join input.txt)
|
|
let created = (call $component $root [create --ttl 600])
|
|
let id = if $created.stdout =~ 'tc-[a-z0-9]{6}' { $created.stdout | str trim } else { $created.stderr | parse --regex '(?P<id>tc-[a-z0-9]{6})' | get id | first | default '' }
|
|
if $id == '' { error make {msg: $'create returned no recoverable id: ($created.stderr); test files: ($root)'} }
|
|
let outcome = try {
|
|
$created | require | ignore
|
|
check ($id =~ '^tc-[a-z0-9]{6}$') 'create returns id'
|
|
let inventory = (call $component $root [ls] | require)
|
|
check ($inventory.stdout | str contains $id) 'ls contains box'
|
|
let exec = (call $component $root [exec $id -- sh -c 'printf hello; printf problem >&2; exit 7'])
|
|
check ($exec.exit_code == 7 and $exec.stdout == 'hello' and ($exec.stderr | str contains 'problem')) 'exec preserves both streams and exit 7'
|
|
call $component $root [put $id /input.txt /tmp/file.txt] | require | ignore
|
|
call $component $root [get $id /tmp/file.txt /returned.txt] | require | ignore
|
|
check ((open --raw ($root | path join returned.txt)) == (open --raw ($root | path join input.txt))) 'file put/get round trip'
|
|
call $component $root [put $id /project /work] | require | ignore
|
|
call $component $root [get $id /work /tree] | require | ignore
|
|
check ((open --raw ($root | path join tree sub test.js)) == (open --raw ($root | path join project sub test.js))) 'tree round trip retains subfolder'
|
|
let npm = (call $component $root [exec $id --timeout 120 -- sh -c 'cd /work && npm test'] | require)
|
|
check ($npm.stdout | str contains 'node sub/test.js') 'npm test runs in box'
|
|
call $component $root [get $id /work/result.txt /result.txt] | require | ignore
|
|
check ((open --raw ($root | path join result.txt)) == "npm test passed\n") 'Node result returns to world'
|
|
let large = (call $component $root [exec $id -- node -e 'process.stdout.write(Buffer.alloc(1200003,255)); process.stderr.write("raw stderr");'] | require)
|
|
check (($large.stdout | str length --utf-8-bytes) < 16600) 'large binary inline output stays bounded'
|
|
let archive = ($large.stderr | parse --regex 'box stdout archive: (?P<path>[^\n]+)' | get path | first)
|
|
let bytes = (open --raw ($root | path join ($archive | str trim --left --char '/')))
|
|
check (($bytes | bytes length) == 1200003) 'full binary archive retains byte total'
|
|
let repeated = (call $component $root [exec $id -- sh -c 'printf collision-check'] | require)
|
|
check ($repeated.stdout == 'collision-check') 'later exec returns output'
|
|
check ((open --raw ($root | path join ($archive | str trim --left --char '/'))) == $bytes) 'later archive leaves earlier output intact'
|
|
let log = (call $component $root [logs $id] | require)
|
|
check ($log.stderr | str contains 'box build archive:') 'logs retains build archive'
|
|
let wit = (^wasm-tools component wit $component | complete)
|
|
check ($wit.exit_code == 0) 'component WIT inspection'
|
|
print $wit.stdout
|
|
let imports = ($wit.stdout | lines | where {|line| $line | str trim | str starts-with 'import ' })
|
|
check ($imports | all {|line| $line | str trim | str starts-with 'import wasi:' }) 'component imports only WASI interfaces'
|
|
null
|
|
} catch {|failure| $failure }
|
|
let removed = (call $component $root [rm $id])
|
|
print $removed.stderr
|
|
check ($removed.exit_code == 0) $'rm removes ($id)'
|
|
let after = (call $component $root [ls] | require)
|
|
check (not ($after.stdout | str contains $id)) 'removed box absent from ls'
|
|
if $outcome != null { error make {msg: $'acceptance failed: ($outcome); retained evidence: ($root)'} }
|
|
print $'PASS; world files and archives: ($root)'
|
|
}
|