Integration tests for swift-libp2p
End-to-end integration tests for swift-libp2p. Unlike the unit tests in the swift-libp2p package (which drive components in isolation, often over EmbeddedChannel), these tests stand up real Application nodes and exercise the full stack over a loopback TCP socket — security handshakes, muxer negotiation, protocol multistream-select, Identify, the peerstore, the connection manager and the event bus.
Most suites are parameterized over the full transport matrix:
| Muxer | Security |
|---|---|
| yamux | noise |
| mplex | plaintext (v2) |
The tests pull in the real conformers as dependencies — swift-libp2p-{yamux,mplex,noise,plaintext} — so a green run means those implementations interoperate against the current swift-libp2p working copy.
- For more information check out the LibP2P Spec
Every suite that stands up real nodes is nested under a single parent suite, IntegrationTestSuites, which carries the .serialized trait so the whole networked tree runs one test at a time. This is deliberate: letting a dozen node pairs race in parallel starves the loopback path badly enough that the slowest transport combinations intermittently exceed their request timeouts.
| Suite | What it verifies |
|---|---|
InternalIntegrationTests |
Ping (by multiaddr and by peer) and echo interop between two nodes, connection/stream reuse counts, and high-volume sequential + bidirectional echo throughput. |
EventNotificationTests |
The full connection/stream lifecycle (connected, upgraded, remotePeer, openedStream, closedStream, identifiedPeer, disconnected) is published on the event bus for both the dialer and the listener. |
PeerStoreTests |
Identify populates the dialer's peerstore with the remote peer's protocols, key and addresses; the reverse protocol index resolves; and manually-added PeerInfo is stored. |
TopologyTests |
A topology notifiee registered for a protocol is told when a supporting peer connects and disconnects — and is not notified for an unsupported protocol. |
IdleTeardownTests |
Once a connection's muxed streams close, the idle connection reaps itself (the default ARCConnection self-close, and the connection manager's automatic-stream-counting reaper with a custom idle timeout). |
ConnectionReuseTests |
Sequential requests reuse a single connection; concurrent requests over an established connection reuse it; and (see Known Gaps) concurrent cold dials to the same peer. |
ListenAddressTests |
Automatic port-picking (/tcp/0) yields a concrete, non-zero, dialable announced address, and two nodes receive distinct ports. |
InMemoryResponderTests |
Drives a route through the responder in-memory (no transport) via the LibP2PTestUtils TestingApplicationTester. Not networked, so it lives outside the serialized tree. |
ExternalIntegrationTests |
Pings a real public IPFS node. Marked intermittent (withKnownIssue) — the remote is fickle, so use sparingly. Left outside the serialized tree. |
Tests/IntegrationTestsTests/TestHelpers.swift provides a small withApp-style toolkit shared by every suite (LibP2PTesting re-exports LibP2P + LibP2PTestUtils, so its withApp, in-memory tester and
ByteBuffer.string conveniences are available):
TestMuxer/TestSecurity—CaseIterableenums used to drive the parameterized matrix.makeNode(...)— builds a configured (not yet started) node; binds/tcp/0by default.withNode { app in ... }/withPeers { host, client in ... }— scoped lifecycle that guaranteesasyncShutdowneven when the body throws.installEchoRoute(_:)— registers a line-delimited/echo/1.0.0route.Application.dialableAddress— the announced listen address encapsulated with the node'sPeerID.Application.echo(_:to:timeout:)— fires an echo request with a generous timeout.waitUntil(...)— polls for asynchronously-delivered state (events, teardown).EventRecorder— subscribes to the whole connection-lifecycle event set and records what arrives.
This package is primarily intended to run in GitHub CI workflows against swift-libp2p, but it can be run locally too:
# Everything (includes the public-node External test and the high-volume interop tests)
swift test
# A single suite
swift test --filter EventNotificationTests
# A single test
swift test --filter PeerStoreTests/identifyPopulatesTheDialersPeerStoreNotes:
- The
ExternalIntegrationTestssuite reaches out to a public IPFS node and is intermittent by design; skip it (or expect the occasional known failure) when offline. - The high-volume
InternalIntegrationTestsinterop tests fire hundreds of requests and can take a little longer.
- None right now. Submit a bug report!
Contributions are welcomed! This code is very much a proof of concept. I can guarantee you there's a better / safer way to accomplish the same results. Any suggestions, improvements, or even just critiques, are welcome!
Let's make this code better together! 🤝
MIT © 2026 Breth Inc.