google.golang.org/grpc@v1.62.1/xds/internal/clusterspecifier/rls/rls_test.go (about) 1 /* 2 * 3 * Copyright 2021 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 19 package rls 20 21 import ( 22 "encoding/json" 23 "testing" 24 25 "github.com/google/go-cmp/cmp" 26 "github.com/google/go-cmp/cmp/cmpopts" 27 "google.golang.org/grpc/internal/grpctest" 28 rlspb "google.golang.org/grpc/internal/proto/grpc_lookup_v1" 29 "google.golang.org/grpc/internal/testutils" 30 "google.golang.org/grpc/xds/internal/clusterspecifier" 31 "google.golang.org/protobuf/proto" 32 "google.golang.org/protobuf/types/known/durationpb" 33 34 _ "google.golang.org/grpc/balancer/rls" // Register the RLS LB policy. 35 _ "google.golang.org/grpc/xds/internal/balancer/cdsbalancer" // Register the CDS LB policy. 36 ) 37 38 func init() { 39 clusterspecifier.Register(rls{}) 40 } 41 42 type s struct { 43 grpctest.Tester 44 } 45 46 func Test(t *testing.T) { 47 grpctest.RunSubTests(t, s{}) 48 } 49 50 // TestParseClusterSpecifierConfig tests the parsing functionality of the RLS 51 // Cluster Specifier Plugin. 52 func (s) TestParseClusterSpecifierConfig(t *testing.T) { 53 tests := []struct { 54 name string 55 rlcs proto.Message 56 wantConfig clusterspecifier.BalancerConfig 57 wantErr bool 58 }{ 59 { 60 61 // This will error because the required_match field is set in grpc key builder 62 name: "invalid-rls-cluster-specifier", 63 rlcs: testutils.MarshalAny(t, &rlspb.RouteLookupClusterSpecifier{ 64 RouteLookupConfig: &rlspb.RouteLookupConfig{ 65 GrpcKeybuilders: []*rlspb.GrpcKeyBuilder{ 66 { 67 Names: []*rlspb.GrpcKeyBuilder_Name{ 68 { 69 Service: "service", 70 Method: "method", 71 }, 72 }, 73 Headers: []*rlspb.NameMatcher{ 74 { 75 Key: "k1", 76 RequiredMatch: true, 77 Names: []string{"v1"}, 78 }, 79 }, 80 }, 81 }, 82 }, 83 }), 84 wantErr: true, 85 }, 86 { 87 name: "valid-rls-cluster-specifier", 88 rlcs: testutils.MarshalAny(t, &rlspb.RouteLookupClusterSpecifier{ 89 RouteLookupConfig: &rlspb.RouteLookupConfig{ 90 GrpcKeybuilders: []*rlspb.GrpcKeyBuilder{ 91 { 92 Names: []*rlspb.GrpcKeyBuilder_Name{ 93 { 94 Service: "service", 95 Method: "method", 96 }, 97 }, 98 Headers: []*rlspb.NameMatcher{ 99 { 100 Key: "k1", 101 Names: []string{"v1"}, 102 }, 103 }, 104 }, 105 }, 106 LookupService: "target", 107 LookupServiceTimeout: &durationpb.Duration{Seconds: 100}, 108 MaxAge: &durationpb.Duration{Seconds: 60}, 109 StaleAge: &durationpb.Duration{Seconds: 50}, 110 CacheSizeBytes: 1000, 111 DefaultTarget: "passthrough:///default", 112 }, 113 }), 114 wantConfig: configWithoutTransformationsWant, 115 }, 116 } 117 for _, test := range tests { 118 cs := clusterspecifier.Get("type.googleapis.com/grpc.lookup.v1.RouteLookupClusterSpecifier") 119 if cs == nil { 120 t.Fatal("Error getting cluster specifier") 121 } 122 lbCfg, err := cs.ParseClusterSpecifierConfig(test.rlcs) 123 124 if (err != nil) != test.wantErr { 125 t.Fatalf("ParseClusterSpecifierConfig(%+v) returned err: %v, wantErr: %v", test.rlcs, err, test.wantErr) 126 } 127 if test.wantErr { // Successfully received an error. 128 return 129 } 130 // Marshal and then unmarshal into any to get rid of nondeterministic 131 // protojson Marshaling. 132 lbCfgJSON, err := json.Marshal(lbCfg) 133 if err != nil { 134 t.Fatalf("json.Marshal(%+v) returned err %v", lbCfg, err) 135 } 136 var got any 137 err = json.Unmarshal(lbCfgJSON, got) 138 if err != nil { 139 t.Fatalf("json.Unmarshal(%+v) returned err %v", lbCfgJSON, err) 140 } 141 wantCfgJSON, err := json.Marshal(test.wantConfig) 142 if err != nil { 143 t.Fatalf("json.Marshal(%+v) returned err %v", test.wantConfig, err) 144 } 145 var want any 146 err = json.Unmarshal(wantCfgJSON, want) 147 if err != nil { 148 t.Fatalf("json.Unmarshal(%+v) returned err %v", lbCfgJSON, err) 149 } 150 if diff := cmp.Diff(want, got, cmpopts.EquateEmpty()); diff != "" { 151 t.Fatalf("ParseClusterSpecifierConfig(%+v) returned expected, diff (-want +got) %v", test.rlcs, diff) 152 } 153 } 154 } 155 156 var configWithoutTransformationsWant = clusterspecifier.BalancerConfig{{"rls_experimental": &lbConfigJSON{ 157 RouteLookupConfig: []byte(`{"grpcKeybuilders":[{"names":[{"service":"service","method":"method"}],"headers":[{"key":"k1","names":["v1"]}]}],"lookupService":"target","lookupServiceTimeout":"100s","maxAge":"60s","staleAge":"50s","cacheSizeBytes":"1000","defaultTarget":"passthrough:///default"}`), 158 ChildPolicy: []map[string]json.RawMessage{ 159 { 160 "cds_experimental": []byte(`{}`), 161 }, 162 }, 163 ChildPolicyConfigTargetFieldName: "cluster", 164 }}}