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