Introduce first tests for the async machine

This commit is contained in:
Arnaud 2026-04-21 17:17:25 +04:00
parent 4a453c53e0
commit 77662d2d68
No known key found for this signature in database
GPG Key ID: A6C7C781817146FA
3 changed files with 72 additions and 5 deletions

View File

@ -17,10 +17,12 @@ import
import pkg/chronos
import pkg/chronicles
import pkg/libp2p
import pkg/libp2p/protocols/connectivity/autonatv2/service
import ./utils
import ./utils/natutils
import ./utils/addrutils
import ./discovery
const
UPNP_TIMEOUT = 200 # ms
@ -61,6 +63,16 @@ type PrefSrcStatus = enum
BindAddressIsPublic
BindAddressIsPrivate
type NatMapper* = ref object of RootObj
method mapNatAddresses*(
m: NatMapper, addrs: seq[MultiAddress], discoveryPort: Port
): tuple[libp2p, discovery: seq[MultiAddress]] {.base, gcsafe, raises: [].} =
raiseAssert "mapNatAddresses not implemented"
type DefaultNatMapper* = ref object of NatMapper
natConfig*: NatConfig
## Also does threadvar initialisation.
## Must be called before redirectPorts() in each thread.
proc getExternalIP*(natStrategy: NatStrategy, quiet = false): Option[IpAddress] =
@ -437,3 +449,31 @@ proc nattedAddress*(
# Invalid multiaddress format - return as is
it
(newAddrs, discoveryAddrs)
method mapNatAddresses*(
m: DefaultNatMapper, addrs: seq[MultiAddress], discoveryPort: Port
): tuple[libp2p, discovery: seq[MultiAddress]] {.gcsafe, raises: [].} =
nattedAddress(m.natConfig, addrs, discoveryPort)
proc handleNatStatus*(
networkReachability: NetworkReachability,
confidence: Opt[float],
mapper: NatMapper,
listenAddrs: seq[MultiAddress],
discoveryPort: Port,
discovery: Discovery,
) {.async: (raises: [CancelledError]).} =
debug "AutoNAT status", reachability = networkReachability, confidence
case networkReachability
of Reachable:
# TODO: switch DHT to server mode, stop relay if running
discard
of NotReachable:
let (announceAddrs, discoveryAddrs) =
mapper.mapNatAddresses(listenAddrs, discoveryPort)
discovery.updateAnnounceRecord(announceAddrs)
discovery.updateDhtRecord(announceAddrs & discoveryAddrs)
of Unknown:
# Nothing to do here, not enough confidence score result
discard

View File

@ -344,15 +344,15 @@ proc new*(
switch.mount(network)
switch.mount(manifestProto)
let natMapper = DefaultNatMapper(natConfig: config.nat)
autonatService.setStatusAndConfidenceHandler(
proc(
networkReachability: NetworkReachability, confidence: Opt[float]
) {.async: (raises: [CancelledError]).} =
if networkReachability == NotReachable:
let (announceAddrs, discoveryAddrs) =
nattedAddress(config.nat, switch.peerInfo.addrs, config.discoveryPort)
discovery.updateAnnounceRecord(announceAddrs)
discovery.updateDhtRecord(announceAddrs & discoveryAddrs)
await handleNatStatus(
networkReachability, confidence, natMapper, switch.peerInfo.addrs,
config.discoveryPort, discovery,
)
)
StorageServer(

View File

@ -1,12 +1,24 @@
import std/[unittest, net]
import pkg/chronos
import pkg/libp2p
import pkg/libp2p/[multiaddress, multihash, multicodec]
import pkg/libp2p/protocols/connectivity/autonatv2/service
import pkg/results
import ../../storage/nat
import ../../storage/discovery
import ../../storage/rng
import ../../storage/utils
import ../../storage/utils/natutils
type MockNatMapper = ref object of NatMapper
mapped: tuple[libp2p, discovery: seq[MultiAddress]]
method mapNatAddresses*(
m: MockNatMapper, addrs: seq[MultiAddress], discoveryPort: Port
): tuple[libp2p, discovery: seq[MultiAddress]] {.raises: [].} =
m.mapped
suite "NAT Address Tests":
test "nattedAddress with local addresses":
# Setup test data
@ -65,3 +77,18 @@ suite "setupAddress":
check ip == none(IpAddress)
check tcpPort == some(Port(5000))
check udpPort == some(Port(5001))
suite "handleNatStatus":
let key = PrivateKey.random(Rng.instance[]).get()
test "NotReachable updates announce addresses":
let disc = Discovery.new(key, announceAddrs = @[])
let announceAddr = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid")
let discAddr = MultiAddress.init("/ip4/1.2.3.4/udp/8090").expect("valid")
let mapper = MockNatMapper(mapped: (@[announceAddr], @[discAddr]))
waitFor handleNatStatus(
NotReachable, Opt.none(float), mapper, @[], Port(8090), disc
)
check disc.announceAddrs == @[announceAddr]