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  }