(t *testing.T)
| 35 | ) |
| 36 | |
| 37 | func (s) TestContextCanceled(t *testing.T) { |
| 38 | ss := &stubserver.StubServer{ |
| 39 | FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { |
| 40 | stream.SetTrailer(metadata.New(map[string]string{"a": "b"})) |
| 41 | return status.Error(codes.PermissionDenied, "perm denied") |
| 42 | }, |
| 43 | } |
| 44 | if err := ss.Start(nil); err != nil { |
| 45 | t.Fatalf("Error starting endpoint server: %v", err) |
| 46 | } |
| 47 | defer ss.Stop() |
| 48 | |
| 49 | // Runs 10 rounds of tests with the given delay and returns counts of status codes. |
| 50 | // Fails in case of trailer/status code inconsistency. |
| 51 | const cntRetry uint = 10 |
| 52 | runTest := func(delay time.Duration) (cntCanceled, cntPermDenied uint) { |
| 53 | for i := uint(0); i < cntRetry; i++ { |
| 54 | ctx, cancel := context.WithTimeout(context.Background(), delay) |
| 55 | defer cancel() |
| 56 | |
| 57 | str, err := ss.Client.FullDuplexCall(ctx) |
| 58 | if err != nil { |
| 59 | continue |
| 60 | } |
| 61 | |
| 62 | _, err = str.Recv() |
| 63 | if err == nil { |
| 64 | t.Fatalf("non-nil error expected from Recv()") |
| 65 | } |
| 66 | |
| 67 | _, trlOk := str.Trailer()["a"] |
| 68 | switch status.Code(err) { |
| 69 | case codes.PermissionDenied: |
| 70 | if !trlOk { |
| 71 | t.Fatalf(`status err: %v; wanted key "a" in trailer but didn't get it`, err) |
| 72 | } |
| 73 | cntPermDenied++ |
| 74 | case codes.DeadlineExceeded: |
| 75 | if trlOk { |
| 76 | t.Fatalf(`status err: %v; didn't want key "a" in trailer but got it`, err) |
| 77 | } |
| 78 | cntCanceled++ |
| 79 | default: |
| 80 | t.Fatalf(`unexpected status err: %v`, err) |
| 81 | } |
| 82 | } |
| 83 | return cntCanceled, cntPermDenied |
| 84 | } |
| 85 | |
| 86 | // Tries to find the delay that causes canceled/perm denied race. |
| 87 | canceledOk, permDeniedOk := false, false |
| 88 | for lower, upper := time.Duration(0), 2*time.Millisecond; lower <= upper; { |
| 89 | delay := lower + (upper-lower)/2 |
| 90 | cntCanceled, cntPermDenied := runTest(delay) |
| 91 | if cntPermDenied > 0 && cntCanceled > 0 { |
| 92 | // Delay that causes the race is found. |
| 93 | return |
| 94 | } |
nothing calls this directly
no test coverage detected