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.
 
 
 

181 lines
5.3 KiB

  1. // Copyright 2017 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package trace
  15. import (
  16. "context"
  17. "io/ioutil"
  18. "log"
  19. "net"
  20. "net/http"
  21. "strings"
  22. "testing"
  23. pb "cloud.google.com/go/trace/testdata/helloworld"
  24. "google.golang.org/grpc"
  25. )
  26. func TestGRPCInterceptors(t *testing.T) {
  27. t.Skip("hangs forever for go < 1.9")
  28. tc := newTestClient(&noopTransport{})
  29. // default sampling with global=1.
  30. parent := tc.SpanFromHeader("parent", "7f27601f17b7a2873739efd18ff83872/123;o=1")
  31. testGRPCInterceptor(t, tc, parent, func(t *testing.T, out, in *Span) {
  32. if in == nil {
  33. t.Fatalf("missing span in the incoming context")
  34. }
  35. if got, want := in.TraceID(), out.TraceID(); got != want {
  36. t.Errorf("incoming call is not tracing the outgoing trace; TraceID = %q; want %q", got, want)
  37. }
  38. if !in.Traced() {
  39. t.Errorf("incoming span is not traced; want traced")
  40. }
  41. })
  42. // default sampling with global=0.
  43. parent = tc.SpanFromHeader("parent", "7f27601f17b7a2873739efd18ff83872/123;o=0")
  44. testGRPCInterceptor(t, tc, parent, func(t *testing.T, out, in *Span) {
  45. if in == nil {
  46. t.Fatalf("missing span in the incoming context")
  47. }
  48. if got, want := in.TraceID(), out.TraceID(); got != want {
  49. t.Errorf("incoming call is not tracing the outgoing trace; TraceID = %q; want %q", got, want)
  50. }
  51. if in.Traced() {
  52. t.Errorf("incoming span is traced; want not traced")
  53. }
  54. })
  55. // sampling all with global=1.
  56. all, _ := NewLimitedSampler(1.0, 1<<32)
  57. tc.SetSamplingPolicy(all)
  58. parent = tc.SpanFromHeader("parent", "7f27601f17b7a2873739efd18ff83872/123;o=1")
  59. testGRPCInterceptor(t, tc, parent, func(t *testing.T, out, in *Span) {
  60. if in == nil {
  61. t.Fatalf("missing span in the incoming context")
  62. }
  63. if got, want := in.TraceID(), out.TraceID(); got != want {
  64. t.Errorf("incoming call is not tracing the outgoing trace; TraceID = %q; want %q", got, want)
  65. }
  66. if !in.Traced() {
  67. t.Errorf("incoming span is not traced; want traced")
  68. }
  69. })
  70. // sampling none with global=1.
  71. none, _ := NewLimitedSampler(0, 0)
  72. tc.SetSamplingPolicy(none)
  73. parent = tc.SpanFromHeader("parent", "7f27601f17b7a2873739efd18ff83872/123;o=1")
  74. testGRPCInterceptor(t, tc, parent, func(t *testing.T, out, in *Span) {
  75. if in == nil {
  76. t.Fatalf("missing span in the incoming context")
  77. }
  78. if got, want := in.TraceID(), out.TraceID(); got != want {
  79. t.Errorf("incoming call is not tracing the outgoing trace; TraceID = %q; want %q", got, want)
  80. }
  81. if in.Traced() {
  82. t.Errorf("incoming span is traced; want not traced")
  83. }
  84. })
  85. // sampling all with no parent span.
  86. tc.SetSamplingPolicy(all)
  87. testGRPCInterceptor(t, tc, nil, func(t *testing.T, out, in *Span) {
  88. if in == nil {
  89. t.Fatalf("missing span in the incoming context")
  90. }
  91. if in.TraceID() == "" {
  92. t.Errorf("incoming call TraceID is empty")
  93. }
  94. if !in.Traced() {
  95. t.Errorf("incoming span is not traced; want traced")
  96. }
  97. })
  98. // sampling none with no parent span.
  99. tc.SetSamplingPolicy(none)
  100. testGRPCInterceptor(t, tc, nil, func(t *testing.T, out, in *Span) {
  101. if in == nil {
  102. t.Fatalf("missing span in the incoming context")
  103. }
  104. if in.TraceID() == "" {
  105. t.Errorf("incoming call TraceID is empty")
  106. }
  107. if in.Traced() {
  108. t.Errorf("incoming span is traced; want not traced")
  109. }
  110. })
  111. }
  112. func testGRPCInterceptor(t *testing.T, tc *Client, parent *Span, assert func(t *testing.T, out, in *Span)) {
  113. incomingCh := make(chan *Span, 1)
  114. addrCh := make(chan net.Addr, 1)
  115. go func() {
  116. lis, err := net.Listen("tcp", "")
  117. if err != nil {
  118. t.Errorf("Failed to listen: %v", err)
  119. }
  120. addrCh <- lis.Addr()
  121. s := grpc.NewServer(grpc.UnaryInterceptor(tc.GRPCServerInterceptor()))
  122. pb.RegisterGreeterServer(s, &grpcServer{
  123. fn: func(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
  124. incomingCh <- FromContext(ctx)
  125. return &pb.HelloReply{}, nil
  126. },
  127. })
  128. if err := s.Serve(lis); err != nil {
  129. t.Errorf("Failed to serve: %v", err)
  130. }
  131. }()
  132. addr := <-addrCh
  133. conn, err := grpc.Dial(addr.String(), grpc.WithInsecure(), grpc.WithBlock(), grpc.WithUnaryInterceptor(tc.GRPCClientInterceptor()))
  134. if err != nil {
  135. t.Fatalf("Did not connect: %v", err)
  136. }
  137. defer conn.Close()
  138. c := pb.NewGreeterClient(conn)
  139. outgoingCtx := NewContext(context.Background(), parent)
  140. _, err = c.SayHello(outgoingCtx, &pb.HelloRequest{})
  141. if err != nil {
  142. log.Fatalf("Could not SayHello: %v", err)
  143. }
  144. assert(t, parent, <-incomingCh)
  145. }
  146. type noopTransport struct{}
  147. func (rt *noopTransport) RoundTrip(req *http.Request) (*http.Response, error) {
  148. resp := &http.Response{
  149. Status: "200 OK",
  150. StatusCode: 200,
  151. Body: ioutil.NopCloser(strings.NewReader("{}")),
  152. }
  153. return resp, nil
  154. }
  155. type grpcServer struct {
  156. fn func(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error)
  157. }
  158. func (s *grpcServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
  159. return s.fn(ctx, in)
  160. }