| 105 | // ═══════════════════════════════════════════════════════════════════════════ |
| 106 | |
| 107 | async function testEpipeError(ctx: TestContext): Promise<void> { |
| 108 | console.log("\n═══ Test 1: EPIPE Error (Client Disconnect) ═══\n"); |
| 109 | |
| 110 | try { |
| 111 | // Start streaming request |
| 112 | const controller = new AbortController(); |
| 113 | const req = fetch(`${ctx.proxy.baseUrl}/v1/chat/completions`, { |
| 114 | method: "POST", |
| 115 | headers: { "Content-Type": "application/json" }, |
| 116 | body: JSON.stringify({ |
| 117 | model: "deepseek/deepseek-chat", |
| 118 | messages: [{ role: "user", content: "test" }], |
| 119 | stream: true, |
| 120 | }), |
| 121 | signal: controller.signal, |
| 122 | }); |
| 123 | |
| 124 | // Kill client after 50ms (mid-stream) |
| 125 | await sleep(50); |
| 126 | controller.abort(); |
| 127 | await req.catch(() => {}); // Expected to fail |
| 128 | |
| 129 | // Wait for cleanup |
| 130 | await sleep(100); |
| 131 | |
| 132 | // Verify proxy still operational |
| 133 | const health = await fetch(`${ctx.proxy.baseUrl}/health`); |
| 134 | assert(health.ok, "Proxy survived client disconnect (EPIPE)"); |
| 135 | } catch (err) { |
| 136 | assert(false, `EPIPE test failed: ${err instanceof Error ? err.message : String(err)}`); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | // ═══════════════════════════════════════════════════════════════════════════ |
| 141 | // Test 2: ECONNRESET Error (Socket Reset) |