Improve tests

This commit is contained in:
Arnaud 2026-05-12 20:44:49 +04:00
parent f015fe31a9
commit 3e982b4af3
No known key found for this signature in database
GPG Key ID: A6C7C781817146FA
5 changed files with 186 additions and 26 deletions

View File

@ -18,13 +18,11 @@ multinodesuite "AutoNAT detection":
let natConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 2)
.withRelay(0)
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(10.seconds)
.withNatMaxQueueSize(1)
# .withLogFile()
# .withLogLevel("DEBUG")
.some
.withNatMaxQueueSize(1).some
)
test "node is reachable when using bootstrap node on same network", natConfig:
let node2 = clients()[1]
@ -41,22 +39,45 @@ multinodesuite "AutoNAT detection":
pollInterval = PollInterval,
)
let endpointIndependentConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 2)
.withRelay(0)
.withNatSimulation(idx = 1, "endpoint-independent")
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(10.seconds)
.withNatMaxQueueSize(1).some
)
# EIF = Endpoint Independent Filtering
test "node with simulated EIF nat is detected as reachable", endpointIndependentConfig:
let node2 = clients()[1]
check eventuallySafe(
(await node2.client.natReachability()).get() == "Reachable",
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check eventuallySafe(
not (await node2.client.natRelayRunning()).get(),
timeout = RelayTimeout,
pollInterval = PollInterval,
)
let autonatConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 2)
.withRelay(idx = 0)
.withNatSimulation(idx = 1)
.withRelay(0)
.withNatSimulation(idx = 1, "address-and-port-dependent")
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(10.seconds)
.withNatMaxQueueSize(1)
# .withLogLevel("DEBUG")
# .debug()
# .withLogFile()
.some
.withNatMaxQueueSize(1).some
)
# node2 is behind simulated NAT: AutoNAT peers try to dial back but are blocked.
test "nat node is detected as not reachable and starts relay", autonatConfig:
# APDF = Address and Port-Dependent Filtering
test "node with simulated APDF nat is detected as not reachable and starts relay",
autonatConfig:
let node2 = clients()[1]
check eventuallySafe(
@ -82,16 +103,17 @@ multinodesuite "AutoNAT detection":
let transitionConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 2)
.withRelay(idx = 0)
.withNatSimulation(idx = 1)
.withRelay(0)
.withNatSimulation(idx = 1, "address-and-port-dependent")
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(5.seconds)
.withNatMaxQueueSize(1).some
)
# node2 starts behind simulated NAT (NotReachable + relay), then NAT is lifted
# and AutoNAT detects Reachable on the next scheduled check.
test "nat node recovers to reachable when nat is lifted", transitionConfig:
# APDF = Address and Port-Dependent Filtering
# EIF = Endpoint Independent Filtering
test "node with simulated APDF nat recovers to reachable and stops relay when nat switches to EIF nat",
transitionConfig:
let node2 = clients()[1]
check eventuallySafe(
@ -131,16 +153,17 @@ multinodesuite "AutoNAT detection":
let natToSimConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 2)
.withRelay(idx = 0)
.withRelay(0)
.withNatSimulation(idx = 1, "endpoint-independent")
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(5.seconds)
.withNatMaxQueueSize(1).some
)
# node2 starts reachable (endpoint-independent NAT sim = pass-through),
# then NAT is tightened to block dial-backs and AutoNAT detects NotReachable.
test "reachable node becomes not reachable when nat is applied", natToSimConfig:
# APDF = Address and Port-Dependent Filtering
test "reachable node becomes not reachable and starts relay when nat switches to APDF nat",
natToSimConfig:
let node2 = clients()[1]
check eventuallySafe(
@ -168,3 +191,61 @@ multinodesuite "AutoNAT detection":
timeout = RelayTimeout,
pollInterval = PollInterval,
)
let multiNatConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 3)
.withRelay(0)
.withNatSimulation(idx = 1, "address-and-port-dependent")
.withNatSimulation(idx = 2, "address-and-port-dependent")
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(5.seconds)
.withNatMaxQueueSize(1).some
)
# APDF = Address and Port-Dependent Filtering
test "two nodes with simulated APDF nat starts relay through the same relay node",
multiNatConfig:
let node2 = clients()[1]
let node3 = clients()[2]
check eventuallySafe(
(await node2.client.natReachability()).get() == "NotReachable",
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check eventuallySafe(
(await node3.client.natReachability()).get() == "NotReachable",
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check eventuallySafe(
(await node2.client.natRelayRunning()).get(),
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check eventuallySafe(
(await node3.client.natRelayRunning()).get(),
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check eventuallySafe(
block:
let addrs = (await node2.client.info()).get["addrs"].getElems.mapIt(it.getStr)
addrs.anyIt("p2p-circuit" in it),
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check eventuallySafe(
block:
let addrs = (await node3.client.info()).get["addrs"].getElems.mapIt(it.getStr)
addrs.anyIt("p2p-circuit" in it),
timeout = RelayTimeout,
pollInterval = PollInterval,
)

View File

@ -0,0 +1,65 @@
import std/json
import std/sequtils
import pkg/chronos
import pkg/questionable/results
import ../multinodes
import ../storageclient
import ../storageconfig
const
RelayTimeout = 30_000
PollInterval = 1_000
multinodesuite "NAT download":
let natDownloadConfig = NodeConfigs(
clients: StorageConfigs
.init(nodes = 3)
.withRelay(idx = 0)
.withNatSimulation(idx = 2, "address-and-port-dependent")
.withNatNumPeersToAsk(1)
.withNatMinConfidence(0.5)
.withNatScheduleInterval(5.seconds)
.withNatMaxQueueSize(1).some
)
# APDF = Address and Port-Dependent Filtering
test "node 3 with simulated APDF downloads content from reachable seed node 2",
natDownloadConfig:
let seed = clients()[1]
let natNode = clients()[2]
let content = "content for nat download test"
let cid = (await seed.client.upload(content)).get
check eventuallySafe(
(await natNode.client.download(cid)).isOk,
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check (await natNode.client.download(cid)).get == content
# APDF = Address and Port-Dependent Filtering
test "reachable node 2 downloads content from node 3 with simulated APDF via relay",
natDownloadConfig:
let seed = clients()[1]
let natNode = clients()[2]
check eventuallySafe(
block:
let addrs = (await natNode.client.info()).get["addrs"].getElems.mapIt(it.getStr)
addrs.anyIt("p2p-circuit" in it),
timeout = RelayTimeout,
pollInterval = PollInterval,
)
let content = "content seeded from nat node"
let cid = (await natNode.client.upload(content)).get
check eventuallySafe(
(await seed.client.download(cid)).isOk,
timeout = RelayTimeout,
pollInterval = PollInterval,
)
check (await seed.client.download(cid)).get == content

View File

@ -219,7 +219,8 @@ template multinodesuite*(suiteName: string, body: untyped) =
for config in clients.configs:
let node = await startClientNode(config)
running.add RunningNode(role: Role.Client, node: node)
await StorageProcess(node).updateBootstrapNodes()
if config.isBootstrapNode:
await StorageProcess(node).updateBootstrapNodes()
teardown:
await teardownImpl()

View File

@ -354,8 +354,21 @@ proc withRelay*(self: StorageConfigs): StorageConfigs {.raises: [StorageConfigEr
config.addCliOption("--relay")
return startConfig
# For testing, a node with extip (not behind nat) is a bootstrap node
proc isBootstrapNode*(config: StorageConfig): bool {.raises: [].} =
let opts = config.cliOptions.getOrDefault(StartUpCmd.noCmd)
try:
if "--nat" in opts and "extip" in opts["--nat"].value:
return true
except KeyError:
warn "Failed to look at the extip config"
return false
return false
proc withNatSimulation*(
self: StorageConfigs, idx: int, filtering = "address-and-port-dependent"
self: StorageConfigs, idx: int, filtering: string
): StorageConfigs {.raises: [StorageConfigError].} =
self.checkBounds idx
@ -364,7 +377,7 @@ proc withNatSimulation*(
return startConfig
proc withNatSimulation*(
self: StorageConfigs, filtering = "address-and-port-dependent"
self: StorageConfigs, filtering: string
): StorageConfigs {.raises: [StorageConfigError].} =
var startConfig = self
for config in startConfig.configs.mitems:

View File

@ -12,7 +12,7 @@ export multinodes
template twonodessuite*(name: string, body: untyped) =
multinodesuite name:
let twoNodesConfig {.inject, used.} =
NodeConfigs(clients: StorageConfigs.init(nodes = 2).some)
NodeConfigs(clients: StorageConfigs.init(nodes = 2).withExtIp(1).some)
var node1 {.inject, used.}: StorageProcess
var node2 {.inject, used.}: StorageProcess