fix(rustproxy): Use cooperative cancellation for background tasks, prune stale caches and metric entries, and switch tests to dynamic port allocation to avoid port conflicts

This commit is contained in:
2026-02-24 20:56:37 +00:00
parent 755c81c042
commit 33cd5330c4
24 changed files with 535 additions and 560 deletions
+50 -39
View File
@@ -9,13 +9,14 @@ import {
createPortOffset
} from '../ts/proxies/smart-proxy/utils/route-helpers.js';
import type { IRouteConfig, IRouteContext } from '../ts/proxies/smart-proxy/models/route-types.js';
import { findFreePorts, assertPortsFree } from './helpers/port-allocator.js';
// Test server and client utilities
let testServers: Array<{ server: net.Server; port: number }> = [];
let smartProxy: SmartProxy;
const TEST_PORT_START = 47750;
const PROXY_PORT_START = 48750;
let TEST_PORTS: number[]; // 3 test server ports
let PROXY_PORTS: number[]; // 6 proxy ports
const TEST_DATA = 'Hello through dynamic port mapper!';
// Cleanup function to close all servers and proxies
@@ -101,53 +102,60 @@ function createTestClient(port: number, data: string): Promise<string> {
// Set up test environment
tap.test('setup port mapping test environment', async () => {
const allPorts = await findFreePorts(9);
TEST_PORTS = allPorts.slice(0, 3);
PROXY_PORTS = allPorts.slice(3, 9);
// Create multiple test servers on different ports
await Promise.all([
createTestServer(TEST_PORT_START), // Server on port 47750
createTestServer(TEST_PORT_START + 1), // Server on port 47751
createTestServer(TEST_PORT_START + 2), // Server on port 47752
createTestServer(TEST_PORTS[0]),
createTestServer(TEST_PORTS[1]),
createTestServer(TEST_PORTS[2]),
]);
// Compute dynamic offset between proxy and test ports
const portOffset = TEST_PORTS[1] - PROXY_PORTS[1];
// Create a SmartProxy with dynamic port mapping routes
smartProxy = new SmartProxy({
routes: [
// Simple function that returns the same port (identity mapping)
createPortMappingRoute({
sourcePortRange: PROXY_PORT_START,
sourcePortRange: PROXY_PORTS[0],
targetHost: 'localhost',
portMapper: (context) => TEST_PORT_START,
portMapper: (context) => TEST_PORTS[0],
name: 'Identity Port Mapping'
}),
// Offset port mapping from 48751 to 47751 (offset -1000)
// Offset port mapping using dynamic offset
createOffsetPortMappingRoute({
ports: PROXY_PORT_START + 1,
ports: PROXY_PORTS[1],
targetHost: 'localhost',
offset: -1000,
name: 'Offset Port Mapping (-1000)'
offset: portOffset,
name: `Offset Port Mapping (${portOffset})`
}),
// Dynamic route with conditional port mapping
createDynamicRoute({
ports: [PROXY_PORT_START + 2, PROXY_PORT_START + 3],
ports: [PROXY_PORTS[2], PROXY_PORTS[3]],
targetHost: (context) => {
// Dynamic host selection based on port
return context.port === PROXY_PORT_START + 2 ? 'localhost' : '127.0.0.1';
return context.port === PROXY_PORTS[2] ? 'localhost' : '127.0.0.1';
},
portMapper: (context) => {
// Port mapping logic based on incoming port
if (context.port === PROXY_PORT_START + 2) {
return TEST_PORT_START;
if (context.port === PROXY_PORTS[2]) {
return TEST_PORTS[0];
} else {
return TEST_PORT_START + 2;
return TEST_PORTS[2];
}
},
name: 'Dynamic Host and Port Mapping'
}),
// Smart load balancer for domain-based routing
createSmartLoadBalancer({
ports: PROXY_PORT_START + 4,
ports: PROXY_PORTS[4],
domainTargets: {
'test1.example.com': 'localhost',
'test2.example.com': '127.0.0.1'
@@ -155,9 +163,9 @@ tap.test('setup port mapping test environment', async () => {
portMapper: (context) => {
// Use different backend ports based on domain
if (context.domain === 'test1.example.com') {
return TEST_PORT_START;
return TEST_PORTS[0];
} else {
return TEST_PORT_START + 1;
return TEST_PORTS[1];
}
},
defaultTarget: 'localhost',
@@ -165,44 +173,45 @@ tap.test('setup port mapping test environment', async () => {
})
]
});
// Start the SmartProxy
await smartProxy.start();
});
// Test 1: Simple identity port mapping (48750 -> 47750)
// Test 1: Simple identity port mapping
tap.test('should map port using identity function', async () => {
const response = await createTestClient(PROXY_PORT_START, TEST_DATA);
expect(response).toEqual(`Server ${TEST_PORT_START} says: ${TEST_DATA}`);
const response = await createTestClient(PROXY_PORTS[0], TEST_DATA);
expect(response).toEqual(`Server ${TEST_PORTS[0]} says: ${TEST_DATA}`);
});
// Test 2: Offset port mapping (48751 -> 47751)
// Test 2: Offset port mapping
tap.test('should map port using offset function', async () => {
const response = await createTestClient(PROXY_PORT_START + 1, TEST_DATA);
expect(response).toEqual(`Server ${TEST_PORT_START + 1} says: ${TEST_DATA}`);
const response = await createTestClient(PROXY_PORTS[1], TEST_DATA);
expect(response).toEqual(`Server ${TEST_PORTS[1]} says: ${TEST_DATA}`);
});
// Test 3: Dynamic port and host mapping (conditional logic)
tap.test('should map port using dynamic logic', async () => {
const response = await createTestClient(PROXY_PORT_START + 2, TEST_DATA);
expect(response).toEqual(`Server ${TEST_PORT_START} says: ${TEST_DATA}`);
const response = await createTestClient(PROXY_PORTS[2], TEST_DATA);
expect(response).toEqual(`Server ${TEST_PORTS[0]} says: ${TEST_DATA}`);
});
// Test 4: Test reuse of createPortOffset helper
tap.test('should use createPortOffset helper for port mapping', async () => {
// Test the createPortOffset helper
const offsetFn = createPortOffset(-1000);
// Test the createPortOffset helper with dynamic offset
const portOffset = TEST_PORTS[1] - PROXY_PORTS[1];
const offsetFn = createPortOffset(portOffset);
const context = {
port: PROXY_PORT_START + 1,
port: PROXY_PORTS[1],
clientIp: '127.0.0.1',
serverIp: '127.0.0.1',
isTls: false,
timestamp: Date.now(),
connectionId: 'test-connection'
} as IRouteContext;
const mappedPort = offsetFn(context);
expect(mappedPort).toEqual(TEST_PORT_START + 1);
expect(mappedPort).toEqual(TEST_PORTS[1]);
});
// Test 5: Test error handling for invalid port mapping functions
@@ -210,7 +219,7 @@ tap.test('should handle errors in port mapping functions', async () => {
// Create a route with a function that throws an error
const errorRoute: IRouteConfig = {
match: {
ports: PROXY_PORT_START + 5
ports: PROXY_PORTS[5]
},
action: {
type: 'forward',
@@ -229,7 +238,7 @@ tap.test('should handle errors in port mapping functions', async () => {
// The connection should fail or timeout
try {
await createTestClient(PROXY_PORT_START + 5, TEST_DATA);
await createTestClient(PROXY_PORTS[5], TEST_DATA);
// Connection should not succeed
expect(false).toBeTrue();
} catch (error) {
@@ -254,6 +263,8 @@ tap.test('cleanup port mapping test environment', async () => {
testServers = [];
smartProxy = null as any;
}
await assertPortsFree([...TEST_PORTS, ...PROXY_PORTS]);
});
export default tap.start();