#!/usr/bin/env node
'use strict'
// Full bridge integration test:
// 1. Start a mock CogServer (TCP echo server on 17001)
// 2. Start bridge server with testnet
// 3. Start bridge client pointing to server
// 4. Connect to client proxy port
// 5. Verify data flows through
const net = require('net')
const { spawn } = require('child_process')
const path = require('path')
const crypto = require('hypercore-crypto')
const b4a = require('b4a')
const BRIDGE = path.join(__dirname, 'bridge.js')
const COG_PORT = 17099 // Mock CogServer
const PROXY_PORT = 17098 // Client proxy
const TEST_SEED = b4a.toString(crypto.randomBytes(32), 'hex')
async function test () {
console.log('=== Bridge Integration Test ===\n')
// Step 1: Mock CogServer — echoes with "OK: " prefix
const mockCog = net.createServer((sock) => {
console.log('[mock-cog] Client connected')
sock.on('data', (d) => {
console.log('[mock-cog] Received:', d.toString().trim())
sock.write('OK: ' + d.toString())
})
sock.on('error', () => {})
})
await new Promise((resolve) => mockCog.listen(COG_PORT, resolve))
console.log('[mock-cog] Listening on port', COG_PORT)
// Step 2: Start bridge server with testnet
const server = spawn('node', [
BRIDGE, 'server',
'--port', String(COG_PORT),
'--seed', TEST_SEED,
'--testnet', '.test-testnet.json'
], { cwd: __dirname })
let serverKey = null
server.stdout.on('data', (d) => {
const line = d.toString()
process.stdout.write('[server] ' + line)
const m = line.match(/Public key: ([a-f0-9]{64})/)
if (m) serverKey = m[1]
})
server.stderr.on('data', (d) => process.stderr.write('[server-err] ' + d.toString()))
// Wait for server to announce on DHT
await new Promise((resolve) => {
const check = setInterval(() => {
if (serverKey) {
clearInterval(check)
resolve()
}
}, 200)
})
// Extra wait for DHT announce
await new Promise(r => setTimeout(r, 2000))
console.log('\n[test] Server key:', serverKey)
// Step 3: Start bridge client using testnet
const client = spawn('node', [
BRIDGE, 'client', serverKey,
'--proxy-port', String(PROXY_PORT),
'--testnet', '.test-testnet.json'
], { cwd: __dirname })
let clientReady = false
client.stdout.on('data', (d) => {
const line = d.toString()
process.stdout.write('[client] ' + line)
if (line.includes('Channel ready') || line.includes('Connected to server')) {
clientReady = true
}
})
client.stderr.on('data', (d) => process.stderr.write('[client-err] ' + d.toString()))
// Wait for client to connect to server
await new Promise((resolve) => {
const check = setInterval(() => {
if (clientReady) {
clearInterval(check)
resolve()
}
}, 200)
// Timeout after 15s
setTimeout(() => {
clearInterval(check)
resolve()
}, 15000)
})
if (!clientReady) {
console.log('\n[test] FAILED: Client never connected to server')
cleanup()
return
}
await new Promise(r => setTimeout(r, 1000))
// Step 4: Connect to proxy port and send data
console.log('\n[test] Connecting to proxy port', PROXY_PORT)
const conn = net.connect(PROXY_PORT, '127.0.0.1')
const result = await new Promise((resolve, reject) => {
conn.on('connect', () => {
console.log('[test] Connected to proxy — sending test data')
conn.write('(cog-version)\n')
})
conn.on('data', (d) => {
console.log('[test] Received:', d.toString().trim())
resolve(d.toString())
})
conn.on('error', (err) => {
console.log('[test] Connection error:', err.message)
reject(err)
})
setTimeout(() => resolve(null), 5000)
})
// Step 5: Verify
if (result && result.includes('OK:')) {
console.log('\n✓ SUCCESS — data flowed through P2P bridge!')
} else {
console.log('\n✗ FAILED — no response from mock CogServer through bridge')
}
function cleanup () {
conn && conn.destroy()
server.kill('SIGINT')
client.kill('SIGINT')
mockCog.close()
setTimeout(() => process.exit(0), 500)
}
cleanup()
}
test().catch(err => {
console.error('Test error:', err)
process.exit(1)
})