ESPSomfy-RTS/test/e2e/test_update.py
cjkas b525a800b0 test: e2e firmware update, and restarts told apart by boot time
With --reboot, a restore of the radio alone brings it back as it was:
on a board without Ethernet it read the radio from the wrong place.

--firmware <firmware.bin> updates the device through /updateFirmware and
checks it still runs a minute later, after it marks the update good.

wait_for_restart compared uptimes, so a test run right after another
restart could see more uptime than before and fail.  It compares boot
times, and waits while the device hasn't restarted yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:59:53 +01:00

48 lines
1.6 KiB
Python

"""A firmware update through /updateFirmware, as the web UI sends it.
Pass --firmware with a firmware.bin built for the device's chip, e.g.
.pio/build/esp32s3/firmware.bin. The device must have an OTA slot: the
release builds do, the C5, C6 and debug builds don't.
"""
import time
import pytest
from proto_client import run_sync
from test_routes import auth, upload
from test_settings import boot_time, wait_for_restart
# The new firmware is marked good once it has run this long with the network
# up; a reset before then boots the old one (docs/adr/0003-pioarduino-idf55.md).
PROVEN_AFTER_S = 60
@pytest.fixture
def firmware(request):
path = request.config.getoption("--firmware")
if not path:
pytest.skip("updates the device's firmware: pass --firmware <firmware.bin>")
with open(path, "rb") as f:
return f.read()
def test_an_update_restarts_on_the_new_firmware_and_stays(host, token, connect, schema, firmware):
c = connect(schema=schema.hash)
_, frames, _ = run_sync(c)
booted = boot_time(schema, frames)
c.close()
status, _, body = upload(host, "/updateFirmware", auth(token), file=firmware)
assert status == 200, body
wait_for_restart(host, token, schema, booted)
# Past the point where it is marked good it is still running, and hasn't
# restarted on the old firmware.
c = connect(schema=schema.hash)
_, frames, _ = run_sync(c)
restarted = boot_time(schema, frames)
c.close()
time.sleep(PROVEN_AFTER_S + 10)
c = connect(schema=schema.hash)
_, frames, _ = run_sync(c)
assert abs(boot_time(schema, frames) - restarted) < 5, "the device restarted again"