mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-07-10 10:19:45 +00:00
Fix interop tests (#4020)
* logosdelivery_create_node takes a flat WakuNodeConf JSON conf (auto-detect) * Fix tools/confutils/conf_from_json.nim not accepting Port(0) * Fix: don't mount lightpush without relay * Add tests
This commit is contained in:
parent
d83900aa9b
commit
28956856bb
@ -13,6 +13,10 @@ const
|
||||
KeyKernelConf = "kernelconf"
|
||||
KeyMessagingOverrides = "messagingoverrides"
|
||||
KeyChannelsOverrides = "channelsoverrides"
|
||||
# [Legacy flat JSON config] Keys that left the kernel and so must be lifted out of
|
||||
# a flat blob before the WakuNodeConf walker sees them (it would reject them).
|
||||
KeyReliabilityEnabled = "reliabilityenabled"
|
||||
KeyReliability = "reliability"
|
||||
|
||||
proc parseMode(s: string): Result[LogosDeliveryMode, string] =
|
||||
case s.strip().toLowerAscii()
|
||||
@ -39,6 +43,50 @@ proc parseOverrides[T](defaults: T, node: JsonNode, label: string): Result[T, st
|
||||
)
|
||||
return ok(conf)
|
||||
|
||||
proc parseFlatConf(
|
||||
mode: LogosDeliveryMode, topJsonNode: var Table[string, (string, JsonNode)]
|
||||
): ConfResult[LogosDeliveryConf] =
|
||||
## [Legacy flat JSON config] Flat shape: a blob of `WakuNodeConf` fields. `mode`
|
||||
## expands to protocol flags over raw kernel defaults, `reliabilityEnabled` routes
|
||||
## to the messaging conf (it left the kernel), and the rest parses as a
|
||||
## `WakuNodeConf`. Full stack. Delete this proc and its call site to drop support.
|
||||
var messaging = MessagingClientConf()
|
||||
var reliabilityFields: Table[string, (string, JsonNode)]
|
||||
for key in [KeyReliabilityEnabled, KeyReliability]:
|
||||
if topJsonNode.hasKey(key):
|
||||
reliabilityFields[key] = topJsonNode.getOrDefault(key)
|
||||
topJsonNode.del(key)
|
||||
if reliabilityFields.len > 0:
|
||||
?applyJsonFieldsToConf(
|
||||
messaging, reliabilityFields, "Failed to parse reliability field",
|
||||
"Unrecognized reliability option(s) found",
|
||||
)
|
||||
|
||||
# [Legacy flat JSON config] The blob is a raw WakuNodeConf, exactly as the
|
||||
# pre-refactor flat create_node parsed it: start from the kernel defaults and apply
|
||||
# the mode's protocol flags (the kernel no longer owns `mode`, so we expand it here,
|
||||
# like the old kernel builder did), then let explicit fields override.
|
||||
var kernel = ?defaultWakuNodeConf()
|
||||
?applyMode(kernel, mode)
|
||||
?applyJsonFieldsToConf(
|
||||
kernel, topJsonNode, "Failed to parse config field",
|
||||
"Unrecognized configuration option(s) found",
|
||||
)
|
||||
|
||||
# [Legacy flat JSON config] Reliability is resolved from the preset by the messaging
|
||||
# layer (the kernel no longer carries it), so a flat blob's `preset` must lift it
|
||||
# here to stay faithful to master. An explicit reliability in the blob still wins.
|
||||
if kernel.preset.len > 0:
|
||||
messaging = merge(?resolvePreset(kernel.preset), messaging)
|
||||
|
||||
return ok(
|
||||
LogosDeliveryConf(
|
||||
kernelConf: KernelConf(kernel),
|
||||
messagingConf: some(messaging),
|
||||
channelsConf: some(ReliableChannelManagerConf()),
|
||||
)
|
||||
)
|
||||
|
||||
proc parseLogosDeliveryConf*(jsonStr: string): ConfResult[LogosDeliveryConf] =
|
||||
var node: JsonNode
|
||||
try:
|
||||
@ -70,6 +118,21 @@ proc parseLogosDeliveryConf*(jsonStr: string): ConfResult[LogosDeliveryConf] =
|
||||
err(unknownKeysError(top, "fleet mode takes only 'kernelConf'; unexpected"))
|
||||
return ok(LogosDeliveryConf.init(KernelConf(kernel)))
|
||||
|
||||
# [Legacy flat JSON config] A wrapper key marks our structured shape. Otherwise any
|
||||
# leftover top-level key besides `preset` (mode is already consumed) is a bare
|
||||
# kernel field -> flat blob. Delete this block to drop flat-shape support.
|
||||
let hasWrapper =
|
||||
top.hasKey(KeyMessagingOverrides) or top.hasKey(KeyChannelsOverrides) or
|
||||
top.hasKey(KeyKernelConf)
|
||||
if not hasWrapper:
|
||||
var bareField = false
|
||||
for k in top.keys:
|
||||
if k != KeyPreset:
|
||||
bareField = true
|
||||
break
|
||||
if bareField:
|
||||
return parseFlatConf(mode, top)
|
||||
|
||||
var preset = ""
|
||||
var messagingOverrides = MessagingClientConf()
|
||||
var channelsOverrides = ReliableChannelManagerConf()
|
||||
|
||||
@ -13,12 +13,8 @@ type LogosDeliveryMode* {.pure.} = enum
|
||||
Core # full service node
|
||||
Fleet # kernel-only node from a raw kernel config
|
||||
|
||||
proc toWakuNodeConf*(
|
||||
self: MessagingClientConf, mode: LogosDeliveryMode
|
||||
): ConfResult[WakuNodeConf] =
|
||||
## Mode sets the protocol flags; set fields map to their kernel counterpart.
|
||||
var conf = ?defaultWakuNodeConf()
|
||||
|
||||
proc applyMode*(conf: var WakuNodeConf, mode: LogosDeliveryMode): ConfResult[void] =
|
||||
## Sets the protocol flags implied by the mode.
|
||||
case mode
|
||||
of LogosDeliveryMode.Core:
|
||||
conf.relay = true
|
||||
@ -36,6 +32,14 @@ proc toWakuNodeConf*(
|
||||
of LogosDeliveryMode.Fleet:
|
||||
return
|
||||
err("fleet mode takes a raw kernel config; use LogosDelivery.new(kernelConf)")
|
||||
return ok()
|
||||
|
||||
proc toWakuNodeConf*(
|
||||
self: MessagingClientConf, mode: LogosDeliveryMode
|
||||
): ConfResult[WakuNodeConf] =
|
||||
## Mode sets the protocol flags; set fields map to their kernel counterpart.
|
||||
var conf = ?defaultWakuNodeConf()
|
||||
?applyMode(conf, mode)
|
||||
|
||||
if self.store.isSome():
|
||||
conf.store = self.store.get()
|
||||
|
||||
@ -797,7 +797,7 @@ proc build*(
|
||||
subscribeShards: subscribeShards,
|
||||
protectedShards: protectedShards,
|
||||
relay: relay,
|
||||
lightPush: lightPush,
|
||||
lightPush: lightPush and relay, # can't mount lightpush without relay
|
||||
peerExchangeService: peerExchange,
|
||||
rendezvous: rendezvous,
|
||||
peerExchangeDiscovery: true,
|
||||
|
||||
@ -172,8 +172,10 @@ suite "parseLogosDeliveryConf - JSON parsing":
|
||||
test "invalid JSON is rejected":
|
||||
check parseLogosDeliveryConf("{ not json }").isErr()
|
||||
|
||||
test "unknown top-level keys are rejected":
|
||||
check parseLogosDeliveryConf("""{"logLevel": "INFO", "mode": "Core"}""").isErr()
|
||||
test "a truly unknown top-level key is rejected (flat walker rejects the field)":
|
||||
# NB: a *known* WakuNodeConf field at top level (e.g. logLevel) is now accepted
|
||||
# as a flat blob; only a field that is not a WakuNodeConf field is rejected.
|
||||
check parseLogosDeliveryConf("""{"totallyBogusField": "x", "mode": "Core"}""").isErr()
|
||||
|
||||
test "override keys accept CLI switch names":
|
||||
let lc = parseLogosDeliveryConf(
|
||||
@ -270,6 +272,8 @@ suite "parseLogosDeliveryConf - JSON parsing":
|
||||
.isErr()
|
||||
|
||||
test "kernelConf is rejected outside fleet mode":
|
||||
# kernelConf is a fleet-only wrapper. Under Core/Edge it is neither consumed by the
|
||||
# structured path nor a flat kernel field, so it must surface as an unknown key.
|
||||
check parseLogosDeliveryConf("""{"mode": "core", "kernelConf": {}}""").isErr()
|
||||
|
||||
suite "LogosDelivery.new - construction (the app-dev entry)":
|
||||
@ -336,3 +340,83 @@ suite "LogosDelivery.new - raw kernel construction":
|
||||
# start()/stop() must skip the nil messaging + channel layers, not deref them
|
||||
(await node.start()).expect("start")
|
||||
(await node.stop()).expect("stop")
|
||||
|
||||
# [Legacy flat JSON config] These suites cover the legacy flat shape; delete them
|
||||
# together with parseFlatConf when flat-shape support is dropped.
|
||||
suite "parseLogosDeliveryConf - flat WakuNodeConf shape (interop compatibility)":
|
||||
test "a flat blob of kernel fields is detected and parsed as a full stack":
|
||||
let lc = parseLogosDeliveryConf(
|
||||
"""{"relay": true, "clusterId": 7, "store": true, "filter": false}"""
|
||||
).valueOr:
|
||||
raiseAssert error
|
||||
check:
|
||||
WakuNodeConf(lc.kernelConf).relay == true
|
||||
WakuNodeConf(lc.kernelConf).clusterId == some(7'u16)
|
||||
lc.messagingConf.isSome() # full stack
|
||||
lc.channelsConf.isSome()
|
||||
|
||||
test "flat blob carrying mode: mode expands to flags, explicit flags override":
|
||||
let lc = parseLogosDeliveryConf(
|
||||
"""{"mode": "Edge", "relay": true, "clusterId": 7}"""
|
||||
).valueOr:
|
||||
raiseAssert error
|
||||
check:
|
||||
WakuNodeConf(lc.kernelConf).relay == true
|
||||
# explicit flat field overrides the Edge default
|
||||
WakuNodeConf(lc.kernelConf).filter == false # Edge default, not set explicitly
|
||||
WakuNodeConf(lc.kernelConf).clusterId == some(7'u16)
|
||||
|
||||
test "flat blob's reliabilityEnabled routes to the messaging conf, not the kernel":
|
||||
let lc = parseLogosDeliveryConf("""{"relay": true, "reliabilityEnabled": true}""").valueOr:
|
||||
raiseAssert error
|
||||
check:
|
||||
lc.messagingConf.get().reliabilityEnabled == some(true)
|
||||
|
||||
test "an unknown key in a flat blob is rejected":
|
||||
check parseLogosDeliveryConf("""{"relay": true, "bogusKey": 1}""").isErr()
|
||||
|
||||
test "a flat blob's preset lifts reliability into the messaging record":
|
||||
# twn defines a p2pReliability; the flat path must resolve it into the messaging
|
||||
# conf (the kernel no longer carries reliability), matching master.
|
||||
let lc = parseLogosDeliveryConf("""{"preset": "twn", "relay": true}""").valueOr:
|
||||
raiseAssert error
|
||||
let fromPreset = resolvePreset("twn").valueOr:
|
||||
raiseAssert error
|
||||
check lc.messagingConf.get().reliabilityEnabled == fromPreset.reliabilityEnabled
|
||||
|
||||
test "port 0 (auto-allocate) is accepted in a flat blob":
|
||||
let lc = parseLogosDeliveryConf(
|
||||
"""{"relay": true, "tcpPort": 0, "discv5UdpPort": 0}"""
|
||||
).valueOr:
|
||||
raiseAssert error
|
||||
check:
|
||||
WakuNodeConf(lc.kernelConf).tcpPort == Port(0)
|
||||
WakuNodeConf(lc.kernelConf).discv5UdpPort == Port(0)
|
||||
|
||||
test "port 0 is accepted in structured messagingOverrides":
|
||||
let lc = parseLogosDeliveryConf("""{"messagingOverrides": {"tcp-port": 0}}""").valueOr:
|
||||
raiseAssert error
|
||||
check lc.messagingConf.get().p2pTcpPort == some(Port(0))
|
||||
|
||||
test "mode/preset with no bare field stays structured; a bare field flips it to flat":
|
||||
# No bare kernel field -> structured: mode owns relay, no per-flag override.
|
||||
let structured = parseLogosDeliveryConf(
|
||||
"""{"mode": "Edge", "preset": "logostest"}"""
|
||||
).valueOr:
|
||||
raiseAssert error
|
||||
check WakuNodeConf(structured.kernelConf).relay == false # Edge, structured
|
||||
# Adding a bare kernel field (relay) flips to flat, where the explicit flag wins;
|
||||
# relay == true is only reachable via the flat path, so it proves the routing.
|
||||
let flat = parseLogosDeliveryConf(
|
||||
"""{"mode": "Edge", "preset": "logostest", "relay": true}"""
|
||||
).valueOr:
|
||||
raiseAssert error
|
||||
check:
|
||||
WakuNodeConf(flat.kernelConf).relay == true
|
||||
WakuNodeConf(flat.kernelConf).preset == "logostest"
|
||||
|
||||
test "a wrapper key alongside a bare kernel field is rejected, not split":
|
||||
# A wrapper key (messagingOverrides) marks the structured shape, so the blob does
|
||||
# not flip to flat; the leftover bare field (relay) then has no structured home and
|
||||
# is rejected. Guards against the discriminator silently splitting a mixed object.
|
||||
check parseLogosDeliveryConf("""{"messagingOverrides": {}, "relay": true}""").isErr()
|
||||
|
||||
@ -53,6 +53,13 @@ proc parseScalarInto[U](
|
||||
let s = jsonScalarToString(jsonValue).valueOr:
|
||||
return
|
||||
err(prefix & " '" & confField & "' from JSON key '" & jsonKey & "': " & error)
|
||||
when U is Port:
|
||||
# `Port(0)` means "auto-allocate an ephemeral port" and is a valid value (see
|
||||
# PR #3828). confutils' `parseCmdArg(Port)` enforces the CLI range 1-65535 and
|
||||
# rejects "0", but the JSON config API must accept it, so handle 0 explicitly and
|
||||
# delegate every other value to confutils.
|
||||
if s == "0":
|
||||
return ok(Port(0))
|
||||
try:
|
||||
ok(parseCmdArg(U, s))
|
||||
except CatchableError as e:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user