Skip to content

Commit 6cf0794

Browse files
authored
Merge pull request #100 from Provenance-Emu/libretro/feature/extended-regression-tests
Add determinism and frameskip invariance regression tests
2 parents 6607b2e + 6e6049b commit 6cf0794

1 file changed

Lines changed: 84 additions & 2 deletions

File tree

test/regression_test.sh

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,94 @@ for rom in "${ROM_DIR}"/*.j64 "${ROM_DIR}"/*.rom; do
160160
fi
161161
else
162162
echo " NEW: ${rom_name} — no baseline yet"
163-
echo " To create: cp ${frame_file} ${baseline_png}"
163+
echo " To create: cp \"${frame_file}\" \"${baseline_png}\""
164164
NEW=$((NEW + 1))
165165
SUMMARY="${SUMMARY}| ${rom_name} | :new: NEW | no baseline | - |\n"
166166
fi
167167
done
168168

169+
# --- Helper: run ROM and return last screenshot path ---
170+
run_and_get_frame() {
171+
local out_dir="$1" envvar_args="$2"
172+
shift 2
173+
# shellcheck disable=SC2086
174+
"${MINIRETRO_BIN}" \
175+
--core "${CORE}" --rom "$1" \
176+
--output "${out_dir}" --system "${out_dir}" \
177+
--frames "${FRAMES}" --dump-frames-every "${DUMP_EVERY}" \
178+
--no-alarm ${envvar_args} >/dev/null 2>&1 || true
179+
find "${out_dir}" -name "screenshot*.png" 2>/dev/null | sort | tail -1
180+
}
181+
182+
# --- Determinism test: run each ROM twice, verify identical output ---
183+
# Validates that emulation is fully deterministic (no rand() in hot paths).
184+
echo ""
185+
echo "==> Running determinism check..."
186+
for rom in "${ROM_DIR}"/*.j64 "${ROM_DIR}"/*.rom; do
187+
[ -f "${rom}" ] || continue
188+
rom_name="$(basename "${rom}" | sed 's/\.[^.]*$//')"
189+
det_dir1="${WORK_DIR}/det1/${rom_name}"
190+
det_dir2="${WORK_DIR}/det2/${rom_name}"
191+
mkdir -p "${det_dir1}" "${det_dir2}"
192+
193+
frame1=$(run_and_get_frame "${det_dir1}" "" "${rom}")
194+
frame2=$(run_and_get_frame "${det_dir2}" "" "${rom}")
195+
196+
if [ -n "${frame1}" ] && [ -n "${frame2}" ]; then
197+
if cmp -s "${frame1}" "${frame2}"; then
198+
echo " PASS: ${rom_name} determinism (identical across runs)"
199+
PASS=$((PASS + 1))
200+
SUMMARY="${SUMMARY}| ${rom_name} (determinism) | :white_check_mark: PASS | identical across runs | - |\n"
201+
else
202+
echo " FAIL: ${rom_name} determinism (output differs between runs)"
203+
cp "${frame1}" "${DIFF_DIR}/${rom_name}_det_run1.png"
204+
cp "${frame2}" "${DIFF_DIR}/${rom_name}_det_run2.png"
205+
FAIL=$((FAIL + 1))
206+
SUMMARY="${SUMMARY}| ${rom_name} (determinism) | :x: FAIL | non-deterministic output | See artifacts |\n"
207+
fi
208+
else
209+
echo " FAIL: ${rom_name} determinism (no frames produced)"
210+
FAIL=$((FAIL + 1))
211+
SUMMARY="${SUMMARY}| ${rom_name} (determinism) | :x: FAIL | no frames produced | - |\n"
212+
fi
213+
done
214+
215+
# --- Frameskip test: verify core options don't affect emulation output ---
216+
# With frameskip, video_cb receives NULL on skipped frames but the
217+
# emulation still runs identically. The last rendered frame should match.
218+
# NOTE: requires the virtualjaguar_frameskip core option (PR #96).
219+
# Without it, both runs use default config, so the test trivially passes.
220+
echo ""
221+
echo "==> Running frameskip invariance check..."
222+
for rom in "${ROM_DIR}"/*.j64 "${ROM_DIR}"/*.rom; do
223+
[ -f "${rom}" ] || continue
224+
rom_name="$(basename "${rom}" | sed 's/\.[^.]*$//')"
225+
fs0_dir="${WORK_DIR}/fs0/${rom_name}"
226+
fs3_dir="${WORK_DIR}/fs3/${rom_name}"
227+
mkdir -p "${fs0_dir}" "${fs3_dir}"
228+
229+
frame_fs0=$(run_and_get_frame "${fs0_dir}" "" "${rom}")
230+
frame_fs3=$(run_and_get_frame "${fs3_dir}" "--envvar virtualjaguar_frameskip=3" "${rom}")
231+
232+
if [ -n "${frame_fs0}" ] && [ -n "${frame_fs3}" ]; then
233+
if cmp -s "${frame_fs0}" "${frame_fs3}"; then
234+
echo " PASS: ${rom_name} frameskip invariance (skip=0 matches skip=3)"
235+
PASS=$((PASS + 1))
236+
SUMMARY="${SUMMARY}| ${rom_name} (frameskip) | :white_check_mark: PASS | skip=0 matches skip=3 | - |\n"
237+
else
238+
echo " FAIL: ${rom_name} frameskip invariance (output differs with frameskip)"
239+
cp "${frame_fs0}" "${DIFF_DIR}/${rom_name}_fs0.png"
240+
cp "${frame_fs3}" "${DIFF_DIR}/${rom_name}_fs3.png"
241+
FAIL=$((FAIL + 1))
242+
SUMMARY="${SUMMARY}| ${rom_name} (frameskip) | :x: FAIL | frameskip changes output | See artifacts |\n"
243+
fi
244+
else
245+
echo " FAIL: ${rom_name} frameskip (no frames produced)"
246+
FAIL=$((FAIL + 1))
247+
SUMMARY="${SUMMARY}| ${rom_name} (frameskip) | :x: FAIL | no frames produced | - |\n"
248+
fi
249+
done
250+
169251
echo ""
170252
echo "==> Results: ${PASS} passed, ${FAIL} failed, ${NEW} new (no baseline)"
171253

@@ -175,7 +257,7 @@ cat > "${DIFF_DIR}/summary.md" <<EOSUMMARY
175257
176258
| ROM | Status | Details | Diff |
177259
|-----|--------|---------|------|
178-
$(echo -e "${SUMMARY}")
260+
$(printf '%b' "${SUMMARY}")
179261
180262
**Platform:** $(uname -s) $(uname -m)
181263
EOSUMMARY

0 commit comments

Comments
 (0)