Files
wadamesh/test/test_wifi_switch_rejoin.cpp
Kaj SchittecatandClaude Opus 5.5 123b051b1a test: the Wi-Fi switches' one rejoin (79b605fe) as a host test
wifiSwitchRejoinService's decision moves into src/ui-touch/WifiSwitchRejoin.h
(same order of checks, same 4 s, same single shot); the service gathers the
Wi-Fi state and asks for the apply when it says so.

test/test_wifi_switch_rejoin.cpp drives it every 20 ms: the T-Deck case
(driver up after 300 ms, first join fails) rejoins once, 4 s after the
driver came up, never again; a join at 2.5 s or 3.98 s is left alone; a
scan from 1 s to 9 s holds it and the count restarts after (and nothing
fires if the scan's apply joins); switched off, no saved network, or a
driver that never starts: nothing; millis() wrap: still 4 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:46:31 +01:00

123 lines
4.3 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
//
// Host test for the Wi-Fi switches' rejoin (79b605fe): src/ui-touch/WifiSwitchRejoin.h,
// the decision wifiSwitchRejoinService runs every UI loop pass after wifiRadioSwitch(true).
//
// c++ -std=c++17 -Wall -Wextra -I src test/test_wifi_switch_rejoin.cpp \
// -o /tmp/test_wifi_switch_rejoin && /tmp/test_wifi_switch_rejoin
#include <assert.h>
#include <stdio.h>
#include <functional>
#include <vector>
#include "ui-touch/WifiSwitchRejoin.h"
using WifiSwitchRejoin::State;
// Run the service every 20 ms (a UI loop pass) from `t0` (the switch: since = t0) until
// `t_end`, with the world given by `at(now)`. Returns the times the rejoin fired.
static std::vector<uint32_t> run(uint32_t t0, uint32_t t_end, const std::function<State(uint32_t)>& at,
uint32_t* since_out = nullptr) {
std::vector<uint32_t> fired;
uint32_t since = t0; // wifiRadioSwitch(true): s_wifi_switch_rejoin_ms = millis()
for (uint32_t now = t0; now <= t_end; now += 20)
if (WifiSwitchRejoin::step(since, now, at(now))) fired.push_back(now);
if (since_out) *since_out = since;
return fired;
}
static State up(bool connected = false) { return State{true, true, connected, true, false}; }
int main() {
const uint32_t T = 50000;
// The T-Deck case: the driver comes up 300 ms after the switch, the first join does
// not take. One rejoin, 4 s after the driver is up; never a second one.
{
auto f = run(T, T + 60000, [&](uint32_t now) {
State s = up();
s.driver_up = now >= T + 300;
return s;
});
assert(f.size() == 1);
assert(f[0] >= T + 300 - 20 + 4000 && f[0] <= T + 300 + 4000); // counted from the last pass that saw it down
}
// A join that works first time (linked at 2.5 s): left alone, the wait ends.
{
uint32_t since = 1;
auto f = run(T, T + 60000, [&](uint32_t now) { return up(now >= T + 2500); }, &since);
assert(f.empty() && since == 0);
}
// Linked just before the 4 s: no rejoin.
{
auto f = run(T, T + 60000, [&](uint32_t now) { return up(now >= T + 3980); });
assert(f.empty());
}
// A scan owns the radio from 1 s to 9 s (Settings > Wi-Fi opened): nothing while it
// runs, and the 4 s count starts again when it ends (the scan's own apply may join).
{
auto f = run(T, T + 60000, [&](uint32_t now) {
State s = up();
s.scanning = now >= T + 1000 && now < T + 9000;
return s;
});
assert(f.size() == 1);
assert(f[0] >= T + 9000 + 4000 - 20 && f[0] < T + 9000 + 4000 + 40);
}
// ...and when the scan's apply joins, nothing fires at all
{
auto f = run(T, T + 60000, [&](uint32_t now) {
State s = up(now >= T + 9500);
s.scanning = now >= T + 1000 && now < T + 9000;
return s;
});
assert(f.empty());
}
// Switched off again within the 4 s: cancelled, nothing fires even if switched on
// later by something else (a new switch starts its own wait).
{
uint32_t since = 1;
auto f = run(T, T + 60000, [&](uint32_t now) { State s = up(); s.wants = now < T + 2000; return s; }, &since);
assert(f.empty() && since == 0);
}
// No saved network to join: nothing to do.
{
auto f = run(T, T + 60000, [&](uint32_t) { State s = up(); s.has_runtime = false; return s; });
assert(f.empty());
}
// The driver never comes up (main.cpp failed to start it): the wait keeps restarting,
// no rejoin is asked of a driver that is not there.
{
uint32_t since = 0;
auto f = run(T, T + 60000, [&](uint32_t) { State s = up(); s.driver_up = false; return s; }, &since);
assert(f.empty() && since != 0);
}
// Nothing pending (switched off, or a switch that never turned it on): nothing happens.
{
uint32_t since = 0;
for (uint32_t now = T; now < T + 20000; now += 20) assert(!WifiSwitchRejoin::step(since, now, up()));
assert(since == 0);
}
// millis() wrapping during the wait: still 4 s.
{
const uint32_t W = 0xFFFFFFFFu - 1000;
uint32_t since = W;
uint32_t fired_at = 0; bool fired = false;
for (uint32_t i = 0; i < 400 && !fired; ++i) {
const uint32_t now = W + i * 20;
if (WifiSwitchRejoin::step(since, now, up())) { fired = true; fired_at = now - W; }
}
assert(fired && fired_at == 4000);
}
printf("test_wifi_switch_rejoin: ok\n");
return 0;
}