diff --git a/tests/integration/1_minute/testnat.nim b/tests/integration/1_minute/testnat.nim new file mode 100644 index 00000000..d7b9288f --- /dev/null +++ b/tests/integration/1_minute/testnat.nim @@ -0,0 +1,44 @@ +import std/json +import std/options +import std/sequtils +import pkg/chronos +import pkg/questionable/results + +import ../multinodes +import ../storageclient +import ../storageconfig + +multinodesuite "AutoNAT integration": + let natConfig = NodeConfigs( + clients: StorageConfigs + .init(nodes = 2) + .withNatNumPeersToAsk(1) + .withNatMinConfidence(0.5) + .withNatScheduleInterval(10.seconds) + .withNatMaxQueueSize(1) + .withLogFile() + .withLogLevel("DEBUG").some + ) + + # Reminder: multinodesuite setup the first node as bootstrap node + test "node is reachable when using bootstrap node on same network", natConfig: + let node1 = clients()[0] + let node2 = clients()[1] + + # Temporary + # DHT exposes only UDP information + # So we force temporary by connection the 2 node together + # to update the autonat reachability + let info = await node2.client.info() + + check not info.isErr + + await node1.client.connectPeer( + info.get()["id"].getStr(), info.get()["addrs"].getElems().mapIt(it.getStr()) + ) + + check eventuallySafe( + (await node1.client.natReachability()).get() == "Reachable", + timeout = 30_000, + pollInterval = 500, + ) diff --git a/tests/integration/storageclient.nim b/tests/integration/storageclient.nim index ec990bb9..c6ef5be0 100644 --- a/tests/integration/storageclient.nim +++ b/tests/integration/storageclient.nim @@ -1,4 +1,5 @@ import std/strutils +import std/sequtils from pkg/libp2p import Cid, `$`, init import pkg/questionable/results @@ -32,17 +33,17 @@ proc request( async: (raw: true, raises: [CancelledError, HttpError]) .} = HttpClientRequestRef - .new( - self.session, - url, - httpMethod, - version = HttpVersion11, - flags = {}, - maxResponseHeadersSize = HttpMaxHeadersSize, - headers = headers, - body = body.toOpenArrayByte(0, len(body) - 1), - ).get - .send() + .new( + self.session, + url, + httpMethod, + version = HttpVersion11, + flags = {}, + maxResponseHeadersSize = HttpMaxHeadersSize, + headers = headers, + body = body.toOpenArrayByte(0, len(body) - 1), + ).get + .send() proc post*( self: StorageClient, @@ -260,3 +261,23 @@ proc hasBlockRaw*( .} = let url = client.baseurl & "/data/" & cid & "/exists" return client.get(url) + +proc connectPeer*( + client: StorageClient, peerId: string, addrs: seq[string] +): Future[void] {.async: (raises: [CancelledError, HttpError]).} = + var url = client.baseurl & "/connect/" & peerId + if addrs.len > 0: + url &= "?" & addrs.mapIt("addrs=" & it).join("&") + let response = await client.get(url) + assert response.status == 200 + +proc natReachability*( + client: StorageClient +): Future[?!string] {.async: (raises: [CancelledError, HttpError]).} = + let info = await client.info() + if info.isErr: + return failure "Failed to get node info" + try: + return info.get()["nat"]["reachability"].getStr().success + except KeyError as e: + return failure e.msg diff --git a/tests/integration/storageconfig.nim b/tests/integration/storageconfig.nim index 4aeb6d60..240d44a2 100644 --- a/tests/integration/storageconfig.nim +++ b/tests/integration/storageconfig.nim @@ -5,6 +5,7 @@ import std/strutils import std/sugar import std/tables from pkg/chronicles import LogLevel +import pkg/chronos import pkg/storage/conf import pkg/storage/units import pkg/confutils @@ -280,3 +281,43 @@ proc withStorageQuota*( for config in startConfig.configs.mitems: config.addCliOption("--storage-quota", $quota) return startConfig + +proc withListenIp*( + self: StorageConfigs, ip: string +): StorageConfigs {.raises: [StorageConfigError].} = + var startConfig = self + for config in startConfig.configs.mitems: + config.addCliOption("--listen-ip", ip) + return startConfig + +proc withNatNumPeersToAsk*( + self: StorageConfigs, numPeersToAsk: int +): StorageConfigs {.raises: [StorageConfigError].} = + var startConfig = self + for config in startConfig.configs.mitems: + config.addCliOption("--nat-num-peers-to-ask", $numPeersToAsk) + return startConfig + +proc withNatMaxQueueSize*( + self: StorageConfigs, maxQueueSize: int +): StorageConfigs {.raises: [StorageConfigError].} = + var startConfig = self + for config in startConfig.configs.mitems: + config.addCliOption("--nat-max-queue-size", $maxQueueSize) + return startConfig + +proc withNatMinConfidence*( + self: StorageConfigs, minConfidence: float +): StorageConfigs {.raises: [StorageConfigError].} = + var startConfig = self + for config in startConfig.configs.mitems: + config.addCliOption("--nat-min-confidence", $minConfidence) + return startConfig + +proc withNatScheduleInterval*( + self: StorageConfigs, scheduleInterval: Duration +): StorageConfigs {.raises: [StorageConfigError].} = + var startConfig = self + for config in startConfig.configs.mitems: + config.addCliOption("--nat-schedule-interval", $scheduleInterval) + return startConfig