Major refactor: Multi-user Chrome MCP extension with remote server architecture
This commit is contained in:
219
app/remote-server/test-multi-user.js
Normal file
219
app/remote-server/test-multi-user.js
Normal file
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* Test script for multi-user session management
|
||||
* This script simulates multiple Chrome extension connections to test session isolation
|
||||
*/
|
||||
|
||||
import WebSocket from 'ws';
|
||||
|
||||
const SERVER_URL = 'ws://localhost:3001/chrome';
|
||||
const NUM_CONNECTIONS = 3;
|
||||
|
||||
class TestConnection {
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
this.ws = null;
|
||||
this.sessionInfo = null;
|
||||
this.connected = false;
|
||||
}
|
||||
|
||||
async connect() {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`🔌 Connection ${this.id}: Connecting to ${SERVER_URL}`);
|
||||
|
||||
this.ws = new WebSocket(SERVER_URL);
|
||||
|
||||
this.ws.on('open', () => {
|
||||
console.log(`✅ Connection ${this.id}: Connected`);
|
||||
this.connected = true;
|
||||
|
||||
// Send connection info
|
||||
const connectionInfo = {
|
||||
type: 'connection_info',
|
||||
userAgent: `TestAgent-${this.id}`,
|
||||
timestamp: Date.now(),
|
||||
extensionId: `test-extension-${this.id}`
|
||||
};
|
||||
|
||||
this.ws.send(JSON.stringify(connectionInfo));
|
||||
});
|
||||
|
||||
this.ws.on('message', (data) => {
|
||||
try {
|
||||
const message = JSON.parse(data.toString());
|
||||
|
||||
if (message.type === 'session_info') {
|
||||
this.sessionInfo = message.sessionInfo;
|
||||
console.log(`📋 Connection ${this.id}: Received session info:`, this.sessionInfo);
|
||||
resolve();
|
||||
} else {
|
||||
console.log(`📨 Connection ${this.id}: Received message:`, message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Connection ${this.id}: Error parsing message:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
this.ws.on('close', () => {
|
||||
console.log(`🔌 Connection ${this.id}: Disconnected`);
|
||||
this.connected = false;
|
||||
});
|
||||
|
||||
this.ws.on('error', (error) => {
|
||||
console.error(`❌ Connection ${this.id}: Error:`, error);
|
||||
reject(error);
|
||||
});
|
||||
|
||||
// Timeout after 5 seconds
|
||||
setTimeout(() => {
|
||||
if (!this.sessionInfo) {
|
||||
reject(new Error(`Connection ${this.id}: Timeout waiting for session info`));
|
||||
}
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
async sendTestMessage() {
|
||||
if (!this.connected || !this.ws) {
|
||||
throw new Error(`Connection ${this.id}: Not connected`);
|
||||
}
|
||||
|
||||
const testMessage = {
|
||||
action: 'callTool',
|
||||
params: {
|
||||
name: 'chrome_navigate',
|
||||
arguments: { url: `https://example.com?user=${this.id}` }
|
||||
},
|
||||
id: `test_${this.id}_${Date.now()}`
|
||||
};
|
||||
|
||||
console.log(`📤 Connection ${this.id}: Sending test message:`, testMessage);
|
||||
this.ws.send(JSON.stringify(testMessage));
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.ws) {
|
||||
this.ws.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function testMultiUserSessions() {
|
||||
console.log('🚀 Starting multi-user session test...\n');
|
||||
|
||||
const connections = [];
|
||||
|
||||
try {
|
||||
// Create and connect multiple test connections
|
||||
for (let i = 1; i <= NUM_CONNECTIONS; i++) {
|
||||
const connection = new TestConnection(i);
|
||||
connections.push(connection);
|
||||
|
||||
console.log(`\n--- Connecting User ${i} ---`);
|
||||
await connection.connect();
|
||||
|
||||
// Wait a bit between connections
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
}
|
||||
|
||||
console.log('\n🎉 All connections established successfully!');
|
||||
console.log('\n📊 Session Summary:');
|
||||
connections.forEach(conn => {
|
||||
console.log(` User ${conn.id}: Session ${conn.sessionInfo.sessionId}, User ID: ${conn.sessionInfo.userId}`);
|
||||
});
|
||||
|
||||
// Test sending messages from each connection
|
||||
console.log('\n--- Testing Message Routing ---');
|
||||
for (const connection of connections) {
|
||||
await connection.sendTestMessage();
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
}
|
||||
|
||||
// Wait for responses
|
||||
console.log('\n⏳ Waiting for responses...');
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
// Test session isolation by checking unique session IDs
|
||||
const sessionIds = connections.map(conn => conn.sessionInfo.sessionId);
|
||||
const uniqueSessionIds = new Set(sessionIds);
|
||||
|
||||
console.log('\n🔍 Session Isolation Test:');
|
||||
console.log(` Total connections: ${connections.length}`);
|
||||
console.log(` Unique session IDs: ${uniqueSessionIds.size}`);
|
||||
console.log(` Session isolation: ${uniqueSessionIds.size === connections.length ? '✅ PASS' : '❌ FAIL'}`);
|
||||
|
||||
// Test user ID uniqueness
|
||||
const userIds = connections.map(conn => conn.sessionInfo.userId);
|
||||
const uniqueUserIds = new Set(userIds);
|
||||
|
||||
console.log(` Unique user IDs: ${uniqueUserIds.size}`);
|
||||
console.log(` User ID isolation: ${uniqueUserIds.size === connections.length ? '✅ PASS' : '❌ FAIL'}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Test failed:', error);
|
||||
} finally {
|
||||
// Clean up connections
|
||||
console.log('\n🧹 Cleaning up connections...');
|
||||
connections.forEach(conn => conn.disconnect());
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('✅ Test completed');
|
||||
process.exit(0);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
async function testSessionPersistence() {
|
||||
console.log('\n🔄 Testing session persistence...');
|
||||
|
||||
const connection = new TestConnection('persistence');
|
||||
|
||||
try {
|
||||
await connection.connect();
|
||||
const originalSessionId = connection.sessionInfo.sessionId;
|
||||
|
||||
console.log(`📋 Original session: ${originalSessionId}`);
|
||||
|
||||
// Disconnect and reconnect
|
||||
connection.disconnect();
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
await connection.connect();
|
||||
const newSessionId = connection.sessionInfo.sessionId;
|
||||
|
||||
console.log(`📋 New session: ${newSessionId}`);
|
||||
console.log(`🔄 Session persistence: ${originalSessionId === newSessionId ? '❌ FAIL (sessions should be different)' : '✅ PASS (new session created)'}`);
|
||||
|
||||
connection.disconnect();
|
||||
} catch (error) {
|
||||
console.error('❌ Session persistence test failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run tests
|
||||
async function runAllTests() {
|
||||
try {
|
||||
await testMultiUserSessions();
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await testSessionPersistence();
|
||||
} catch (error) {
|
||||
console.error('❌ Tests failed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if server is running
|
||||
console.log('🔍 Checking if remote server is running...');
|
||||
const testWs = new WebSocket(SERVER_URL);
|
||||
|
||||
testWs.on('open', () => {
|
||||
testWs.close();
|
||||
console.log('✅ Server is running, starting tests...\n');
|
||||
runAllTests();
|
||||
});
|
||||
|
||||
testWs.on('error', (error) => {
|
||||
console.error('❌ Cannot connect to server. Please start the remote server first:');
|
||||
console.error(' cd app/remote-server && npm run dev');
|
||||
console.error('\nError:', error.message);
|
||||
process.exit(1);
|
||||
});
|
Reference in New Issue
Block a user