Skip to content

proposal: x/net/nettest: add MakeLocalPipe to construct local listener and connections #30984

Description

@mdlayher

I'm currently implementing my own net.Conn type and am working on tests using nettest.TestConn: https://godoc.org/golang.org/x/net/nettest#TestConn.

The nettest.MakePipe function provides adequate functionality for my needs, but a fair amount of boilerplate is required to create a nettest.MakePipe that can:

  • set up a local net.Listener
  • dial and point a net.Conn at the listener
  • do appropriate cleanup and error handling

As it turns out, there's a pretty useful function to make a local pipe in one of the tests: https://go.googlesource.com/net/+/refs/heads/master/nettest/conntest_test.go

I propose we generalize and export this function for use with net.Listener and net.Conn implementations of any type. I'm happy to accept name suggestions, but my proposed signature and WIP documentation is as follows:

// MakeLocalPipe creates a local net.Listener and points another net.Conn at the
// listener, producing a MakePipe function suitable for use with TestConn.
// 
// The listen function should produce a net.Listener, but should not invoke Accept or
// any other methods on the listener. The dial function receives the address of the
// listener, and should produce a net.Conn pointed at the listener. If dial is nil,
// net.Dial will be invoked with the network and address information from addr.
func MakeLocalPipe(
    listen func() (net.Listener, error),
    dial func(addr net.Addr) (net.Conn, error),
) nettest.MakePipe

Usage is as follows:

Producing a local pipe with a TCP listener and connection, using net.Dial as a default dial function.

nettest.TestConn(t, nettest.MakeLocalPipe(
    func() (net.Listener, error) {
        return net.Listen("tcp", ":0")
    },
    // dial: net.Dial(addr.Network(), addr.String())
    nil,
))

Producing a local pipe with a custom listener and connection implemented outside of the stdlib (https://github.com/mdlayher/vsock)

nettest.TestConn(t, nettest.MakeLocalPipe(
    func() (net.Listener, error) {
        return vsock.Listen(0)
    },
    func(addr net.Addr) (net.Conn, error) {
        a := addr.(*vsock.Addr)
        return vsock.Dial(a.ContextID, a.Port)
    },
))

I don't mind putting this code in my own repository or similar if deemed unnecessary, but it seems like this would be an appropriate addition to nettest, since it enables easy setup of scaffolding for use with nettest.TestConn.

/cc @dsnet @mikioh

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status
    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions