1
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"
35 _ "google.golang.org/grpc/xds/internal/balancer/cdsbalancer"
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
51
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
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 {
128 return
129 }
130
131
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 }}}
165
View as plain text