You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

112 lines
3.0 KiB

  1. /*
  2. *
  3. * Copyright 2019 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package test
  19. import (
  20. "context"
  21. "testing"
  22. "time"
  23. "google.golang.org/grpc/codes"
  24. "google.golang.org/grpc/metadata"
  25. "google.golang.org/grpc/status"
  26. testpb "google.golang.org/grpc/test/grpc_testing"
  27. )
  28. func (s) TestContextCanceled(t *testing.T) {
  29. ss := &stubServer{
  30. fullDuplexCall: func(stream testpb.TestService_FullDuplexCallServer) error {
  31. stream.SetTrailer(metadata.New(map[string]string{"a": "b"}))
  32. return status.Error(codes.PermissionDenied, "perm denied")
  33. },
  34. }
  35. if err := ss.Start(nil); err != nil {
  36. t.Fatalf("Error starting endpoint server: %v", err)
  37. }
  38. defer ss.Stop()
  39. // Runs 10 rounds of tests with the given delay and returns counts of status codes.
  40. // Fails in case of trailer/status code inconsistency.
  41. const cntRetry uint = 10
  42. runTest := func(delay time.Duration) (cntCanceled, cntPermDenied uint) {
  43. for i := uint(0); i < cntRetry; i++ {
  44. ctx, cancel := context.WithTimeout(context.Background(), delay)
  45. defer cancel()
  46. str, err := ss.client.FullDuplexCall(ctx)
  47. if err != nil {
  48. continue
  49. }
  50. _, err = str.Recv()
  51. if err == nil {
  52. t.Fatalf("non-nil error expected from Recv()")
  53. }
  54. _, trlOk := str.Trailer()["a"]
  55. switch status.Code(err) {
  56. case codes.PermissionDenied:
  57. if !trlOk {
  58. t.Fatalf(`status err: %v; wanted key "a" in trailer but didn't get it`, err)
  59. }
  60. cntPermDenied++
  61. case codes.DeadlineExceeded:
  62. if trlOk {
  63. t.Fatalf(`status err: %v; didn't want key "a" in trailer but got it`, err)
  64. }
  65. cntCanceled++
  66. default:
  67. t.Fatalf(`unexpected status err: %v`, err)
  68. }
  69. }
  70. return cntCanceled, cntPermDenied
  71. }
  72. // Tries to find the delay that causes canceled/perm denied race.
  73. canceledOk, permDeniedOk := false, false
  74. for lower, upper := time.Duration(0), 2*time.Millisecond; lower <= upper; {
  75. delay := lower + (upper-lower)/2
  76. cntCanceled, cntPermDenied := runTest(delay)
  77. if cntPermDenied > 0 && cntCanceled > 0 {
  78. // Delay that causes the race is found.
  79. return
  80. }
  81. // Set OK flags.
  82. if cntCanceled > 0 {
  83. canceledOk = true
  84. }
  85. if cntPermDenied > 0 {
  86. permDeniedOk = true
  87. }
  88. if cntPermDenied == 0 {
  89. // No perm denied, increase the delay.
  90. lower += (upper-lower)/10 + 1
  91. } else {
  92. // All perm denied, decrease the delay.
  93. upper -= (upper-lower)/10 + 1
  94. }
  95. }
  96. if !canceledOk || !permDeniedOk {
  97. t.Fatalf(`couldn't find the delay that causes canceled/perm denied race.`)
  98. }
  99. }