From d9abbec934ba5bf95d48b9510668cd7226ce8c5d Mon Sep 17 00:00:00 2001 From: Robin knaapen Date: Sun, 11 Apr 2021 18:22:48 +0200 Subject: [PATCH] Workaround for Go 1.16 (#642) * Fix Go1.16 * Add more tests * Add build tag * Add Go 1.16 to appveyor.yml --- appveyor.yml | 3 + net.go | 40 +++++------ net_go116_test.go | 172 ++++++++++++++++++++++++++++++++++++++++++++++ queries_test.go | 13 ++++ 4 files changed, 208 insertions(+), 20 deletions(-) create mode 100644 net_go116_test.go diff --git a/appveyor.yml b/appveyor.yml index dfcb62de..ecb893a3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -39,6 +39,9 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 GOVERSION: 115 SQLINSTANCE: SQL2017 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + GOVERSION: 116 + SQLINSTANCE: SQL2017 install: - set GOROOT=c:\go%GOVERSION% diff --git a/net.go b/net.go index dccfde35..bb7b784c 100644 --- a/net.go +++ b/net.go @@ -7,8 +7,8 @@ import ( ) type timeoutConn struct { - c net.Conn - timeout time.Duration + c net.Conn + timeout time.Duration } func newTimeoutConn(conn net.Conn, timeout time.Duration) *timeoutConn { @@ -51,21 +51,21 @@ func (c timeoutConn) RemoteAddr() net.Addr { } func (c timeoutConn) SetDeadline(t time.Time) error { - panic("Not implemented") + return c.c.SetDeadline(t) } func (c timeoutConn) SetReadDeadline(t time.Time) error { - panic("Not implemented") + return c.c.SetReadDeadline(t) } func (c timeoutConn) SetWriteDeadline(t time.Time) error { - panic("Not implemented") + return c.c.SetWriteDeadline(t) } // this connection is used during TLS Handshake // TDS protocol requires TLS handshake messages to be sent inside TDS packets type tlsHandshakeConn struct { - buf *tdsBuffer + buf *tdsBuffer packetPending bool continueRead bool } @@ -105,27 +105,27 @@ func (c *tlsHandshakeConn) Write(b []byte) (n int, err error) { } func (c *tlsHandshakeConn) Close() error { - panic("Not implemented") + return c.buf.transport.Close() } func (c *tlsHandshakeConn) LocalAddr() net.Addr { - panic("Not implemented") + return nil } func (c *tlsHandshakeConn) RemoteAddr() net.Addr { - panic("Not implemented") + return nil } -func (c *tlsHandshakeConn) SetDeadline(t time.Time) error { - panic("Not implemented") +func (c *tlsHandshakeConn) SetDeadline(_ time.Time) error { + return nil } -func (c *tlsHandshakeConn) SetReadDeadline(t time.Time) error { - panic("Not implemented") +func (c *tlsHandshakeConn) SetReadDeadline(_ time.Time) error { + return nil } -func (c *tlsHandshakeConn) SetWriteDeadline(t time.Time) error { - panic("Not implemented") +func (c *tlsHandshakeConn) SetWriteDeadline(_ time.Time) error { + return nil } // this connection just delegates all methods to it's wrapped connection @@ -148,21 +148,21 @@ func (c passthroughConn) Close() error { } func (c passthroughConn) LocalAddr() net.Addr { - panic("Not implemented") + return c.c.LocalAddr() } func (c passthroughConn) RemoteAddr() net.Addr { - panic("Not implemented") + return c.c.RemoteAddr() } func (c passthroughConn) SetDeadline(t time.Time) error { - panic("Not implemented") + return c.c.SetDeadline(t) } func (c passthroughConn) SetReadDeadline(t time.Time) error { - panic("Not implemented") + return c.c.SetReadDeadline(t) } func (c passthroughConn) SetWriteDeadline(t time.Time) error { - panic("Not implemented") + return c.c.SetWriteDeadline(t) } diff --git a/net_go116_test.go b/net_go116_test.go new file mode 100644 index 00000000..79dc0779 --- /dev/null +++ b/net_go116_test.go @@ -0,0 +1,172 @@ +// +build go1.16 + +package mssql + +import ( + "context" + "net" + "testing" + "time" +) + +func assertPanic(t *testing.T, paniced bool) { + v := recover() + if paniced && v == nil { + t.Fatalf(`expected panic but it did not`) + } + + if !paniced && v != nil { + t.Fatalf(`expected no panic but it did`) + } +} + +func TestTimeoutConn(t *testing.T) { + _, conn := net.Pipe() + + tconn := newTimeoutConn(conn, time.Minute) + t.Run(`set deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Millisecond * 100) + + err := tconn.SetDeadline(deadline) + if err != nil { + t.Fatalf(`SetDeadline should return nil`) + } + }) + + t.Run(`set read deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Minute) + + err := tconn.SetReadDeadline(deadline) + if err != nil { + t.Fatalf(`SetReadDeadline should return nil`) + } + }) + + t.Run(`set write deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Minute) + + err := tconn.SetWriteDeadline(deadline) + if err != nil { + t.Fatalf(`SetWriteDeadline should return nil`) + } + }) +} + +func TestTLSHandshakeConn(t *testing.T) { + SetLogger(testLogger{t}) + + connector, err := NewConnector(makeConnStr(t).String()) + if err != nil { + t.Error(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + + toconn, err := dialConnection(ctx, connector, connector.params) + if err != nil { + t.Error(err) + } + + outbuf := newTdsBuffer(connector.params.packetSize, toconn) + handshakeConn := tlsHandshakeConn{buf: outbuf} + + t.Run(`set deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Millisecond * 100) + + err := handshakeConn.SetDeadline(deadline) + if err != nil { + t.Fatalf(`SetDeadline should return nil`) + } + }) + + t.Run(`set read deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Minute) + + err := handshakeConn.SetReadDeadline(deadline) + if err != nil { + t.Fatalf(`SetReadDeadline should return nil`) + } + }) + + t.Run(`set write deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Minute) + + err := handshakeConn.SetWriteDeadline(deadline) + if err != nil { + t.Fatalf(`SetWriteDeadline should return nil`) + } + }) + + t.Run(`get remote addr`, func(t *testing.T) { + addr := handshakeConn.RemoteAddr() + if addr != nil { + t.Fatalf(`RemoteAddr should return nil`) + } + }) +} + +func TestPassthroughConn(t *testing.T) { + SetLogger(testLogger{t}) + + connector, err := NewConnector(makeConnStr(t).String()) + if err != nil { + t.Error(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + + toconn, err := dialConnection(ctx, connector, connector.params) + if err != nil { + t.Error(err) + } + + outbuf := newTdsBuffer(connector.params.packetSize, toconn) + + handshakeConn := tlsHandshakeConn{buf: outbuf} + passthrough := passthroughConn{c: &handshakeConn} + + t.Run(`set deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Millisecond * 100) + + err := passthrough.SetDeadline(deadline) + if err != nil { + t.Fatalf(`SetDeadline should return nil`) + } + }) + + t.Run(`set read deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Minute) + + err := passthrough.SetReadDeadline(deadline) + if err != nil { + t.Fatalf(`SetReadDeadline should return nil`) + } + }) + + t.Run(`set write deadline`, func(t *testing.T) { + defer assertPanic(t, false) + deadline := time.Now().Add(time.Minute) + + err := passthrough.SetWriteDeadline(deadline) + if err != nil { + t.Fatalf(`SetWriteDeadline should return nil`) + } + }) + + t.Run(`get remote addr`, func(t *testing.T) { + addr := passthrough.RemoteAddr() + if addr != nil { + t.Fatalf(`RemoteAddr should return nil`) + } + }) +} diff --git a/queries_test.go b/queries_test.go index f89f9013..0589491b 100644 --- a/queries_test.go +++ b/queries_test.go @@ -2230,3 +2230,16 @@ func TestDisconnect2(t *testing.T) { t.Fatal("timeout") } } + +func TestClose(t *testing.T) { + conn := open(t) + + defer func() { + v := recover() + if v != nil { + t.Fatal(`Close should not panic:`, v) + } + }() + + conn.Close() +}