/**
* Manual test script for GatewayIdentity with real hyperident setup
*
* Run: node test/manual-test.js
*/
import { GatewayIdentity } from '../lib/gateway-identity.js'
import { ServiceRegistry } from '../lib/service-registry.js'
console.log('🧪 Hyperident Gateway - Manual Test\n')
console.log('=' .repeat(60))
async function runTests() {
try {
// Test 1: Initialize GatewayIdentity
console.log('\n📝 Test 1: Initialize GatewayIdentity')
const identity = new GatewayIdentity({
subnet: '10.22.0.0/16',
staticMappings: {
'git-daemon': '10.22.0.10',
'fedicore': '10.22.0.5'
}
})
console.log('✅ GatewayIdentity created')
console.log(` Subnet: ${identity.subnet}`)
console.log(` Network prefix: ${identity.networkPrefix}`)
console.log(` CIDR: /${identity.cidr}`)
// Test 2: Load hyperident profiles
console.log('\n📝 Test 2: Load hyperident profiles')
try {
const profiles = await identity.loadProfiles()
console.log('✅ Profiles loaded from ~/.hyperident/')
console.log(` Found ${Object.keys(profiles).length} profiles:`)
for (const [name, profile] of Object.entries(profiles)) {
console.log(` - ${name}: ${profile.description || '(no description)'}`)
}
} catch (error) {
console.log(`⚠️ Could not load profiles: ${error.message}`)
console.log(' Make sure hyperident is initialized:')
console.log(' cd /home/fleeky/hyper-tests/hyperident && node index.js init')
return
}
// Test 3: Topic derivation
console.log('\n📝 Test 3: Derive topics from profiles')
const profiles = await identity.loadProfiles()
const profileNames = Object.keys(profiles).slice(0, 3) // Test first 3
for (const profileName of profileNames) {
const topic = await identity.deriveServiceTopic(profileName)
const ip = identity.assignIP(topic)
console.log(`\n Profile: ${profileName}`)
console.log(` Topic: ${topic.toString('hex').substring(0, 32)}...`)
console.log(` IP: ${ip}`)
}
// Test 4: Determinism
console.log('\n📝 Test 4: Verify deterministic IP assignment')
const testProfile = profileNames[0]
const topic1 = await identity.deriveServiceTopic(testProfile)
const topic2 = await identity.deriveServiceTopic(testProfile)
const ip1 = identity.assignIP(topic1)
const ip2 = identity.assignIP(topic2)
console.log(` Profile: ${testProfile}`)
console.log(` Topic 1: ${topic1.toString('hex').substring(0, 16)}...`)
console.log(` Topic 2: ${topic2.toString('hex').substring(0, 16)}...`)
console.log(` IP 1: ${ip1}`)
console.log(` IP 2: ${ip2}`)
if (topic1.toString('hex') === topic2.toString('hex') && ip1 === ip2) {
console.log(' ✅ Deterministic: Same profile → same topic → same IP')
} else {
console.log(' ❌ NOT deterministic!')
}
// Test 5: Service registration
console.log('\n📝 Test 5: Register services')
// Only register if profiles exist
if (profiles['git-daemon']) {
const gitService = await identity.registerService({
name: 'git-daemon',
profile: 'git-daemon',
port: 9418,
transport: 'tcp'
})
console.log('\n ✅ git-daemon registered')
console.log(` IP: ${gitService.ip}:${gitService.port}`)
console.log(` Topic: ${gitService.topic.substring(0, 16)}...`)
} else {
console.log('\n ⚠️ Skipping git-daemon (profile not found)')
console.log(' Create with: hyperident create-profile git-daemon')
}
if (profiles['fedicore']) {
const fedicoreService = await identity.registerService({
name: 'fedicore',
profile: 'fedicore',
port: 3000,
transport: 'tcp'
})
console.log('\n ✅ fedicore registered')
console.log(` IP: ${fedicoreService.ip}:${fedicoreService.port}`)
console.log(` Topic: ${fedicoreService.topic.substring(0, 16)}...`)
} else {
console.log('\n ⚠️ Skipping fedicore (profile not found)')
console.log(' Create with: hyperident create-profile fedicore')
}
// Test 6: Service lookup
console.log('\n📝 Test 6: Service lookup')
const services = identity.listServices()
console.log(` Registered services: ${services.length}`)
for (const service of services) {
const found = identity.lookup(service.ip)
console.log(` - ${service.name}: ${service.ip} → ${found ? '✅ Found' : '❌ Not found'}`)
}
// Test 7: ServiceRegistry
console.log('\n📝 Test 7: ServiceRegistry')
const registry = new ServiceRegistry(identity)
const stats = registry.getStats()
console.log(` Total services: ${stats.total}`)
console.log(` Online: ${stats.online}`)
console.log(` Offline: ${stats.offline}`)
console.log(` Total connections: ${stats.totalConnections}`)
// Test 8: Export mappings
console.log('\n📝 Test 8: Export service mappings')
const mappings = identity.exportMappings()
console.log(' Service → IP mappings:')
console.log(JSON.stringify(mappings, null, 2))
// Test 9: Static IP mapping
console.log('\n📝 Test 9: Verify static IP mappings')
if (services.find(s => s.name === 'git-daemon')) {
const gitService = services.find(s => s.name === 'git-daemon')
if (gitService.ip === '10.22.0.10') {
console.log(' ✅ git-daemon uses static IP: 10.22.0.10')
} else {
console.log(` ⚠️ git-daemon IP: ${gitService.ip} (expected: 10.22.0.10)`)
}
}
if (services.find(s => s.name === 'fedicore')) {
const fedicoreService = services.find(s => s.name === 'fedicore')
if (fedicoreService.ip === '10.22.0.5') {
console.log(' ✅ fedicore uses static IP: 10.22.0.5')
} else {
console.log(` ⚠️ fedicore IP: ${fedicoreService.ip} (expected: 10.22.0.5)`)
}
}
// Test 10: Collision detection
console.log('\n📝 Test 10: Collision detection')
try {
// Try to register same profile again (will cause collision)
if (profiles['git-daemon']) {
await identity.registerService({
name: 'git-daemon-duplicate',
profile: 'git-daemon', // Same profile = same topic = same IP
port: 9999
})
console.log(' ❌ Should have detected collision!')
}
} catch (error) {
console.log(` ✅ Collision detected: ${error.message}`)
}
// Summary
console.log('\n' + '='.repeat(60))
console.log('📊 Test Summary')
console.log('='.repeat(60))
console.log('✅ All core features validated')
console.log('\nNext steps:')
console.log('- Implement UTUNManager for virtual network interface')
console.log('- Implement HyperswarmRouter for P2P connections')
console.log('- Test end-to-end packet routing')
} catch (error) {
console.error('\n❌ Test failed:', error.message)
console.error(error.stack)
process.exit(1)
}
}
runTests()