@@ -3,7 +3,8 @@
|
|||||||
A decentralized peer-to-peer network implementation using WebRTC for communication in a double ring topology with optional Oracle nodes for enhanced network services.
|
A decentralized peer-to-peer network implementation using WebRTC for communication in a double ring topology with optional Oracle nodes for enhanced network services.
|
||||||
|
|
||||||
**🌐 Live Demo**: https://ringnet.cloud
|
**🌐 Live Demo**: https://ringnet.cloud
|
||||||
**📂 Repository**: https://git.manalejandro.com/ale/ringnet
|
**📂 Repository**: https://git.manalejandro.com/ale/ringnet
|
||||||
|
**📝 Documentation**: https://pad.manalejandro.com/p/2ringsnet
|
||||||
|
|
||||||
## 🌟 Features
|
## 🌟 Features
|
||||||
|
|
||||||
|
|||||||
0
demo-auto-positioning.js
Archivo normal
0
demo-auto-positioning.js
Archivo normal
@@ -1,62 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
console.log(chalk.blue(`
|
|
||||||
📊 RingNet Dashboard Demo
|
|
||||||
|
|
||||||
This demonstration shows how to use the RingNet dashboard
|
|
||||||
to monitor your network in real-time.
|
|
||||||
|
|
||||||
🚀 Step 1: Start the Dashboard Server
|
|
||||||
${chalk.green('npm run start:dashboard')}
|
|
||||||
|
|
||||||
The dashboard will be available at: ${chalk.cyan('http://localhost:3000')}
|
|
||||||
|
|
||||||
🔗 Step 2: Start Nodes with Dashboard Integration
|
|
||||||
${chalk.green('npm run start:oracle -- --port 8080 --dashboard http://localhost:3000')}
|
|
||||||
${chalk.green('npm run start:node -- --port 8081 --bootstrap localhost:8080 --dashboard http://localhost:3000')}
|
|
||||||
${chalk.green('npm run start:node -- --port 8082 --bootstrap localhost:8080 --dashboard http://localhost:3000')}
|
|
||||||
|
|
||||||
📈 Step 3: Monitor Your Network
|
|
||||||
Open ${chalk.cyan('http://localhost:3000')} in your browser to see:
|
|
||||||
|
|
||||||
✅ Real-time Network Statistics
|
|
||||||
- Total active nodes
|
|
||||||
- Oracle nodes count
|
|
||||||
- Total connections
|
|
||||||
- Last update time
|
|
||||||
|
|
||||||
✅ Live Node List
|
|
||||||
- Node status indicators
|
|
||||||
- Node types (Oracle/Regular)
|
|
||||||
- Ring positions
|
|
||||||
- Connection health
|
|
||||||
|
|
||||||
✅ Interactive Ring Topology
|
|
||||||
- Visual ring structure
|
|
||||||
- Node positioning
|
|
||||||
- Click nodes for details
|
|
||||||
- Color-coded by type
|
|
||||||
|
|
||||||
✅ REST API Access
|
|
||||||
- GET /api/nodes - List all nodes
|
|
||||||
- GET /api/network/stats - Network statistics
|
|
||||||
- GET /api/network/topology - Ring topology
|
|
||||||
- GET /api/nodes/:id - Node details
|
|
||||||
|
|
||||||
📡 API Examples:
|
|
||||||
${chalk.cyan('curl http://localhost:3000/api/network/stats')}
|
|
||||||
${chalk.cyan('curl http://localhost:3000/api/nodes')}
|
|
||||||
${chalk.cyan('curl http://localhost:3000/api/network/topology')}
|
|
||||||
|
|
||||||
🔄 Features:
|
|
||||||
- Auto-refresh every 5 seconds
|
|
||||||
- Inactive node detection (5 minute timeout)
|
|
||||||
- Responsive design for mobile/desktop
|
|
||||||
- Real-time topology updates
|
|
||||||
- Connection health monitoring
|
|
||||||
|
|
||||||
The dashboard provides a comprehensive view of your RingNet
|
|
||||||
network without affecting node performance!
|
|
||||||
`));
|
|
||||||
72
demo.js
72
demo.js
@@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
console.log(chalk.blue.bold('🔗 Ring Network Demo Setup\n'));
|
|
||||||
|
|
||||||
console.log(`
|
|
||||||
${chalk.green('Welcome to the Ring Network!')}
|
|
||||||
|
|
||||||
Your two-ring network with WebRTC and Oracle nodes is now ready to use.
|
|
||||||
|
|
||||||
${chalk.yellow('🚀 Quick Start Guide:')}
|
|
||||||
|
|
||||||
1. ${chalk.cyan('Start the first node (Oracle) as bootstrap:')}
|
|
||||||
npm run start:oracle -- --port 8080
|
|
||||||
|
|
||||||
2. ${chalk.cyan('In a new terminal, start a regular node:')}
|
|
||||||
npm run start:node -- --port 8081 --bootstrap localhost:8080
|
|
||||||
|
|
||||||
3. ${chalk.cyan('In another terminal, start another Oracle:')}
|
|
||||||
npm run start:oracle -- --port 8082 --bootstrap localhost:8080
|
|
||||||
|
|
||||||
4. ${chalk.cyan('Add more nodes as needed:')}
|
|
||||||
npm run start:node -- --port 8083 --bootstrap localhost:8080
|
|
||||||
|
|
||||||
${chalk.magenta('💡 Interactive Commands (once nodes are running):')}
|
|
||||||
|
|
||||||
${chalk.yellow('Regular Node Commands:')}
|
|
||||||
• send <message> - Send message through the ring
|
|
||||||
• info - Show network information
|
|
||||||
• peers - List connected peers
|
|
||||||
• help - Show all commands
|
|
||||||
• quit - Exit the node
|
|
||||||
|
|
||||||
${chalk.yellow('Oracle Node Commands (additional):')}
|
|
||||||
• health - Perform network health check
|
|
||||||
• metrics - Show network metrics
|
|
||||||
• analyze - Analyze network topology
|
|
||||||
• store <key> <val> - Store data in distributed storage
|
|
||||||
• get <key> - Retrieve stored data
|
|
||||||
• propose <text> - Create consensus proposal
|
|
||||||
• vote <id> <y/n> - Vote on a proposal
|
|
||||||
|
|
||||||
${chalk.blue('🔮 Oracle Services Available:')}
|
|
||||||
• Network Analysis - Topology and health monitoring
|
|
||||||
• Data Storage - Distributed key-value store
|
|
||||||
• Consensus - Distributed decision making
|
|
||||||
• Routing - Advanced routing strategies
|
|
||||||
• Health Monitoring - Continuous network monitoring
|
|
||||||
• Metrics Collection - Performance and usage statistics
|
|
||||||
|
|
||||||
${chalk.red('📖 Additional Resources:')}
|
|
||||||
• Run example: npm run example
|
|
||||||
• Run tests: npm test
|
|
||||||
• View help: npm start
|
|
||||||
• Read README.md for detailed documentation
|
|
||||||
|
|
||||||
${chalk.green('🎯 Network Features:')}
|
|
||||||
✅ Double ring topology (inner + outer rings)
|
|
||||||
✅ WebRTC peer-to-peer connections
|
|
||||||
✅ Automatic peer discovery
|
|
||||||
✅ Message routing through rings
|
|
||||||
✅ Oracle nodes with enhanced capabilities
|
|
||||||
✅ Distributed data storage
|
|
||||||
✅ Consensus mechanisms
|
|
||||||
✅ Network health monitoring
|
|
||||||
✅ Fault tolerance and resilience
|
|
||||||
|
|
||||||
${chalk.cyan('Happy networking! 🌐')}
|
|
||||||
`);
|
|
||||||
|
|
||||||
process.exit(0);
|
|
||||||
@@ -18,10 +18,7 @@
|
|||||||
"start:node": "node node.js",
|
"start:node": "node node.js",
|
||||||
"start:dashboard": "cd server && npm start",
|
"start:dashboard": "cd server && npm start",
|
||||||
"dashboard:dev": "cd server && npm run dev",
|
"dashboard:dev": "cd server && npm run dev",
|
||||||
"demo": "node demo.js",
|
"example": "node examples/basic-example.js"
|
||||||
"demo:dashboard": "node demo-dashboard.js",
|
|
||||||
"example": "node examples/basic-example.js",
|
|
||||||
"test": "node test/test-network.js"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@koush/wrtc": "^0.5.3",
|
"@koush/wrtc": "^0.5.3",
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
A REST API and web dashboard for monitoring RingNet network topology, nodes, and connections in real-time.
|
A REST API and web dashboard for monitoring RingNet network topology, nodes, and connections in real-time.
|
||||||
|
|
||||||
**🌐 Live Demo**: https://ringnet.cloud
|
**🌐 Live Demo**: https://ringnet.cloud
|
||||||
**📂 Repository**: https://git.manalejandro.com/ale/ringnet
|
**📂 Repository**: https://git.manalejandro.com/ale/ringnet
|
||||||
|
**📝 Documentation**: https://pad.manalejandro.com/p/2ringsnet
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repo-link, .domain-link {
|
.repo-link, .docs-link, .domain-link {
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repo-link:hover, .domain-link:hover {
|
.repo-link:hover, .docs-link:hover, .domain-link:hover {
|
||||||
background: rgba(255, 255, 255, 0.2);
|
background: rgba(255, 255, 255, 0.2);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||||
@@ -292,6 +292,7 @@
|
|||||||
<h1>🔗 RingNet Dashboard</h1>
|
<h1>🔗 RingNet Dashboard</h1>
|
||||||
<div class="header-links">
|
<div class="header-links">
|
||||||
<a href="https://git.manalejandro.com/ale/ringnet" target="_blank" class="repo-link">📂 Repository</a>
|
<a href="https://git.manalejandro.com/ale/ringnet" target="_blank" class="repo-link">📂 Repository</a>
|
||||||
|
<a href="https://pad.manalejandro.com/p/2ringsnet" target="_blank" class="docs-link">📝 Docs</a>
|
||||||
<a href="https://ringnet.cloud" target="_blank" class="domain-link">🌐 ringnet.cloud</a>
|
<a href="https://ringnet.cloud" target="_blank" class="domain-link">🌐 ringnet.cloud</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -342,6 +343,7 @@
|
|||||||
<p>
|
<p>
|
||||||
RingNet - Decentralized P2P Network |
|
RingNet - Decentralized P2P Network |
|
||||||
<a href="https://git.manalejandro.com/ale/ringnet" target="_blank">Source Code</a> |
|
<a href="https://git.manalejandro.com/ale/ringnet" target="_blank">Source Code</a> |
|
||||||
|
<a href="https://pad.manalejandro.com/p/2ringsnet" target="_blank">Documentation</a> |
|
||||||
<a href="https://ringnet.cloud" target="_blank">ringnet.cloud</a>
|
<a href="https://ringnet.cloud" target="_blank">ringnet.cloud</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
0
test/test-auto-positioning.js
Archivo normal
0
test/test-auto-positioning.js
Archivo normal
@@ -1,339 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
import { RingNode } from '../src/ring-node.js';
|
|
||||||
import { OracleNode } from '../src/oracle-node.js';
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
console.log(chalk.blue.bold('🧪 Ring Network Test Suite\n'));
|
|
||||||
|
|
||||||
class NetworkTester {
|
|
||||||
constructor() {
|
|
||||||
this.nodes = [];
|
|
||||||
this.testResults = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
async delay(ms) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
log(message, type = 'info') {
|
|
||||||
const colors = {
|
|
||||||
info: chalk.blue,
|
|
||||||
success: chalk.green,
|
|
||||||
error: chalk.red,
|
|
||||||
warning: chalk.yellow
|
|
||||||
};
|
|
||||||
console.log(`${colors[type]}${message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async runTest(name, testFn) {
|
|
||||||
this.log(`\n🔬 Running test: ${name}`, 'info');
|
|
||||||
try {
|
|
||||||
const startTime = Date.now();
|
|
||||||
await testFn();
|
|
||||||
const duration = Date.now() - startTime;
|
|
||||||
this.log(`✅ Test passed: ${name} (${duration}ms)`, 'success');
|
|
||||||
this.testResults.push({ name, status: 'passed', duration });
|
|
||||||
} catch (error) {
|
|
||||||
this.log(`❌ Test failed: ${name} - ${error.message}`, 'error');
|
|
||||||
this.testResults.push({ name, status: 'failed', error: error.message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async setupBasicNetwork() {
|
|
||||||
this.log('🏗️ Setting up basic network with 1 Oracle and 2 regular nodes', 'info');
|
|
||||||
|
|
||||||
// Create Oracle node
|
|
||||||
const oracle = new OracleNode({
|
|
||||||
id: 'oracle-1',
|
|
||||||
port: 8080
|
|
||||||
});
|
|
||||||
this.nodes.push(oracle);
|
|
||||||
|
|
||||||
// Create regular nodes
|
|
||||||
const node1 = new RingNode({
|
|
||||||
id: 'node-1',
|
|
||||||
port: 8081
|
|
||||||
});
|
|
||||||
this.nodes.push(node1);
|
|
||||||
|
|
||||||
const node2 = new RingNode({
|
|
||||||
id: 'node-2',
|
|
||||||
port: 8082
|
|
||||||
});
|
|
||||||
this.nodes.push(node2);
|
|
||||||
|
|
||||||
// Allow nodes to initialize
|
|
||||||
await this.delay(2000);
|
|
||||||
|
|
||||||
return { oracle, node1, node2 };
|
|
||||||
}
|
|
||||||
|
|
||||||
async testNodeInitialization() {
|
|
||||||
const { oracle, node1, node2 } = await this.setupBasicNetwork();
|
|
||||||
|
|
||||||
// Verify nodes are properly initialized
|
|
||||||
if (!oracle.id || !oracle.isOracle) {
|
|
||||||
throw new Error('Oracle node not properly initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!node1.id || node1.isOracle) {
|
|
||||||
throw new Error('Regular node 1 not properly initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!node2.id || node2.isOracle) {
|
|
||||||
throw new Error('Regular node 2 not properly initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Oracle ID: ${oracle.id}`, 'info');
|
|
||||||
this.log(`Node 1 ID: ${node1.id}`, 'info');
|
|
||||||
this.log(`Node 2 ID: ${node2.id}`, 'info');
|
|
||||||
}
|
|
||||||
|
|
||||||
async testPeerConnections() {
|
|
||||||
const { oracle, node1, node2 } = this.nodes.length > 0 ?
|
|
||||||
{ oracle: this.nodes[0], node1: this.nodes[1], node2: this.nodes[2] } :
|
|
||||||
await this.setupBasicNetwork();
|
|
||||||
|
|
||||||
// Simulate peer connections
|
|
||||||
// In a real test, we would actually establish WebRTC connections
|
|
||||||
// For this test, we'll simulate the connection state
|
|
||||||
|
|
||||||
oracle.knownNodes.set(node1.id, { port: node1.port });
|
|
||||||
oracle.knownNodes.set(node2.id, { port: node2.port });
|
|
||||||
|
|
||||||
node1.knownNodes.set(oracle.id, { port: oracle.port, isOracle: true });
|
|
||||||
node1.knownNodes.set(node2.id, { port: node2.port });
|
|
||||||
|
|
||||||
node2.knownNodes.set(oracle.id, { port: oracle.port, isOracle: true });
|
|
||||||
node2.knownNodes.set(node1.id, { port: node1.port });
|
|
||||||
|
|
||||||
// Update oracle nodes list
|
|
||||||
node1.oracleNodes.add(oracle.id);
|
|
||||||
node2.oracleNodes.add(oracle.id);
|
|
||||||
|
|
||||||
this.log(`Oracle knows ${oracle.knownNodes.size} nodes`, 'info');
|
|
||||||
this.log(`Node 1 knows ${node1.knownNodes.size} nodes`, 'info');
|
|
||||||
this.log(`Node 2 knows ${node2.knownNodes.size} nodes`, 'info');
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRingTopology() {
|
|
||||||
const { oracle, node1, node2 } = this.nodes.length > 0 ?
|
|
||||||
{ oracle: this.nodes[0], node1: this.nodes[1], node2: this.nodes[2] } :
|
|
||||||
await this.setupBasicNetwork();
|
|
||||||
|
|
||||||
// Simulate ring topology setup
|
|
||||||
// Oracle -> Node1 -> Node2 -> Oracle (inner ring)
|
|
||||||
oracle.rings.inner.right = node1.id;
|
|
||||||
oracle.rings.inner.left = node2.id;
|
|
||||||
|
|
||||||
node1.rings.inner.left = oracle.id;
|
|
||||||
node1.rings.inner.right = node2.id;
|
|
||||||
|
|
||||||
node2.rings.inner.left = node1.id;
|
|
||||||
node2.rings.inner.right = oracle.id;
|
|
||||||
|
|
||||||
// Oracle -> Node2 -> Node1 -> Oracle (outer ring - reversed)
|
|
||||||
oracle.rings.outer.right = node2.id;
|
|
||||||
oracle.rings.outer.left = node1.id;
|
|
||||||
|
|
||||||
node1.rings.outer.left = node2.id;
|
|
||||||
node1.rings.outer.right = oracle.id;
|
|
||||||
|
|
||||||
node2.rings.outer.left = oracle.id;
|
|
||||||
node2.rings.outer.right = node1.id;
|
|
||||||
|
|
||||||
// Verify ring integrity
|
|
||||||
const oracleHasValidRings = oracle.rings.inner.left && oracle.rings.inner.right &&
|
|
||||||
oracle.rings.outer.left && oracle.rings.outer.right;
|
|
||||||
|
|
||||||
if (!oracleHasValidRings) {
|
|
||||||
throw new Error('Oracle rings not properly configured');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('Ring topology established successfully', 'success');
|
|
||||||
}
|
|
||||||
|
|
||||||
async testOracleServices() {
|
|
||||||
const oracle = this.nodes[0];
|
|
||||||
|
|
||||||
if (!oracle.isOracle) {
|
|
||||||
throw new Error('First node is not an Oracle');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test network analysis
|
|
||||||
const analysis = oracle.analyzeNetwork();
|
|
||||||
if (!analysis.networkSize || !analysis.ringTopology) {
|
|
||||||
throw new Error('Network analysis failed');
|
|
||||||
}
|
|
||||||
this.log(`Network analysis: ${analysis.networkSize} nodes`, 'info');
|
|
||||||
|
|
||||||
// Test data storage
|
|
||||||
const storeResult = oracle.handleDataStorage({
|
|
||||||
operation: 'set',
|
|
||||||
key: 'test-key',
|
|
||||||
value: 'test-value'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!storeResult.success) {
|
|
||||||
throw new Error('Data storage (set) failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
const getResult = oracle.handleDataStorage({
|
|
||||||
operation: 'get',
|
|
||||||
key: 'test-key'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!getResult.success || getResult.value !== 'test-value') {
|
|
||||||
throw new Error('Data storage (get) failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('Oracle data storage working correctly', 'success');
|
|
||||||
|
|
||||||
// Test consensus
|
|
||||||
const proposalId = 'test-proposal-' + Date.now();
|
|
||||||
const consensusResult = oracle.handleConsensus({
|
|
||||||
proposalId,
|
|
||||||
proposal: 'Test proposal for network upgrade'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!consensusResult.success) {
|
|
||||||
throw new Error('Consensus proposal creation failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('Oracle consensus mechanism working', 'success');
|
|
||||||
|
|
||||||
// Test health check
|
|
||||||
const health = oracle.performHealthCheck();
|
|
||||||
if (!health.checks) {
|
|
||||||
throw new Error('Health check failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Health check: ${health.healthy ? 'Healthy' : 'Issues detected'}`,
|
|
||||||
health.healthy ? 'success' : 'warning');
|
|
||||||
}
|
|
||||||
|
|
||||||
async testMessageRouting() {
|
|
||||||
// This test simulates message routing through the ring
|
|
||||||
// In a real implementation, this would test actual WebRTC communication
|
|
||||||
|
|
||||||
const oracle = this.nodes[0];
|
|
||||||
let messageReceived = false;
|
|
||||||
|
|
||||||
// Set up message handler
|
|
||||||
oracle.on('ringMessage', ({ from, payload }) => {
|
|
||||||
if (payload.type === 'test-message') {
|
|
||||||
messageReceived = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Simulate sending a message
|
|
||||||
oracle.emit('ringMessage', {
|
|
||||||
from: 'test-sender',
|
|
||||||
payload: { type: 'test-message', content: 'Hello Ring!' }
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.delay(100);
|
|
||||||
|
|
||||||
if (!messageReceived) {
|
|
||||||
throw new Error('Message routing failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('Message routing test passed', 'success');
|
|
||||||
}
|
|
||||||
|
|
||||||
async testNetworkResilience() {
|
|
||||||
const { oracle, node1, node2 } = this.nodes.length > 0 ?
|
|
||||||
{ oracle: this.nodes[0], node1: this.nodes[1], node2: this.nodes[2] } :
|
|
||||||
await this.setupBasicNetwork();
|
|
||||||
|
|
||||||
// Simulate node disconnection
|
|
||||||
const originalPeerCount = oracle.knownNodes.size;
|
|
||||||
|
|
||||||
// Remove node2 from network
|
|
||||||
oracle.handlePeerDisconnection(node2.id);
|
|
||||||
node1.handlePeerDisconnection(node2.id);
|
|
||||||
|
|
||||||
if (oracle.knownNodes.has(node2.id)) {
|
|
||||||
throw new Error('Node not properly removed from network');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify network adapted to disconnection
|
|
||||||
const newPeerCount = oracle.knownNodes.size;
|
|
||||||
if (newPeerCount >= originalPeerCount) {
|
|
||||||
throw new Error('Network did not adapt to peer disconnection');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Network adapted to disconnection: ${originalPeerCount} -> ${newPeerCount} nodes`, 'success');
|
|
||||||
}
|
|
||||||
|
|
||||||
async cleanup() {
|
|
||||||
this.log('\n🧹 Cleaning up test environment', 'info');
|
|
||||||
|
|
||||||
for (const node of this.nodes) {
|
|
||||||
try {
|
|
||||||
await node.destroy();
|
|
||||||
} catch (error) {
|
|
||||||
this.log(`Warning: Error cleaning up node ${node.id}: ${error.message}`, 'warning');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.nodes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
printResults() {
|
|
||||||
this.log('\n📊 Test Results Summary:', 'info');
|
|
||||||
|
|
||||||
const passed = this.testResults.filter(r => r.status === 'passed').length;
|
|
||||||
const failed = this.testResults.filter(r => r.status === 'failed').length;
|
|
||||||
|
|
||||||
this.log(`✅ Passed: ${passed}`, 'success');
|
|
||||||
this.log(`❌ Failed: ${failed}`, failed > 0 ? 'error' : 'info');
|
|
||||||
|
|
||||||
if (failed > 0) {
|
|
||||||
this.log('\nFailed tests:', 'error');
|
|
||||||
this.testResults
|
|
||||||
.filter(r => r.status === 'failed')
|
|
||||||
.forEach(r => {
|
|
||||||
this.log(` - ${r.name}: ${r.error}`, 'error');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalDuration = this.testResults.reduce((sum, r) => sum + (r.duration || 0), 0);
|
|
||||||
this.log(`\nTotal test duration: ${totalDuration}ms`, 'info');
|
|
||||||
|
|
||||||
return failed === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async runAllTests() {
|
|
||||||
try {
|
|
||||||
await this.runTest('Node Initialization', () => this.testNodeInitialization());
|
|
||||||
await this.runTest('Peer Connections', () => this.testPeerConnections());
|
|
||||||
await this.runTest('Ring Topology', () => this.testRingTopology());
|
|
||||||
await this.runTest('Oracle Services', () => this.testOracleServices());
|
|
||||||
await this.runTest('Message Routing', () => this.testMessageRouting());
|
|
||||||
await this.runTest('Network Resilience', () => this.testNetworkResilience());
|
|
||||||
} finally {
|
|
||||||
await this.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.printResults();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run tests if this file is executed directly
|
|
||||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
||||||
const tester = new NetworkTester();
|
|
||||||
|
|
||||||
tester.runAllTests()
|
|
||||||
.then(success => {
|
|
||||||
console.log(chalk.blue.bold('\n🏁 Test suite completed'));
|
|
||||||
process.exit(success ? 0 : 1);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error(chalk.red.bold(`\n💥 Test suite crashed: ${error.message}`));
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { NetworkTester };
|
|
||||||
Referencia en una nueva incidencia
Block a user