Skip to content

Commit

Permalink
test: restore tests from #2313 (#2328)
Browse files Browse the repository at this point in the history
Reinstates tests removed as part of #2313
  • Loading branch information
achingbrain authored Dec 20, 2023
1 parent 5def667 commit 6fd681d
Show file tree
Hide file tree
Showing 5 changed files with 421 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@chainsafe/libp2p-gossipsub": "^11.0.0",
"@chainsafe/libp2p-noise": "^14.0.0",
"@chainsafe/libp2p-yamux": "^6.0.1",
"@libp2p/bootstrap": "^10.0.7",
"@libp2p/circuit-relay-v2": "^1.0.0",
"@libp2p/crypto": "^3.0.2",
"@libp2p/daemon-client": "^8.0.1",
Expand All @@ -50,6 +51,7 @@
"@libp2p/interop": "^10.0.0",
"@libp2p/kad-dht": "^12.0.0",
"@libp2p/logger": "^4.0.1",
"@libp2p/mdns": "^10.0.7",
"@libp2p/mplex": "^10.0.0",
"@libp2p/peer-id": "^4.0.0",
"@libp2p/peer-id-factory": "^4.0.1",
Expand Down
106 changes: 106 additions & 0 deletions packages/integration-tests/test/bootstrap.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* eslint-env mocha */

import { bootstrap } from '@libp2p/bootstrap'
import { TypedEventEmitter, peerDiscoverySymbol } from '@libp2p/interface'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import { webSockets } from '@libp2p/websockets'
import { multiaddr } from '@multiformats/multiaddr'
import { expect } from 'aegir/chai'
import { createLibp2p } from 'libp2p'
import defer from 'p-defer'
import sinon from 'sinon'
import type { Libp2p, PeerDiscovery, PeerDiscoveryEvents, PeerId } from '@libp2p/interface'

const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0/ws')

class TestPeerDiscovery extends TypedEventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
get [peerDiscoverySymbol] (): PeerDiscovery {
return this
}

readonly [Symbol.toStringTag] = '@libp2p/test-peer-discovery'
}

describe('bootstrap', () => {
let peerId: PeerId
let remotePeerId1: PeerId
let remotePeerId2: PeerId
let libp2p: Libp2p

beforeEach(async () => {
[peerId, remotePeerId1, remotePeerId2] = await Promise.all([
createEd25519PeerId(),
createEd25519PeerId(),
createEd25519PeerId()
])
})

afterEach(async () => {
if (libp2p != null) {
await libp2p.stop()
}
})

it('should ignore self on discovery', async () => {
const discovery = new TestPeerDiscovery()

libp2p = await createLibp2p({
peerId,
peerDiscovery: [
() => discovery
]
})

await libp2p.start()
const discoverySpy = sinon.spy()
libp2p.addEventListener('peer:discovery', discoverySpy)
discovery.safeDispatchEvent('peer', {
detail: {
id: libp2p.peerId,
multiaddrs: [],
protocols: []
}
})

expect(discoverySpy.called).to.eql(false)
})

it('bootstrap should discover all peers in the list', async () => {
const deferred = defer()

const bootstrappers = [
`${listenAddr.toString()}/p2p/${remotePeerId1.toString()}`,
`${listenAddr.toString()}/p2p/${remotePeerId2.toString()}`
]

libp2p = await createLibp2p({
transports: [
webSockets()
],
peerDiscovery: [
bootstrap({
list: bootstrappers
})
]
})

const expectedPeers = new Set([
remotePeerId1.toString(),
remotePeerId2.toString()
])

libp2p.addEventListener('peer:discovery', (evt) => {
const { id } = evt.detail

expectedPeers.delete(id.toString())
if (expectedPeers.size === 0) {
libp2p.removeEventListener('peer:discovery')
deferred.resolve()
}
})

await libp2p.start()

return deferred.promise
})
})
222 changes: 222 additions & 0 deletions packages/integration-tests/test/dht.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/* eslint-env mocha */

import { yamux } from '@chainsafe/libp2p-yamux'
import { kadDHT, passthroughMapper } from '@libp2p/kad-dht'
import { mplex } from '@libp2p/mplex'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import { plaintext } from '@libp2p/plaintext'
import { tcp } from '@libp2p/tcp'
import { multiaddr } from '@multiformats/multiaddr'
import { expect } from 'aegir/chai'
import { createLibp2p } from 'libp2p'
import pDefer from 'p-defer'
import pWaitFor from 'p-wait-for'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import type { Libp2p, PeerId } from '@libp2p/interface'
import type { KadDHT } from '@libp2p/kad-dht'
import type { Multiaddr } from '@multiformats/multiaddr'
import type { Libp2pOptions } from 'libp2p'

export const subsystemMulticodecs = [
'/test/kad/1.0.0',
'/other/1.0.0'
]

const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/8000')
const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/8001')

