mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-06-03 20:51:19 +00:00
749fdc114f
RED commit: `dc4c0800` — CI: https://github.com/Kpa-clawbot/CoreScope/actions?query=branch%3Afix%2Fissue-1279-p2 Closes the remaining six 🟢 P2 items in umbrella #1279 (PR #1280 shipped P0+P1, PR #1276 shipped ACK/RESPONSE/PATH legend rows). ### Item-by-item | # | Item | Where | Test | |---|---|---|---| | 1 | `payloadTypeNames` parity | `cmd/server/store.go` | `cmd/server/issue1279_p2_test.go::TestPayloadTypeNamesAll13` | | 2 | Legend rows: Anon Req / Grp Data / Multipart / Control / Raw Custom | `public/live.js` | `test-issue-1279-legend-p2-e2e.js` (Playwright) | | 3 | TransportCodes detail-row + `code1=` / `code2=` filter grammar | `public/packets.js`, `public/packet-filter.js` | `test-issue-1279-p2-code-filter.js` (6 cases) | | 4 | Multibyte capability badge on node detail/list rows | `public/nodes.js::renderNodeBadges` | `n.hash_size >= 2` (observable Feat1/Feat2 proxy; firmware `AdvertDataHelpers.h:14-16`) | | 5 | RAW_CUSTOM (0x0F) `{rawLength, firstByteTag}` decode + detail-row | `cmd/server/decoder.go`, `cmd/ingestor/decoder.go`, `public/packets.js` | `TestDecodeRawCustomExposesLengthAndTag` × 2 + updated `TestDecodePayloadRAWCustom` | | 6 | Sensor advert telemetry firmware-derivation comments | `cmd/ingestor/decoder.go:363-380` | pure comments — exempt per AGENTS | ### Firmware refs cited inline - `firmware/src/Packet.h:19-32` — PAYLOAD_TYPE_* constants - `firmware/src/Packet.h:46` — TransportCodes wire layout - `firmware/src/Mesh.cpp:577` — `createRawData` - `firmware/src/helpers/SensorMesh.{h,cpp}` — sensor advert telemetry derivation - `firmware/src/helpers/AdvertDataHelpers.h:14-16` — Feat1/Feat2 ### TDD Red `dc4c0800` proves the assertions gate behavior: - `payloadTypeNames` had only 12 entries (no 0x0F). - RAW_CUSTOM decoded as `UNKNOWN` with no envelope fields. Green `<HEAD>` makes both green; per-item tests included. ### Cross-stack note Cross-stack: justified — items 1/5 add decoder output fields; items 2/3/4/5 surface those fields in the UI in the same PR per #1279 acceptance. ### Out of scope Item 4 surfaces the observable multibyte capability via the persisted `hash_size` (Feat1/Feat2 wire bits are only on transient adverts and not stored per-node today); persisting raw Feat1/Feat2 per-node is left for a follow-up. Fixes #1279 --------- Co-authored-by: bot <bot@corescope>
63 lines
2.1 KiB
Go
63 lines
2.1 KiB
Go
package main
|
|
|
|
// Tests for issue #1279 P2 items:
|
|
// - Item 1: payloadTypeNames map must include ALL 13 firmware payload types.
|
|
// - Item 5: RAW_CUSTOM (0x0F) decoder must expose rawLength + firstByteTag.
|
|
//
|
|
// Firmware refs:
|
|
// - firmware/src/Packet.h:19-32 (PAYLOAD_TYPE_*) — 0..0xB plus 0xF (RAW_CUSTOM)
|
|
// - firmware/src/Mesh.cpp:577 (createRawData) — application-defined payload
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPayloadTypeNamesAll13(t *testing.T) {
|
|
// Firmware-defined: 0..9, 0x0A, 0x0B, 0x0F — 13 total.
|
|
want := map[int]string{
|
|
0x00: "REQ", 0x01: "RESPONSE", 0x02: "TXT_MSG", 0x03: "ACK",
|
|
0x04: "ADVERT", 0x05: "GRP_TXT", 0x06: "GRP_DATA", 0x07: "ANON_REQ",
|
|
0x08: "PATH", 0x09: "TRACE", 0x0A: "MULTIPART", 0x0B: "CONTROL",
|
|
0x0F: "RAW_CUSTOM",
|
|
}
|
|
if len(payloadTypeNames) != len(want) {
|
|
t.Errorf("payloadTypeNames has %d entries, want %d", len(payloadTypeNames), len(want))
|
|
}
|
|
for code, name := range want {
|
|
got, ok := payloadTypeNames[code]
|
|
if !ok {
|
|
t.Errorf("payloadTypeNames missing 0x%02X (%s)", code, name)
|
|
continue
|
|
}
|
|
if got != name {
|
|
t.Errorf("payloadTypeNames[0x%02X] = %q, want %q", code, got, name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDecodeRawCustomExposesLengthAndTag(t *testing.T) {
|
|
// Build a RAW_CUSTOM packet: header byte = (route<<6 | type<<2 | ver),
|
|
// type=0x0F. Route FLOOD (1), version 1: (1<<6)|(0x0F<<2)|1 = 0x7D.
|
|
// Path byte: 0 hops, hash_size=1 → upper bits 0, lower 0 → 0x00.
|
|
// Payload: first byte tag 0xA5, then arbitrary data.
|
|
hexStr := "7D00A5DEADBEEF"
|
|
pkt, err := DecodePacket(hexStr, false)
|
|
if err != nil {
|
|
t.Fatalf("decode: %v", err)
|
|
}
|
|
if pkt.Payload.Type != "RAW_CUSTOM" {
|
|
t.Fatalf("payload type = %q, want RAW_CUSTOM", pkt.Payload.Type)
|
|
}
|
|
if pkt.Payload.RawLength == nil {
|
|
t.Fatal("RawLength should be set for RAW_CUSTOM")
|
|
}
|
|
// payload = 4 bytes (A5 DE AD BE EF) — wait, A5 DE AD BE EF = 5 bytes.
|
|
if *pkt.Payload.RawLength != 5 {
|
|
t.Errorf("RawLength=%d, want 5", *pkt.Payload.RawLength)
|
|
}
|
|
if !strings.EqualFold(pkt.Payload.FirstByteTag, "A5") {
|
|
t.Errorf("FirstByteTag=%q, want A5", pkt.Payload.FirstByteTag)
|
|
}
|
|
}
|