github.com/polarismesh/polaris@v1.17.8/plugin/healthchecker/redis/checker_redis_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 heartbeatredis 19 20 import ( 21 "context" 22 "sync/atomic" 23 "testing" 24 "time" 25 26 "github.com/stretchr/testify/assert" 27 28 "github.com/polarismesh/polaris/common/redispool" 29 commontime "github.com/polarismesh/polaris/common/time" 30 "github.com/polarismesh/polaris/plugin" 31 ) 32 33 type mockPool struct { 34 setValues map[string]map[string]bool 35 itemValues map[string]string 36 compatible bool 37 recoverTimeSec int64 38 } 39 40 // Start 启动ckv连接池工作 41 func (m *mockPool) Start() { 42 m.setValues = make(map[string]map[string]bool) 43 m.itemValues = make(map[string]string) 44 } 45 46 // Sdd 使用连接池,向redis发起Sdd请求 47 func (m *mockPool) Sdd(id string, members []string) *redispool.Resp { 48 values, ok := m.setValues[id] 49 if !ok { 50 values = make(map[string]bool) 51 m.setValues[id] = values 52 } 53 for _, member := range members { 54 values[member] = true 55 } 56 return &redispool.Resp{Compatible: m.compatible} 57 } 58 59 // Srem 使用连接池,向redis发起Srem请求 60 func (m *mockPool) Srem(id string, members []string) *redispool.Resp { 61 values, ok := m.setValues[id] 62 if ok { 63 for _, member := range members { 64 delete(values, member) 65 } 66 } 67 return &redispool.Resp{Compatible: m.compatible} 68 } 69 70 // Get 使用连接池,向redis发起Get请求 71 func (m *mockPool) Get(id string) *redispool.Resp { 72 value, ok := m.itemValues[id] 73 return &redispool.Resp{ 74 Value: value, 75 Exists: ok, 76 Compatible: m.compatible, 77 } 78 } 79 80 // Set 使用连接池,向redis发起Set请求 81 func (m *mockPool) Set(id string, redisObj redispool.RedisObject) *redispool.Resp { 82 value := redisObj.Serialize(m.compatible) 83 m.itemValues[id] = value 84 return &redispool.Resp{ 85 Value: value, 86 Exists: true, 87 Compatible: m.compatible, 88 } 89 } 90 91 // Del 使用连接池,向redis发起Del请求 92 func (m *mockPool) Del(id string) *redispool.Resp { 93 delete(m.itemValues, id) 94 return &redispool.Resp{ 95 Exists: true, 96 Compatible: m.compatible, 97 } 98 } 99 100 // RecoverTimeSec the time second record when recover 101 func (m *mockPool) RecoverTimeSec() int64 { 102 return m.recoverTimeSec 103 } 104 105 func TestReportAndCheck(t *testing.T) { 106 pool := &mockPool{} 107 checker := &RedisHealthChecker{ 108 hbPool: pool, 109 checkPool: pool, 110 } 111 checker.hbPool.Start() 112 checker.checkPool.Start() 113 114 startTime := commontime.CurrentMillisecond() / 1000 115 instanceId := "testId" 116 host := "localhost" 117 var count int64 118 var port uint32 = 8888 119 reportReq := &plugin.ReportRequest{ 120 QueryRequest: plugin.QueryRequest{ 121 InstanceId: instanceId, 122 Host: host, 123 Port: port, 124 }, 125 LocalHost: "127.0.0.1", 126 CurTimeSec: startTime, 127 Count: atomic.AddInt64(&count, 1), 128 } 129 err := checker.Report(context.Background(), reportReq) 130 assert.Nil(t, err) 131 132 queryResp, err := checker.Query(context.Background(), &reportReq.QueryRequest) 133 assert.Nil(t, err) 134 assert.Equal(t, reportReq.CurTimeSec, queryResp.LastHeartbeatSec) 135 136 // after 3 seconds 137 curTimeSec := startTime + 3 138 checkReq := &plugin.CheckRequest{ 139 QueryRequest: plugin.QueryRequest{ 140 InstanceId: instanceId, 141 Host: host, 142 Port: port, 143 Healthy: true, 144 }, 145 ExpireDurationSec: 2, 146 CurTimeSec: func() int64 { 147 return curTimeSec 148 }, 149 } 150 resp, err := checker.Check(checkReq) 151 assert.Nil(t, err) 152 assert.False(t, resp.StayUnchanged) 153 assert.False(t, resp.Healthy) 154 155 reportReq.CurTimeSec = curTimeSec 156 reportReq.Count = atomic.AddInt64(&count, 1) 157 err = checker.Report(context.Background(), reportReq) 158 assert.Nil(t, err) 159 160 time.Sleep(3 * time.Second) 161 checker.Suspend() 162 startTime = commontime.CurrentMillisecond() / 1000 163 reportReq.CurTimeSec = startTime 164 reportReq.Count = atomic.AddInt64(&count, 1) 165 err = checker.Report(context.Background(), reportReq) 166 assert.Nil(t, err) 167 168 checkReq = &plugin.CheckRequest{ 169 QueryRequest: plugin.QueryRequest{ 170 InstanceId: instanceId, 171 Host: host, 172 Port: port, 173 Healthy: true, 174 }, 175 ExpireDurationSec: 2, 176 CurTimeSec: func() int64 { 177 return startTime 178 }, 179 } 180 resp, err = checker.Check(checkReq) 181 assert.Nil(t, err) 182 assert.True(t, resp.StayUnchanged) 183 184 // after 4 seconds 185 time.Sleep(4 * time.Second) 186 checkReq = &plugin.CheckRequest{ 187 QueryRequest: plugin.QueryRequest{ 188 InstanceId: instanceId, 189 Host: host, 190 Port: port, 191 Healthy: true, 192 }, 193 ExpireDurationSec: 2, 194 CurTimeSec: func() int64 { 195 return commontime.CurrentMillisecond() / 1000 196 }, 197 } 198 resp, err = checker.Check(checkReq) 199 assert.Nil(t, err) 200 assert.False(t, resp.StayUnchanged) 201 assert.False(t, resp.Healthy) 202 }