google.golang.org/grpc@v1.74.2/balancer/ringhash/config_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 ringhash 20 21 import ( 22 "encoding/json" 23 "testing" 24 25 "github.com/google/go-cmp/cmp" 26 27 "google.golang.org/grpc/internal/envconfig" 28 iringhash "google.golang.org/grpc/internal/ringhash" 29 "google.golang.org/grpc/internal/testutils" 30 ) 31 32 func (s) TestParseConfig(t *testing.T) { 33 tests := []struct { 34 name string 35 js string 36 envConfigCap uint64 37 requestHeaderEnvVar bool 38 want *iringhash.LBConfig 39 wantErr bool 40 }{ 41 { 42 name: "OK", 43 js: `{"minRingSize": 1, "maxRingSize": 2}`, 44 requestHeaderEnvVar: true, 45 want: &iringhash.LBConfig{MinRingSize: 1, MaxRingSize: 2}, 46 }, 47 { 48 name: "OK with default min", 49 js: `{"maxRingSize": 2000}`, 50 requestHeaderEnvVar: true, 51 want: &iringhash.LBConfig{MinRingSize: defaultMinSize, MaxRingSize: 2000}, 52 }, 53 { 54 name: "OK with default max", 55 js: `{"minRingSize": 2000}`, 56 requestHeaderEnvVar: true, 57 want: &iringhash.LBConfig{MinRingSize: 2000, MaxRingSize: defaultMaxSize}, 58 }, 59 { 60 name: "min greater than max", 61 js: `{"minRingSize": 10, "maxRingSize": 2}`, 62 requestHeaderEnvVar: true, 63 want: nil, 64 wantErr: true, 65 }, 66 { 67 name: "min greater than max greater than global limit", 68 js: `{"minRingSize": 6000, "maxRingSize": 5000}`, 69 requestHeaderEnvVar: true, 70 want: nil, 71 wantErr: true, 72 }, 73 { 74 name: "max greater than global limit", 75 js: `{"minRingSize": 1, "maxRingSize": 6000}`, 76 requestHeaderEnvVar: true, 77 want: &iringhash.LBConfig{MinRingSize: 1, MaxRingSize: 4096}, 78 }, 79 { 80 name: "min and max greater than global limit", 81 js: `{"minRingSize": 5000, "maxRingSize": 6000}`, 82 requestHeaderEnvVar: true, 83 want: &iringhash.LBConfig{MinRingSize: 4096, MaxRingSize: 4096}, 84 }, 85 { 86 name: "min and max less than raised global limit", 87 js: `{"minRingSize": 5000, "maxRingSize": 6000}`, 88 envConfigCap: 8000, 89 requestHeaderEnvVar: true, 90 want: &iringhash.LBConfig{MinRingSize: 5000, MaxRingSize: 6000}, 91 }, 92 { 93 name: "min and max greater than raised global limit", 94 js: `{"minRingSize": 10000, "maxRingSize": 10000}`, 95 envConfigCap: 8000, 96 requestHeaderEnvVar: true, 97 want: &iringhash.LBConfig{MinRingSize: 8000, MaxRingSize: 8000}, 98 }, 99 { 100 name: "min greater than upper bound", 101 js: `{"minRingSize": 8388610, "maxRingSize": 10}`, 102 requestHeaderEnvVar: true, 103 want: nil, 104 wantErr: true, 105 }, 106 { 107 name: "max greater than upper bound", 108 js: `{"minRingSize": 10, "maxRingSize": 8388610}`, 109 requestHeaderEnvVar: true, 110 want: nil, 111 wantErr: true, 112 }, 113 { 114 name: "request metadata key set", 115 js: `{"requestHashHeader": "x-foo"}`, 116 requestHeaderEnvVar: true, 117 want: &iringhash.LBConfig{ 118 MinRingSize: defaultMinSize, 119 MaxRingSize: defaultMaxSize, 120 RequestHashHeader: "x-foo", 121 }, 122 }, 123 { 124 name: "request metadata key set with uppercase letters", 125 js: `{"requestHashHeader": "x-FOO"}`, 126 requestHeaderEnvVar: true, 127 want: &iringhash.LBConfig{ 128 MinRingSize: defaultMinSize, 129 MaxRingSize: defaultMaxSize, 130 RequestHashHeader: "x-foo", 131 }, 132 }, 133 { 134 name: "invalid request hash header", 135 js: `{"requestHashHeader": "!invalid"}`, 136 requestHeaderEnvVar: true, 137 want: nil, 138 wantErr: true, 139 }, 140 { 141 name: "binary request hash header", 142 js: `{"requestHashHeader": "header-with-bin"}`, 143 requestHeaderEnvVar: true, 144 want: nil, 145 wantErr: true, 146 }, 147 { 148 name: "request hash header cleared when RingHashSetRequestHashKey env var is false", 149 js: `{"requestHashHeader": "x-foo"}`, 150 requestHeaderEnvVar: false, 151 want: &iringhash.LBConfig{ 152 MinRingSize: defaultMinSize, 153 MaxRingSize: defaultMaxSize, 154 }, 155 }, 156 } 157 for _, tt := range tests { 158 t.Run(tt.name, func(t *testing.T) { 159 if tt.envConfigCap != 0 { 160 testutils.SetEnvConfig(t, &envconfig.RingHashCap, tt.envConfigCap) 161 } 162 testutils.SetEnvConfig(t, &envconfig.RingHashSetRequestHashKey, tt.requestHeaderEnvVar) 163 got, err := parseConfig(json.RawMessage(tt.js)) 164 if (err != nil) != tt.wantErr { 165 t.Errorf("parseConfig() error = %v, wantErr %v", err, tt.wantErr) 166 return 167 } 168 if diff := cmp.Diff(got, tt.want); diff != "" { 169 t.Errorf("parseConfig() got unexpected output, diff (-got +want): %v", diff) 170 } 171 }) 172 } 173 }