github.com/polarismesh/polaris@v1.17.8/service/faultdetect_config_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_test 19 20 import ( 21 "context" 22 "fmt" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/golang/protobuf/ptypes" 28 "github.com/golang/protobuf/ptypes/wrappers" 29 apifault "github.com/polarismesh/specification/source/go/api/v1/fault_tolerance" 30 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 31 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 32 "github.com/stretchr/testify/assert" 33 34 "github.com/polarismesh/polaris/service" 35 ) 36 37 func buildUnnamedFaultDetectRule() *apifault.FaultDetectRule { 38 return &apifault.FaultDetectRule{ 39 Namespace: service.DefaultNamespace, 40 Description: "comment me", 41 TargetService: &apifault.FaultDetectRule_DestinationService{ 42 Service: "testDestService", 43 Namespace: "test", 44 Method: &apimodel.MatchString{Type: apimodel.MatchString_IN, Value: &wrappers.StringValue{Value: "/foo"}}, 45 }, 46 Interval: 60, 47 Timeout: 60, 48 Port: 8888, 49 Protocol: apifault.FaultDetectRule_HTTP, 50 } 51 } 52 53 func buildFaultDetectRule(index int) *apifault.FaultDetectRule { 54 return &apifault.FaultDetectRule{ 55 Name: fmt.Sprintf("test-faultdetect-rule-%d", index), 56 Namespace: service.DefaultNamespace, 57 Description: "comment me", 58 TargetService: &apifault.FaultDetectRule_DestinationService{ 59 Service: "testDestService", 60 Namespace: "test", 61 Method: &apimodel.MatchString{Type: apimodel.MatchString_IN, Value: &wrappers.StringValue{Value: "/foo"}}, 62 }, 63 Interval: 60, 64 Timeout: 60, 65 Port: 8888, 66 Protocol: apifault.FaultDetectRule_HTTP, 67 HttpConfig: &apifault.HttpProtocolConfig{ 68 Method: "POST", 69 Url: "/health", 70 Headers: []*apifault.HttpProtocolConfig_MessageHeader{ 71 { 72 Key: "Content-Type", 73 Value: "application/json", 74 }, 75 }, 76 Body: "<html>test</html>", 77 }, 78 TcpConfig: &apifault.TcpProtocolConfig{Send: "0x1111", Receive: []string{"0x2223", "0x8981"}}, 79 UdpConfig: &apifault.UdpProtocolConfig{Send: "0x1111", Receive: []string{"0x2223", "0x8981"}}, 80 } 81 } 82 83 func createFaultDetectRules(discoverSuit *DiscoverTestSuit, count int) ([]*apifault.FaultDetectRule, *apiservice.BatchWriteResponse) { 84 fdRules := make([]*apifault.FaultDetectRule, 0, count) 85 for i := 0; i < count; i++ { 86 fbRule := buildFaultDetectRule(i) 87 fdRules = append(fdRules, fbRule) 88 } 89 resp := discoverSuit.DiscoverServer().CreateFaultDetectRules(discoverSuit.DefaultCtx, fdRules) 90 return fdRules, resp 91 } 92 93 func cleanFaultDetectRules(discoverSuit *DiscoverTestSuit, response *apiservice.BatchWriteResponse) { 94 fdRules := parseResponseToFaultDetectRules(response) 95 if len(fdRules) > 0 { 96 discoverSuit.DiscoverServer().DeleteFaultDetectRules(discoverSuit.DefaultCtx, fdRules) 97 } 98 } 99 100 func checkFaultDetectRuleResponse(t *testing.T, requests []*apifault.FaultDetectRule, response *apiservice.BatchWriteResponse) { 101 assertions := assert.New(t) 102 assertions.Equal(len(requests), len(response.Responses)) 103 for _, resp := range response.Responses { 104 assertions.Equal(uint32(apimodel.Code_ExecuteSuccess), resp.GetCode().GetValue()) 105 msg := &apifault.FaultDetectRule{} 106 err := ptypes.UnmarshalAny(resp.GetData(), msg) 107 assertions.Nil(err) 108 assertions.True(len(msg.GetId()) > 0) 109 } 110 } 111 112 func parseResponseToFaultDetectRules(response *apiservice.BatchWriteResponse) []*apifault.FaultDetectRule { 113 fdRules := make([]*apifault.FaultDetectRule, 0, len(response.GetResponses())) 114 for _, resp := range response.GetResponses() { 115 if resp.GetCode().GetValue() != uint32(apimodel.Code_ExecuteSuccess) { 116 continue 117 } 118 msg := &apifault.FaultDetectRule{} 119 _ = ptypes.UnmarshalAny(resp.GetData(), msg) 120 fdRules = append(fdRules, msg) 121 } 122 return fdRules 123 } 124 125 // TestCreateFaultDetectRule test create faultdetect rule 126 func TestCreateFaultDetectRule(t *testing.T) { 127 discoverSuit := &DiscoverTestSuit{} 128 if err := discoverSuit.Initialize(); err != nil { 129 t.Fatal(err) 130 } 131 defer discoverSuit.Destroy() 132 133 t.Run("正常创建探测规则,返回成功", func(t *testing.T) { 134 fdRules, resp := createFaultDetectRules(discoverSuit, testCount) 135 defer cleanFaultDetectRules(discoverSuit, resp) 136 checkFaultDetectRuleResponse(t, fdRules, resp) 137 }) 138 139 t.Run("重复创建探测规则,返回错误", func(t *testing.T) { 140 fdRules, resp := createFaultDetectRules(discoverSuit, 1) 141 defer cleanFaultDetectRules(discoverSuit, resp) 142 checkFaultDetectRuleResponse(t, fdRules, resp) 143 144 if resp := discoverSuit.DiscoverServer().CreateFaultDetectRules(discoverSuit.DefaultCtx, fdRules); !respSuccess(resp) { 145 t.Logf("pass: %s", resp.GetInfo().GetValue()) 146 } else { 147 t.Fatal("error, duplicate rule can not be passed") 148 } 149 }) 150 151 t.Run("创建探测规则,删除,再创建,返回成功", func(t *testing.T) { 152 fdRules, resp := createFaultDetectRules(discoverSuit, 1) 153 cleanFaultDetectRules(discoverSuit, resp) 154 155 fdRules, resp = createFaultDetectRules(discoverSuit, 1) 156 defer cleanFaultDetectRules(discoverSuit, resp) 157 checkFaultDetectRuleResponse(t, fdRules, resp) 158 }) 159 160 t.Run("创建探测规则时,没有传递规则名,返回错误", func(t *testing.T) { 161 fdRule := buildUnnamedFaultDetectRule() 162 if resp := discoverSuit.DiscoverServer().CreateFaultDetectRules(discoverSuit.DefaultCtx, []*apifault.FaultDetectRule{fdRule}); !respSuccess(resp) { 163 t.Logf("pass: %s", resp.GetInfo().GetValue()) 164 } else { 165 t.Fatal("error, unnamed rule can not be passed") 166 } 167 }) 168 169 t.Run("并发创建探测规则,返回成功", func(t *testing.T) { 170 var wg sync.WaitGroup 171 for i := 0; i < 50; i++ { 172 wg.Add(1) 173 go func(index int) { 174 defer wg.Done() 175 fdRule := buildFaultDetectRule(index) 176 fdRules := []*apifault.FaultDetectRule{fdRule} 177 resp := discoverSuit.DiscoverServer().CreateFaultDetectRules(discoverSuit.DefaultCtx, fdRules) 178 cleanFaultDetectRules(discoverSuit, resp) 179 }(i) 180 } 181 wg.Wait() 182 }) 183 184 t.Run("创建探测规则,并通过客户端接口查询,返回正确规则", func(t *testing.T) { 185 fdRules, resp := createFaultDetectRules(discoverSuit, 1) 186 defer cleanFaultDetectRules(discoverSuit, resp) 187 checkFaultDetectRuleResponse(t, fdRules, resp) 188 time.Sleep(5 * time.Second) 189 discoverResp := discoverSuit.DiscoverServer().GetFaultDetectWithCache(context.Background(), &apiservice.Service{ 190 Name: &wrappers.StringValue{Value: "testDestService"}, 191 Namespace: &wrappers.StringValue{Value: "test"}, 192 }) 193 assert.Equal(t, int(apimodel.Code_ExecuteSuccess), int(discoverResp.GetCode().GetValue())) 194 faultDetector := discoverResp.GetFaultDetector() 195 assert.NotNil(t, faultDetector) 196 assert.Equal(t, 1, len(faultDetector.GetRules())) 197 }) 198 } 199 200 func TestModifyFaultDetectRule(t *testing.T) { 201 discoverSuit := &DiscoverTestSuit{} 202 if err := discoverSuit.Initialize(); err != nil { 203 t.Fatal(err) 204 } 205 defer discoverSuit.Destroy() 206 207 t.Run("正常修改探测规则,返回成功", func(t *testing.T) { 208 fdRules, resp := createFaultDetectRules(discoverSuit, testCount) 209 defer cleanFaultDetectRules(discoverSuit, resp) 210 checkFaultDetectRuleResponse(t, fdRules, resp) 211 212 for i := range fdRules { 213 fdRules[i].Description = "update faultdetect rule info" 214 } 215 216 resp = discoverSuit.DiscoverServer().UpdateFaultDetectRules(discoverSuit.DefaultCtx, fdRules) 217 assert.Equal(t, apimodel.Code_ExecuteSuccess, apimodel.Code(resp.GetCode().GetValue())) 218 219 qresp := discoverSuit.DiscoverServer().GetFaultDetectRules(discoverSuit.DefaultCtx, map[string]string{}) 220 assertions := assert.New(t) 221 for _, resp := range qresp.Data { 222 msg := &apifault.FaultDetectRule{} 223 err := ptypes.UnmarshalAny(resp, msg) 224 assertions.Nil(err) 225 assertions.True(len(msg.GetId()) > 0) 226 assertions.Equal("update faultdetect rule info", msg.Description) 227 } 228 }) 229 }