169 lines
5.7 KiB
Bash
Executable file
169 lines
5.7 KiB
Bash
Executable file
#!/bin/sh
|
|
set -eu
|
|
|
|
if [ "$#" -ne 1 ]; then
|
|
echo "usage: $0 LONG_CONTEXT_SERVER_GATE" >&2
|
|
exit 2
|
|
fi
|
|
|
|
runner=$1
|
|
fixture=$(mktemp -d /private/tmp/gem-server-gate-resume.XXXXXX)
|
|
listener_pid=
|
|
cleanup()
|
|
{
|
|
if [ -n "$listener_pid" ] && kill -0 "$listener_pid" 2>/dev/null; then
|
|
kill "$listener_pid"
|
|
wait "$listener_pid" 2>/dev/null || true
|
|
fi
|
|
rm -rf "$fixture"
|
|
}
|
|
trap cleanup EXIT INT TERM HUP
|
|
|
|
mkdir -p "$fixture/build" "$fixture/scripts"
|
|
printf 'fixture model\n' > "$fixture/model.gguf"
|
|
printf 'fixture prompt\n' > "$fixture/prompt.txt"
|
|
# The single-quoted fragments below are the literal body of a generated fixture.
|
|
# shellcheck disable=SC2016
|
|
printf '%s\n' '#!/bin/sh' \
|
|
'set -eu' \
|
|
'if [ "$1" = print-config ]; then' \
|
|
' if [ -e .changed-config ]; then' \
|
|
' printf '\''{"engine":"gem-native-c-metal","context":4098,"kv_type":"f32","route":"changed"}\n'\''' \
|
|
' else' \
|
|
' printf '\''{"engine":"gem-native-c-metal","context":4098,"kv_type":"f32","route":"fixture"}\n'\''' \
|
|
' fi' \
|
|
' exit 0' \
|
|
'fi' \
|
|
': > .serve-attempted' \
|
|
'printf '\''serve must not run during a completed-sample resume\n'\'' >&2' \
|
|
'exit 99' > "$fixture/build/gem"
|
|
printf '%s\n' '#!/bin/sh' 'printf '\''{"token_count":4096}\n'\''' \
|
|
> "$fixture/build/gem-tokenize"
|
|
printf '%s\n' '#!/bin/sh' 'exit 99' > "$fixture/scripts/server-stream-probe.sh"
|
|
chmod +x "$fixture/build/gem" "$fixture/build/gem-tokenize" \
|
|
"$fixture/scripts/server-stream-probe.sh"
|
|
|
|
port=$((20000 + ($$ % 20000)))
|
|
nc -l 127.0.0.1 "$port" >/dev/null 2>&1 &
|
|
listener_pid=$!
|
|
attempt=0
|
|
while ! lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1; do
|
|
attempt=$((attempt + 1))
|
|
if [ "$attempt" -ge 50 ]; then
|
|
echo "fixture listener did not become ready" >&2
|
|
exit 1
|
|
fi
|
|
sleep 0.02
|
|
done
|
|
|
|
set +e
|
|
(
|
|
cd "$fixture"
|
|
GEM_MODEL_SHA256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
GEM_STREAM_MAX_TOKENS=2 \
|
|
"$runner" model.gguf 4098 prompt.txt results "$port"
|
|
)
|
|
initial_status=$?
|
|
set -e
|
|
if [ "$initial_status" -ne 1 ]; then
|
|
echo "initial occupied-port run returned $initial_status, expected 1" >&2
|
|
exit 1
|
|
fi
|
|
kill "$listener_pid"
|
|
wait "$listener_pid" 2>/dev/null || true
|
|
listener_pid=
|
|
|
|
set +e
|
|
(
|
|
cd "$fixture"
|
|
GEM_MODEL_SHA256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
GEM_STREAM_MAX_TOKENS=2 GEM_GATE_PREFLIGHT_MIN_TOKENS=0 \
|
|
GEM_GATE_MAX_LOAD_PER_CPU=0.000001 \
|
|
"$runner" model.gguf 4098 prompt.txt results-busy "$port" >/dev/null 2>&1
|
|
)
|
|
preflight_status=$?
|
|
set -e
|
|
if [ "$preflight_status" -ne 1 ] ||
|
|
! jq -e '.status == "fail"' "$fixture/results-busy/host-preflight-1.json" >/dev/null ||
|
|
[ -e "$fixture/.serve-attempted" ]; then
|
|
echo "busy-host preflight did not fail before server launch" >&2
|
|
exit 1
|
|
fi
|
|
|
|
sample=1
|
|
while [ "$sample" -le 3 ]; do
|
|
printf 'gem: prompt prefill 4096/4096 tokens (100.00%%), fixture sample %s\n' \
|
|
"$sample" > "$fixture/results/server-$sample.log"
|
|
printf 'data: {"choices":[{"delta":{"content":"x"}}]}\n\ndata: [DONE]\n\n' \
|
|
> "$fixture/results/stream-$sample.sse"
|
|
jq -n --argjson sample "$sample" \
|
|
'{schema_version: 1, engine: "gem-native-c-metal", model: "gemma4",
|
|
requested_max_tokens: 2, http_code: 200,
|
|
header_ttfb_seconds: 0.01,
|
|
first_visible_event_seconds: (0.02 + ($sample / 1000)),
|
|
completion_seconds: 0.04, visible_event_count: 1,
|
|
finish_reason: "stop",
|
|
usage: {prompt_tokens: 4096, completion_tokens: 2, total_tokens: 4098}}' \
|
|
> "$fixture/results/measurement-$sample.json"
|
|
sample=$((sample + 1))
|
|
done
|
|
|
|
(
|
|
cd "$fixture"
|
|
GEM_MODEL_SHA256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
GEM_STREAM_MAX_TOKENS=2 GEM_GATE_RESUME=1 \
|
|
"$runner" model.gguf 4098 prompt.txt results "$port" >/dev/null
|
|
)
|
|
jq -e '.repetitions == 3 and .resumed_samples == 3 and (.samples | length) == 3' \
|
|
"$fixture/results/summary.json" >/dev/null
|
|
|
|
printf 'nonempty but missing final prefill record\n' > "$fixture/results/server-2.log"
|
|
set +e
|
|
(
|
|
cd "$fixture"
|
|
GEM_MODEL_SHA256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
GEM_STREAM_MAX_TOKENS=2 GEM_GATE_RESUME=1 \
|
|
"$runner" model.gguf 4098 prompt.txt results "$port" >/dev/null 2>&1
|
|
)
|
|
log_status=$?
|
|
set -e
|
|
if [ "$log_status" -ne 1 ] || [ ! -e "$fixture/.serve-attempted" ]; then
|
|
echo "missing final prefill record was silently resumed" >&2
|
|
exit 1
|
|
fi
|
|
rm "$fixture/.serve-attempted"
|
|
printf 'gem: prompt prefill 4096/4096 tokens (100.00%%), fixture sample 2\n' \
|
|
> "$fixture/results/server-2.log"
|
|
|
|
touch "$fixture/.changed-config"
|
|
set +e
|
|
(
|
|
cd "$fixture"
|
|
GEM_MODEL_SHA256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
GEM_STREAM_MAX_TOKENS=2 GEM_GATE_RESUME=1 \
|
|
"$runner" model.gguf 4098 prompt.txt results "$port" >/dev/null 2>&1
|
|
)
|
|
config_status=$?
|
|
set -e
|
|
if [ "$config_status" -ne 2 ]; then
|
|
echo "changed native configuration returned $config_status, expected 2" >&2
|
|
exit 1
|
|
fi
|
|
rm "$fixture/.changed-config"
|
|
|
|
jq '.prompt_sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"' \
|
|
"$fixture/results/gate-config.json" > "$fixture/results/gate-config.tmp"
|
|
mv "$fixture/results/gate-config.tmp" "$fixture/results/gate-config.json"
|
|
set +e
|
|
(
|
|
cd "$fixture"
|
|
GEM_MODEL_SHA256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
GEM_STREAM_MAX_TOKENS=2 GEM_GATE_RESUME=1 \
|
|
"$runner" model.gguf 4098 prompt.txt results "$port" >/dev/null 2>&1
|
|
)
|
|
provenance_status=$?
|
|
set -e
|
|
if [ "$provenance_status" -ne 2 ]; then
|
|
echo "changed gate provenance returned $provenance_status, expected 2" >&2
|
|
exit 1
|
|
fi
|