Skip to content

Commit 08558d0

Browse files
committed
protocol: more deadline tests
1 parent 9481030 commit 08558d0

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed

protocol_test.go

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,47 @@ func TestUseWithReadHeaderTimeout(t *testing.T) {
223223
}
224224
}
225225

226+
func TestNewConnSetReadHeaderTimeoutOption(t *testing.T) {
227+
conn, peer := net.Pipe()
228+
t.Cleanup(func() {
229+
if closeErr := conn.Close(); closeErr != nil {
230+
t.Errorf("failed to close connection: %v", closeErr)
231+
}
232+
})
233+
t.Cleanup(func() {
234+
if closeErr := peer.Close(); closeErr != nil {
235+
t.Errorf("failed to close peer connection: %v", closeErr)
236+
}
237+
})
238+
239+
// Ensure SetReadHeaderTimeout sets the connection-specific timeout.
240+
timeout := 150 * time.Millisecond
241+
proxyConn := NewConn(conn, SetReadHeaderTimeout(timeout))
242+
if proxyConn.readHeaderTimeout != timeout {
243+
t.Fatalf("expected readHeaderTimeout %v, got %v", timeout, proxyConn.readHeaderTimeout)
244+
}
245+
}
246+
247+
func TestNewConnSetReadHeaderTimeoutIgnoresNegative(t *testing.T) {
248+
conn, peer := net.Pipe()
249+
t.Cleanup(func() {
250+
if closeErr := conn.Close(); closeErr != nil {
251+
t.Errorf("failed to close connection: %v", closeErr)
252+
}
253+
})
254+
t.Cleanup(func() {
255+
if closeErr := peer.Close(); closeErr != nil {
256+
t.Errorf("failed to close peer connection: %v", closeErr)
257+
}
258+
})
259+
260+
// Negative values should be ignored, leaving the timeout unset.
261+
proxyConn := NewConn(conn, SetReadHeaderTimeout(-1))
262+
if proxyConn.readHeaderTimeout != 0 {
263+
t.Fatalf("expected readHeaderTimeout to remain 0, got %v", proxyConn.readHeaderTimeout)
264+
}
265+
}
266+
226267
func TestReadHeaderTimeoutRespectsEarlierDeadline(t *testing.T) {
227268
const (
228269
headerTimeout = 200 * time.Millisecond
@@ -2038,6 +2079,54 @@ type testConn struct {
20382079
net.Conn // nil; crash on any unexpected use
20392080
}
20402081

2082+
type deadlineConn struct {
2083+
deadline time.Time
2084+
readDeadline time.Time
2085+
writeDeadline time.Time
2086+
}
2087+
2088+
func (c *deadlineConn) Read(_ []byte) (int, error) { return 0, io.EOF }
2089+
func (c *deadlineConn) Write(p []byte) (int, error) { return len(p), nil }
2090+
func (c *deadlineConn) Close() error { return nil }
2091+
func (c *deadlineConn) LocalAddr() net.Addr { return dummyAddr("local") }
2092+
func (c *deadlineConn) RemoteAddr() net.Addr { return dummyAddr("remote") }
2093+
func (c *deadlineConn) SetDeadline(t time.Time) error {
2094+
c.deadline = t
2095+
return nil
2096+
}
2097+
func (c *deadlineConn) SetReadDeadline(t time.Time) error {
2098+
c.readDeadline = t
2099+
return nil
2100+
}
2101+
func (c *deadlineConn) SetWriteDeadline(t time.Time) error {
2102+
c.writeDeadline = t
2103+
return nil
2104+
}
2105+
2106+
type noReadFromConn struct {
2107+
written bytes.Buffer
2108+
}
2109+
2110+
func (c *noReadFromConn) Read(_ []byte) (int, error) { return 0, io.EOF }
2111+
func (c *noReadFromConn) Write(p []byte) (int, error) {
2112+
return c.written.Write(p)
2113+
}
2114+
func (c *noReadFromConn) Close() error { return nil }
2115+
func (c *noReadFromConn) LocalAddr() net.Addr { return dummyAddr("local") }
2116+
func (c *noReadFromConn) RemoteAddr() net.Addr { return dummyAddr("remote") }
2117+
func (c *noReadFromConn) SetDeadline(time.Time) error { return nil }
2118+
func (c *noReadFromConn) SetReadDeadline(time.Time) error {
2119+
return nil
2120+
}
2121+
func (c *noReadFromConn) SetWriteDeadline(time.Time) error {
2122+
return nil
2123+
}
2124+
2125+
type dummyAddr string
2126+
2127+
func (a dummyAddr) Network() string { return "dummy" }
2128+
func (a dummyAddr) String() string { return string(a) }
2129+
20412130
func (c *testConn) ReadFrom(r io.Reader) (int64, error) {
20422131
c.readFromCalledWith = r
20432132
b, err := io.ReadAll(r)
@@ -2095,6 +2184,127 @@ func TestCopyFromWrappedConnectionToWrappedConnection(t *testing.T) {
20952184
}
20962185
}
20972186

2187+
func TestDeadlineWrappersDelegate(t *testing.T) {
2188+
conn := &deadlineConn{}
2189+
proxyConn := NewConn(conn)
2190+
2191+
deadline := time.Now().Add(2 * time.Second)
2192+
readDeadline := time.Now().Add(3 * time.Second)
2193+
writeDeadline := time.Now().Add(4 * time.Second)
2194+
2195+
// Ensure deadline setters pass through to the underlying connection.
2196+
if err := proxyConn.SetDeadline(deadline); err != nil {
2197+
t.Fatalf("unexpected SetDeadline error: %v", err)
2198+
}
2199+
if err := proxyConn.SetReadDeadline(readDeadline); err != nil {
2200+
t.Fatalf("unexpected SetReadDeadline error: %v", err)
2201+
}
2202+
if err := proxyConn.SetWriteDeadline(writeDeadline); err != nil {
2203+
t.Fatalf("unexpected SetWriteDeadline error: %v", err)
2204+
}
2205+
2206+
if !conn.deadline.Equal(deadline) {
2207+
t.Fatalf("SetDeadline did not pass through value")
2208+
}
2209+
if !conn.readDeadline.Equal(readDeadline) {
2210+
t.Fatalf("SetReadDeadline did not pass through value")
2211+
}
2212+
if !conn.writeDeadline.Equal(writeDeadline) {
2213+
t.Fatalf("SetWriteDeadline did not pass through value")
2214+
}
2215+
}
2216+
2217+
func TestReadFromFallbackCopiesToConn(t *testing.T) {
2218+
conn := &noReadFromConn{}
2219+
proxyConn := NewConn(conn)
2220+
2221+
payload := []byte("payload")
2222+
if _, err := proxyConn.ReadFrom(bytes.NewReader(payload)); err != nil {
2223+
t.Fatalf("unexpected ReadFrom error: %v", err)
2224+
}
2225+
2226+
// When the inner connection does not implement io.ReaderFrom,
2227+
// ReadFrom should fall back to io.Copy and write the payload.
2228+
if !bytes.Equal(conn.written.Bytes(), payload) {
2229+
t.Fatalf("unexpected write content: %q", conn.written.String())
2230+
}
2231+
}
2232+
2233+
func TestWriteToDrainsBufferedData(t *testing.T) {
2234+
l, err := net.Listen("tcp", testLocalhostRandomPort)
2235+
if err != nil {
2236+
t.Fatalf("err: %v", err)
2237+
}
2238+
2239+
pl := &Listener{Listener: l}
2240+
2241+
header := &Header{
2242+
Version: 2,
2243+
Command: PROXY,
2244+
TransportProtocol: TCPv4,
2245+
SourceAddr: &net.TCPAddr{
2246+
IP: net.ParseIP(testSourceIPv4Addr),
2247+
Port: 1000,
2248+
},
2249+
DestinationAddr: &net.TCPAddr{
2250+
IP: net.ParseIP(testDestinationIPv4Addr),
2251+
Port: 2000,
2252+
},
2253+
}
2254+
2255+
payload := []byte("ping")
2256+
2257+
cliResult := make(chan error)
2258+
go func() {
2259+
conn, err := net.Dial("tcp", pl.Addr().String())
2260+
if err != nil {
2261+
cliResult <- err
2262+
return
2263+
}
2264+
2265+
// Write the header followed by payload to populate the reader buffer.
2266+
if _, err := header.WriteTo(conn); err != nil {
2267+
cliResult <- err
2268+
return
2269+
}
2270+
if _, err := conn.Write(payload); err != nil {
2271+
cliResult <- err
2272+
return
2273+
}
2274+
2275+
// Close the client so WriteTo's io.Copy completes.
2276+
if err := conn.Close(); err != nil {
2277+
cliResult <- err
2278+
return
2279+
}
2280+
2281+
close(cliResult)
2282+
}()
2283+
2284+
conn, err := pl.Accept()
2285+
if err != nil {
2286+
t.Fatalf("err: %v", err)
2287+
}
2288+
t.Cleanup(func() {
2289+
if closeErr := conn.Close(); closeErr != nil {
2290+
t.Errorf("failed to close connection: %v", closeErr)
2291+
}
2292+
})
2293+
2294+
var out bytes.Buffer
2295+
if _, err := conn.(*Conn).WriteTo(&out); err != nil {
2296+
t.Fatalf("unexpected WriteTo error: %v", err)
2297+
}
2298+
if !bytes.Equal(out.Bytes(), payload) {
2299+
t.Fatalf("unexpected WriteTo output: %q", out.String())
2300+
}
2301+
2302+
err = <-cliResult
2303+
if err != nil {
2304+
t.Fatalf("client error: %v", err)
2305+
}
2306+
}
2307+
20982308
func benchmarkTCPProxy(size int, b *testing.B) {
20992309
// create and start the echo backend
21002310
backend, err := net.Listen("tcp", testLocalhostRandomPort)

0 commit comments

Comments
 (0)