123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- /*
- *
- * Copyright 2019 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- package test
- import (
- "context"
- "testing"
- "time"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/metadata"
- "google.golang.org/grpc/status"
- testpb "google.golang.org/grpc/test/grpc_testing"
- )
- func (s) TestContextCanceled(t *testing.T) {
- ss := &stubServer{
- fullDuplexCall: func(stream testpb.TestService_FullDuplexCallServer) error {
- stream.SetTrailer(metadata.New(map[string]string{"a": "b"}))
- return status.Error(codes.PermissionDenied, "perm denied")
- },
- }
- if err := ss.Start(nil); err != nil {
- t.Fatalf("Error starting endpoint server: %v", err)
- }
- defer ss.Stop()
- // Runs 10 rounds of tests with the given delay and returns counts of status codes.
- // Fails in case of trailer/status code inconsistency.
- const cntRetry uint = 10
- runTest := func(delay time.Duration) (cntCanceled, cntPermDenied uint) {
- for i := uint(0); i < cntRetry; i++ {
- ctx, cancel := context.WithTimeout(context.Background(), delay)
- defer cancel()
- str, err := ss.client.FullDuplexCall(ctx)
- if err != nil {
- continue
- }
- _, err = str.Recv()
- if err == nil {
- t.Fatalf("non-nil error expected from Recv()")
- }
- _, trlOk := str.Trailer()["a"]
- switch status.Code(err) {
- case codes.PermissionDenied:
- if !trlOk {
- t.Fatalf(`status err: %v; wanted key "a" in trailer but didn't get it`, err)
- }
- cntPermDenied++
- case codes.DeadlineExceeded:
- if trlOk {
- t.Fatalf(`status err: %v; didn't want key "a" in trailer but got it`, err)
- }
- cntCanceled++
- default:
- t.Fatalf(`unexpected status err: %v`, err)
- }
- }
- return cntCanceled, cntPermDenied
- }
- // Tries to find the delay that causes canceled/perm denied race.
- canceledOk, permDeniedOk := false, false
- for lower, upper := time.Duration(0), 2*time.Millisecond; lower <= upper; {
- delay := lower + (upper-lower)/2
- cntCanceled, cntPermDenied := runTest(delay)
- if cntPermDenied > 0 && cntCanceled > 0 {
- // Delay that causes the race is found.
- return
- }
- // Set OK flags.
- if cntCanceled > 0 {
- canceledOk = true
- }
- if cntPermDenied > 0 {
- permDeniedOk = true
- }
- if cntPermDenied == 0 {
- // No perm denied, increase the delay.
- lower += (upper-lower)/10 + 1
- } else {
- // All perm denied, decrease the delay.
- upper -= (upper-lower)/10 + 1
- }
- }
- if !canceledOk || !permDeniedOk {
- t.Fatalf(`couldn't find the delay that causes canceled/perm denied race.`)
- }
- }
|