snapshot of https://github.com/grpc/grpc-go.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / vet-proto (push) Failing after 1s
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / vet-proto (push) Failing after 1s
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
This commit is contained in:
515
balancer/rls/config_test.go
Normal file
515
balancer/rls/config_test.go
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rls
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
_ "google.golang.org/grpc/balancer/grpclb" // grpclb for config parsing.
|
||||
_ "google.golang.org/grpc/internal/resolver/passthrough" // passthrough resolver.
|
||||
)
|
||||
|
||||
// testEqual reports whether the lbCfgs a and b are equal. This is to be used
|
||||
// only from tests. This ignores the keyBuilderMap field because its internals
|
||||
// are not exported, and hence not possible to specify in the want section of
|
||||
// the test. This is fine because we already have tests to make sure that the
|
||||
// keyBuilder is parsed properly from the service config.
|
||||
func testEqual(a, b *lbConfig) bool {
|
||||
return a.lookupService == b.lookupService &&
|
||||
a.lookupServiceTimeout == b.lookupServiceTimeout &&
|
||||
a.maxAge == b.maxAge &&
|
||||
a.staleAge == b.staleAge &&
|
||||
a.cacheSizeBytes == b.cacheSizeBytes &&
|
||||
a.defaultTarget == b.defaultTarget &&
|
||||
a.controlChannelServiceConfig == b.controlChannelServiceConfig &&
|
||||
a.childPolicyName == b.childPolicyName &&
|
||||
a.childPolicyTargetField == b.childPolicyTargetField &&
|
||||
childPolicyConfigEqual(a.childPolicyConfig, b.childPolicyConfig)
|
||||
}
|
||||
|
||||
// TestParseConfig verifies successful config parsing scenarios.
|
||||
func (s) TestParseConfig(t *testing.T) {
|
||||
childPolicyTargetFieldVal, _ := json.Marshal(dummyChildPolicyTarget)
|
||||
tests := []struct {
|
||||
desc string
|
||||
input []byte
|
||||
wantCfg *lbConfig
|
||||
}{
|
||||
{
|
||||
// This input validates a few cases:
|
||||
// - A top-level unknown field should not fail.
|
||||
// - An unknown field in routeLookupConfig proto should not fail.
|
||||
// - lookupServiceTimeout is set to its default value, since it is not specified in the input.
|
||||
// - maxAge is clamped to maxMaxAge if staleAge is not set.
|
||||
// - staleAge is ignored because it is higher than maxAge in the input.
|
||||
// - cacheSizeBytes is greater than the hard upper limit of 5MB
|
||||
desc: "with transformations 1",
|
||||
input: []byte(`{
|
||||
"top-level-unknown-field": "unknown-value",
|
||||
"routeLookupConfig": {
|
||||
"unknown-field": "unknown-value",
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": ":///target",
|
||||
"maxAge" : "500s",
|
||||
"staleAge": "600s",
|
||||
"cacheSizeBytes": 100000000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicy": [
|
||||
{"cds_experimental": {"Cluster": "my-fav-cluster"}},
|
||||
{"unknown-policy": {"unknown-field": "unknown-value"}},
|
||||
{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}
|
||||
],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantCfg: &lbConfig{
|
||||
lookupService: ":///target",
|
||||
lookupServiceTimeout: 10 * time.Second, // This is the default value.
|
||||
maxAge: 500 * time.Second, // Max age is not clamped when stale age is set.
|
||||
staleAge: 300 * time.Second, // StaleAge is clamped because it was higher than maxMaxAge.
|
||||
cacheSizeBytes: maxCacheSize,
|
||||
defaultTarget: "passthrough:///default",
|
||||
childPolicyName: "grpclb",
|
||||
childPolicyTargetField: "serviceName",
|
||||
childPolicyConfig: map[string]json.RawMessage{
|
||||
"childPolicy": json.RawMessage(`[{"pickfirst": {}}]`),
|
||||
"serviceName": json.RawMessage(childPolicyTargetFieldVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "maxAge not clamped when staleAge is set",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": ":///target",
|
||||
"maxAge" : "500s",
|
||||
"staleAge": "200s",
|
||||
"cacheSizeBytes": 100000000
|
||||
},
|
||||
"childPolicy": [
|
||||
{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}
|
||||
],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantCfg: &lbConfig{
|
||||
lookupService: ":///target",
|
||||
lookupServiceTimeout: 10 * time.Second, // This is the default value.
|
||||
maxAge: 500 * time.Second, // Max age is not clamped when stale age is set.
|
||||
staleAge: 200 * time.Second, // This is stale age within maxMaxAge.
|
||||
cacheSizeBytes: maxCacheSize,
|
||||
childPolicyName: "grpclb",
|
||||
childPolicyTargetField: "serviceName",
|
||||
childPolicyConfig: map[string]json.RawMessage{
|
||||
"childPolicy": json.RawMessage(`[{"pickfirst": {}}]`),
|
||||
"serviceName": json.RawMessage(childPolicyTargetFieldVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "maxAge clamped when staleAge is not set",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": ":///target",
|
||||
"maxAge" : "500s",
|
||||
"cacheSizeBytes": 100000000
|
||||
},
|
||||
"childPolicy": [
|
||||
{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}
|
||||
],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantCfg: &lbConfig{
|
||||
lookupService: ":///target",
|
||||
lookupServiceTimeout: 10 * time.Second, // This is the default value.
|
||||
maxAge: 300 * time.Second, // Max age is clamped when stale age is not set.
|
||||
staleAge: 300 * time.Second,
|
||||
cacheSizeBytes: maxCacheSize,
|
||||
childPolicyName: "grpclb",
|
||||
childPolicyTargetField: "serviceName",
|
||||
childPolicyConfig: map[string]json.RawMessage{
|
||||
"childPolicy": json.RawMessage(`[{"pickfirst": {}}]`),
|
||||
"serviceName": json.RawMessage(childPolicyTargetFieldVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "without transformations",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "target",
|
||||
"lookupServiceTimeout" : "100s",
|
||||
"maxAge": "60s",
|
||||
"staleAge" : "50s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"routeLookupChannelServiceConfig": {"loadBalancingConfig": [{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}]},
|
||||
"childPolicy": [{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantCfg: &lbConfig{
|
||||
lookupService: "target",
|
||||
lookupServiceTimeout: 100 * time.Second,
|
||||
maxAge: 60 * time.Second,
|
||||
staleAge: 50 * time.Second,
|
||||
cacheSizeBytes: 1000,
|
||||
defaultTarget: "passthrough:///default",
|
||||
controlChannelServiceConfig: `{"loadBalancingConfig": [{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}]}`,
|
||||
childPolicyName: "grpclb",
|
||||
childPolicyTargetField: "serviceName",
|
||||
childPolicyConfig: map[string]json.RawMessage{
|
||||
"childPolicy": json.RawMessage(`[{"pickfirst": {}}]`),
|
||||
"serviceName": json.RawMessage(childPolicyTargetFieldVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
builder := rlsBB{}
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
lbCfg, err := builder.ParseConfig(test.input)
|
||||
if err != nil || !testEqual(lbCfg.(*lbConfig), test.wantCfg) {
|
||||
t.Errorf("ParseConfig(%s) = {%+v, %v}, want {%+v, nil}", string(test.input), lbCfg, err, test.wantCfg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseConfigErrors verifies config parsing failure scenarios.
|
||||
func (s) TestParseConfigErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
input []byte
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
desc: "empty input",
|
||||
input: nil,
|
||||
wantErr: "rls: json unmarshal failed for service config",
|
||||
},
|
||||
{
|
||||
desc: "bad json",
|
||||
input: []byte(`bad bad json`),
|
||||
wantErr: "rls: json unmarshal failed for service config",
|
||||
},
|
||||
{
|
||||
desc: "bad grpcKeyBuilder",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "requiredMatch": true, "names": ["v1"]}]
|
||||
}]
|
||||
}
|
||||
}`),
|
||||
wantErr: "rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set",
|
||||
},
|
||||
{
|
||||
desc: "empty lookup service",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}]
|
||||
}
|
||||
}`),
|
||||
wantErr: "rls: empty lookup_service in route lookup config",
|
||||
},
|
||||
{
|
||||
desc: "unregistered scheme in lookup service URI",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "badScheme:///target"
|
||||
}
|
||||
}`),
|
||||
wantErr: "rls: unregistered scheme in lookup_service",
|
||||
},
|
||||
{
|
||||
desc: "invalid lookup service timeout",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "315576000001s"
|
||||
}
|
||||
}`),
|
||||
wantErr: "google.protobuf.Duration value out of range",
|
||||
},
|
||||
{
|
||||
desc: "invalid max age",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge" : "315576000001s"
|
||||
}
|
||||
}`),
|
||||
wantErr: "google.protobuf.Duration value out of range",
|
||||
},
|
||||
{
|
||||
desc: "invalid stale age",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge" : "10s",
|
||||
"staleAge" : "315576000001s"
|
||||
}
|
||||
}`),
|
||||
wantErr: "google.protobuf.Duration value out of range",
|
||||
},
|
||||
{
|
||||
desc: "invalid max age stale age combo",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"staleAge" : "10s"
|
||||
}
|
||||
}`),
|
||||
wantErr: "rls: stale_age is set, but max_age is not in route lookup config",
|
||||
},
|
||||
{
|
||||
desc: "cache_size_bytes field is not set",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge": "30s",
|
||||
"staleAge" : "25s",
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "rls: cache_size_bytes must be set to a non-zero value",
|
||||
},
|
||||
{
|
||||
desc: "routeLookupChannelServiceConfig is not in service config format",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "target",
|
||||
"lookupServiceTimeout" : "100s",
|
||||
"maxAge": "60s",
|
||||
"staleAge" : "50s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"routeLookupChannelServiceConfig": "unknown",
|
||||
"childPolicy": [{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "cannot unmarshal string into Go value of type grpc.jsonSC",
|
||||
},
|
||||
{
|
||||
desc: "routeLookupChannelServiceConfig contains unknown LB policy",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "target",
|
||||
"lookupServiceTimeout" : "100s",
|
||||
"maxAge": "60s",
|
||||
"staleAge" : "50s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"routeLookupChannelServiceConfig": {
|
||||
"loadBalancingConfig": [{"not_a_balancer1": {} }, {"not_a_balancer2": {}}]
|
||||
},
|
||||
"childPolicy": [{"grpclb": {"childPolicy": [{"pickfirst": {}}]}}],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "no supported policies found in config",
|
||||
},
|
||||
{
|
||||
desc: "no child policy",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge": "30s",
|
||||
"staleAge" : "25s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "rls: invalid childPolicy config: no supported policies found",
|
||||
},
|
||||
{
|
||||
desc: "no known child policy",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge": "30s",
|
||||
"staleAge" : "25s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicy": [
|
||||
{"cds_experimental": {"Cluster": "my-fav-cluster"}},
|
||||
{"unknown-policy": {"unknown-field": "unknown-value"}}
|
||||
],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "rls: invalid childPolicy config: no supported policies found",
|
||||
},
|
||||
{
|
||||
desc: "invalid child policy config - more than one entry in map",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge": "30s",
|
||||
"staleAge" : "25s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicy": [
|
||||
{
|
||||
"cds_experimental": {"Cluster": "my-fav-cluster"},
|
||||
"unknown-policy": {"unknown-field": "unknown-value"}
|
||||
}
|
||||
],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "does not contain exactly 1 policy/config pair",
|
||||
},
|
||||
{
|
||||
desc: "no childPolicyConfigTargetFieldName",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge": "30s",
|
||||
"staleAge" : "25s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicy": [
|
||||
{"cds_experimental": {"Cluster": "my-fav-cluster"}},
|
||||
{"unknown-policy": {"unknown-field": "unknown-value"}},
|
||||
{"grpclb": {}}
|
||||
]
|
||||
}`),
|
||||
wantErr: "rls: childPolicyConfigTargetFieldName field is not set in service config",
|
||||
},
|
||||
{
|
||||
desc: "child policy config validation failure",
|
||||
input: []byte(`{
|
||||
"routeLookupConfig": {
|
||||
"grpcKeybuilders": [{
|
||||
"names": [{"service": "service", "method": "method"}],
|
||||
"headers": [{"key": "k1", "names": ["v1"]}]
|
||||
}],
|
||||
"lookupService": "passthrough:///target",
|
||||
"lookupServiceTimeout" : "10s",
|
||||
"maxAge": "30s",
|
||||
"staleAge" : "25s",
|
||||
"cacheSizeBytes": 1000,
|
||||
"defaultTarget": "passthrough:///default"
|
||||
},
|
||||
"childPolicy": [
|
||||
{"cds_experimental": {"Cluster": "my-fav-cluster"}},
|
||||
{"unknown-policy": {"unknown-field": "unknown-value"}},
|
||||
{"grpclb": {"childPolicy": "not-an-array"}}
|
||||
],
|
||||
"childPolicyConfigTargetFieldName": "serviceName"
|
||||
}`),
|
||||
wantErr: "rls: childPolicy config validation failed",
|
||||
},
|
||||
}
|
||||
|
||||
builder := rlsBB{}
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
lbCfg, err := builder.ParseConfig(test.input)
|
||||
if lbCfg != nil || !strings.Contains(fmt.Sprint(err), test.wantErr) {
|
||||
t.Errorf("ParseConfig(%s) = {%+v, %v}, want {nil, %s}", string(test.input), lbCfg, err, test.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user