Skip to content

Commit fa92d10

Browse files
marc0oloclaude
andcommitted
fix(rust/guards): fix set -e interaction with expected-panicking canister calls
The panicking calls return a non-zero exit code (canister rejection). In the old script, 'A && B; C' meant if B failed, set -e exited before C ran — so the assertion after the panic was never checked. Fix: split setup and panicking call onto separate lines, add '|| true' to the panicking call to explicitly allow failure. The setup call still uses '&&' so it fails loudly if the state reset itself fails. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent bfd4818 commit fa92d10

1 file changed

Lines changed: 15 additions & 11 deletions

File tree

‎rust/guards/test.sh‎

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,39 @@ icp canister call backend set_non_processed_items '(vec { "mint" })' && \
99
echo "PASS" || (echo "FAIL" && exit 1)
1010

1111
echo "=== Test 2: guard marks item as processed despite panicking callback (TrueAsyncCall) ==="
12-
icp canister call backend set_non_processed_items '(vec { "mint" })' && \
13-
icp canister call backend process_single_item_with_panicking_callback '("mint", variant { TrueAsyncCall })' 2>/dev/null; \
14-
result=$(icp canister call --query backend is_item_processed '("mint")') && \
12+
# The panicking call is expected to return a rejection — ic-cdk uses call_on_cleanup to
13+
# drop locals after the panic, committing the guard's state change before the rollback.
14+
icp canister call backend set_non_processed_items '(vec { "mint" })'
15+
icp canister call backend process_single_item_with_panicking_callback '("mint", variant { TrueAsyncCall })' 2>/dev/null || true
16+
result=$(icp canister call --query backend is_item_processed '("mint")') && \
1517
echo "$result" && \
1618
echo "$result" | grep -q 'true' && \
1719
echo "PASS" || (echo "FAIL" && exit 1)
1820

1921
echo "=== Test 3: guard fails to mark item as processed when no true async call (FalseAsyncCall) ==="
20-
icp canister call backend set_non_processed_items '(vec { "mint" })' && \
21-
icp canister call backend process_single_item_with_panicking_callback '("mint", variant { FalseAsyncCall })' 2>/dev/null; \
22-
result=$(icp canister call --query backend is_item_processed '("mint")') && \
22+
# Without a true async await boundary, the entire function runs in one message.
23+
# The panic rolls back all state changes including the guard's drop.
24+
icp canister call backend set_non_processed_items '(vec { "mint" })'
25+
icp canister call backend process_single_item_with_panicking_callback '("mint", variant { FalseAsyncCall })' 2>/dev/null || true
26+
result=$(icp canister call --query backend is_item_processed '("mint")') && \
2327
echo "$result" && \
2428
echo "$result" | grep -q 'false' && \
2529
echo "PASS" || (echo "FAIL" && exit 1)
2630

2731
echo "=== Test 4: guard marks first item as processed when processing multiple items (TrueAsyncCall) ==="
28-
icp canister call backend set_non_processed_items '(vec { "mint1"; "mint2"; "mint3" })' && \
29-
icp canister call backend process_all_items_with_panicking_callback '("mint2", variant { TrueAsyncCall })' 2>/dev/null; \
30-
result1=$(icp canister call --query backend is_item_processed '("mint1")') && \
32+
icp canister call backend set_non_processed_items '(vec { "mint1"; "mint2"; "mint3" })'
33+
icp canister call backend process_all_items_with_panicking_callback '("mint2", variant { TrueAsyncCall })' 2>/dev/null || true
34+
result1=$(icp canister call --query backend is_item_processed '("mint1")') && \
3135
result2=$(icp canister call --query backend is_item_processed '("mint2")') && \
3236
echo "mint1: $result1, mint2: $result2" && \
3337
echo "$result1" | grep -q 'true' && \
3438
echo "$result2" | grep -q 'false' && \
3539
echo "PASS" || (echo "FAIL" && exit 1)
3640

3741
echo "=== Test 5: set_non_processed_items resets state ==="
42+
icp canister call backend set_non_processed_items '(vec { "mint" })'
43+
icp canister call backend process_single_item_with_panicking_callback '("mint", variant { TrueAsyncCall })' 2>/dev/null || true
3844
icp canister call backend set_non_processed_items '(vec { "mint" })' && \
39-
icp canister call backend process_single_item_with_panicking_callback '("mint", variant { TrueAsyncCall })' 2>/dev/null; \
40-
icp canister call backend set_non_processed_items '(vec { "mint" })' && \
4145
result=$(icp canister call --query backend is_item_processed '("mint")') && \
4246
echo "$result" && \
4347
echo "$result" | grep -q 'false' && \

0 commit comments

Comments
 (0)