Files
capy-bearer/scripts/test_capy_native.sh
udoandClaude Fable 5.1 ca8edb6bd1 Delete the queued task API, the task pool, and the job API
Tasks are fire-and-forget only: function TASK:NAME(props : dval) and
task_execute(target, timeout_seconds, props). The durable queue, the
TASK_WORKERS pool with its leases, cancellation, admission health and recovery,
task, task_status, task_await, task_cancel, the background form of shell_exec,
job_status, job_result, job_await, job_cancel, http_request_async, the job
directory and its --job-worker helper, their pages, fixtures, guide sections,
settings documentation and parity rows are gone. A bare TASK handler is a
compile error.

shell_exec(command, {on_done: "/unit.capy:NAME"}) keeps the one job use that
mattered: the command runs in the detached task runner, and TASK:NAME of the
unit receives command, exit_code, stdout, stderr, timed_out and
output_truncated when it finishes. Unit path resolution is shared by tasks and
services. The tasks guide is "Tasks and commands" with a stable slug change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 01:14:19 +00:00

192 lines
12 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
cd "$(dirname "$0")/.."
BUILD_DIR="$PWD/tmp/capy-native-tests"
mkdir -p "$BUILD_DIR"
exec 9>"$BUILD_DIR/suite.lock"
flock -w 300 9
SECONDS=0
stage_started=0
stage_done() {
echo "$1: $((SECONDS - stage_started))s"
stage_started=$SECONDS
}
COMMON=(-std=c++20 -O1 -Wall -Wextra -Werror -pedantic -Isrc/capy)
ABI_VERSION=$(awk '/BEARER_WASM_CORE_ABI_VERSION/ {print $3; exit}' src/wasm/abi.h)
PARITY_MANIFEST="$BUILD_DIR/capy-capability-manifest.md"
needs_rebuild() {
local output=$1
shift
[[ ! -x "$output" ]] || find "$@" -newer "$output" -print -quit | grep -q .
}
if [[ ! -f "$BUILD_DIR/release" ]] || needs_rebuild "$BUILD_DIR/capyc" src/capy src/wasm/abi.h src/lib/markup-context.h scripts/build_capy.sh; then
scripts/build_capy.sh "$BUILD_DIR/capyc" release
touch "$BUILD_DIR/release"
else
echo "Reusing $BUILD_DIR/capyc"
fi
CAPYC="$BUILD_DIR/capyc" scripts/test_capy_reproducible_artifact.sh
"$BUILD_DIR/capyc" --check-stdlib src/capy/stdlib.capy src/capy/stdlib.embedded.h
python3 - <<'STATIC_GATE'
from pathlib import Path
import re
handlers = re.compile(r'^\s*function\s+(?:RENDER|COMPONENT(?::\s*[A-Za-z_][A-Za-z0-9_]*)?|CLI(?::\s*[A-Za-z_][A-Za-z0-9_]*)?|WS|TASK:\s*[A-Za-z_][A-Za-z0-9_]*|SERVICE:\s*[A-Za-z_][A-Za-z0-9_]*|INIT|ONCE|SERVE_HTTP(?::\s*[A-Za-z_][A-Za-z0-9_]*)?)\s*(?:\(([^)]*)\))?', re.M)
removed = re.compile(r'\b(?:request_context|request_param|request_get|request_post|request_cookie|request_session|request_body|request_base_url|request_script_url|request_query_path|request_query_route|cli_input|cli_arg|ws_message|ws_connection_id|ws_scope|ws_opcode|ws_is_binary|ws_connections|ws_connection_count|to_bool|to_f64|to_s64|to_u64|to_lower|to_upper|dval_to_json|dval_to_stringmap|request_route_from_raw_path|expand_path|path_is_within|path_real|route_from_raw_path|route_path_is_safe|route_path_normalize|route_path_sanitize|request_perf|password_needs_rehash|ascii_safe_name|component_exists|memcache_escape_key|sha256_hex|hmac_sha256_hex|shell_spawn|process_start_directory)\s*\(')
paths = [path for line in __import__('subprocess').check_output(['git', 'ls-files', '*.capy'], text=True).splitlines() if (path := Path(line)).is_file()]
errors = []
for path in paths:
source = path.read_text()
for match in handlers.finditer(source):
header = source[match.start():match.end()]
props_handler = re.match(r'\s*function\s+(?:COMPONENT|TASK|SERVICE)', header) is not None
declared = [part.strip().replace(' ', '') for part in (match.group(1) or '').split(',') if part.strip()]
allowed = {(), ('request:dval',)} | ({('props:dval',), ('props:dval', 'request:dval')} if props_handler else set())
if tuple(declared) not in allowed:
shape = '(props : dval, request : dval)' if props_handler else '(request : dval)'
errors.append(f'{path}:{source.count(chr(10), 0, match.start()) + 1}: handler parameters must be a prefix-free subset of {shape}')
code = re.sub(r'"(?:\\.|[^"\\])*"', '""', source)
if re.search(r'\brequest\s*:\s*request\b', code):
errors.append(f'{path}: public request type is not allowed')
if removed.search(code):
errors.append(f'{path}: removed request reader is not allowed')
fixture = Path('site/tests/capy-request-context.capy').read_text()
for field in ('method', 'query', 'form', 'headers', 'cookies', 'body', 'files', 'route', 'url', 'server', 'session', 'config', 'call', 'connection', 'unit', 'websocket'):
if f'request.{field}' not in fixture:
errors.append(f'site/tests/capy-request-context.capy: missing request schema field {field}')
if errors:
raise SystemExit('\n'.join(errors))
STATIC_GATE
if git grep -nE '[0-9](s32|s64|u64)\b' -- src/capy/stdlib.capy 'site/**/*.capy' 'site/doc/**/*.txt' docs/capy-language.md; then
echo "Capy source or documentation still uses a removed numeric suffix" >&2
exit 1
fi
python3 scripts/generate_capy_doc_signatures.py --capyc "$BUILD_DIR/capyc" --check
python3 - <<'PY'
from pathlib import Path
import re
stdlib = Path("src/capy/stdlib.capy").read_text()
core = Path("src/wasm/core.cpp").read_text()
for host in re.findall(r"host function (__bearer_\w+)\(operation : s32", stdlib):
assert not re.search(re.escape(host) + r"\(\s*\d", stdlib), host
assert not re.search(r"\bcase\s+\d+\s*:\s*|(?:\boperation\s*[=!<>]=?\s*\d|\d\s*[=!<>]=?\s*\boperation)", core)
assert "function request_apply" not in stdlib and not re.search(r"\bglobal\s*>\s*21\b", core)
PY
scripts/test_hardened_http_native.sh
scripts/test_crypto_operation_native.sh
scripts/test_dvalue_none_native.sh
scripts/test_capy_exact_handle_native.sh
"$BUILD_DIR/capyc" --parity-manifest "$PARITY_MANIFEST"
cmp "$PARITY_MANIFEST" docs/capy-capability-manifest.md
expected_manifest_pages=$(find site/doc/source/api site/doc/source/type site/doc/source/handler -type f -name '*.txt' | wc -l)
[[ $(grep -c '^| `' "$PARITY_MANIFEST") -eq $expected_manifest_pages ]]
stage_done "Compiler build and native support checks"
python3 scripts/test_native_build.py "$BUILD_DIR/frontend" -- clang++ "${COMMON[@]}" \
src/capy/frontend.cpp scripts/test_capy_native_frontend.cpp
mapfile -t fixtures < <({ git ls-files 'site/**/*.capy'; printf '%s\n' site/tests/capy-mutable-array-struct.capy site/tests/capy-dval-identity.capy; } | sort -u | while read -r path; do [[ -f "$path" ]] && printf '%s\n' "$path"; done)
"$BUILD_DIR/frontend" "${fixtures[@]}"
python3 scripts/test_native_build.py "$BUILD_DIR/wasm" -- clang++ "${COMMON[@]}" \
src/capy/wasm.cpp scripts/test_capy_native_wasm.cpp
"$BUILD_DIR/wasm"
python3 scripts/test_native_build.py "$BUILD_DIR/compiler" -- clang++ "${COMMON[@]}" \
src/capy/frontend.cpp src/capy/wasm.cpp src/capy/compiler.cpp scripts/test_capy_native_compiler.cpp
"$BUILD_DIR/compiler"
wasm-validate /tmp/capy-native.wasm
"$BUILD_DIR/capyc" site/tests/capy-phase1.capy \
-o "$BUILD_DIR/phase1.wasm" --source-map "$BUILD_DIR/phase1.wasm.source-map" --abi-version "$ABI_VERSION"
wasm-validate "$BUILD_DIR/phase1.wasm"
"$BUILD_DIR/capyc" --check-unit "$BUILD_DIR/phase1.wasm" "$ABI_VERSION"
mkdir -p "$BUILD_DIR/repeat"
"$BUILD_DIR/capyc" site/tests/capy-phase1.capy \
-o "$BUILD_DIR/repeat/phase1.wasm" --source-map "$BUILD_DIR/repeat/phase1.wasm.source-map" --abi-version "$ABI_VERSION"
cmp "$BUILD_DIR/phase1.wasm" "$BUILD_DIR/repeat/phase1.wasm"
cmp "$BUILD_DIR/phase1.wasm.source-map" "$BUILD_DIR/repeat/phase1.wasm.source-map"
cp "$BUILD_DIR/phase1.wasm" "$BUILD_DIR/wrapper.wasm"
wasm-validate "$BUILD_DIR/wrapper.wasm"
stage_done "Frontend, Wasm, and compiler assertions"
compile_tracked_fixture() {
local source=$1 artifact="$BUILD_DIR/${1//\//_}.wasm"
"$BUILD_DIR/capyc" "$source" -o "$artifact" --source-map "$artifact.source-map" --abi-version "$ABI_VERSION"
wasm-validate "$artifact"
"$BUILD_DIR/capyc" --check-unit "$artifact" "$ABI_VERSION"
}
export -f compile_tracked_fixture
export BUILD_DIR ABI_VERSION
fixture_jobs=$(nproc)
((fixture_jobs <= 4)) || fixture_jobs=4
printf '%s\0' "${fixtures[@]}" | xargs -0 -r -n1 -P "$fixture_jobs" bash -c 'compile_tracked_fixture "$1"' _
unset -f compile_tracked_fixture
stage_done "Tracked fixture compilation and validation"
wasm-objdump -x "$BUILD_DIR/phase1.wasm" >"$BUILD_DIR/phase1.objdump"
! grep -q 'bearer_request_context_brrb\|bearer_response_set_\|bearer_print_s64\|bearer_print_u64\|bearer_print_f64\|bearer_format_s64\|bearer_format_u64\|bearer_format_f64\|bearer_time\|bearer_file_\|bearer_unit_info_brrb\|bearer_units_list_brrb\|bearer_unit_compile\|bearer_codec\|bearer_regex\\|bearer_string_nonblank\|bearer_dv_merge\|bearer_sqlite_' "$BUILD_DIR/phase1.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-wide-scalars.capy.wasm" >"$BUILD_DIR/wide-scalars.objdump"
! grep -q 'env.bearer_format_s64\|env.bearer_format_u64' "$BUILD_DIR/wide-scalars.objdump"
! grep -q 'env.bearer_format_f64' "$BUILD_DIR/wide-scalars.objdump"
grep -q 'env.bearer_print_bytes' "$BUILD_DIR/wide-scalars.objdump"
! grep -q 'env.bearer_print_s64\|env.bearer_print_u64\|env.bearer_print_f64' "$BUILD_DIR/wide-scalars.objdump"
grep -q 'env.bearer_time' "$BUILD_DIR/wide-scalars.objdump"
grep -q 'env.bearer_time_precise' "$BUILD_DIR/wide-scalars.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-markup.capy.wasm" >"$BUILD_DIR/markup.objdump"
! grep -q 'env.bearer_format_s64\|env.bearer_format_u64' "$BUILD_DIR/markup.objdump"
! grep -q 'env.bearer_format_f64' "$BUILD_DIR/markup.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-files.capy.wasm" >"$BUILD_DIR/files.objdump"
for import in file_open file_read file_write file_seek file_tell file_fsync file_close file_temp file_unlink; do
grep -q "env.bearer_$import" "$BUILD_DIR/files.objdump"
done
wasm-objdump -x "$BUILD_DIR/site_tests_capy-final-parity.capy.wasm" >"$BUILD_DIR/final-parity.objdump"
for import in file_pread file_pwrite; do grep -q "env.bearer_$import" "$BUILD_DIR/final-parity.objdump"; done
grep -q 'env.bearer_dv_text_parsing' "$BUILD_DIR/final-parity.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-strings.capy.wasm" >"$BUILD_DIR/strings.objdump"
grep -q 'env.bearer_string_substr' "$BUILD_DIR/strings.objdump"
grep -q 'env.bearer_string_strpos' "$BUILD_DIR/strings.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-string-hostpath.capy.wasm" >"$BUILD_DIR/string-hostpath.objdump"
! grep -q 'env.bearer_dv_text_parsing\|env.bearer_dv_codec_archive\|env.bearer_string_nonblank' "$BUILD_DIR/string-hostpath.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-codecs.capy.wasm" >"$BUILD_DIR/codecs.objdump"
grep -q 'env.bearer_codec' "$BUILD_DIR/codecs.objdump"
grep -q 'env.bearer_dv_f64' "$BUILD_DIR/codecs.objdump"
grep -q 'env.bearer_dv_extract_f64' "$BUILD_DIR/codecs.objdump"
grep -q 'env.bearer_dv_extract_bool' "$BUILD_DIR/codecs.objdump"
! grep -q 'env.bearer_dv_f64_brrb\|env.bearer_dv_bool_brrb' "$BUILD_DIR/codecs.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-regex.capy.wasm" >"$BUILD_DIR/regex.objdump"
grep -q 'env.bearer_regex_match' "$BUILD_DIR/regex.objdump"
grep -q 'env.bearer_regex_dval' "$BUILD_DIR/regex.objdump"
grep -q 'env.bearer_regex_text' "$BUILD_DIR/regex.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-coreutil.capy.wasm" >"$BUILD_DIR/coreutil.objdump"
for import in dv_text_parsing dv_route_path dv_runtime_diagnostics; do
grep -q "env.bearer_$import" "$BUILD_DIR/coreutil.objdump"
done
wasm-objdump -x "$BUILD_DIR/site_tests_capy-string-lists.capy.wasm" >"$BUILD_DIR/string-lists.objdump"
grep -q 'env.bearer_dv_text_parsing' "$BUILD_DIR/string-lists.objdump"
! grep -q 'env.bearer_string_nonblank' "$BUILD_DIR/string-lists.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-first-empty.capy.wasm" >"$BUILD_DIR/first-empty.objdump"
! grep -q 'env.bearer_string_nonblank' "$BUILD_DIR/first-empty.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-dval-merge.capy.wasm" >"$BUILD_DIR/dval-merge.objdump"
grep -q 'env.bearer_dv_merge' "$BUILD_DIR/dval-merge.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-sqlite.capy.wasm" >"$BUILD_DIR/sqlite.objdump"
for import in sqlite_connect sqlite_disconnect sqlite_error sqlite_query sqlite_insert_id sqlite_affected_rows; do
grep -q "env.bearer_$import" "$BUILD_DIR/sqlite.objdump"
done
wasm-objdump -x "$BUILD_DIR/site_tests_capy-unit-admin.capy.wasm" >"$BUILD_DIR/unit-admin.objdump"
for import in unit_info_brrb units_list_brrb unit_compile; do
grep -q "env.bearer_$import" "$BUILD_DIR/unit-admin.objdump"
done
wasm-objdump -x "$BUILD_DIR/site_tests_capy-request-parity.capy.wasm" >"$BUILD_DIR/request-parity.objdump"
grep -q 'env.bearer_dv_request_workspace' "$BUILD_DIR/request-parity.objdump"
! grep -q 'env.bearer_request_context_brrb\|env.bearer_redirect\|env.bearer_session_start' "$BUILD_DIR/request-parity.objdump"
wasm-objdump -x "$BUILD_DIR/site_tests_capy-request-context.capy.wasm" >"$BUILD_DIR/request-context.objdump"
! grep -q 'env.bearer_handler_input_dval\|env.bearer_dv_request' "$BUILD_DIR/request-context.objdump"
! grep -q 'env.bearer_request_context_brrb\|env.bearer_request_context_for_brrb\|env.bearer_request_value\|env.bearer_request_body' "$BUILD_DIR/request-context.objdump"
! grep -q 'env.bearer_response_set_status\|env.bearer_response_set_header' "$BUILD_DIR/request-context.objdump"
stage_done "Artifact import checks"
if [[ ${1:-} == "--benchmarks" ]]; then
CAPYC="$BUILD_DIR/capyc" scripts/benchmark_capy_compiler_scaling.sh
stage_done "Compiler scaling benchmarks"
fi
echo "native Capy frontend, Wasm, compiler, CLI, and tracked fixture checks passed in ${SECONDS}s"