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  }