mirror of
https://github.com/alexhopeoconnor/WiFiManager.git
synced 2026-10-22 02:32:10 +10:00
fix: harden portal OTA release
This commit is contained in:
@@ -73,6 +73,26 @@ class FakeSerial:
|
||||
self.close()
|
||||
|
||||
|
||||
class FakeClock:
|
||||
def __init__(self):
|
||||
self.value = 0.0
|
||||
|
||||
def __call__(self):
|
||||
return self.value
|
||||
|
||||
def advance(self, seconds):
|
||||
self.value += seconds
|
||||
|
||||
|
||||
class BlockingEmptySerial(FakeSerial):
|
||||
clock = None
|
||||
|
||||
def read(self, _size):
|
||||
type(self).read_calls += 1
|
||||
type(self).clock.advance(0.25)
|
||||
return b""
|
||||
|
||||
|
||||
def load_capture_module():
|
||||
fake_serial_module = types.ModuleType("serial")
|
||||
fake_serial_module.Serial = FakeSerial
|
||||
@@ -126,6 +146,57 @@ def main():
|
||||
assert ("open", False, False, "/dev/fake") in FakeSerial.events
|
||||
assert ("close",) in FakeSerial.events
|
||||
assert FakeSerial.read_calls == 2
|
||||
|
||||
# An immediate empty-return backend must back off progressively instead of
|
||||
# spinning. This takes no real sleep because the sleeper is injected.
|
||||
FakeSerial.read_calls = 0
|
||||
with tempfile.TemporaryDirectory() as temporary_directory:
|
||||
output = Path(temporary_directory) / "serial-ota.log"
|
||||
ready = Path(temporary_directory) / "serial-ota.ready"
|
||||
empty_sleeps = []
|
||||
assert module.capture(
|
||||
"/dev/fake",
|
||||
output,
|
||||
ready,
|
||||
should_stop=lambda: FakeSerial.read_calls >= 5,
|
||||
sleep=empty_sleeps.append,
|
||||
) == 0
|
||||
assert empty_sleeps == [0.01, 0.02, 0.04, 0.08]
|
||||
|
||||
# A normal 250 ms serial timeout is already rate-limited by the device
|
||||
# driver, so it must not receive an additional backoff sleep.
|
||||
module.serial.Serial = BlockingEmptySerial
|
||||
BlockingEmptySerial.events = []
|
||||
BlockingEmptySerial.read_calls = 0
|
||||
clock = FakeClock()
|
||||
BlockingEmptySerial.clock = clock
|
||||
with tempfile.TemporaryDirectory() as temporary_directory:
|
||||
output = Path(temporary_directory) / "serial-ota.log"
|
||||
ready = Path(temporary_directory) / "serial-ota.ready"
|
||||
empty_sleeps = []
|
||||
assert module.capture(
|
||||
"/dev/fake",
|
||||
output,
|
||||
ready,
|
||||
should_stop=lambda: BlockingEmptySerial.read_calls >= 2,
|
||||
clock=clock,
|
||||
sleep=empty_sleeps.append,
|
||||
) == 0
|
||||
assert empty_sleeps == []
|
||||
module.serial.Serial = FakeSerial
|
||||
|
||||
FakeSerial.read_calls = 0
|
||||
with tempfile.TemporaryDirectory() as temporary_directory:
|
||||
output = Path(temporary_directory) / "serial-ota.log"
|
||||
ready = Path(temporary_directory) / "serial-ota.ready"
|
||||
assert module.capture(
|
||||
"/dev/fake",
|
||||
output,
|
||||
ready,
|
||||
should_stop=lambda: False,
|
||||
deadline_seconds=0.0,
|
||||
) == 2
|
||||
|
||||
print("WiFiManager passive OTA serial-capture test-harness check passed")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check OTA fixture identity and environment locking without PlatformIO or a board.
|
||||
set -euo pipefail
|
||||
|
||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
temporary_root="$(mktemp -d "${TMPDIR:-/tmp}/wifimanager-ota-identity-test.XXXXXX")"
|
||||
chmod 700 "$temporary_root"
|
||||
cleanup() {
|
||||
rm -rf -- "$temporary_root"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
export ARDUINO_TEST_HARNESS_LOCK_DIR="$temporary_root/locks"
|
||||
export WIFIMANAGER_OTA_IDENTITY_DIR="$temporary_root/identity"
|
||||
# shellcheck source=tools/lib/ota-fixture-identity.sh
|
||||
source "$root/tools/lib/ota-fixture-identity.sh"
|
||||
# shellcheck source=tools/lib/harness-locks.sh
|
||||
source "$root/tools/lib/harness-locks.sh"
|
||||
|
||||
wm_write_ota_fixture_identity A
|
||||
identity_file="$WIFIMANAGER_OTA_IDENTITY_DIR/ota_fixture_identity.h"
|
||||
[[ "$(stat -c '%a' "$WIFIMANAGER_OTA_IDENTITY_DIR")" == 700 ]]
|
||||
[[ "$(stat -c '%a' "$identity_file")" == 600 ]]
|
||||
rg -Fqx '#define WM_OTA_FIXTURE_IMAGE "A"' "$identity_file"
|
||||
|
||||
wm_lock_ota_fixture_environment esp8266_ota
|
||||
collision_output="$temporary_root/lock-collision.log"
|
||||
if (
|
||||
root="$root"
|
||||
export WIFIMANAGER_OTA_IDENTITY_DIR="$temporary_root/other-identity"
|
||||
# shellcheck source=tools/lib/ota-fixture-identity.sh
|
||||
source "$root/tools/lib/ota-fixture-identity.sh"
|
||||
wm_lock_ota_fixture_environment esp8266_ota
|
||||
) 2>"$collision_output"; then
|
||||
echo "A second test-harness process unexpectedly acquired the same OTA environment lock." >&2
|
||||
exit 1
|
||||
fi
|
||||
rg -Fqx "OTA fixture environment 'esp8266_ota' is already in use by another local test-harness run." "$collision_output"
|
||||
|
||||
wm_harness_lock_resource "test resource" "identity-test:shared-resource"
|
||||
if (
|
||||
# shellcheck source=tools/lib/harness-locks.sh
|
||||
source "$root/tools/lib/harness-locks.sh"
|
||||
wm_harness_lock_resource "test resource" "identity-test:shared-resource"
|
||||
) 2>"$collision_output"; then
|
||||
echo "A second test-harness process unexpectedly acquired the same resource lock." >&2
|
||||
exit 1
|
||||
fi
|
||||
rg -Fqx 'Cannot start: test resource is already in use by another local test-harness process.' "$collision_output"
|
||||
|
||||
wm_remove_ota_fixture_identity
|
||||
[[ ! -e "$identity_file" ]]
|
||||
echo "WiFiManager OTA fixture identity test-harness check passed"
|
||||
Reference in New Issue
Block a user