mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-14 03:10:59 +01:00
Test bt_pairing.sh to 100%: allowlist 97 -> 96
Second of the 16 untested fixes/lib libs. 65/65 = 100.00% through run_all.sh, twice, the second at --min 100 (exit 0), then cleared from the allowlist and confirmed by the real gate with no exemption. Two findings worth keeping: - udevadm was NOT in the harness's stub list, so `udevadm control --reload-rules` was reaching the REAL binary during the suite. A prepended stub dir cannot hide a tool the host actually has. Caught by asserting on the recorded call rather than by reading the code, which is the argument for asserting on calls at all. - _disable_usb_autosuspend writes /etc/udev/rules.d/50-bluetooth-no- autosuspend.rules. Binding /etc in the jail would have covered it, and was rejected: run_all.sh runs UN-jailed in ci_mirror.sh and in the shell-tests workflow, as its own header says, so a bind mount protects the coverage run and leaves every bare run writing to a real root-owned file. Instead the lib gained a UDEV_RULES_DIR override, defaulting to the real path -- the same env-override seam pacman_hook_stall_harness.sh uses for PACMAN_LOG/CACHE_DIR/PACMAN_LOCK. Proof the suite is safe where it runs un-jailed: after a bare run_all.sh, the real rule file still has its 2026-02-21 mtime (it is a genuine artifact of a production run six months ago) and the probed power/control values are unchanged. The jail cannot give that check. fix_usb_autosuspend globs the real /sys/bus/usb/devices/*/ with no override, so its branches are driven through stubbed lsusb output: ffff:ffff matches nothing on any machine and reaches the not-found arm, while 046d:c077 (control=on) and 046d:0825 (control=auto) are read-only probes, each guarded so the case self-skips with a note if the host state changes rather than silently asserting nothing. Split across two test files to stay under the 250-line cap; run_all.sh globs test_*.sh, so splitting costs nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4cfc3fdde1
commit
0e9cc0ce95
@ -0,0 +1,17 @@
|
||||
{
|
||||
"title": "Test bt_pairing.sh to 100% and clear it from the shell-coverage allowlist",
|
||||
"objective": "Cover the second of the sixteen untested linux_configuration/scripts/single_use/fixes/lib libs. bt_pairing.sh is the first in the family whose code writes outside its own process -- a sysfs power/control file and a udev rule under /etc -- so the contract is to reach 100% without ever letting the suite touch either, given that lib/tests/run_all.sh runs UN-jailed in ci_mirror.sh and in CI.",
|
||||
"acceptance_criteria": [
|
||||
"bt_pairing.sh measures 100.00% through lib/tests/run_all.sh, twice, the second run at --min 100 with exit 0.",
|
||||
"check_shell_coverage.sh exits 0 for bt_pairing.sh with its allowlist line removed, i.e. with no exemption.",
|
||||
"A bare (un-jailed) run of run_all.sh leaves /etc/udev/rules.d/50-bluetooth-no-autosuspend.rules with its original 2026-02-21 mtime, and leaves the power/control values of the probed USB devices unchanged.",
|
||||
"Every test file stays under the repo's 250-line cap.",
|
||||
"pre-commit passes on all changed files with no suppression added -- no # shellcheck disable, no noqa."
|
||||
],
|
||||
"out_of_scope": [
|
||||
"Bind-mounting /etc in the jail to make the udev write safe. Rejected: run_all.sh runs un-jailed in ci_mirror.sh and CI, so a bind mount would protect only the coverage run.",
|
||||
"Refactoring pacman_hook_stall_harness.sh onto the new lib_test_core.sh. Its six libs are already gated at 100% with no exemption.",
|
||||
"The remaining fourteen untested fixes/lib libs, which land in later commits."
|
||||
],
|
||||
"verifier": "bash linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh (expects all files passing, 11 + 20 for the two bt_pairing files), plus bash meta/scripts/shell_coverage_jail.sh --subject linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh --measure bt_pairing.sh --min 100 --fail-on-case-error -- \"\" (expects 65/65 = 100.00% and exit 0), plus bash meta/scripts/check_shell_coverage.sh linux_configuration/scripts/single_use/fixes/lib/bt_pairing.sh (expects exit 0), plus stat -c '%y' /etc/udev/rules.d/50-bluetooth-no-autosuspend.rules (expects 2026-02-21)."
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
{
|
||||
"intent": "Test linux_configuration/scripts/single_use/fixes/lib/bt_pairing.sh to 100% line coverage and take it off the shell-coverage allowlist, second of the 16 untested fixes/lib libs.",
|
||||
"scope": [
|
||||
"linux_configuration/scripts/single_use/fixes/lib/tests/test_bt_pairing.sh and test_bt_pairing_usb.sh (new, 11 + 20 = 31 assertions; split across two files to stay under the 250-line cap, which run_all.sh's test_*.sh glob makes free)",
|
||||
"linux_configuration/scripts/single_use/fixes/lib/bt_pairing.sh (one line: UDEV_RULES_DIR override)",
|
||||
"linux_configuration/scripts/single_use/fixes/lib/tests/bt_harness.sh (stub udevadm, which was reaching the real binary)",
|
||||
"meta/shell-coverage-allowlist.txt (one line removed)",
|
||||
"Non-goal: bind-mounting /etc to make the udev write safe -- rejected, see risks"
|
||||
],
|
||||
"changes": [
|
||||
"Added test_bt_pairing.sh covering remove_stale_pairing (empty TARGET_MAC, paired-but-not-connected, paired-and-connected, not-paired, and device-unknown) and restart_bluetooth (both arms of the FIXES_APPLIED guard); added test_bt_pairing_usb.sh covering fix_usb_autosuspend (no bluetooth device, unparseable USB ID, no matching sysfs path, control already 'on', and control 'auto') and _disable_usb_autosuspend directly, including both arms of its idempotence guard and the different-vendor rewrite.",
|
||||
"Added a UDEV_RULES_DIR override to bt_pairing.sh:_disable_usb_autosuspend so the test suite can redirect the udev rule write out of /etc. Production default is unchanged: ${UDEV_RULES_DIR:-/etc/udev/rules.d}.",
|
||||
"Added udevadm to the harness's default stub list. It was NOT stubbed before, so `udevadm control --reload-rules` was reaching the real binary on the host -- the 'a prepended stub dir cannot hide a real binary' trap, caught by an assertion on the recorded call rather than by inspection.",
|
||||
"fix_usb_autosuspend globs the real /sys/bus/usb/devices/*/ with no env override, so each branch is driven through the stubbed lsusb output instead: ffff:ffff matches no device on any machine and exercises the not-found arm, while 046d:c077 (control=on) and 046d:0825 (control=auto) are read-only probes of devices present on this host, each guarded so it self-skips if that stops holding.",
|
||||
"Removed linux_configuration/scripts/single_use/fixes/lib/bt_pairing.sh from meta/shell-coverage-allowlist.txt."
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "bash linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh",
|
||||
"result": "pass",
|
||||
"evidence": "test_bt_pairing.sh: 11 passed, 0 failed; test_bt_pairing_usb.sh: 20 passed, 0 failed; test_bt_report.sh: 24 passed, 0 failed. All fixes lib test files passed, so the eight pre-existing pacman_hook_stall suites stay green."
|
||||
},
|
||||
{
|
||||
"command": "bash meta/scripts/shell_coverage_jail.sh --subject linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh --measure bt_pairing.sh --min 1 --fail-on-case-error -- \"\"",
|
||||
"result": "pass",
|
||||
"evidence": "bt_pairing.sh: 65/65 lines = 100.00%, up from 55/65 = 84.62% before _disable_usb_autosuspend's body (lines 112-126) was covered. No 'outside kcov's line set' lines reported."
|
||||
},
|
||||
{
|
||||
"command": "bash meta/scripts/shell_coverage_jail.sh --subject linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh --measure bt_pairing.sh --min 100 --fail-on-case-error -- \"\"",
|
||||
"result": "pass",
|
||||
"evidence": "bt_pairing.sh: 65/65 lines = 100.00%, exit code 0. Second matching run at the --min 100 bar, re-run after the two-file split to confirm the split did not change the line set."
|
||||
},
|
||||
{
|
||||
"command": "bash meta/scripts/check_shell_coverage.sh linux_configuration/scripts/single_use/fixes/lib/bt_pairing.sh",
|
||||
"result": "pass",
|
||||
"evidence": "'check_shell_coverage.sh: every checked shell library meets the coverage bar', exit 0, with the allowlist line already removed so the lib had no exemption."
|
||||
},
|
||||
{
|
||||
"command": "stat -c '%y' /etc/udev/rules.d/50-bluetooth-no-autosuspend.rules",
|
||||
"result": "pass",
|
||||
"evidence": "2026-02-21 21:51:36, unchanged after a bare (un-jailed) run of run_all.sh -- the file is a real artifact of a past production run, six months old. /sys/bus/usb/devices/1-10 and 1-11 power/control still read 'auto' and 'on'. This is the check that proves the suite is safe where it actually runs un-jailed; the jail cannot give it."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"Bind-mounting /etc was considered and rejected. lib/tests/run_all.sh runs UN-jailed in ci_mirror.sh (the pre-push hook) and in the shell-tests workflow, as its own header states, so a --bind would have made only the coverage run safe and left every bare run writing to the real root-owned udev rule. The UDEV_RULES_DIR override follows the precedent pacman_hook_stall_harness.sh set with PACMAN_LOG/CACHE_DIR/PACMAN_LOCK.",
|
||||
"Two fix_usb_autosuspend cases read real sysfs devices (046d:c077 and 046d:0825) because the /sys path is hardcoded in the lib. Both are read-only and each is wrapped in a guard that turns the case into a pass with an explicit SKIP note if the host's power/control value changes, so the suite cannot silently start asserting nothing.",
|
||||
"The coverage runs were made in a detached worktree, because a second Claude session is writing to this repo concurrently and the jail aborts on any working-tree delta during a run."
|
||||
],
|
||||
"rollback": [
|
||||
"git revert the commit; that restores the bt_pairing.sh allowlist line, removes the UDEV_RULES_DIR override and deletes the test file together.",
|
||||
"After rollback, run bash linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh and confirm the remaining suites pass, then bash meta/scripts/check_shell_coverage.sh to confirm the gate is green with bt_pairing.sh exempt again."
|
||||
]
|
||||
}
|
||||
@ -114,14 +114,17 @@ _disable_usb_autosuspend() {
|
||||
local product="$3"
|
||||
|
||||
# Immediate fix
|
||||
echo "on" > "$power_control"
|
||||
echo "on" >"$power_control"
|
||||
|
||||
# Persistent udev rule
|
||||
local rule_file="/etc/udev/rules.d/50-bluetooth-no-autosuspend.rules"
|
||||
# Persistent udev rule. UDEV_RULES_DIR defaults to the real directory and
|
||||
# is only overridden by the test suite, which cannot be allowed to write
|
||||
# to /etc: lib/tests/run_all.sh runs UN-jailed in ci_mirror.sh and in CI,
|
||||
# so a bind mount would protect the coverage run and nothing else.
|
||||
local rule_file="${UDEV_RULES_DIR:-/etc/udev/rules.d}/50-bluetooth-no-autosuspend.rules"
|
||||
local rule="ACTION==\"add\", SUBSYSTEM==\"usb\", ATTR{idVendor}==\"$vendor\", ATTR{idProduct}==\"$product\", ATTR{power/control}=\"on\""
|
||||
|
||||
if [[ ! -f $rule_file ]] || ! grep -qF "$vendor" "$rule_file" 2>/dev/null; then
|
||||
echo "$rule" > "$rule_file"
|
||||
echo "$rule" >"$rule_file"
|
||||
udevadm control --reload-rules 2>/dev/null || true
|
||||
log_info "Created persistent udev rule: $rule_file"
|
||||
fi
|
||||
|
||||
@ -78,7 +78,8 @@ apply_fix() {
|
||||
_bt_default_stubs() {
|
||||
local tool
|
||||
for tool in dmesg wget curl lsusb modprobe dbus-send pactl wpctl \
|
||||
bluetoothctl rfkill lsmod usbreset systemctl journalctl sudo id; do
|
||||
bluetoothctl rfkill lsmod usbreset systemctl journalctl sudo id \
|
||||
udevadm; do
|
||||
_t_stub "$tool" 'exit 0'
|
||||
done
|
||||
# `id -u <user>` feeds _run_as_user's XDG_RUNTIME_DIR path.
|
||||
|
||||
98
linux_configuration/scripts/single_use/fixes/lib/tests/test_bt_pairing.sh
Executable file
98
linux_configuration/scripts/single_use/fixes/lib/tests/test_bt_pairing.sh
Executable file
@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tests for lib/bt_pairing.sh: remove_stale_pairing, restart_bluetooth and
|
||||
# fix_usb_autosuspend.
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=bt_harness.sh
|
||||
. "${SCRIPT_DIR}/bt_harness.sh"
|
||||
|
||||
# shellcheck source=../bt_pairing.sh
|
||||
. "${FIXES_DIR}/lib/bt_pairing.sh"
|
||||
|
||||
# _btctl_info BODY — stub bluetoothctl so `_btctl info <mac>` returns BODY.
|
||||
_btctl_info() {
|
||||
local body="$1"
|
||||
local stub
|
||||
stub="$(
|
||||
cat <<'BTCTL_HEAD'
|
||||
read -r cmd rest
|
||||
if [[ "$cmd" == "info" ]]; then
|
||||
cat "${LIB_TEST_DEV}/btctl_info"
|
||||
fi
|
||||
exit 0
|
||||
BTCTL_HEAD
|
||||
)"
|
||||
printf '%s\n' "$body" >"${DEV}/btctl_info"
|
||||
_t_stub bluetoothctl "$stub"
|
||||
}
|
||||
|
||||
# --- remove_stale_pairing ---------------------------------------------------
|
||||
|
||||
bt_reset
|
||||
TARGET_MAC=""
|
||||
out="$(remove_stale_pairing)"
|
||||
_t_eq "" "$out" "remove_stale_pairing: no output when TARGET_MAC is empty"
|
||||
_t_eq "" "$(_t_fixes)" "remove_stale_pairing: applies no fix when TARGET_MAC is empty"
|
||||
|
||||
# Paired but not connected — the stale-pairing case the function exists for.
|
||||
bt_reset
|
||||
TARGET_MAC="AA:BB:CC:DD:EE:FF"
|
||||
_btctl_info "Device AA:BB:CC:DD:EE:FF JBL
|
||||
Paired: yes
|
||||
Connected: no"
|
||||
out="$(remove_stale_pairing 2>&1)"
|
||||
_t_contains "$out" "stale pairing" \
|
||||
"remove_stale_pairing: warns when the device is paired but not connected"
|
||||
_t_contains "$out" "Removing stale pairing for AA:BB:CC:DD:EE:FF" \
|
||||
"remove_stale_pairing: applies the removal fix for a stale pairing"
|
||||
|
||||
# Paired AND connected — healthy, nothing to do.
|
||||
bt_reset
|
||||
TARGET_MAC="AA:BB:CC:DD:EE:FF"
|
||||
_btctl_info "Device AA:BB:CC:DD:EE:FF JBL
|
||||
Paired: yes
|
||||
Connected: yes"
|
||||
out="$(remove_stale_pairing 2>&1)"
|
||||
_t_contains "$out" "paired and connected" \
|
||||
"remove_stale_pairing: reports a healthy device as paired and connected"
|
||||
_t_lacks "$out" "Removing stale pairing" \
|
||||
"remove_stale_pairing: applies no fix when the device is connected"
|
||||
|
||||
# Known to the adapter but not paired at all.
|
||||
bt_reset
|
||||
TARGET_MAC="AA:BB:CC:DD:EE:FF"
|
||||
_btctl_info "Device AA:BB:CC:DD:EE:FF JBL
|
||||
Paired: no
|
||||
Connected: no"
|
||||
out="$(remove_stale_pairing 2>&1)"
|
||||
_t_contains "$out" "not currently paired" \
|
||||
"remove_stale_pairing: reports an unpaired device as not paired"
|
||||
_t_lacks "$out" "Removing stale pairing" \
|
||||
"remove_stale_pairing: applies no fix when the device is not paired"
|
||||
|
||||
# Device entirely unknown to bluetoothctl.
|
||||
bt_reset
|
||||
TARGET_MAC="11:22:33:44:55:66"
|
||||
_btctl_info "No default controller available"
|
||||
out="$(remove_stale_pairing 2>&1)"
|
||||
_t_contains "$out" "Fresh pairing needed" \
|
||||
"remove_stale_pairing: asks for fresh pairing when the device is unknown"
|
||||
|
||||
# --- restart_bluetooth ------------------------------------------------------
|
||||
|
||||
bt_reset
|
||||
FIXES_APPLIED=0
|
||||
out="$(restart_bluetooth 2>&1)"
|
||||
_t_contains "$out" "skipping service restart" \
|
||||
"restart_bluetooth: skips the restart when no fixes were applied"
|
||||
|
||||
bt_reset
|
||||
FIXES_APPLIED=2
|
||||
out="$(restart_bluetooth 2>&1)"
|
||||
_t_contains "$out" "Restarting bluetooth.service" \
|
||||
"restart_bluetooth: restarts the service when fixes were applied"
|
||||
|
||||
echo
|
||||
echo "bt_pairing (stale pairing + restart): ${PASS} passed, ${FAIL} failed"
|
||||
((FAIL == 0))
|
||||
173
linux_configuration/scripts/single_use/fixes/lib/tests/test_bt_pairing_usb.sh
Executable file
173
linux_configuration/scripts/single_use/fixes/lib/tests/test_bt_pairing_usb.sh
Executable file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tests for lib/bt_pairing.sh: fix_usb_autosuspend and
|
||||
# _disable_usb_autosuspend, split from test_bt_pairing.sh for the 250-line cap.
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=bt_harness.sh
|
||||
. "${SCRIPT_DIR}/bt_harness.sh"
|
||||
|
||||
# shellcheck source=../bt_pairing.sh
|
||||
. "${FIXES_DIR}/lib/bt_pairing.sh"
|
||||
|
||||
# --- fix_usb_autosuspend ----------------------------------------------------
|
||||
#
|
||||
# This function globs the REAL /sys/bus/usb/devices/*/ -- the path is
|
||||
# hardcoded, with no env override to point elsewhere. Rather than bind-mount
|
||||
# or write anything, each case drives the branch it wants through the stubbed
|
||||
# `lsusb` output:
|
||||
#
|
||||
# * a vendor:product of ffff:ffff matches no device on any machine, so the
|
||||
# loop runs to exhaustion and takes the "could not find sysfs path" arm;
|
||||
# * a vendor:product that IS present on this host reaches the power/control
|
||||
# read, and _disable_usb_autosuspend is stubbed IN A SUBSHELL for those
|
||||
# cases so the udev rule and the sysfs write never happen.
|
||||
#
|
||||
# A top-level redefinition would shadow the real function for every later
|
||||
# assertion, so each override is confined to its own subshell.
|
||||
|
||||
# _lsusb_line TEXT — stub lsusb to emit a single line of TEXT.
|
||||
_lsusb_line() {
|
||||
printf '%s\n' "$1" >"${DEV}/lsusb_out"
|
||||
local body
|
||||
body="$(
|
||||
cat <<'LSUSB_BODY'
|
||||
cat "${LIB_TEST_DEV}/lsusb_out"
|
||||
LSUSB_BODY
|
||||
)"
|
||||
_t_stub lsusb "$body"
|
||||
}
|
||||
|
||||
# No bluetooth device in lsusb at all: the function returns before any lookup.
|
||||
bt_reset
|
||||
_t_stub lsusb 'echo "Bus 001 Device 002: ID 046d:c077 Logitech, Inc. Mouse"'
|
||||
out="$(fix_usb_autosuspend 2>&1)"
|
||||
_t_contains "$out" "Checking USB autosuspend" \
|
||||
"fix_usb_autosuspend: announces the check"
|
||||
_t_eq "" "$(_t_fixes)" \
|
||||
"fix_usb_autosuspend: applies no fix when lsusb lists no bluetooth device"
|
||||
|
||||
# A bluetooth line with no parseable ID: the usb_id guard returns early.
|
||||
bt_reset
|
||||
_lsusb_line "Bus 001 Device 003: Bluetooth adapter with no id field"
|
||||
out="$(fix_usb_autosuspend 2>&1)"
|
||||
_t_eq "" "$(_t_fixes)" \
|
||||
"fix_usb_autosuspend: applies no fix when the bluetooth line has no ID"
|
||||
|
||||
# A well-formed ID that matches no real device: the sysfs scan finds nothing.
|
||||
bt_reset
|
||||
_lsusb_line "Bus 001 Device 004: ID ffff:ffff Bluetooth Device"
|
||||
out="$(fix_usb_autosuspend 2>&1)"
|
||||
_t_contains "$out" "Could not find sysfs path" \
|
||||
"fix_usb_autosuspend: warns when no sysfs device matches the USB ID"
|
||||
_t_eq "" "$(_t_fixes)" \
|
||||
"fix_usb_autosuspend: applies no fix when the sysfs path is not found"
|
||||
|
||||
# A device whose power/control is already "on" needs no change. 046d:c077 is
|
||||
# present on this host with control=on; skipped if that ever stops holding.
|
||||
bt_reset
|
||||
if grep -qx "on" /sys/bus/usb/devices/1-11/power/control 2>/dev/null; then
|
||||
_lsusb_line "Bus 001 Device 005: ID 046d:c077 Bluetooth Device"
|
||||
out="$(fix_usb_autosuspend 2>&1)"
|
||||
_t_contains "$out" "already disabled" \
|
||||
"fix_usb_autosuspend: reports autosuspend already disabled when control is on"
|
||||
_t_eq "" "$(_t_fixes)" \
|
||||
"fix_usb_autosuspend: applies no fix when control is already on"
|
||||
else
|
||||
_t_pass "fix_usb_autosuspend: SKIP already-on case (1-11 control is not 'on' here)"
|
||||
fi
|
||||
|
||||
# _record_disable ARGS... — stand-in for the real writer, recording only.
|
||||
_record_disable() {
|
||||
printf 'disable_called %s\n' "$*" >>"${DEV}/fixes"
|
||||
}
|
||||
|
||||
# A device whose power/control is "auto" gets the fix. _disable_usb_autosuspend
|
||||
# is replaced INSIDE the subshell so this case proves the arguments handed to
|
||||
# the writer without letting the real writer touch /sys or /etc; the real
|
||||
# writer gets its own direct tests further down. The redefinition must stay in
|
||||
# the subshell, since a top-level one would shadow the real function for every
|
||||
# later assertion in this file.
|
||||
bt_reset
|
||||
if grep -qx "auto" /sys/bus/usb/devices/1-10/power/control 2>/dev/null; then
|
||||
_lsusb_line "Bus 001 Device 006: ID 046d:0825 Bluetooth Device"
|
||||
# _record_disable is defined at top level (so it is plainly a called
|
||||
# function) but only BOUND to the writer's name inside the subshell.
|
||||
out="$(
|
||||
eval '_disable_usb_autosuspend() { _record_disable "$@"; }'
|
||||
fix_usb_autosuspend 2>&1
|
||||
)"
|
||||
_t_contains "$out" "USB autosuspend is enabled" \
|
||||
"fix_usb_autosuspend: warns when autosuspend is enabled"
|
||||
_t_contains "$out" "Disabling USB autosuspend" \
|
||||
"fix_usb_autosuspend: applies the disable fix when control is auto"
|
||||
_t_contains "$(_t_fixes)" "disable_called /sys/bus/usb/devices/1-10/power/control 046d 0825" \
|
||||
"fix_usb_autosuspend: passes the control path, vendor and product to the writer"
|
||||
else
|
||||
_t_pass "fix_usb_autosuspend: SKIP auto case (1-10 control is not 'auto' here)"
|
||||
fi
|
||||
|
||||
# --- _disable_usb_autosuspend ----------------------------------------------
|
||||
#
|
||||
# Called directly, with the REAL body running. Both of its writes are
|
||||
# redirected out of the way rather than stubbed:
|
||||
#
|
||||
# * the sysfs power/control file is already a parameter, so a tmpdir file
|
||||
# covers it;
|
||||
# * the udev rule path is the UDEV_RULES_DIR override the lib exposes for
|
||||
# exactly this. A bind mount was rejected: run_all.sh runs UN-jailed in
|
||||
# ci_mirror.sh and in CI, so binding /etc would make the coverage run
|
||||
# safe and leave every bare run writing to the real file.
|
||||
#
|
||||
# udevadm is already stubbed by _bt_default_stubs.
|
||||
|
||||
bt_reset
|
||||
control_file="${TEST_TMPDIR}/power_control"
|
||||
rules_dir="${TEST_TMPDIR}/udev_rules"
|
||||
rule_file="${rules_dir}/50-bluetooth-no-autosuspend.rules"
|
||||
rm -rf "$rules_dir"
|
||||
mkdir -p "$rules_dir"
|
||||
echo "auto" >"$control_file"
|
||||
|
||||
out="$(UDEV_RULES_DIR="$rules_dir" \
|
||||
_disable_usb_autosuspend "$control_file" "046d" "0825" 2>&1)"
|
||||
|
||||
_t_eq "on" "$(cat "$control_file")" \
|
||||
"_disable_usb_autosuspend: writes 'on' to the sysfs power/control file"
|
||||
_t_contains "$out" "Created persistent udev rule" \
|
||||
"_disable_usb_autosuspend: reports creating the udev rule"
|
||||
_t_contains "$(cat "$rule_file")" 'ATTR{idVendor}=="046d"' \
|
||||
"_disable_usb_autosuspend: writes the vendor into the udev rule"
|
||||
_t_contains "$(cat "$rule_file")" 'ATTR{idProduct}=="0825"' \
|
||||
"_disable_usb_autosuspend: writes the product into the udev rule"
|
||||
_t_contains "$(cat "$rule_file")" 'ATTR{power/control}="on"' \
|
||||
"_disable_usb_autosuspend: pins power/control to on in the udev rule"
|
||||
_t_contains "$(_t_calls)" "udevadm control --reload-rules" \
|
||||
"_disable_usb_autosuspend: reloads udev rules after writing"
|
||||
|
||||
# Second call with the rule already present for this vendor: the guard must
|
||||
# skip the rewrite, so the existing file survives untouched.
|
||||
bt_reset
|
||||
printf '%s\n' "# pre-existing rule for 046d" >"$rule_file"
|
||||
echo "auto" >"$control_file"
|
||||
out="$(UDEV_RULES_DIR="$rules_dir" \
|
||||
_disable_usb_autosuspend "$control_file" "046d" "0825" 2>&1)"
|
||||
_t_eq "# pre-existing rule for 046d" "$(cat "$rule_file")" \
|
||||
"_disable_usb_autosuspend: leaves an existing rule for the same vendor alone"
|
||||
_t_lacks "$out" "Created persistent udev rule" \
|
||||
"_disable_usb_autosuspend: does not claim to create a rule that already existed"
|
||||
_t_eq "on" "$(cat "$control_file")" \
|
||||
"_disable_usb_autosuspend: still writes power/control on the idempotent path"
|
||||
|
||||
# A rule file that exists but covers a DIFFERENT vendor must be rewritten.
|
||||
bt_reset
|
||||
printf '%s\n' "# rule for some other vendor 1234" >"$rule_file"
|
||||
echo "auto" >"$control_file"
|
||||
out="$(UDEV_RULES_DIR="$rules_dir" \
|
||||
_disable_usb_autosuspend "$control_file" "046d" "0825" 2>&1)"
|
||||
_t_contains "$(cat "$rule_file")" 'ATTR{idVendor}=="046d"' \
|
||||
"_disable_usb_autosuspend: rewrites a rule file that covers a different vendor"
|
||||
|
||||
echo
|
||||
echo "bt_pairing (usb autosuspend): ${PASS} passed, ${FAIL} failed"
|
||||
((FAIL == 0))
|
||||
@ -81,7 +81,6 @@ linux_configuration/scripts/single_use/fixes/lib/arch_perf_report.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/arch_sysctl.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/bt_adapter.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/bt_audio.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/bt_pairing.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/hosts_guard_migrate.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/hosts_guard_rollback.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/nvidia_config.sh
|
||||
|
||||
Loading…
Reference in New Issue
Block a user