Skip to content

Commit

Permalink
chore: add interop tests (#194)
Browse files Browse the repository at this point in the history
* chore: add interop tests

* chore: update @libp2p/interop version

* fix depcheck

Co-authored-by: Cayman <[email protected]>
  • Loading branch information
mpetrunic and wemeetagain authored Aug 16, 2022
1 parent aa85698 commit 78921b9
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 2 deletions.
13 changes: 12 additions & 1 deletion .github/workflows/js-test-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,19 @@ jobs:
directory: ./.nyc_output
flags: electron-renderer

test-interop:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: lts/*
- uses: ipfs/aegir/actions/cache-node-modules@master
- run: npm run test:interop -- --bail

release:
needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer]
needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer, test-interop]
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/master' # with #262 - 'refs/heads/${{{ github.default_branch }}}'
steps:
Expand Down
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"test:node": "aegir test -t node",
"test:browser": "aegir test -t browser -t webworker",
"test:electron-main": "aegir test -t electron-main",
"test:interop": "aegir test -t node -f dist/test/interop.js",
"docs": "aegir docs",
"proto:gen": "protons ./src/proto/payload.proto",
"prepublish": "npm run build"
Expand All @@ -78,20 +79,30 @@
"@stablelib/x25519": "^1.0.1",
"it-length-prefixed": "^8.0.2",
"it-pair": "^2.0.2",
"it-stream-types": "^1.0.4",
"it-pb-stream": "^2.0.2",
"it-pipe": "^2.0.3",
"it-stream-types": "^1.0.4",
"protons-runtime": "^3.1.0",
"uint8arraylist": "^2.3.2",
"uint8arrays": "^3.1.0"
},
"devDependencies": {
"@libp2p/daemon-client": "2.0.3",
"@libp2p/daemon-server": "^2.0.4",
"@libp2p/interface-connection-encrypter-compliance-tests": "^2.0.1",
"@libp2p/interop": "^2.1.0",
"@libp2p/mplex": "^5.0.0",
"@libp2p/peer-id-factory": "^1.0.8",
"@libp2p/tcp": "^3.0.3",
"@multiformats/multiaddr": "^10.3.3",
"aegir": "^37.3.0",
"benchmark": "^2.1.4",
"execa": "^6.1.0",
"go-libp2p": "^0.0.6",
"iso-random-stream": "^2.0.2",
"libp2p": "0.37.3-f439d9b",
"mkdirp": "^1.0.4",
"p-defer": "^4.0.0",
"protons": "^5.1.0",
"sinon": "^14.0.0",
"util": "^0.12.4"
Expand Down
114 changes: 114 additions & 0 deletions test/interop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { connectInteropTests } from '@libp2p/interop'
import type { SpawnOptions, Daemon, DaemonFactory } from '@libp2p/interop'
import { createServer } from '@libp2p/daemon-server'
import { createClient } from '@libp2p/daemon-client'
import { createLibp2p, Libp2pOptions } from 'libp2p'
import { TCP } from '@libp2p/tcp'
import { Multiaddr } from '@multiformats/multiaddr'
import { path as p2pd } from 'go-libp2p'
import { execa } from 'execa'
import pDefer from 'p-defer'
import { logger } from '@libp2p/logger'
import { Mplex } from '@libp2p/mplex'
import fs from 'fs'
import { unmarshalPrivateKey } from '@libp2p/crypto/keys'
import type { PeerId } from '@libp2p/interface-peer-id'
import { peerIdFromKeys } from '@libp2p/peer-id'
import { Noise } from '../src/index.js'

async function createGoPeer (options: SpawnOptions): Promise<Daemon> {
const controlPort = Math.floor(Math.random() * (50000 - 10000 + 1)) + 10000
const apiAddr = new Multiaddr(`/ip4/0.0.0.0/tcp/${controlPort}`)

const log = logger(`go-libp2p:${controlPort}`)

const opts = [
`-listen=${apiAddr.toString()}`,
'-hostAddrs=/ip4/0.0.0.0/tcp/0'
]

if (options.noise === true) {
opts.push('-noise=true')
}

if (options.key != null) {
opts.push(`-id=${options.key}`)
}

const deferred = pDefer()
const proc = execa(p2pd(), opts)

proc.stdout?.on('data', (buf: Buffer) => {
const str = buf.toString()
log(str)

// daemon has started
if (str.includes('Control socket:')) {
deferred.resolve()
}
})

proc.stderr?.on('data', (buf) => {
log.error(buf.toString())
})

await deferred.promise

return {
client: createClient(apiAddr),
stop: async () => {
await proc.kill()
}
}
}

async function createJsPeer (options: SpawnOptions): Promise<Daemon> {
let peerId: PeerId | undefined

if (options.key != null) {
const keyFile = fs.readFileSync(options.key)
const privateKey = await unmarshalPrivateKey(keyFile)
peerId = await peerIdFromKeys(privateKey.public.bytes, privateKey.bytes)
}

const opts: Libp2pOptions = {
peerId,
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0']
},
transports: [new TCP()],
streamMuxers: [new Mplex()],
connectionEncryption: [new Noise()]
}

const node = await createLibp2p(opts)
const server = await createServer(new Multiaddr('/ip4/0.0.0.0/tcp/0'), node as any)
await server.start()

return {
client: createClient(server.getMultiaddr()),
stop: async () => {
await server.stop()
await node.stop()
}
}
}

async function main (): Promise<void> {
const factory: DaemonFactory = {
async spawn (options: SpawnOptions) {
if (options.type === 'go') {
return await createGoPeer(options)
}

return await createJsPeer(options)
}
}

await connectInteropTests(factory)
}

main().catch(err => {
console.error(err) // eslint-disable-line no-console
process.exit(1)
})

0 comments on commit 78921b9

Please sign in to comment.