OverviewFilesCommitsIssuesDocsReleasesPeers

p2p-bridge / test-bridge.js

157 lines · javascript ref:
#!/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)
})