From b9fb21aff33095dba35f52406210c7013f9ef777 Mon Sep 17 00:00:00 2001 From: Amp Date: Tue, 27 Oct 2026 16:11:59 +0000 Subject: [PATCH] test(zero-swift): keep frames that arrive with the WebSocket upgrade response NIOTransport, the e2e tests' Linux transport, used NIO's default leftOverBytesStrategy (.dropBytes), so WebSocket frames in the same TCP read as the 101 response were discarded. Behind the chaos proxy's throttle, connected and pokeStart could share that read; the client then saw the poke's binary chunk alone and stopped with "received a binary poke chunk without pokeStart" (the flaky slowReaderLargePokeCompletesOnOneConnection failure). Forward the bytes to the WebSocket decoder instead. Amp-Thread-ID: https://ampcode.com/threads/T-01a17664-8fd0-76be-8fd5-75ac6e7aa0d8 Co-authored-by: tmm --- swift/Tests/E2ETests/NIOTransport.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/swift/Tests/E2ETests/NIOTransport.swift b/swift/Tests/E2ETests/NIOTransport.swift index dec123fb02..6749b82074 100644 --- a/swift/Tests/E2ETests/NIOTransport.swift +++ b/swift/Tests/E2ETests/NIOTransport.swift @@ -56,11 +56,14 @@ public struct NIOTransport: Transport { headers.add(name: "Host", value: "\(host):\(port)") if let secProtocol { headers.add(name: "Sec-WebSocket-Protocol", value: secProtocol) } let head = HTTPRequestHead(version: .http1_1, method: .GET, uri: uri, headers: headers) + var configuration = NIOUpgradableHTTPClientPipelineConfiguration( + upgradeConfiguration: .init( + upgradeRequestHead: head, upgraders: [upgrader], + notUpgradingCompletionHandler: { $0.eventLoop.makeCompletedFuture { .declined } })) + // Frames that arrive in the same read as the 101 response belong to the WebSocket; the default drops them. + configuration.leftOverBytesStrategy = .forwardBytes return try channel.pipeline.syncOperations.configureUpgradableHTTPClientPipeline( - configuration: .init( - upgradeConfiguration: .init( - upgradeRequestHead: head, upgraders: [upgrader], - notUpgradingCompletionHandler: { $0.eventLoop.makeCompletedFuture { .declined } }))) + configuration: configuration) } } switch try await upgrade.get() {