github.com/cloudwego/kitex@v0.9.0/pkg/rpcinfo/remoteinfo/remoteInfo_test.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package remoteinfo_test 18 19 import ( 20 "sync" 21 "testing" 22 23 "github.com/golang/mock/gomock" 24 25 "github.com/cloudwego/kitex/internal" 26 mocksdiscovery "github.com/cloudwego/kitex/internal/mocks/discovery" 27 "github.com/cloudwego/kitex/internal/test" 28 "github.com/cloudwego/kitex/pkg/discovery" 29 "github.com/cloudwego/kitex/pkg/rpcinfo" 30 "github.com/cloudwego/kitex/pkg/rpcinfo/remoteinfo" 31 "github.com/cloudwego/kitex/pkg/utils" 32 ) 33 34 func TestRemoteInfo(t *testing.T) { 35 test.PanicAt(t, func() { 36 _ = remoteinfo.NewRemoteInfo(nil, "method") 37 }, func(err interface{}) bool { 38 e, ok := err.(error) 39 return ok && e.Error() == "nil basicInfo" 40 }) 41 42 bi := &rpcinfo.EndpointBasicInfo{ 43 ServiceName: "service", 44 Method: "method0", 45 Tags: map[string]string{"a": "b"}, 46 } 47 ri := remoteinfo.NewRemoteInfo(bi, "method1") 48 test.Assert(t, ri != nil) 49 test.Assert(t, ri.ServiceName() == "service") 50 test.Assert(t, ri.Method() == "method1") 51 test.Assert(t, ri.DefaultTag("a", "-") == "b") 52 test.Assert(t, ri.DefaultTag("x", "-") == "-") 53 } 54 55 func TestAsRemoteInfo(t *testing.T) { 56 test.Assert(t, remoteinfo.AsRemoteInfo(nil) == nil) 57 58 ei := rpcinfo.EmptyEndpointInfo() 59 test.Assert(t, remoteinfo.AsRemoteInfo(ei) == nil) 60 61 bi := &rpcinfo.EndpointBasicInfo{ 62 ServiceName: "service", 63 Method: "method0", 64 Tags: map[string]string{"a": "b", "1": "2"}, 65 } 66 ri := remoteinfo.NewRemoteInfo(bi, "method1") 67 ri.SetTagLock("1") 68 test.Assert(t, ri.GetInstance() == nil) 69 70 ei = ri.ImmutableView() 71 ri2 := remoteinfo.AsRemoteInfo(ei) 72 test.Assert(t, ri2 != nil) 73 74 ri2.SetServiceName("service2") 75 test.Assert(t, ri2.SetTag("a", "aa") == nil) 76 test.Assert(t, ri2.SetTag("1", "11") != nil) 77 78 test.Assert(t, ri.ServiceName() == "service2") 79 test.Assert(t, ri.DefaultTag("a", "-") == "aa") 80 test.Assert(t, ri.DefaultTag("1", "-") == "2") 81 test.Assert(t, ri.GetInstance() == nil) 82 test.Assert(t, ri.Address() == nil) 83 84 ins := discovery.NewInstance("n", "a", 1, nil) 85 ri2.SetInstance(ins) 86 test.Assert(t, ri.GetInstance() == ins) 87 na := ri.Address() 88 test.Assert(t, na.Network() == "n" && na.String() == "a") 89 90 _, ok := ins.(remoteinfo.RefreshableInstance) 91 na = utils.NewNetAddr("nnn", "aaa") 92 test.Assert(t, ri2.SetRemoteAddr(na) == ok) 93 if ok { 94 na2 := ri.GetInstance().Address() 95 test.Assert(t, na2 != nil) 96 test.Assert(t, na2.Network() == "nnn", na2.Network(), na2) 97 test.Assert(t, na2.String() == "aaa") 98 } 99 } 100 101 func TestSetTag(t *testing.T) { 102 lockKey := "lock" 103 unlockKey := "unlock" 104 bi := &rpcinfo.EndpointBasicInfo{ 105 ServiceName: "service", 106 Tags: map[string]string{lockKey: "a", unlockKey: "b"}, 107 } 108 ri := remoteinfo.NewRemoteInfo(bi, "method1") 109 110 ri.SetTagLock(lockKey) 111 val, exist := ri.Tag(lockKey) 112 test.Assert(t, val == "a") 113 test.Assert(t, exist) 114 val, exist = ri.Tag(unlockKey) 115 test.Assert(t, val == "b") 116 test.Assert(t, exist) 117 118 // lock key cannot be reset 119 ri.SetTag(lockKey, "aa") 120 val, _ = ri.Tag(lockKey) 121 test.Assert(t, val == "a") 122 123 // lock key still can be reset with ForceSetTag 124 ri.ForceSetTag(lockKey, "aa") 125 val, _ = ri.Tag(lockKey) 126 test.Assert(t, val == "aa") 127 128 // unlock key can be reset 129 ri.SetTag(unlockKey, "bb") 130 val, _ = ri.Tag(unlockKey) 131 test.Assert(t, val == "bb") 132 133 // unlock key can be reset 134 ri.ForceSetTag(unlockKey, "bb") 135 val, _ = ri.Tag(unlockKey) 136 test.Assert(t, val == "bb") 137 } 138 139 func TestGetTag(t *testing.T) { 140 clusterKey, idcKey, myCluster, myIDC, mock := "cluster", "idc", "myCluster", "myIDC", "mock" 141 142 ctrl := gomock.NewController(t) 143 defer ctrl.Finish() 144 inst := mocksdiscovery.NewMockInstance(ctrl) 145 inst.EXPECT().Tag(gomock.Any()).DoAndReturn( 146 func(key string) (string, bool) { 147 switch key { 148 case clusterKey: 149 return myCluster, true 150 case idcKey: 151 return myIDC, true 152 } 153 return "", false 154 }).AnyTimes() 155 156 bi := &rpcinfo.EndpointBasicInfo{ 157 ServiceName: "service", 158 } 159 ri := remoteinfo.NewRemoteInfo(bi, "method1") 160 161 // case1: no cluster and idc 162 valCluster, clusterOk := ri.Tag(clusterKey) 163 valIDC, idcOk := ri.Tag(idcKey) 164 test.Assert(t, !clusterOk) 165 test.Assert(t, valCluster == "", valCluster) 166 test.Assert(t, !idcOk) 167 test.Assert(t, valIDC == "", valIDC) 168 169 // case2: have cluster and idc which value are from tag set 170 ri.SetTag(clusterKey, mock) 171 ri.SetTag(idcKey, mock) 172 valCluster, clusterOk = ri.Tag(clusterKey) 173 valIDC, idcOk = ri.Tag(idcKey) 174 test.Assert(t, clusterOk) 175 test.Assert(t, valCluster == mock, valCluster) 176 test.Assert(t, idcOk) 177 test.Assert(t, valIDC == mock, valIDC) 178 179 // case3: have cluster and idc which value are from instance, the priority of tags from instance is higher than tag set 180 ri.SetInstance(inst) 181 valCluster, clusterOk = ri.Tag(clusterKey) 182 valIDC, idcOk = ri.Tag(idcKey) 183 test.Assert(t, clusterOk) 184 test.Assert(t, valCluster == myCluster, valCluster) 185 test.Assert(t, idcOk) 186 test.Assert(t, valIDC == myIDC, valIDC) 187 } 188 189 func TestRecycleRace(t *testing.T) { 190 ri := remoteinfo.NewRemoteInfo(&rpcinfo.EndpointBasicInfo{ServiceName: "service", Tags: map[string]string{"key1": "val1"}}, "method1") 191 192 // test the data race problem caused by tag modification 193 var wg sync.WaitGroup 194 wg.Add(2) 195 go func() { 196 ri.ForceSetTag("key11", "val11") 197 wg.Done() 198 }() 199 go func() { 200 ri.(internal.Reusable).Recycle() 201 wg.Done() 202 }() 203 wg.Wait() 204 }