Signed-off-by: Maisem Ali <maisem@tailscale.com>main
parent
e0e677a8f6
commit
57756ef673
@ -0,0 +1,22 @@ |
||||
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nettest |
||||
|
||||
import ( |
||||
"net" |
||||
"testing" |
||||
|
||||
"golang.org/x/net/nettest" |
||||
) |
||||
|
||||
func TestConn(t *testing.T) { |
||||
nettest.TestConn(t, func() (c1 net.Conn, c2 net.Conn, stop func(), err error) { |
||||
c1, c2 = NewConn("test", bufferSize) |
||||
return c1, c2, func() { |
||||
c1.Close() |
||||
c2.Close() |
||||
}, nil |
||||
}) |
||||
} |
||||
@ -0,0 +1,83 @@ |
||||
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nettest |
||||
|
||||
import ( |
||||
"context" |
||||
"net" |
||||
"strings" |
||||
"sync" |
||||
) |
||||
|
||||
const ( |
||||
bufferSize = 256 * 1024 |
||||
) |
||||
|
||||
// Listener is a net.Listener using using NewConn to create pairs of network
|
||||
// connections connected in memory using a buffered pipe. It also provides a
|
||||
// Dial method to establish new connections.
|
||||
type Listener struct { |
||||
addr connAddr |
||||
ch chan Conn |
||||
closeOnce sync.Once |
||||
closed chan struct{} |
||||
} |
||||
|
||||
// Listen returns a new Listener for the provided address.
|
||||
func Listen(addr string) *Listener { |
||||
return &Listener{ |
||||
addr: connAddr(addr), |
||||
ch: make(chan Conn), |
||||
closed: make(chan struct{}), |
||||
} |
||||
} |
||||
|
||||
// Addr implements net.Listener.Addr.
|
||||
func (l *Listener) Addr() net.Addr { |
||||
return l.addr |
||||
} |
||||
|
||||
// Close closes the pipe listener.
|
||||
func (l *Listener) Close() error { |
||||
l.closeOnce.Do(func() { |
||||
close(l.closed) |
||||
}) |
||||
return nil |
||||
} |
||||
|
||||
// Accept blocks until a new connection is available or the listener is closed.
|
||||
func (l *Listener) Accept() (net.Conn, error) { |
||||
select { |
||||
case c := <-l.ch: |
||||
return c, nil |
||||
case <-l.closed: |
||||
return nil, net.ErrClosed |
||||
} |
||||
} |
||||
|
||||
// Dial connects to the listener using the provided context.
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// connection is complete, an error is returned. Once successfully connected
|
||||
// any expiration of the context will not affect the connection.
|
||||
func (l *Listener) Dial(ctx context.Context, network, addr string) (net.Conn, error) { |
||||
if !strings.HasSuffix(network, "tcp") { |
||||
return nil, net.UnknownNetworkError(network) |
||||
} |
||||
if connAddr(addr) != l.addr { |
||||
return nil, &net.AddrError{ |
||||
Err: "invalid address", |
||||
Addr: addr, |
||||
} |
||||
} |
||||
c, s := NewConn(addr, bufferSize) |
||||
select { |
||||
case <-ctx.Done(): |
||||
return nil, ctx.Err() |
||||
case <-l.closed: |
||||
return nil, net.ErrClosed |
||||
case l.ch <- s: |
||||
return c, nil |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nettest |
||||
|
||||
import ( |
||||
"context" |
||||
"testing" |
||||
) |
||||
|
||||
func TestListener(t *testing.T) { |
||||
l := Listen("srv.local") |
||||
defer l.Close() |
||||
go func() { |
||||
c, err := l.Accept() |
||||
if err != nil { |
||||
t.Error(err) |
||||
return |
||||
} |
||||
defer c.Close() |
||||
}() |
||||
|
||||
if c, err := l.Dial(context.Background(), "tcp", "invalid"); err == nil { |
||||
c.Close() |
||||
t.Fatalf("dial to invalid address succeeded") |
||||
} |
||||
c, err := l.Dial(context.Background(), "tcp", "srv.local") |
||||
if err != nil { |
||||
t.Fatalf("dial failed: %v", err) |
||||
return |
||||
} |
||||
c.Close() |
||||
} |
||||
Loading…
Reference in new issue