mirror of
https://github.com/meshtastic/firmware.git
synced 2026-09-16 08:30:04 -04:00
* fix(nodedb): track whether each node was heard on the current LoRa config Set NODEINFO_BITFIELD_HEARD_ON_CURRENT_LORA on a genuine RF hear and clear it for every node when the LoRa slot config moves, so clients can tell which nodes went unreachable after a preset, region, slot or primary-channel-name change. Hooked into MeshService::reloadConfig(), the single funnel for the device menu, admin/CLI and scanned-URL paths, plus NodeDB::restorePreferences(), which reboots without passing through it. Fixes #11745 * fix(nodedb): store the slot each node was heard on instead of sweeping a bit A client scanning for traffic rolls through presets with live set_config writes, so every hop reached reloadConfig and the sweep cleared the marks on the way out and again on the way home. Each node now carries a 12-bit fingerprint of the slot it was heard on in spare bitfield bits, and heard_on_current_lora is derived by comparing that against the slot the radio is committed to. Config changes no longer touch the node database at all. * fix(nodedb): keep comments inside the two-line limit, rename a test Trunk read test_fingerprint_channelNumIsASlotChange as a Lob API key, since it is test_ followed by exactly 35 alphanumerics, so the tail is now shorter. The comments added under src/ are back within the one-or-two-line limit in AGENTS.md. * fix(nodedb): drop legacy bitfield bits above 10 during v24 migration v24 assigned bits 0..10, so a legacy record carrying anything higher would arrive claiming an RF hear with a stray slot fingerprint, and a never-heard node would read as reachable whenever that stray value matched ours. The migration now masks those bits off, and a new case in test_nodedb_legacy_migration pins it.
9.0 KiB
9.0 KiB
| 1 | # Shared-state manifest for the native test suites. | ||
|---|---|---|---|
| 2 | # | ||
| 3 | # Every suite runs inside its own scratch $HOME (bin/pio-test-isolate.sh), so leftovers cannot reach | ||
| 4 | # the next suite. This file is not what makes that safe - it is what makes each suite's intent | ||
| 5 | # | ||
| 6 | # The invariant behind the flags: mutation *inside* a suite is free, carrying state *across* a suite | ||
| 7 | # boundary is never permitted. No flag grants cross-suite carry - a suite that needs another suite's | ||
| 8 | # output needs an explicit fixture, not inheritance. That is the whole bug, and per-suite isolation | ||
| 9 | # keeps it impossible by construction rather than by policy. | ||
| 10 | # | ||
| 11 | # Format - three tab-separated columns, the same shape as an allowlist entry: | ||
| 12 | # | ||
| 13 | # <suite> | <flags> | <reason> |
| 14 | # | ||
| 15 | # The reason column is mandatory and is reviewed on change. One central file rather than a file per | ||
| 16 | # suite, so every opt-out is visible in one diffable list and attracts review pressure; per-suite | ||
| 17 | # files hide growth. bin/run-tests.sh prints how many suites declare non-default handling, so the | ||
| 18 | # number creeping upward is visible without anyone auditing this file. | ||
| 19 | # | ||
| 20 | # Flags (space separated; the default is no entry at all): | ||
| 21 | # | ||
| 22 | # writes=<a,b> files this suite mutates inside its sandbox. Matched against the path relative | ||
| 23 | # to the scratch $HOME or just the basename, so `nodes.proto` is enough. A | ||
| 24 | # declared write makes the change CLEAN instead of DIRTY - the list is the | ||
| 25 | # documentation. A declared file that does NOT change is reported as MISSING, | ||
| 26 | # which catches silently-broken persistence. | ||
| 27 | # state=per-suite state persists across this suite's own test cases; the default is per-test. | ||
| 28 | # Use for persistence round-trips, migration ladders, anything where test N must | ||
| 29 | # observe test N-1's write. With this set, only the suite boundary is checked - | ||
| 30 | # per-test checking would flag every test by design. | ||
| 31 | # | ||
| 32 | # state=per-suite is the one to watch. It is legitimate, and it is also the pattern that let | ||
| 33 | # test_nodedb_blocked accumulate 198 protected nodes across its test cases. Requiring the flag makes | ||
| 34 | # that an explicit, defended choice instead of an accident of setUp(). | ||
| 35 | # | ||
| 36 | # To propose entries from a real run: ./bin/run-tests.sh --write-manifest prints the lines it would | ||
| 37 | # add, for a human to paste and justify. It never applies them itself, and CI never applies them at | ||
| 38 | # all - an auto-accepted baseline is the same rot as an auto-updated snapshot. | ||
| 39 | # | ||
| 40 | # errors=<max> | <min>..<max> | <min>.. caps a suite's LOG_ERROR lines, default 100. A range, not a | ||
| 41 | # ceiling: for a fuzz suite the floor is the half that matters. test_fuzz_decode logging ~100k | ||
| 42 | # rejections is the suite working; the same suite logging none means it stopped feeding malformed | ||
| 43 | # input, and every case would still pass. Bounds are wide on purpose - they catch a path that has | ||
| 44 | # stopped running, not a drift of a few hundred lines. | ||
| 45 | # | ||
| 46 | # suite | flags | reason |
| 47 | test_admin_radio | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat,Messages_default.msgs errors=400 | per-test NodeDB fixture, and the admin handlers under test persist config, channels and node metadata |
| 48 | test_admin_session_repro | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB, whose constructor persists a default set when the prefs directory is empty |
| 49 | test_event_channel_phone_api | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB, whose constructor persists a default set when the prefs directory is empty |
| 50 | test_event_channel_router | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto errors=200 | subclasses NodeDB for the event-channel fixtures; the base constructor persists a default set when the prefs directory is empty |
| 51 | test_firmware_edition | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | persists an event firmware_edition in devicestate, then reboots a NodeDB to prove a vanilla build resets it |
| 52 | test_fuzz_decode | errors=20000..250000 | fuzzes protobuf decode; every rejection logs. A collapse to near zero means the corpus stopped reaching the decoder |
| 53 | test_fuzz_packets | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat,Messages_default.msgs errors=5000..60000 | drives decode of fuzzed packets through the real NodeDB and message store |
| 54 | test_hop_scaling | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB to hold the hop-distance fixtures |
| 55 | test_hop_start_policy | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB (isFromUs needs nodeDB->getNodeNum()), whose constructor persists a default set when the prefs directory is empty |
| 56 | test_mesh_beacon | writes=module.proto | exercises the beacon's module-config save path |
| 57 | test_mesh_module | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat | module framework tests construct a NodeDB |
| 58 | test_mqtt | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto errors=1000..12000 | constructs a NodeDB for node lookups in the MQTT paths |
| 59 | test_muted_source | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB (isToUs needs nodeDB->getNodeNum(), and the DM branch looks the sender up), whose constructor persists a default set when the prefs directory is empty |
| 60 | test_nexthop_routing | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | next-hop selection reads and updates the node DB |
| 61 | test_nodedb_blocked | state=per-suite writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat | saturates the DB with MAX_NUM_NODES-2 favourited nodes to test the protected cap; a later test's removeNodeByNum() persists that state, and the cap test depends on the fill from the test before it |
| 62 | test_nodedb_boot_recovery | state=per-suite writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | deliberate boot-recovery ladder: corrupts/deletes/restores the pref files and reboots a NodeDB per test to pin the DECODE_FAILED identity freeze, so each test observes the previous test's on-disk state |
| 63 | test_nodedb_identity_hygiene | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat,Messages_default.msgs | constructs a NodeDB; addFromContact persists the node DB after every merge, the reboot test proves the key-erasure guard survives a reload, and the should_ignore path rewrites the message store |
| 64 | test_nodedb_legacy_migration | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat | each test hand-writes a v24-format nodes.proto fixture and cold-boots a NodeDB, whose constructor persists the migrated v25 database (warm.dat via the over-cap eviction absorb) |
| 65 | test_nodedb_lora_slot | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB, whose constructor persists a default set when the prefs directory is empty; the tests themselves only mutate config.lora in RAM and restore it in tearDown |
| 66 | test_nodedb_v25_roundtrip | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat | v25 persistence round-trips: every test saves nodes.proto and cold-boots a NodeDB whose constructor persists the default segments; warm.dat on the node-DB save cadence |
| 67 | test_packet_signing | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat errors=300 | needs a NodeDB holding both peers' keys for the PKI encode/decode paths |
| 68 | test_phone_api_config_dump | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | per-test NodeDB fixture backing full PhoneAPI want_config dumps; the constructor persists a default config/channel/node set in a fresh sandbox |
| 69 | test_pki_admin_fallback | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | needs a NodeDB holding admin keys for the fallback paths |
| 70 | test_reliable_ack_matrix | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | constructs a NodeDB (whose constructor persists a default set when the prefs directory is empty) for the sender-key lookups in the ACK/NAK matrix |
| 71 | test_stream_api | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | drives real PhoneAPI handshakes, which read and persist config and the node DB |
| 72 | test_traceroute_nexthop | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto | traceroute route selection reads the node DB |
| 73 | test_traffic_management | writes=config.proto,module.proto,device.proto,channels.proto,nodes.proto,warm.dat errors=3000..12000 | constructs a NodeDB for the per-node rate-limit and dedup state; test_tm_fuzz_nodenum_blitz feeds malformed payloads, and each rejection logs (measured 7985) |
| 74 | test_transmit_history | writes=transmit_history.dat | persistence round-trip: what it asserts is that retransmission state survives a save/load |
| 75 | test_warm_store | writes=warm.dat | persistence round-trip of the warm-tier snapshot, which is the tier's whole contract |