Skip to content

Commit cdff7de

Browse files
committed
test-suite: refine clean aliases and multicoprocessor resume UX
1 parent 3eea4e3 commit cdff7de

File tree

3 files changed

+143
-35
lines changed

3 files changed

+143
-35
lines changed

test-suite/README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,13 @@ cd test-suite/fhevm
9898
bun run deploy --network testnet
9999
bun run test input-proof
100100
bun run telemetry-smoke
101-
bun run clean --purge-local-cache
101+
bun run clean --purge-build-cache
102102
```
103103

104104
All `clean` purge flags are fhevm-scoped:
105105
- `--purge-images` removes images referenced by fhevm compose services.
106-
- `--purge-build-cache` and `--purge-local-cache` remove local Buildx cache directory (`.buildx-cache` by default, or `FHEVM_BUILDX_CACHE_DIR` if set).
106+
- `--purge-build-cache` removes the local Buildx cache directory (`.buildx-cache` by default, or `FHEVM_BUILDX_CACHE_DIR` if set).
107+
- `--purge-local-cache` is a compatibility alias for `--purge-build-cache`.
107108
- `--purge-networks` removes Docker networks labeled with the active compose project only.
108109

109110
For `deploy --coprocessors N` with `N > 1`, `cast` (Foundry) must be installed locally to derive per-coprocessor accounts from `MNEMONIC`.
@@ -186,11 +187,11 @@ For agent workflows, prefer explicit command+flag forms from this table.
186187
| `test` | `-v, --verbose` | Verbose test output. |
187188
| `test` | `-r, --no-relayer` | Disable Rust relayer in tests. |
188189
| `test` | `--no-hardhat-compile` | Skip compile when artifacts are already up-to-date. |
189-
| `clean` | `--purge` | Shorthand for all purge flags below. |
190+
| `clean` | `--purge` | Shorthand for `--purge-images --purge-build-cache --purge-networks`. |
190191
| `clean` | `--purge-images` | Remove images referenced by fhevm compose services only. |
191192
| `clean` | `--purge-build-cache` | Remove local Buildx cache dir (`.buildx-cache` or `FHEVM_BUILDX_CACHE_DIR`). |
192193
| `clean` | `--purge-networks` | Remove Docker networks labeled with the active compose project only. |
193-
| `clean` | `--purge-local-cache` | Remove local Buildx cache dir (`.buildx-cache` or `FHEVM_BUILDX_CACHE_DIR`). |
194+
| `clean` | `--purge-local-cache` | Alias of `--purge-build-cache` (kept for compatibility). |
194195
| `pause` / `unpause` | `host` or `gateway` | Contract pause controls. |
195196
| `upgrade` | `<service>` | Restart selected service compose stack. |
196197
| `logs` | `<service>` | Stream container logs for one service. |
@@ -217,6 +218,9 @@ When resuming:
217218
- Services **before** the resume step are preserved (containers + volumes kept)
218219
- Services **from** the resume step onwards are torn down and redeployed
219220

221+
Multicoprocessor safety note:
222+
- If you change multicoprocessor topology (`--coprocessors` and/or `--coprocessor-threshold`) while using `--resume` from `coprocessor` or later, the CLI intentionally forces resume from `minio` to reset key material coherently across all coprocessors.
223+
220224
### Deploying a single step
221225

222226
To redeploy only a single service without touching others:

test-suite/fhevm/scripts/bun/cli.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ type CleanOptions = {
5555
purgeImages: boolean;
5656
purgeBuildCache: boolean;
5757
purgeNetworks: boolean;
58-
purgeLocalCache: boolean;
5958
};
6059

6160
type TestOptions = {
@@ -82,14 +81,16 @@ function printLogo(): void {
8281
}
8382

8483
function usage(): void {
84+
const testTypes = Object.keys(TEST_TYPE_CONFIG).join("|");
85+
8586
printLogo();
8687
console.log(`${COLORS.bold}Usage:${COLORS.reset} ${COLORS.yellow}fhevm-cli${COLORS.reset} ${COLORS.cyan}COMMAND [OPTIONS]${COLORS.reset}`);
8788
console.log("");
8889
console.log(`${COLORS.bold}${COLORS.lightBlue}Commands:${COLORS.reset}`);
8990
console.log(` ${COLORS.yellow}deploy${COLORS.reset} ${COLORS.cyan}[--build] [--local] [--network testnet|mainnet] [--coprocessors N] [--coprocessor-threshold T] [--resume STEP] [--only STEP] [--telemetry-smoke] [--strict-otel]${COLORS.reset} Deploy the full fhevm stack`);
9091
console.log(` ${COLORS.yellow}pause${COLORS.reset} ${COLORS.cyan}[CONTRACTS]${COLORS.reset} Pause specific contracts (host|gateway)`);
9192
console.log(` ${COLORS.yellow}unpause${COLORS.reset} ${COLORS.cyan}[CONTRACTS]${COLORS.reset} Unpause specific contracts (host|gateway)`);
92-
console.log(` ${COLORS.yellow}test${COLORS.reset} ${COLORS.cyan}[TYPE]${COLORS.reset} Run tests (input-proof|user-decryption|public-decryption|delegated-user-decryption|random|random-subset|operators|erc20|debug)`);
93+
console.log(` ${COLORS.yellow}test${COLORS.reset} ${COLORS.cyan}[TYPE]${COLORS.reset} Run tests (${testTypes})`);
9394
console.log(` ${COLORS.yellow}upgrade${COLORS.reset} ${COLORS.cyan}[SERVICE]${COLORS.reset} Upgrade specific service`);
9495
console.log(` ${COLORS.yellow}clean${COLORS.reset} ${COLORS.cyan}[--purge] [--purge-images] [--purge-build-cache] [--purge-networks] [--purge-local-cache]${COLORS.reset} Clean stack resources`);
9596
console.log(` ${COLORS.yellow}logs${COLORS.reset} ${COLORS.cyan}[SERVICE]${COLORS.reset} View logs for a specific service`);
@@ -115,11 +116,11 @@ function usage(): void {
115116
console.log(` ${COLORS.cyan}--no-hardhat-compile${COLORS.reset} Skip Hardhat compilation step`);
116117
console.log("");
117118
console.log(`${COLORS.bold}${COLORS.lightBlue}Clean Options:${COLORS.reset}`);
118-
console.log(` ${COLORS.cyan}--purge${COLORS.reset} Equivalent to --purge-images --purge-build-cache --purge-networks --purge-local-cache`);
119+
console.log(` ${COLORS.cyan}--purge${COLORS.reset} Equivalent to --purge-images --purge-build-cache --purge-networks`);
119120
console.log(` ${COLORS.cyan}--purge-images${COLORS.reset} Remove images for fhevm compose services only`);
120121
console.log(` ${COLORS.cyan}--purge-build-cache${COLORS.reset} Remove local fhevm Buildx cache directory`);
121-
console.log(` ${COLORS.cyan}--purge-networks${COLORS.reset} Remove fhevm-prefixed Docker networks`);
122-
console.log(` ${COLORS.cyan}--purge-local-cache${COLORS.reset} Remove local Buildx cache dir (.buildx-cache or FHEVM_BUILDX_CACHE_DIR)`);
122+
console.log(` ${COLORS.cyan}--purge-networks${COLORS.reset} Remove networks labeled for the active fhevm compose project only`);
123+
console.log(` ${COLORS.cyan}--purge-local-cache${COLORS.reset} Alias of --purge-build-cache (kept for compatibility)`);
123124
console.log("");
124125
console.log(`${COLORS.bold}${COLORS.lightBlue}Examples:${COLORS.reset}`);
125126
console.log(` ${COLORS.purple}./fhevm-cli deploy${COLORS.reset}`);
@@ -139,7 +140,7 @@ function usage(): void {
139140
console.log(` ${COLORS.purple}./fhevm-cli upgrade coprocessor${COLORS.reset}`);
140141
console.log(` ${COLORS.purple}./fhevm-cli telemetry-smoke${COLORS.reset}`);
141142
console.log(` ${COLORS.purple}./fhevm-cli clean --purge${COLORS.reset}`);
142-
console.log(` ${COLORS.purple}./fhevm-cli clean --purge-local-cache${COLORS.reset}`);
143+
console.log(` ${COLORS.purple}./fhevm-cli clean --purge-build-cache${COLORS.reset}`);
143144
console.log(` ${COLORS.purple}FHEVM_DOCKER_PROJECT=fhevm-dev ./fhevm-cli deploy${COLORS.reset}`);
144145
console.log(`${COLORS.blue}============================================================${COLORS.reset}`);
145146
}
@@ -2107,7 +2108,7 @@ function resolveEffectiveResumeStep(options: DeployOptions): string | undefined
21072108
const adjustedStep = "minio";
21082109
if (options.resumeStep !== adjustedStep) {
21092110
logWarn(
2110-
`Requested resume step '${options.resumeStep}' is too late for multicoprocessor topology changes. Forcing resume from '${adjustedStep}' to reset key material and chain state coherently.`,
2111+
`Requested resume step '${options.resumeStep}' is too late for multicoprocessor topology changes. Forcing resume from '${adjustedStep}' for a full key-material reset (this intentionally redeploys the full stack to keep key digests coherent).`,
21112112
);
21122113
}
21132114
return adjustedStep;
@@ -2569,15 +2570,13 @@ function parseCleanArgs(args: string[]): CleanOptions {
25692570
purgeImages: false,
25702571
purgeBuildCache: false,
25712572
purgeNetworks: false,
2572-
purgeLocalCache: false,
25732573
};
25742574

25752575
for (const arg of args) {
25762576
if (arg === "--purge") {
25772577
options.purgeImages = true;
25782578
options.purgeBuildCache = true;
25792579
options.purgeNetworks = true;
2580-
options.purgeLocalCache = true;
25812580
continue;
25822581
}
25832582
if (arg === "--purge-images") {
@@ -2593,7 +2592,7 @@ function parseCleanArgs(args: string[]): CleanOptions {
25932592
continue;
25942593
}
25952594
if (arg === "--purge-local-cache") {
2596-
options.purgeLocalCache = true;
2595+
options.purgeBuildCache = true;
25972596
continue;
25982597
}
25992598
usageError(`Unknown option for clean: ${arg}`);
@@ -2623,11 +2622,7 @@ function clean(args: string[]): void {
26232622
}
26242623

26252624
if (options.purgeBuildCache) {
2626-
logInfo("Removing local fhevm Buildx cache only.");
2627-
purgeLocalBuildxCache();
2628-
}
2629-
2630-
if (options.purgeLocalCache && !options.purgeBuildCache) {
2625+
logInfo("Removing local fhevm Buildx cache directory.");
26312626
purgeLocalBuildxCache();
26322627
}
26332628

test-suite/fhevm/scripts/tests/deploy-fhevm-stack.behavior.sh

Lines changed: 125 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,36 @@ case "${subcommand}" in
8989
exit 1
9090
fi
9191
fi
92+
exit 0
93+
;;
94+
exec)
95+
while [[ $# -gt 0 ]]; do
96+
case "$1" in
97+
-e)
98+
shift 2
99+
;;
100+
*)
101+
break
102+
;;
103+
esac
104+
done
105+
106+
container="${1:-}"
107+
shift || true
108+
109+
if [[ "${1:-}" == "curl" ]]; then
110+
if [[ "$*" == *"http://fhevm-relayer:3000/v2/keyurl"* ]]; then
111+
cat <<'JSON'
112+
{"response":{"fheKeyInfo":[{"fhePublicKey":{"urls":["http://mock-fhevm/key"]}}],"crs":{"2048":{"urls":["http://mock-fhevm/crs"]}}}}
113+
JSON
114+
exit 0
115+
fi
116+
117+
if [[ "$*" == *"http://mock-fhevm/key"* || "$*" == *"http://mock-fhevm/crs"* ]]; then
118+
exit 0
119+
fi
120+
fi
121+
92122
exit 0
93123
;;
94124
ps)
@@ -130,6 +160,42 @@ case "${subcommand}" in
130160
fi
131161
exit 0
132162
;;
163+
volume)
164+
action="${1:-}"
165+
shift || true
166+
if [[ "${action}" == "ls" ]]; then
167+
filter_name=""
168+
while [[ $# -gt 0 ]]; do
169+
case "$1" in
170+
--filter)
171+
if [[ "${2:-}" == name=* ]]; then
172+
filter_name="${2#name=}"
173+
fi
174+
shift 2
175+
;;
176+
--format)
177+
shift 2
178+
;;
179+
*)
180+
shift
181+
;;
182+
esac
183+
done
184+
185+
names_csv="${DOCKER_VOLUME_NAMES:-fhevm_minio_secrets}"
186+
IFS=',' read -r -a names <<< "${names_csv}"
187+
exact="${filter_name#^}"
188+
exact="${exact%\$}"
189+
190+
for name in "${names[@]}"; do
191+
if [[ -z "${exact}" || "${name}" == "${exact}" ]]; then
192+
echo "${name}"
193+
fi
194+
done
195+
exit 0
196+
fi
197+
exit 0
198+
;;
133199
inspect)
134200
if [[ "${1:-}" == "-f" ]]; then
135201
format="${2:-}"
@@ -298,6 +364,7 @@ run_deploy() {
298364
export TEST_COMMAND_LOG="${COMMAND_LOG}"
299365
export DOCKER_COMPLETE_SERVICES="${DOCKER_COMPLETE_SERVICES:-${DEFAULT_COMPLETE_SERVICES}}"
300366
export DOCKER_MINIO_IP="${DOCKER_MINIO_IP:-172.20.0.2}"
367+
export DOCKER_RUNNING_NAMES="${DOCKER_RUNNING_NAMES:-fhevm-relayer,fhevm-test-suite-e2e-debug}"
301368

302369
./deploy-fhevm-stack.sh "$@"
303370
) > "${output_file}" 2>&1
@@ -313,6 +380,7 @@ run_cli() {
313380
export TEST_COMMAND_LOG="${COMMAND_LOG}"
314381
export DOCKER_COMPLETE_SERVICES="${DOCKER_COMPLETE_SERVICES:-${DEFAULT_COMPLETE_SERVICES}}"
315382
export DOCKER_MINIO_IP="${DOCKER_MINIO_IP:-172.20.0.2}"
383+
export DOCKER_RUNNING_NAMES="${DOCKER_RUNNING_NAMES:-fhevm-relayer,fhevm-test-suite-e2e-debug}"
316384

317385
bun scripts/bun/cli.ts "$@"
318386
) > "${output_file}" 2>&1
@@ -414,8 +482,8 @@ test_default_flow_and_env_patch() {
414482
assert_contains "${COMMAND_LOG}" "coprocessor-docker-compose.yml up -d"
415483
assert_contains "${COMMAND_LOG}" "kms-connector-docker-compose.yml up -d"
416484
assert_contains "${COMMAND_LOG}" "gateway-mocked-payment-docker-compose.yml up -d"
417-
assert_contains "${COMMAND_LOG}" "gateway-sc-docker-compose.yml up -d"
418-
assert_contains "${COMMAND_LOG}" "host-sc-docker-compose.yml up -d"
485+
assert_contains "${COMMAND_LOG}" "gateway-sc-docker-compose.yml up --force-recreate -d gateway-sc-deploy"
486+
assert_contains "${COMMAND_LOG}" "host-sc-docker-compose.yml up --force-recreate -d host-sc-deploy"
419487
assert_contains "${COMMAND_LOG}" "relayer-docker-compose.yml up -d"
420488
assert_contains "${COMMAND_LOG}" "test-suite-docker-compose.yml up -d"
421489
assert_contains "${COMMAND_LOG}" "setup-kms-signer"
@@ -453,26 +521,63 @@ test_resume_preserves_prior_steps_and_restarts_tail() {
453521

454522
assert_contains "${COMMAND_LOG}" "kms-connector-docker-compose.yml up -d"
455523
assert_contains "${COMMAND_LOG}" "gateway-mocked-payment-docker-compose.yml up -d"
456-
assert_contains "${COMMAND_LOG}" "gateway-sc-docker-compose.yml up -d"
457-
assert_contains "${COMMAND_LOG}" "host-sc-docker-compose.yml up -d"
524+
assert_contains "${COMMAND_LOG}" "gateway-sc-docker-compose.yml up --force-recreate -d gateway-sc-deploy"
525+
assert_contains "${COMMAND_LOG}" "host-sc-docker-compose.yml up --force-recreate -d host-sc-deploy"
458526
assert_contains "${COMMAND_LOG}" "relayer-docker-compose.yml up -d"
459527
assert_contains "${COMMAND_LOG}" "test-suite-docker-compose.yml up -d"
460528

461-
assert_contains "${COMMAND_LOG}" "test-suite-docker-compose.yml down -v --remove-orphans"
462-
assert_contains "${COMMAND_LOG}" "relayer-docker-compose.yml down -v --remove-orphans"
463-
assert_contains "${COMMAND_LOG}" "host-sc-docker-compose.yml down -v --remove-orphans"
464-
assert_contains "${COMMAND_LOG}" "gateway-sc-docker-compose.yml down -v --remove-orphans"
465-
assert_contains "${COMMAND_LOG}" "gateway-mocked-payment-docker-compose.yml down -v --remove-orphans"
466-
assert_contains "${COMMAND_LOG}" "kms-connector-docker-compose.yml down -v --remove-orphans"
467-
assert_not_contains "${COMMAND_LOG}" "coprocessor-docker-compose.yml down -v --remove-orphans"
529+
assert_contains "${COMMAND_LOG}" "test-suite-docker-compose.yml down -v"
530+
assert_contains "${COMMAND_LOG}" "relayer-docker-compose.yml down -v"
531+
assert_contains "${COMMAND_LOG}" "host-sc-docker-compose.yml down -v"
532+
assert_contains "${COMMAND_LOG}" "gateway-sc-docker-compose.yml down -v"
533+
assert_contains "${COMMAND_LOG}" "gateway-mocked-payment-docker-compose.yml down -v"
534+
assert_contains "${COMMAND_LOG}" "kms-connector-docker-compose.yml down -v"
535+
assert_not_contains "${COMMAND_LOG}" "coprocessor-docker-compose.yml down -v"
468536

469-
assert_order "${COMMAND_LOG}" "test-suite-docker-compose.yml down -v --remove-orphans" "kms-connector-docker-compose.yml down -v --remove-orphans"
537+
assert_order "${COMMAND_LOG}" "test-suite-docker-compose.yml down -v" "kms-connector-docker-compose.yml down -v"
470538
assert_order "${COMMAND_LOG}" "docker inspect -f {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} fhevm-minio" "kms-connector-docker-compose.yml up -d"
471539

472540
unset DOCKER_RUNNING_NAMES
473541
cleanup_fixture
474542
}
475543

544+
test_multicoprocessor_resume_forces_minio_reset() {
545+
setup_fixture
546+
547+
cat > "${FIXTURE_ROOT}/env/staging/.env.gateway-sc" <<'ENV'
548+
MNEMONIC=test test test test test test test test test test test junk
549+
COPROCESSOR_THRESHOLD=1
550+
NUM_COPROCESSORS=1
551+
COPROCESSOR_TX_SENDER_ADDRESS_0=0x1111111111111111111111111111111111111111
552+
COPROCESSOR_SIGNER_ADDRESS_0=0x1111111111111111111111111111111111111111
553+
COPROCESSOR_S3_BUCKET_URL_0=http://minio:9000/ct128
554+
ENV
555+
556+
cat > "${FIXTURE_ROOT}/env/staging/.env.host-sc" <<'ENV'
557+
COPROCESSOR_THRESHOLD=1
558+
NUM_COPROCESSORS=1
559+
COPROCESSOR_SIGNER_ADDRESS_0=0x1111111111111111111111111111111111111111
560+
ENV
561+
562+
cat > "${FIXTURE_ROOT}/env/staging/.env.coprocessor" <<'ENV'
563+
AWS_ENDPOINT_URL=http://minio:9000
564+
DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/coprocessor"
565+
TX_SENDER_PRIVATE_KEY=0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
566+
ENV
567+
568+
local output_file="${TEST_TMP_DIR}/multicoprocessor-resume-forced-minio.out"
569+
if ! run_deploy "${output_file}" --resume coprocessor --coprocessors 2 --coprocessor-threshold 2; then
570+
echo "Deploy with resume+multicoprocessor should succeed" >&2
571+
cat "${output_file}" >&2
572+
return 1
573+
fi
574+
575+
assert_contains "${output_file}" "Forcing resume from 'minio'."
576+
assert_contains "${COMMAND_LOG}" "minio-docker-compose.yml down -v"
577+
assert_contains "${COMMAND_LOG}" "minio-docker-compose.yml up -d"
578+
cleanup_fixture
579+
}
580+
476581
test_only_runs_single_step() {
477582
setup_fixture
478583

@@ -483,7 +588,7 @@ test_only_runs_single_step() {
483588
return 1
484589
fi
485590

486-
assert_contains "${COMMAND_LOG}" "coprocessor-docker-compose.yml down -v --remove-orphans"
591+
assert_contains "${COMMAND_LOG}" "coprocessor-docker-compose.yml down -v"
487592
assert_contains "${COMMAND_LOG}" "coprocessor-docker-compose.yml up -d"
488593
assert_not_contains "${COMMAND_LOG}" "host-node-docker-compose.yml up -d"
489594
assert_not_contains "${COMMAND_LOG}" "gateway-node-docker-compose.yml up -d"
@@ -727,13 +832,13 @@ test_clean_purge_invokes_prunes() {
727832
return 1
728833
fi
729834

730-
assert_contains "${COMMAND_LOG}" "docker compose -p fhevm down -v --remove-orphans"
731-
assert_contains "${COMMAND_LOG}" "docker network ls --format {{.Name}}"
835+
assert_contains "${COMMAND_LOG}" "minio-docker-compose.yml down -v"
836+
assert_contains "${COMMAND_LOG}" "docker network ls --filter label=com.docker.compose.project=fhevm --format {{.Name}}"
732837
assert_contains "${COMMAND_LOG}" "down -v --remove-orphans --rmi all"
733838
assert_not_contains "${COMMAND_LOG}" "docker image prune -af"
734839
assert_not_contains "${COMMAND_LOG}" "docker builder prune -af"
735840
assert_contains "${output_file}" "Removing images referenced by fhevm compose services only."
736-
assert_contains "${output_file}" "Removing local fhevm Buildx cache only."
841+
assert_contains "${output_file}" "Removing local fhevm Buildx cache directory."
737842
assert_contains "${output_file}" "Removed local Buildx cache directory"
738843
if [[ -d "${FIXTURE_ROOT}/.buildx-cache" ]]; then
739844
echo "Assertion failed: .buildx-cache should be removed by clean --purge" >&2
@@ -764,6 +869,9 @@ test_command_and_flag_matrix() {
764869
export FHEVM_GRAFANA_DASHBOARD_HTML_FILE="${dashboard_fixture}"
765870

766871
run_cli_ok "help-command" help
872+
assert_contains "${TEST_TMP_DIR}/help-command.out" "input-proof-compute-decrypt"
873+
assert_contains "${TEST_TMP_DIR}/help-command.out" "paused-host-contracts"
874+
assert_contains "${TEST_TMP_DIR}/help-command.out" "paused-gateway-contracts"
767875
run_cli_ok "help-short" -h
768876
run_cli_ok "help-long" --help
769877

@@ -829,6 +937,7 @@ main() {
829937
test_quoted_otel_endpoint_is_accepted
830938
test_multicoprocessor_flags_are_validated
831939
test_multicoprocessor_env_and_extra_instances
940+
test_multicoprocessor_resume_forces_minio_reset
832941
test_clean_purge_invokes_prunes
833942
test_telemetry_smoke_requires_jaeger
834943
test_command_and_flag_matrix

0 commit comments

Comments
 (0)