@@ -149,14 +149,166 @@ commands:
149149 - checkout
150150 - setup_environment :
151151 cache_key : v4.2.0-rust-1.88.0-<< parameters.workspace_member >><< parameters.cache_key_suffix >>-cache
152+
153+ - run :
154+ name : Install cargo-nextest
155+ command : |
156+ cargo install cargo-nextest --locked || true
157+
152158 - run :
153159 name : " Run Tests"
154160 timeout : << parameters.timeout >>
155161 no_output_timeout : << parameters.no_output_timeout >>
156- command : RUST_MIN_STACK=67108864 cargo test --package=<< parameters.workspace_member >> << parameters.flags >>
162+ command : |
163+ set -euo pipefail
164+ export CARGO_TERM_COLOR=never
165+
166+ # Create artifact + nextest output directories
167+ mkdir -p artifacts target/nextest/ci
168+
169+ # Create artifact + nextest output directories
170+ OUT="artifacts/<< parameters.workspace_member >>-nextest.txt"
171+ CSV="artifacts/<< parameters.workspace_member >>-test-times.csv"
172+ TOP="artifacts/<< parameters.workspace_member >>-slow-tests-top30.csv"
173+ JUNIT="target/nextest/ci/junit.xml"
174+
175+ # Extract and trim flags from parameters
176+ FLAGS_FULL="<< parameters.flags >>"
177+ FLAGS_TRIM="$(printf '%s' "$FLAGS_FULL" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
178+
179+ # Split flags into cargo build flags (before --) and libtest args (after --)
180+ RIGHT_OF_SEP=""
181+ if printf '%s' "$FLAGS_TRIM" | grep -q ' -- '; then
182+ BUILD_FLAGS="${FLAGS_TRIM%% -- *}"
183+ RIGHT_OF_SEP="${FLAGS_TRIM#* -- }"
184+ elif printf '%s' "$FLAGS_TRIM" | grep -Eq '^--[[:space:]]'; then
185+ BUILD_FLAGS=""
186+ RIGHT_OF_SEP="${FLAGS_TRIM#-- }"
187+ else
188+ BUILD_FLAGS="$FLAGS_TRIM"
189+ fi
190+
191+ # Remove any --test target flags,they cause nextest build errors
192+ BUILD_FLAGS_SANITIZED="$(printf '%s' "$BUILD_FLAGS" \
193+ | sed -E "s/(^|[[:space:]])--test[[:space:]]+'[^']*'([[:space:]]|$)/ /g" \
194+ | sed -E 's/(^|[[:space:]])--test[[:space:]]+\"[^\"]*\"([[:space:]]|$)/ /g' \
195+ | sed -E 's/(^|[[:space:]])--test[[:space:]]+[^[:space:]]+([[:space:]]|$)/ /g' \
196+ | tr -s ' ' | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' \
197+ )"
198+
199+ # Build nextest filter expression from any --skip <pattern> arguments
200+ FILTER_EXPR=""
201+ if [ -n "$RIGHT_OF_SEP" ]; then
202+ SKIPS="$(printf '%s\n' "$RIGHT_OF_SEP" \
203+ | sed -E 's/[[:space:]]+/ /g' \
204+ | grep -oE -- '--skip[[:space:]]+(\"[^\"]+\"|'\''[^'\'']+'\''|[^[:space:]]+)' || true)"
205+ if [ -n "$SKIPS" ]; then
206+ EXPRS=""
207+ tmpf="$(mktemp)"
208+ printf '%s\n' "$SKIPS" > "$tmpf"
209+ while IFS= read -r line; do
210+ pat="${line#--skip }"
211+ pat="${pat%\"}"; pat="${pat#\"}"
212+ pat="${pat%\'}"; pat="${pat#\'}"
213+ pat_rx="${pat//\//\\/}" # escape forward slashes for regex
214+ if [ -z "$EXPRS" ]; then
215+ EXPRS="test(/$pat_rx/)"
216+ else
217+ EXPRS="$EXPRS or test(/$pat_rx/)"
218+ fi
219+ done < "$tmpf"
220+ rm -f "$tmpf"
221+ if [ -n "$EXPRS" ]; then
222+ FILTER_EXPR="not ($EXPRS)"
223+ fi
224+ fi
225+ fi
226+
227+ # Detect and extract --test-threads value (used to set JOBS)
228+ TEST_THREADS=""
229+ if [ -n "$RIGHT_OF_SEP" ]; then
230+ # form: --test-threads=8
231+ TEST_THREADS="$(printf '%s\n' "$RIGHT_OF_SEP" | sed -nE 's/.*--test-threads=([0-9]+).*/\1/p' | head -n1)"
232+ if [ -z "$TEST_THREADS" ]; then
233+ # form: --test-threads 8
234+ TEST_THREADS="$(printf '%s\n' "$RIGHT_OF_SEP" | sed -nE 's/.*--test-threads[[:space:]]+([0-9]+).*/\1/p' | head -n1)"
235+ fi
236+ fi
237+
238+ # Default JOBS, overridden by TEST_THREADS if set
239+ JOBS="${NEXTEST_JOBS:-2}"
240+ if [ -n "$TEST_THREADS" ]; then
241+ JOBS="$TEST_THREADS"
242+ fi
243+
244+ # Create nextest config (disable fail-fast, add slow-timeout + JUnit output)
245+ SLOW_PERIOD="${NEXTEST_SLOW_PERIOD:-60s}"
246+ CFG_ARGS=()
247+ TMPD="$(mktemp -d)"
248+ if [ -f ".config/nextest.toml" ]; then
249+ CFG_ARGS+=(--config-file ".config/nextest.toml")
250+ fi
251+ {
252+ printf '%s\n' '[profile.ci]'
253+ printf '%s\n' 'fail-fast = false'
254+ printf '%s\n' "slow-timeout = \"${SLOW_PERIOD}\""
255+ printf '%s\n' ''
256+ printf '%s\n' '[profile.ci.junit]'
257+ printf '%s\n' 'path = "junit.xml"'
258+ } > "$TMPD/nextest-override.toml"
259+ CFG_ARGS+=(--config-file "$TMPD/nextest-override.toml")
260+
261+ # Print configuration summary for debugging
262+ echo "==> nextest package: << parameters.workspace_member >>"
263+ echo "==> build flags (sanitized): '${BUILD_FLAGS_SANITIZED}'"
264+ echo "==> filter-expr: ${FILTER_EXPR:-<none>} (right-of-sep: ${RIGHT_OF_SEP:-<none>})"
265+ echo "==> test-threads override: ${TEST_THREADS:-<none>}"
266+ echo "==> jobs: ${JOBS}"
267+
268+ # Use plain cargo test if --no-run was requested
269+ # Otherwise, run tests with cargo nextest
270+ if printf '%s' " $BUILD_FLAGS_SANITIZED " | grep -q ' --no-run '; then
271+ cargo test --package="<< parameters.workspace_member >>" $BUILD_FLAGS_SANITIZED | tee "$OUT"
272+ : > "$CSV"; : > "$TOP"
273+ else
274+ cargo nextest run \
275+ -p "<< parameters.workspace_member >>" $BUILD_FLAGS_SANITIZED \
276+ --profile ci -j "${JOBS}" "${CFG_ARGS[@]}" \
277+ --status-level fail --hide-progress-bar \
278+ --no-tests=pass \
279+ ${FILTER_EXPR:+--filter-expr "$FILTER_EXPR"} \
280+ 2>&1 | tee "$OUT"
281+
282+ # Parse junit.xml to extract test timings
283+ if [ -f "$JUNIT" ]; then
284+ awk -v RS='<testcase ' '
285+ NR>1 {
286+ name=""; classname=""; time="";
287+ start=index($0,"classname=\""); if(start>0){ start+=11; rest=substr($0,start); end=index(rest,"\""); if(end>0) classname=substr(rest,1,end-1) }
288+ start=index($0,"name=\""); if(start>0){ start+=6; rest=substr($0,start); end=index(rest,"\""); if(end>0) name=substr(rest,1,end-1) }
289+ start=index($0,"time=\""); if(start>0){ start+=6; rest=substr($0,start); end=index(rest,"\""); if(end>0) time=substr(rest,1,end-1) }
290+ if(name!="" && time!=""){ full=(classname!=""?classname"::"name:name); printf "%s,%s\n", full, time }
291+ }
292+ ' "$JUNIT" > "$CSV" || true
293+
294+ # Sort and store top 30 slowest tests
295+ sort -t, -k2,2nr "$CSV" | head -n 30 > "$TOP" || true
296+ else
297+ echo "WARN: $JUNIT not found; no timings extracted." >&2
298+ : > "$CSV"; : > "$TOP"
299+ fi
300+ fi
301+
302+ - store_artifacts :
303+ path : artifacts
304+ destination : test-timings/<< parameters.workspace_member >>
305+ - store_test_results :
306+ path : target/nextest/ci
307+
157308 - clear_environment :
158309 cache_key : v4.2.0-rust-1.88.0-<< parameters.workspace_member >><< parameters.cache_key_suffix >>-cache
159310
311+
160312 install_rust_nightly :
161313 description : " Install Rust nightly toolchain"
162314 steps :
@@ -446,7 +598,8 @@ jobs:
446598 - run_test :
447599 workspace_member : snarkvm-ledger
448600 flags : --release --features=rocks -- --test-threads=2
449- timeout : 20m
601+ no_output_timeout : 20m
602+ timeout : 30m
450603
451604 ledger-with-valid-solutions :
452605 executor : rust-docker
@@ -470,6 +623,8 @@ jobs:
470623 steps :
471624 - run_test :
472625 workspace_member : snarkvm-ledger-block
626+ no_output_timeout : 20m
627+ timeout : 30m
473628
474629 ledger-committee :
475630 executor : rust-docker
@@ -593,6 +748,8 @@ jobs:
593748 workspace_member : snarkvm-parameters
594749 flags : -- --test-threads=2 --ignored test_load_bytes_mini
595750 cache_key_suffix : -v-{{ epoch }}
751+ no_output_timeout : 20m
752+ timeout : 30m
596753
597754 synthesizer :
598755 executor : rust-docker
@@ -601,11 +758,14 @@ jobs:
601758 - run_test :
602759 workspace_member : snarkvm-synthesizer
603760 flags : --lib --bins
604- timeout : 20m
761+ no_output_timeout : 20m
762+ timeout : 30m
605763
606764 synthesizer-test :
607765 executor : rust-docker
608766 resource_class : << pipeline.parameters.twoxlarge >>
767+ environment :
768+ NEXTEST_JOBS : " 4"
609769 steps :
610770 - run_test :
611771 workspace_member : snarkvm-synthesizer
@@ -631,7 +791,7 @@ jobs:
631791 # test_vm_execute_and_finalize can take over 10 minutes in the current setup
632792 no_output_timeout : 20m
633793 workspace_member : snarkvm-synthesizer
634- flags : --test '*' --features test -- --test-threads=4
794+ flags : --test '*' --features test -- --test-threads=4
635795 cache_key_suffix : -integration
636796
637797 synthesizer-process :
@@ -662,6 +822,8 @@ jobs:
662822 synthesizer-program-integration :
663823 executor : rust-docker
664824 resource_class : << pipeline.parameters.twoxlarge >>
825+ environment :
826+ NEXTEST_JOBS : " 4"
665827 steps :
666828 - run_test :
667829 workspace_member : snarkvm-synthesizer-program
0 commit comments