109 lines
4.6 KiB
JavaScript
109 lines
4.6 KiB
JavaScript
import net from 'net';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { TunnelAgent } from './TunnelAgent.js';
|
|
describe('TunnelAgent', () => {
|
|
it('should create an empty agent', async () => {
|
|
const agent = new TunnelAgent();
|
|
expect(agent.started).toBe(false);
|
|
const info = await agent.listen();
|
|
expect(info.port).toBeGreaterThan(0);
|
|
agent.destroy();
|
|
});
|
|
it('should create a new server and accept connections', async () => {
|
|
const agent = new TunnelAgent();
|
|
expect(agent.started).toBe(false);
|
|
const info = await agent.listen();
|
|
const sock = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sock.once('connect', resolve));
|
|
const agentSock = await new Promise((resolve, reject) => {
|
|
agent.createConnection({}, (err, sock) => {
|
|
if (err)
|
|
reject(err);
|
|
resolve(sock);
|
|
});
|
|
});
|
|
agentSock.write('foo');
|
|
await new Promise(resolve => sock.once('readable', resolve));
|
|
expect(sock.read().toString()).toBe('foo');
|
|
agent.destroy();
|
|
sock.destroy();
|
|
});
|
|
it('should reject connections over the max', async () => {
|
|
const agent = new TunnelAgent({ maxTcpSockets: 2 });
|
|
expect(agent.started).toBe(false);
|
|
const info = await agent.listen();
|
|
const sock1 = net.createConnection({ port: info.port });
|
|
const sock2 = net.createConnection({ port: info.port });
|
|
const p1 = new Promise(resolve => sock1.once('connect', resolve));
|
|
const p2 = new Promise(resolve => sock2.once('connect', resolve));
|
|
await Promise.all([p1, p2]);
|
|
const sock3 = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sock3.once('close', resolve));
|
|
agent.destroy();
|
|
sock1.destroy();
|
|
sock2.destroy();
|
|
sock3.destroy();
|
|
});
|
|
it('should queue createConnection requests', async () => {
|
|
const agent = new TunnelAgent();
|
|
expect(agent.started).toBe(false);
|
|
const info = await agent.listen();
|
|
let fulfilled = false;
|
|
const waitSockPromise = new Promise((resolve, reject) => {
|
|
agent.createConnection({}, (err, sock) => {
|
|
fulfilled = true;
|
|
if (err)
|
|
reject(err);
|
|
resolve(sock);
|
|
});
|
|
});
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
expect(fulfilled).toBe(false);
|
|
const sock = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sock.once('connect', resolve));
|
|
await waitSockPromise;
|
|
agent.destroy();
|
|
sock.destroy();
|
|
});
|
|
it('should emit online event when a socket connects', async () => {
|
|
const agent = new TunnelAgent();
|
|
const info = await agent.listen();
|
|
const onlinePromise = new Promise(resolve => agent.once('online', resolve));
|
|
const sock = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sock.once('connect', resolve));
|
|
await onlinePromise;
|
|
agent.destroy();
|
|
sock.destroy();
|
|
});
|
|
it('should emit offline event when socket disconnects', async () => {
|
|
const agent = new TunnelAgent();
|
|
const info = await agent.listen();
|
|
const offlinePromise = new Promise(resolve => agent.once('offline', resolve));
|
|
const sock = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sock.once('connect', resolve));
|
|
sock.end();
|
|
await offlinePromise;
|
|
agent.destroy();
|
|
sock.destroy();
|
|
});
|
|
it('should emit offline event only when last socket disconnects', async () => {
|
|
const agent = new TunnelAgent();
|
|
const info = await agent.listen();
|
|
const offlinePromise = new Promise(resolve => agent.once('offline', resolve));
|
|
const sockA = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sockA.once('connect', resolve));
|
|
const sockB = net.createConnection({ port: info.port });
|
|
await new Promise(resolve => sockB.once('connect', resolve));
|
|
sockA.end();
|
|
const timeout = new Promise(resolve => setTimeout(resolve, 500));
|
|
await Promise.race([offlinePromise, timeout]);
|
|
sockB.end();
|
|
await offlinePromise;
|
|
agent.destroy();
|
|
});
|
|
it('should return stats', async () => {
|
|
const agent = new TunnelAgent();
|
|
expect(agent.stats()).toEqual({ connectedSockets: 0 });
|
|
});
|
|
});
|
|
//# sourceMappingURL=TunnelAgent.spec.js.map
|