async function getRemoteAddr (remotePeerId: PeerId, libp2p: Libp2p): Promise<Multiaddr> {
const { addresses } = await libp2p.peerStore.get(remotePeerId)

if (addresses.length === 0) {
throw new Error('No addrs found')
}

const addr = addresses[0]

return addr.multiaddr.encapsulate(`/p2p/${remotePeerId.toString()}`)
}

describe('DHT subsystem operates correctly', () => {
let peerId: PeerId
let remotePeerId: PeerId
let libp2p: Libp2p<{ dht: KadDHT }>
let remoteLibp2p: Libp2p<{ dht: KadDHT }>
let remAddr: Multiaddr

beforeEach(async () => {
[peerId, remotePeerId] = await Promise.all([
createEd25519PeerId(),
createEd25519PeerId()
])
})

describe('dht started before connect', () => {
beforeEach(async () => {
libp2p = await createLibp2p({
peerId,
addresses: {
listen: [listenAddr.toString()]
},
transports: [
tcp()
],
connectionEncryption: [
plaintext()
],
streamMuxers: [
yamux(),
mplex()
],
services: {
dht: kadDHT({
protocol: subsystemMulticodecs[0],
peerInfoMapper: passthroughMapper,
allowQueryWithZeroPeers: true
})
}
})

remoteLibp2p = await createLibp2p({
peerId: remotePeerId,
addresses: {
listen: [remoteListenAddr.toString()]
},
transports: [
tcp()
],
connectionEncryption: [
plaintext()
],
streamMuxers: [
yamux(),
mplex()
],
services: {
dht: kadDHT({
protocol: subsystemMulticodecs[0],
peerInfoMapper: passthroughMapper,
allowQueryWithZeroPeers: true
})
}
})

await Promise.all([
libp2p.start(),
remoteLibp2p.start()
])

await libp2p.peerStore.patch(remotePeerId, {
multiaddrs: [remoteListenAddr]
})
remAddr = await getRemoteAddr(remotePeerId, libp2p)
})

afterEach(async () => {
if (libp2p != null) {
await libp2p.stop()
}

if (remoteLibp2p != null) {
await remoteLibp2p.stop()
}
})

it('should get notified of connected peers on dial', async () => {
const stream = await libp2p.dialProtocol(remAddr, subsystemMulticodecs)

expect(stream).to.exist()

return Promise.all([
// @ts-expect-error private field
pWaitFor(() => libp2p.services.dht.routingTable.size === 1),
// @ts-expect-error private field
pWaitFor(() => remoteLibp2p.services.dht.routingTable.size === 1)
])
})

it('should put on a peer and get from the other', async () => {
const key = uint8ArrayFromString('hello')
const value = uint8ArrayFromString('world')

await libp2p.dialProtocol(remotePeerId, subsystemMulticodecs)
await Promise.all([
// @ts-expect-error private field
pWaitFor(() => libp2p.services.dht.routingTable.size === 1),
// @ts-expect-error private field
pWaitFor(() => remoteLibp2p.services.dht.routingTable.size === 1)
])

await libp2p.contentRouting.put(key, value)

const fetchedValue = await remoteLibp2p.contentRouting.get(key)
expect(fetchedValue).to.equalBytes(value)
})
})

it('kad-dht should discover other peers', async () => {
const remotePeerId1 = await createEd25519PeerId()
const remotePeerId2 = await createEd25519PeerId()

const deferred = pDefer()

const getConfig = (peerId: PeerId): Libp2pOptions<{ dht: KadDHT }> => ({
peerId,
addresses: {
listen: [
listenAddr.toString()
]
},
services: {
dht: kadDHT({
protocol: subsystemMulticodecs[0],
peerInfoMapper: passthroughMapper,
allowQueryWithZeroPeers: true
})
}
})

const localConfig = getConfig(peerId)

libp2p = await createLibp2p(localConfig)

const remoteLibp2p1 = await createLibp2p(getConfig(remotePeerId1))
const remoteLibp2p2 = await createLibp2p(getConfig(remotePeerId2))

libp2p.addEventListener('peer:discovery', (evt) => {
const { id } = evt.detail

if (id.equals(remotePeerId1)) {
libp2p.removeEventListener('peer:discovery')
deferred.resolve()
}
})

await Promise.all([
libp2p.start(),
remoteLibp2p1.start(),
remoteLibp2p2.start()
])

await libp2p.peerStore.patch(remotePeerId1, {
multiaddrs: remoteLibp2p1.getMultiaddrs()
})
await remoteLibp2p2.peerStore.patch(remotePeerId1, {
multiaddrs: remoteLibp2p1.getMultiaddrs()
})

// Topology:
// A -> B
// C -> B
await Promise.all([
libp2p.dial(remotePeerId1),
remoteLibp2p2.dial(remotePeerId1)
])

await deferred.promise
return Promise.all([
remoteLibp2p1.stop(),
remoteLibp2p2.stop()
])
})
})
Loading

0 comments on commit 6fd681d

Please sign in to comment.