mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
tests: cover input_phys autoconf matching and the stale-index blind spot
input_phys matching had no test coverage because the test joypad driver never reported a physical location: input_autoconfigure_connect was called with a NULL phys, so every profile's input_phys was a mismatch and the scoring branch was unreachable. That is why #19540 reached a release. Teach the test driver to carry a phys in the .ratst connect string, after a "@@" separator, and split it back out of the device name. Existing step scripts have no "@@" and are unaffected. P7 pins the ranking itself: two profiles with identical vendor/product ids and identical input_device, differing only in input_phys, so the match must beat the mismatch 60 to 40. Run in both file orders, because the reported symptom looked order-dependent, and both cold and through the index. P8 pins the regression. It demotes a profile below its rival before the index is built, then promotes it back with a size-preserving edit, which leaves only the modification times to tell the edited directory from the indexed one - the case a *.cfg count can never catch. The rival is untouched, so its recorded claim stays honest and passes the winner re-score, which is what let the wrong profile through. Both variants are checked: one with a second's delay, and one without, where the index write and the edit can land in the same whole second. Verified to fail on the unfixed binary and pass on the fixed one. The index is built with a device nothing matches, since a connect scoring 60 takes the scan's early exit and discards the index build - so the phys device itself cannot be the one that writes it.
This commit is contained in:
1 parent
4da19c51d3
commit
90d3bef87a
5 files changed
+128
-3
No files matched your search
@@ -285,14 +285,33 @@ end:
|
||||
/* Test input file handling end */
|
||||
/********************************/
|
||||
|
||||
static char test_joypad_name_buf[MAX_USERS][256];
|
||||
|
||||
static const char *test_joypad_name(unsigned pad)
|
||||
{
|
||||
const char *n;
|
||||
char *at;
|
||||
if (pad >= MAX_USERS || (!test_joypads[pad].name
|
||||
|| !*test_joypads[pad].name))
|
||||
return NULL;
|
||||
if (strstr(test_joypads[pad].name, ") "))
|
||||
return strstr(test_joypads[pad].name, ") ") + 2;
|
||||
return test_joypads[pad].name;
|
||||
n = strstr(test_joypads[pad].name, ") ") + 2;
|
||||
else
|
||||
n = test_joypads[pad].name;
|
||||
strlcpy(test_joypad_name_buf[pad], n, sizeof(test_joypad_name_buf[pad]));
|
||||
if ((at = strstr(test_joypad_name_buf[pad], "@@")))
|
||||
*at = '\0';
|
||||
return test_joypad_name_buf[pad];
|
||||
}
|
||||
|
||||
static const char *test_joypad_phys(unsigned pad)
|
||||
{
|
||||
const char *at;
|
||||
if (pad >= MAX_USERS || !test_joypads[pad].name)
|
||||
return NULL;
|
||||
if ((at = strstr(test_joypads[pad].name, "@@")))
|
||||
return at + 2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_joypad_autodetect_add(unsigned autoconf_pad)
|
||||
@@ -314,7 +333,7 @@ static void test_joypad_autodetect_add(unsigned autoconf_pad)
|
||||
|
||||
input_autoconfigure_connect(
|
||||
test_joypad_name(autoconf_pad),
|
||||
NULL, NULL,
|
||||
NULL, test_joypad_phys(autoconf_pad),
|
||||
"test",
|
||||
autoconf_pad,
|
||||
vid,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
input_driver = "test"
|
||||
input_device = "Test joypad device P"
|
||||
input_vendor_id = 31
|
||||
input_product_id = 32
|
||||
input_phys = "usb-0000:00:14.0-3/input0"
|
||||
input_device_display_name = "Test joypad phys match"
|
||||
input_b_btn = "0"
|
||||
@@ -0,0 +1,7 @@
|
||||
input_driver = "test"
|
||||
input_device = "Test joypad device P"
|
||||
input_vendor_id = 31
|
||||
input_product_id = 32
|
||||
input_phys = "usb-0000:00:99.9-9/input9"
|
||||
input_device_display_name = "Test joypad phys mismatch"
|
||||
input_b_btn = "0"
|
||||
@@ -90,6 +90,14 @@ run() {
|
||||
|
||||
index_hash() { md5sum "$INDEX" 2>/dev/null | cut -d' ' -f1; }
|
||||
|
||||
# Point the next run at a different .ratst without touching the
|
||||
# profile directory, so a phase can build an index with one device and
|
||||
# then connect a different one against it.
|
||||
use_ratst() {
|
||||
sed -i "s#^test_input_file_joypad = .*#test_input_file_joypad = \"$RATST_DIR/$1\"#" \
|
||||
"$HOME_DIR/.config/retroarch/retroarch.cfg"
|
||||
}
|
||||
|
||||
say "== autoconf regression suite: $RETROARCH"
|
||||
[ -x "$RETROARCH" ] || { say "binary not found/executable"; exit 1; }
|
||||
|
||||
@@ -174,6 +182,81 @@ assert_seen 'not configured' "P6 unknown device unconfigured on
|
||||
&& pass "P6 identical index not rewritten for a no-match device" \
|
||||
|| fail "P6 index churned on an unrecognised device"
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
say "-- P7: input_phys ranking - matching phys outranks a bogus one"
|
||||
# TestpadP_phys and TestpadQ_physbogus carry identical vendor/product
|
||||
# ids and an identical input_device, so they differ only in
|
||||
# input_phys: 60 for the match against 40 for the mismatch. Q sorts
|
||||
# after P here, so the run is repeated below with the order reversed -
|
||||
# ranking must not depend on which file the walk reaches first.
|
||||
setup test_input_autoconf_phys.ratst
|
||||
run
|
||||
assert_seen 'phys match configured in port 1' "P7 matching phys wins on a fresh scan"
|
||||
assert_absent 'phys mismatch configured' "P7 bogus phys not selected"
|
||||
run
|
||||
assert_seen 'phys match configured in port 1' "P7 matching phys wins via the index"
|
||||
|
||||
setup test_input_autoconf_phys.ratst
|
||||
mv "$AUTOCONF/TestpadP_phys.cfg" "$AUTOCONF/AA_phys.cfg"
|
||||
run
|
||||
assert_seen 'phys match configured in port 1' "P7 matching phys wins when it sorts first"
|
||||
assert_absent 'phys mismatch configured' "P7 bogus phys not selected when it sorts last"
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
say "-- P8: in-place edit promoting a non-winner - index must not hide it"
|
||||
# The regression behind #19540. The index re-scores only its winner,
|
||||
# so an entry it *understates* never gets re-read: before the
|
||||
# directory fingerprint, a rival whose own claim was honest verified
|
||||
# cleanly and was configured, at its own lower affinity, without the
|
||||
# directory ever being scanned.
|
||||
#
|
||||
# Both edits below are size-preserving, so only the modification times
|
||||
# separate the edited directory from the indexed one - which is
|
||||
# exactly the case a *.cfg count could never catch.
|
||||
setup test_input_autoconf_unknown.ratst
|
||||
# Demote TestpadP below TestpadQ *before* the index is built: with a
|
||||
# wrong device name and a wrong phys it scores 20, against Q's honest
|
||||
# 40. Both edits are size-preserving, here and below.
|
||||
sed -i -e 's#Test joypad device P#Test joypad device X#' \
|
||||
-e 's#usb-0000:00:14.0-3/input0#usb-0000:00:77.7-7/input7#' \
|
||||
"$AUTOCONF/TestpadP_phys.cfg"
|
||||
# Build the index with a device nothing matches: a connect that scored
|
||||
# 60 would take the scan's early exit and discard the index build, so
|
||||
# the phys device itself cannot be the one that writes it.
|
||||
run
|
||||
[ -s "$INDEX" ] || fail "P8 no index to go stale"
|
||||
# Now promote P back to a 60 while the index still records it at 20.
|
||||
# Q is untouched, so Q's recorded 40 stays honest - and an honest
|
||||
# claim is what verification checks. The index therefore ranks Q top,
|
||||
# re-scores only Q, finds 40 as promised and configures it, never
|
||||
# reading the profile that now scores 60. That is #19540.
|
||||
sleep 1
|
||||
sed -i -e 's#Test joypad device X#Test joypad device P#' \
|
||||
-e 's#usb-0000:00:77.7-7/input7#usb-0000:00:14.0-3/input0#' \
|
||||
"$AUTOCONF/TestpadP_phys.cfg"
|
||||
use_ratst test_input_autoconf_phys.ratst
|
||||
run
|
||||
assert_seen 'phys match configured in port 1' \
|
||||
"P8 promoted profile selected after a size-preserving edit"
|
||||
assert_absent 'phys mismatch configured' \
|
||||
"P8 understated index does not hide the true winner"
|
||||
|
||||
# Same edit, but with no sleep: the index and the edit can land in the
|
||||
# same whole second, which the stored timestamp alone cannot separate.
|
||||
setup test_input_autoconf_unknown.ratst
|
||||
sed -i -e 's#Test joypad device P#Test joypad device X#' \
|
||||
-e 's#usb-0000:00:14.0-3/input0#usb-0000:00:77.7-7/input7#' \
|
||||
"$AUTOCONF/TestpadP_phys.cfg"
|
||||
run
|
||||
[ -s "$INDEX" ] || fail "P8 no index for the same-second case"
|
||||
sed -i -e 's#Test joypad device X#Test joypad device P#' \
|
||||
-e 's#usb-0000:00:77.7-7/input7#usb-0000:00:14.0-3/input0#' \
|
||||
"$AUTOCONF/TestpadP_phys.cfg"
|
||||
use_ratst test_input_autoconf_phys.ratst
|
||||
run
|
||||
assert_seen 'phys match configured in port 1' \
|
||||
"P8 same-second edit still rescanned"
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
rm -rf "$WORK"
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"comment": "Physical-location (input_phys) autoconfig matching. Device P (001f:0020) is described by two profiles with identical vendor/product ids and identical input_device, distinguished only by input_phys. The bogus-phys profile sorts first, so a correct run must rank the matching-phys profile above it (60 vs 40) rather than take the first acceptable file. The connect string carries the device's phys after '@@'.",
|
||||
"action": 1,
|
||||
"param_num": 0,
|
||||
"param_str": "(001f:0020) Test joypad device P@@usb-0000:00:14.0-3/input0",
|
||||
"frame": 0
|
||||
}
|
||||
]
|
||||
Reference in new issue
Block a user