github.com/polarismesh/polaris@v1.17.8/cache/service/circuitbreaker_test.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package service 19 20 import ( 21 "fmt" 22 "testing" 23 "time" 24 25 "github.com/golang/mock/gomock" 26 27 "github.com/polarismesh/polaris/common/model" 28 "github.com/polarismesh/polaris/store/mock" 29 ) 30 31 /** 32 * @brief 创建一个测试mock circuitBreakerCache 33 */ 34 func newTestCircuitBreakerCache(t *testing.T) (*gomock.Controller, *mock.MockStore, *circuitBreakerCache) { 35 ctl := gomock.NewController(t) 36 37 storage := mock.NewMockStore(ctl) 38 rlc := NewCircuitBreakerCache(storage, nil) 39 storage.EXPECT().GetUnixSecond(gomock.Any()).AnyTimes().Return(time.Now().Unix(), nil) 40 var opt map[string]interface{} 41 _ = rlc.Initialize(opt) 42 return ctl, storage, rlc.(*circuitBreakerCache) 43 } 44 45 /** 46 * @brief 生成熔断规则测试数据 47 */ 48 func genModelCircuitBreakers(beginNum, total int) []*model.CircuitBreakerRule { 49 out := make([]*model.CircuitBreakerRule, 0, total) 50 51 for i := beginNum; i < total+beginNum; i++ { 52 item := &model.CircuitBreakerRule{ 53 ID: fmt.Sprintf("id-%d", i), 54 Name: fmt.Sprintf("rule-%d", i), 55 DstService: fmt.Sprintf("svc-%d", i), 56 DstNamespace: "test", 57 Valid: true, 58 ModifyTime: time.Unix(int64(i), 0), 59 } 60 out = append(out, item) 61 } 62 return out 63 } 64 65 /** 66 * @brief 统计缓存中的熔断数据 67 */ 68 func getCircuitBreakerCount(cbc *circuitBreakerCache) int { 69 return cbc.GetCircuitBreakerCount() 70 } 71 72 /** 73 * TestCircuitBreakersUpdate 生成熔断规则测试数据 74 */ 75 func TestCircuitBreakersUpdate(t *testing.T) { 76 ctl, storage, cbc := newTestCircuitBreakerCache(t) 77 defer ctl.Finish() 78 79 total := 10 80 serviceWithCircuitBreakers := genModelCircuitBreakers(0, total) 81 82 t.Run("正常更新缓存,可以获取到数据", func(t *testing.T) { 83 _ = cbc.Clear() 84 85 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 86 Return(serviceWithCircuitBreakers, nil) 87 if err := cbc.Update(); err != nil { 88 t.Fatalf("error: %s", err.Error()) 89 } 90 91 // 检查数目是否一致 92 if getCircuitBreakerCount(cbc) == total { 93 t.Log("pass") 94 } else { 95 t.Fatalf("actual count is %d", getCircuitBreakerCount(cbc)) 96 } 97 }) 98 99 t.Run("缓存数据为空", func(t *testing.T) { 100 _ = cbc.Clear() 101 102 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 103 Return(nil, nil) 104 if err := cbc.Update(); err != nil { 105 t.Fatalf("error: %s", err.Error()) 106 } 107 108 if getCircuitBreakerCount(cbc) == 0 { 109 t.Log("pass") 110 } else { 111 t.Fatalf("actual count is %d", getCircuitBreakerCount(cbc)) 112 } 113 }) 114 115 t.Run("lastMtime正确更新", func(t *testing.T) { 116 _ = cbc.Clear() 117 118 currentTime := time.Now() 119 serviceWithCircuitBreakers[0].ModifyTime = currentTime 120 storage.EXPECT().GetUnixSecond(gomock.Any()).Return(currentTime.Unix(), nil).AnyTimes() 121 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 122 Return(serviceWithCircuitBreakers, nil) 123 if err := cbc.Update(); err != nil { 124 t.Fatalf("error: %s", err.Error()) 125 } 126 127 if cbc.OriginLastFetchTime().Unix() == currentTime.Unix() { 128 t.Log("pass") 129 } else { 130 t.Fatalf("last mtime error") 131 } 132 }) 133 134 t.Run("数据库返回错误, update错误", func(t *testing.T) { 135 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 136 Return(nil, fmt.Errorf("storage error")) 137 if err := cbc.Update(); err != nil { 138 t.Log("pass") 139 } else { 140 t.Fatalf("error") 141 } 142 }) 143 } 144 145 /** 146 * TestCircuitBreakerUpdate2 统计缓存中的熔断规则数据 147 */ 148 func TestCircuitBreakerUpdate2(t *testing.T) { 149 ctl, storage, cbc := newTestCircuitBreakerCache(t) 150 defer ctl.Finish() 151 152 total := 10 153 154 t.Run("更新缓存后,增加部分数据,缓存正常更新", func(t *testing.T) { 155 _ = cbc.Clear() 156 157 serviceWithCircuitBreakers := genModelCircuitBreakers(0, total) 158 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 159 Return(serviceWithCircuitBreakers, nil) 160 if err := cbc.Update(); err != nil { 161 t.Fatalf("error: %s", err.Error()) 162 } 163 164 serviceWithCircuitBreakers = genModelCircuitBreakers(10, total) 165 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 166 Return(serviceWithCircuitBreakers, nil) 167 if err := cbc.Update(); err != nil { 168 t.Fatalf("error: %s", err.Error()) 169 } 170 171 if getCircuitBreakerCount(cbc) == total*2 { 172 t.Log("pass") 173 } else { 174 t.Fatalf("actual count is %d", getCircuitBreakerCount(cbc)) 175 } 176 }) 177 178 t.Run("更新缓存后,删除部分数据,缓存正常更新", func(t *testing.T) { 179 _ = cbc.Clear() 180 181 serviceWithCircuitBreakers := genModelCircuitBreakers(0, total) 182 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 183 Return(serviceWithCircuitBreakers, nil) 184 if err := cbc.Update(); err != nil { 185 t.Fatalf("error: %s", err.Error()) 186 } 187 188 for i := 0; i < total; i += 2 { 189 serviceWithCircuitBreakers[i].Valid = false 190 } 191 192 storage.EXPECT().GetCircuitBreakerRulesForCache(gomock.Any(), cbc.IsFirstUpdate()). 193 Return(serviceWithCircuitBreakers, nil) 194 if err := cbc.Update(); err != nil { 195 t.Fatalf("error: %s", err.Error()) 196 } 197 198 if getCircuitBreakerCount(cbc) == total/2 { 199 t.Log("pass") 200 } else { 201 t.Fatalf("actual count is %d", getCircuitBreakerCount(cbc)) 202 } 203 }) 204 }