internal: rewrite TestDialWithMultipleBackendsNotSendingServerPreface ()

- Remove the slice of servers approach, since there's specific
logic at server 2 that's different from server 1. This has the
advantage of making the test more readable without sacrificing
anything (given the previous point).

- Defer server close at initialization time instead of at the
end.

- Remove a time.Sleep(time.Second): use timeout + select around
serverDone instead.

- Use a goroutine to keep the connection reading, instead of
using a for loop in the server goroutine. This causes the
defer close(server2Done) to happen immediately after preface
is sent, which combined with the aforementioned time.Sleep
removal causes the test to go from 1.00s to ~0.05s.
This commit is contained in:
Jean de Klerk
2019-01-08 16:48:09 -08:00
committed by GitHub
parent 0a391ff2b7
commit 76cc50721c

@ -62,72 +62,59 @@ func assertState(wantState connectivity.State, cc *ClientConn) (connectivity.Sta
} }
func (s) TestDialWithMultipleBackendsNotSendingServerPreface(t *testing.T) { func (s) TestDialWithMultipleBackendsNotSendingServerPreface(t *testing.T) {
numServers := 2 lis1, err := net.Listen("tcp", "localhost:0")
servers := make([]net.Listener, numServers) if err != nil {
var err error t.Fatalf("Error while listening. Err: %v", err)
for i := 0; i < numServers; i++ { }
servers[i], err = net.Listen("tcp", "localhost:0") defer lis1.Close()
lis1Addr := resolver.Address{Addr: lis1.Addr().String()}
lis1Done := make(chan struct{})
// 1st listener accepts the connection and immediately closes it.
go func() {
defer close(lis1Done)
conn, err := lis1.Accept()
if err != nil { if err != nil {
t.Fatalf("Error while listening. Err: %v", err) t.Errorf("Error while accepting. Err: %v", err)
return
} }
conn.Close()
}()
lis2, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error while listening. Err: %v", err)
} }
dones := make([]chan struct{}, numServers) defer lis2.Close()
for i := 0; i < numServers; i++ { lis2Done := make(chan struct{})
dones[i] = make(chan struct{}) lis2Addr := resolver.Address{Addr: lis2.Addr().String()}
} // 2nd listener should get a connection attempt since the first one failed.
for i := 0; i < numServers; i++ { go func() {
go func(i int) { defer close(lis2Done)
defer func() { _, err := lis2.Accept() // Closing the client will clean up this conn.
close(dones[i]) if err != nil {
}() t.Errorf("Error while accepting. Err: %v", err)
conn, err := servers[i].Accept() return
if err != nil { }
t.Errorf("Error while accepting. Err: %v", err) }()
return
}
defer conn.Close()
switch i {
case 0: // 1st server accepts the connection and immediately closes it.
case 1: // 2nd server accepts the connection and sends settings frames.
framer := http2.NewFramer(conn, conn)
if err := framer.WriteSettings(http2.Setting{}); err != nil {
t.Errorf("Error while writing settings frame. %v", err)
return
}
conn.SetDeadline(time.Now().Add(time.Second))
buf := make([]byte, 1024)
for { // Make sure the connection stays healthy.
_, err = conn.Read(buf)
if err == nil {
continue
}
if nerr, ok := err.(net.Error); !ok || !nerr.Timeout() {
t.Errorf("Server expected the conn.Read(_) to timeout instead got error: %v", err)
}
return
}
}
}(i)
}
r, cleanup := manual.GenerateAndRegisterManualResolver() r, cleanup := manual.GenerateAndRegisterManualResolver()
defer cleanup() defer cleanup()
resolvedAddrs := make([]resolver.Address, numServers) r.InitialAddrs([]resolver.Address{lis1Addr, lis2Addr})
for i := 0; i < numServers; i++ {
resolvedAddrs[i] = resolver.Address{Addr: servers[i].Addr().String()}
}
r.InitialAddrs(resolvedAddrs)
client, err := Dial(r.Scheme()+":///test.server", WithInsecure()) client, err := Dial(r.Scheme()+":///test.server", WithInsecure())
if err != nil { if err != nil {
t.Errorf("Dial failed. Err: %v", err) t.Fatalf("Dial failed. Err: %v", err)
} else {
defer client.Close()
} }
time.Sleep(time.Second) // Close the servers after a second for cleanup. defer client.Close()
for _, s := range servers { timeout := time.After(5 * time.Second)
s.Close() select {
case <-timeout:
t.Fatal("timed out waiting for server 1 to finish")
case <-lis1Done:
} }
for _, done := range dones { select {
<-done case <-timeout:
t.Fatal("timed out waiting for server 2 to finish")
case <-lis2Done:
} }
} }