@@ -45,6 +45,7 @@ import (
4545 "google.golang.org/grpc/internal/grpctest"
4646 "google.golang.org/grpc/internal/leakcheck"
4747 "google.golang.org/grpc/internal/testutils"
48+ "google.golang.org/grpc/metadata"
4849 "google.golang.org/grpc/resolver"
4950 "google.golang.org/grpc/status"
5051)
@@ -2136,6 +2137,70 @@ func (s) TestHeadersHTTPStatusGRPCStatus(t *testing.T) {
21362137 }
21372138}
21382139
2140+ func (s ) TestWriteHeaderConnectionError (t * testing.T ) {
2141+ server , client , cancel := setUp (t , 0 , notifyCall )
2142+ defer cancel ()
2143+ defer server .stop ()
2144+
2145+ waitWhileTrue (t , func () (bool , error ) {
2146+ server .mu .Lock ()
2147+ defer server .mu .Unlock ()
2148+
2149+ if len (server .conns ) == 0 {
2150+ return true , fmt .Errorf ("timed-out while waiting for connection to be created on the server" )
2151+ }
2152+ return false , nil
2153+ })
2154+
2155+ server .mu .Lock ()
2156+
2157+ if len (server .conns ) != 1 {
2158+ t .Fatalf ("Server has %d connections from the client, want 1" , len (server .conns ))
2159+ }
2160+
2161+ // Get the server transport for the connecton to the client.
2162+ var serverTransport * http2Server
2163+ for k := range server .conns {
2164+ serverTransport = k .(* http2Server )
2165+ }
2166+ notifyChan := make (chan struct {})
2167+ server .h .notify = notifyChan
2168+ server .mu .Unlock ()
2169+
2170+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
2171+ defer cancel ()
2172+ cstream , err := client .NewStream (ctx , & CallHdr {})
2173+ if err != nil {
2174+ t .Fatalf ("Client failed to create first stream. Err: %v" , err )
2175+ }
2176+
2177+ <- notifyChan // Wait for server stream to be established.
2178+ var sstream * Stream
2179+ // Access stream on the server.
2180+ serverTransport .mu .Lock ()
2181+ for _ , v := range serverTransport .activeStreams {
2182+ if v .id == cstream .id {
2183+ sstream = v
2184+ }
2185+ }
2186+ serverTransport .mu .Unlock ()
2187+ if sstream == nil {
2188+ t .Fatalf ("Didn't find stream corresponding to client cstream.id: %v on the server" , cstream .id )
2189+ }
2190+
2191+ client .Close (fmt .Errorf ("closed manually by test" ))
2192+
2193+ // Wait for server transport to be closed.
2194+ <- serverTransport .done
2195+
2196+ // Write header on a closed server transport.
2197+ err = serverTransport .WriteHeader (sstream , metadata.MD {})
2198+ st := status .Convert (err )
2199+ if st .Code () != codes .Unavailable {
2200+ t .Fatalf ("WriteHeader() failed with status code %s, want %s" , st .Code (), codes .Unavailable )
2201+ }
2202+ }
2203+
21392204func (s ) TestPingPong1B (t * testing.T ) {
21402205 runPingPongTest (t , 1 )
21412206}
0 commit comments