"""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 ") 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"