dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/utils/serviceconfig/serviceconfig_test.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. 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 * 20 * Copyright 2021 gRPC authors. 21 * 22 */ 23 24 package serviceconfig 25 26 import ( 27 "encoding/json" 28 "fmt" 29 "testing" 30 ) 31 32 import ( 33 "github.com/google/go-cmp/cmp" 34 35 "google.golang.org/grpc/balancer" 36 37 externalserviceconfig "google.golang.org/grpc/serviceconfig" 38 ) 39 40 type testBalancerConfigType struct { 41 externalserviceconfig.LoadBalancingConfig `json:"-"` 42 43 Check bool `json:"check"` 44 } 45 46 var testBalancerConfig = testBalancerConfigType{Check: true} 47 48 const ( 49 testBalancerBuilderName = "test-bb" 50 testBalancerBuilderNotParserName = "test-bb-not-parser" 51 52 testBalancerConfigJSON = `{"check":true}` 53 ) 54 55 type testBalancerBuilder struct { 56 balancer.Builder 57 } 58 59 func (testBalancerBuilder) ParseConfig(js json.RawMessage) (externalserviceconfig.LoadBalancingConfig, error) { 60 if string(js) != testBalancerConfigJSON { 61 return nil, fmt.Errorf("unexpected config json") 62 } 63 return testBalancerConfig, nil 64 } 65 66 func (testBalancerBuilder) Name() string { 67 return testBalancerBuilderName 68 } 69 70 type testBalancerBuilderNotParser struct { 71 balancer.Builder 72 } 73 74 func (testBalancerBuilderNotParser) Name() string { 75 return testBalancerBuilderNotParserName 76 } 77 78 func init() { 79 balancer.Register(testBalancerBuilder{}) 80 balancer.Register(testBalancerBuilderNotParser{}) 81 } 82 83 func TestBalancerConfigUnmarshalJSON(t *testing.T) { 84 tests := []struct { 85 name string 86 json string 87 want BalancerConfig 88 wantErr bool 89 }{ 90 { 91 name: "empty json", 92 json: "", 93 wantErr: true, 94 }, 95 { 96 // The config should be a slice of maps, but each map should have 97 // exactly one entry. 98 name: "more than one entry for a map", 99 json: `[{"balancer1":"1","balancer2":"2"}]`, 100 wantErr: true, 101 }, 102 { 103 name: "no balancer registered", 104 json: `[{"balancer1":"1"},{"balancer2":"2"}]`, 105 wantErr: true, 106 }, 107 { 108 name: "OK", 109 json: fmt.Sprintf("[{%q: %v}]", testBalancerBuilderName, testBalancerConfigJSON), 110 want: BalancerConfig{ 111 Name: testBalancerBuilderName, 112 Config: testBalancerConfig, 113 }, 114 wantErr: false, 115 }, 116 { 117 name: "first balancer not registered", 118 json: fmt.Sprintf(`[{"balancer1":"1"},{%q: %v}]`, testBalancerBuilderName, testBalancerConfigJSON), 119 want: BalancerConfig{ 120 Name: testBalancerBuilderName, 121 Config: testBalancerConfig, 122 }, 123 wantErr: false, 124 }, 125 { 126 name: "balancer registered but builder not parser", 127 json: fmt.Sprintf("[{%q: %v}]", testBalancerBuilderNotParserName, testBalancerConfigJSON), 128 want: BalancerConfig{ 129 Name: testBalancerBuilderNotParserName, 130 Config: nil, 131 }, 132 wantErr: false, 133 }, 134 } 135 for _, tt := range tests { 136 t.Run(tt.name, func(t *testing.T) { 137 var bc BalancerConfig 138 if err := bc.UnmarshalJSON([]byte(tt.json)); (err != nil) != tt.wantErr { 139 t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr) 140 } 141 if !cmp.Equal(bc, tt.want) { 142 t.Errorf("diff: %v", cmp.Diff(bc, tt.want)) 143 } 144 }) 145 } 146 } 147 148 func TestBalancerConfigMarshalJSON(t *testing.T) { 149 tests := []struct { 150 name string 151 bc BalancerConfig 152 wantJSON string 153 }{ 154 { 155 name: "OK", 156 bc: BalancerConfig{ 157 Name: testBalancerBuilderName, 158 Config: testBalancerConfig, 159 }, 160 wantJSON: `[{"test-bb": {"check":true}}]`, 161 }, 162 { 163 name: "OK config is nil", 164 bc: BalancerConfig{ 165 Name: testBalancerBuilderNotParserName, 166 Config: nil, // nil should be marshaled to an empty config "{}". 167 }, 168 wantJSON: `[{"test-bb-not-parser": {}}]`, 169 }, 170 } 171 for _, tt := range tests { 172 t.Run(tt.name, func(t *testing.T) { 173 b, err := tt.bc.MarshalJSON() 174 if err != nil { 175 t.Fatalf("failed to marshal: %v", err) 176 } 177 178 if str := string(b); str != tt.wantJSON { 179 t.Fatalf("got str %q, want %q", str, tt.wantJSON) 180 } 181 182 var bc BalancerConfig 183 if err := bc.UnmarshalJSON(b); err != nil { 184 t.Errorf("failed to unmarshal: %v", err) 185 } 186 if !cmp.Equal(bc, tt.bc) { 187 t.Errorf("diff: %v", cmp.Diff(bc, tt.bc)) 188 } 189 }) 190 } 191 }