internal/jsonrpc2/servertest: replace closerList with connList

closerList was already unnecessarily abstract, and tracking connections
will allow us to also wait for all connections to finish.

Share functionality by embedding this type in PipeServer, TCPServer.

Change-Id: Ib2cb2157c1477f904bc278aa91902f5c633afe13
Reviewed-on: https://go-review.googlesource.com/c/tools/+/238547
Reviewed-by: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/internal/jsonrpc2/servertest/servertest.go b/internal/jsonrpc2/servertest/servertest.go
index 71fef21..392e084 100644
--- a/internal/jsonrpc2/servertest/servertest.go
+++ b/internal/jsonrpc2/servertest/servertest.go
@@ -25,11 +25,12 @@
 // connection. Once initialized, its Addr field may be used to connect a
 // jsonrpc2 client.
 type TCPServer struct {
+	*connList
+
 	Addr string
 
 	ln     net.Listener
 	framer jsonrpc2.Framer
-	cls    *closerList
 }
 
 // NewTCPServer returns a new test server listening on local tcp port and
@@ -44,7 +45,7 @@
 		framer = jsonrpc2.NewHeaderStream
 	}
 	go jsonrpc2.Serve(ctx, ln, server, 0)
-	return &TCPServer{Addr: ln.Addr().String(), ln: ln, framer: framer, cls: &closerList{}}
+	return &TCPServer{Addr: ln.Addr().String(), ln: ln, framer: framer, connList: &connList{}}
 }
 
 // Connect dials the test server and returns a jsonrpc2 Connection that is
@@ -55,20 +56,15 @@
 		panic(fmt.Sprintf("servertest: failed to connect to test instance: %v", err))
 	}
 	conn := jsonrpc2.NewConn(s.framer(netConn))
-	s.cls.add(conn.Close)
+	s.add(conn)
 	return conn
 }
 
-// Close closes all server connections.
-func (s *TCPServer) Close() error {
-	return s.cls.Close()
-}
-
 // PipeServer is a test server that handles connections over io.Pipes.
 type PipeServer struct {
+	*connList
 	server jsonrpc2.StreamServer
 	framer jsonrpc2.Framer
-	cls    *closerList
 }
 
 // NewPipeServer returns a test server that can be connected to via io.Pipes.
@@ -76,7 +72,7 @@
 	if framer == nil {
 		framer = jsonrpc2.NewRawStream
 	}
-	return &PipeServer{server: server, framer: framer, cls: &closerList{}}
+	return &PipeServer{server: server, framer: framer, connList: &connList{}}
 }
 
 // Connect creates new io.Pipes and binds them to the underlying StreamServer.
@@ -84,40 +80,35 @@
 	sPipe, cPipe := net.Pipe()
 	serverStream := s.framer(sPipe)
 	serverConn := jsonrpc2.NewConn(serverStream)
-	s.cls.add(serverConn.Close)
+	s.add(serverConn)
 	go s.server.ServeStream(ctx, serverConn)
 
 	clientStream := s.framer(cPipe)
 	clientConn := jsonrpc2.NewConn(clientStream)
-	s.cls.add(clientConn.Close)
+	s.add(clientConn)
 	return clientConn
 }
 
-// Close closes all connected pipes.
-func (s *PipeServer) Close() error {
-	return s.cls.Close()
-}
-
-// closerList tracks closers to run when a testserver is closed.  This is a
+// connList tracks closers to run when a testserver is closed.  This is a
 // convenience, so that callers don't have to worry about closing each
 // connection.
-type closerList struct {
-	mu      sync.Mutex
-	closers []func() error
+type connList struct {
+	mu    sync.Mutex
+	conns []jsonrpc2.Conn
 }
 
-func (l *closerList) add(closer func() error) {
+func (l *connList) add(conn jsonrpc2.Conn) {
 	l.mu.Lock()
 	defer l.mu.Unlock()
-	l.closers = append(l.closers, closer)
+	l.conns = append(l.conns, conn)
 }
 
-func (l *closerList) Close() error {
+func (l *connList) Close() error {
 	l.mu.Lock()
 	defer l.mu.Unlock()
 	var errmsgs []string
-	for _, closer := range l.closers {
-		if err := closer(); err != nil {
+	for _, conn := range l.conns {
+		if err := conn.Close(); err != nil {
 			errmsgs = append(errmsgs, err.Error())
 		}
 	}