custom_lb_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. *
  3. * Copyright 2023 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 xds
  19. import (
  20. "context"
  21. "errors"
  22. "fmt"
  23. "testing"
  24. "time"
  25. "google.golang.org/grpc"
  26. "google.golang.org/grpc/credentials/insecure"
  27. "google.golang.org/grpc/internal"
  28. "google.golang.org/grpc/internal/grpctest"
  29. "google.golang.org/grpc/internal/stubserver"
  30. "google.golang.org/grpc/internal/testutils"
  31. testgrpc "google.golang.org/grpc/interop/grpc_testing"
  32. testpb "google.golang.org/grpc/interop/grpc_testing"
  33. "google.golang.org/grpc/metadata"
  34. "google.golang.org/grpc/resolver"
  35. "google.golang.org/grpc/resolver/manual"
  36. "google.golang.org/grpc/serviceconfig"
  37. )
  38. var defaultTestTimeout = 5 * time.Second
  39. type s struct {
  40. grpctest.Tester
  41. }
  42. func Test(t *testing.T) {
  43. grpctest.RunSubTests(t, s{})
  44. }
  45. // TestCustomLB tests the Custom LB for the interop client. It configures the
  46. // custom lb as the top level Load Balancing policy of the channel, then asserts
  47. // it can successfully make an RPC and also that the rpc behavior the Custom LB
  48. // is configured with makes it's way to the server in metadata.
  49. func (s) TestCustomLB(t *testing.T) {
  50. errCh := testutils.NewChannel()
  51. // Setup a backend which verifies the expected rpc-behavior metadata is
  52. // present in the request.
  53. backend := &stubserver.StubServer{
  54. UnaryCallF: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
  55. md, ok := metadata.FromIncomingContext(ctx)
  56. if !ok {
  57. errCh.Send(errors.New("failed to receive metadata"))
  58. return &testpb.SimpleResponse{}, nil
  59. }
  60. rpcBMD := md.Get("rpc-behavior")
  61. if len(rpcBMD) != 1 {
  62. errCh.Send(errors.New("only one value received for metadata key rpc-behavior"))
  63. return &testpb.SimpleResponse{}, nil
  64. }
  65. wantVal := "error-code-0"
  66. if rpcBMD[0] != wantVal {
  67. errCh.Send(fmt.Errorf("metadata val for key \"rpc-behavior\": got val %v, want val %v", rpcBMD[0], wantVal))
  68. return &testpb.SimpleResponse{}, nil
  69. }
  70. // Success.
  71. errCh.Send(nil)
  72. return &testpb.SimpleResponse{}, nil
  73. },
  74. }
  75. if err := backend.StartServer(); err != nil {
  76. t.Fatalf("Failed to start backend: %v", err)
  77. }
  78. t.Logf("Started good TestService backend at: %q", backend.Address)
  79. defer backend.Stop()
  80. lbCfgJSON := `{
  81. "loadBalancingConfig": [
  82. {
  83. "test.RpcBehaviorLoadBalancer": {
  84. "rpcBehavior": "error-code-0"
  85. }
  86. }
  87. ]
  88. }`
  89. sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lbCfgJSON)
  90. mr := manual.NewBuilderWithScheme("customlb-e2e")
  91. defer mr.Close()
  92. mr.InitialState(resolver.State{
  93. Addresses: []resolver.Address{
  94. {Addr: backend.Address},
  95. },
  96. ServiceConfig: sc,
  97. })
  98. cc, err := grpc.Dial(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
  99. if err != nil {
  100. t.Fatalf("grpc.Dial() failed: %v", err)
  101. }
  102. defer cc.Close()
  103. ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  104. defer cancel()
  105. testServiceClient := testgrpc.NewTestServiceClient(cc)
  106. // Make a Unary RPC. This RPC should be successful due to the round_robin
  107. // leaf balancer. Also, the custom load balancer should inject the
  108. // "rpc-behavior" string it is configured with into the metadata sent to
  109. // server.
  110. if _, err := testServiceClient.UnaryCall(ctx, &testpb.SimpleRequest{}); err != nil {
  111. t.Fatalf("EmptyCall() failed: %v", err)
  112. }
  113. val, err := errCh.Receive(ctx)
  114. if err != nil {
  115. t.Fatalf("error receiving from errCh: %v", err)
  116. }
  117. // Should receive nil on the error channel which implies backend verified it
  118. // correctly received the correct "rpc-behavior" metadata.
  119. if err, ok := val.(error); ok {
  120. t.Fatalf("error in backend verifications on metadata received: %v", err)
  121. }
  122. }