github.com/polarismesh/polaris@v1.17.8/service/common_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  	"encoding/json"
    22  	"fmt"
    23  	"strconv"
    24  	"strings"
    25  	"testing"
    26  
    27  	_ "github.com/go-sql-driver/mysql"
    28  	"github.com/golang/protobuf/ptypes"
    29  	"github.com/golang/protobuf/ptypes/duration"
    30  	"github.com/golang/protobuf/ptypes/wrappers"
    31  	apifault "github.com/polarismesh/specification/source/go/api/v1/fault_tolerance"
    32  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    33  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    34  	apitraffic "github.com/polarismesh/specification/source/go/api/v1/traffic_manage"
    35  	bolt "go.etcd.io/bbolt"
    36  
    37  	_ "github.com/polarismesh/polaris/auth/defaultauth"
    38  	_ "github.com/polarismesh/polaris/cache"
    39  	api "github.com/polarismesh/polaris/common/api/v1"
    40  	"github.com/polarismesh/polaris/common/log"
    41  	"github.com/polarismesh/polaris/common/utils"
    42  	_ "github.com/polarismesh/polaris/plugin/cmdb/memory"
    43  	_ "github.com/polarismesh/polaris/plugin/discoverevent/local"
    44  	_ "github.com/polarismesh/polaris/plugin/healthchecker/memory"
    45  	_ "github.com/polarismesh/polaris/plugin/healthchecker/redis"
    46  	_ "github.com/polarismesh/polaris/plugin/history/logger"
    47  	_ "github.com/polarismesh/polaris/plugin/password"
    48  	_ "github.com/polarismesh/polaris/plugin/ratelimit/lrurate"
    49  	_ "github.com/polarismesh/polaris/plugin/ratelimit/token"
    50  	_ "github.com/polarismesh/polaris/plugin/statis/logger"
    51  	_ "github.com/polarismesh/polaris/plugin/statis/prometheus"
    52  	"github.com/polarismesh/polaris/service"
    53  	_ "github.com/polarismesh/polaris/store/boltdb"
    54  	sqldb "github.com/polarismesh/polaris/store/mysql"
    55  	testsuit "github.com/polarismesh/polaris/test/suit"
    56  )
    57  
    58  const (
    59  	tblNameNamespace          = "namespace"
    60  	tblNameInstance           = "instance"
    61  	tblNameService            = "service"
    62  	tblNameRouting            = "routing"
    63  	tblRateLimitConfig        = "ratelimit_config"
    64  	tblRateLimitRevision      = "ratelimit_revision"
    65  	tblCircuitBreaker         = "circuitbreaker_rule"
    66  	tblCircuitBreakerRelation = "circuitbreaker_rule_relation"
    67  	tblNameL5                 = "l5"
    68  	tblNameRoutingV2          = "routing_config_v2"
    69  	tblClient                 = "client"
    70  )
    71  
    72  type DiscoverTestSuit struct {
    73  	testsuit.DiscoverTestSuit
    74  }
    75  
    76  // 从数据库彻底删除服务名对应的服务
    77  func (d *DiscoverTestSuit) cleanServiceName(name string, namespace string) {
    78  	// log.Infof("clean service %s, %s", name, namespace)
    79  	d.GetTestDataClean().CleanService(name, namespace)
    80  }
    81  
    82  // 从数据库彻底删除实例
    83  func (d *DiscoverTestSuit) cleanInstance(instanceID string) {
    84  	d.GetTestDataClean().CleanInstance(instanceID)
    85  }
    86  
    87  // 增加一个服务
    88  func (d *DiscoverTestSuit) createCommonService(t *testing.T, id int) (*apiservice.Service, *apiservice.Service) {
    89  	serviceReq := genMainService(id)
    90  	for i := 0; i < 10; i++ {
    91  		k := fmt.Sprintf("key-%d-%d", id, i)
    92  		v := fmt.Sprintf("value-%d-%d", id, i)
    93  		serviceReq.Metadata[k] = v
    94  	}
    95  
    96  	d.cleanServiceName(serviceReq.GetName().GetValue(), serviceReq.GetNamespace().GetValue())
    97  
    98  	resp := d.DiscoverServer().CreateServices(d.DefaultCtx, []*apiservice.Service{serviceReq})
    99  	if !respSuccess(resp) {
   100  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   101  	}
   102  
   103  	return serviceReq, resp.Responses[0].GetService()
   104  }
   105  
   106  func (d *DiscoverTestSuit) HeartBeat(t *testing.T, service *apiservice.Service, instanceID string) {
   107  	req := &apiservice.Instance{
   108  		ServiceToken: utils.NewStringValue(service.GetToken().GetValue()),
   109  		Id:           utils.NewStringValue(instanceID),
   110  	}
   111  
   112  	resp := d.HealthCheckServer().Report(d.DefaultCtx, req)
   113  	if !respSuccess(resp) {
   114  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   115  	}
   116  }
   117  
   118  func (d *DiscoverTestSuit) GetLastHeartBeat(t *testing.T, service *apiservice.Service,
   119  	instanceID string) *apiservice.Response {
   120  	req := &apiservice.Instance{
   121  		ServiceToken: utils.NewStringValue(service.GetToken().GetValue()),
   122  		Id:           utils.NewStringValue(instanceID),
   123  	}
   124  
   125  	return d.HealthCheckServer().GetLastHeartbeat(req)
   126  }
   127  
   128  // 生成服务的主要数据
   129  func genMainService(id int) *apiservice.Service {
   130  	return &apiservice.Service{
   131  		Name:       utils.NewStringValue(fmt.Sprintf("test-service-%d", id)),
   132  		Namespace:  utils.NewStringValue(service.DefaultNamespace),
   133  		Metadata:   make(map[string]string),
   134  		Ports:      utils.NewStringValue(fmt.Sprintf("ports-%d", id)),
   135  		Business:   utils.NewStringValue(fmt.Sprintf("business-%d", id)),
   136  		Department: utils.NewStringValue(fmt.Sprintf("department-%d", id)),
   137  		CmdbMod1:   utils.NewStringValue(fmt.Sprintf("cmdb-mod1-%d", id)),
   138  		CmdbMod2:   utils.NewStringValue(fmt.Sprintf("cmdb-mod2-%d", id)),
   139  		CmdbMod3:   utils.NewStringValue(fmt.Sprintf("cmdb-mod2-%d", id)),
   140  		Comment:    utils.NewStringValue(fmt.Sprintf("service-comment-%d", id)),
   141  		Owners:     utils.NewStringValue(fmt.Sprintf("service-owner-%d", id)),
   142  	}
   143  }
   144  
   145  // removeCommonService
   146  func (d *DiscoverTestSuit) removeCommonServices(t *testing.T, req []*apiservice.Service) {
   147  	if resp := d.DiscoverServer().DeleteServices(d.DefaultCtx, req); !respSuccess(resp) {
   148  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   149  	}
   150  }
   151  
   152  // removeCommonService
   153  func (d *DiscoverTestSuit) removeCommonServiceAliases(t *testing.T, req []*apiservice.ServiceAlias) {
   154  	if resp := d.DiscoverServer().DeleteServiceAliases(d.DefaultCtx, req); !respSuccess(resp) {
   155  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   156  	}
   157  }
   158  
   159  // 新增一个实例ById
   160  func (d *DiscoverTestSuit) createCommonInstanceById(t *testing.T, svc *apiservice.Service, count int, instanceID string) (
   161  	*apiservice.Instance, *apiservice.Instance) {
   162  	instanceReq := &apiservice.Instance{
   163  		ServiceToken: utils.NewStringValue(svc.GetToken().GetValue()),
   164  		Service:      utils.NewStringValue(svc.GetName().GetValue()),
   165  		Namespace:    utils.NewStringValue(svc.GetNamespace().GetValue()),
   166  		VpcId:        utils.NewStringValue(fmt.Sprintf("vpcid-%d", count)),
   167  		Host:         utils.NewStringValue(fmt.Sprintf("9.9.9.%d", count)),
   168  		Port:         utils.NewUInt32Value(8000 + uint32(count)),
   169  		Protocol:     utils.NewStringValue(fmt.Sprintf("protocol-%d", count)),
   170  		Version:      utils.NewStringValue(fmt.Sprintf("version-%d", count)),
   171  		Priority:     utils.NewUInt32Value(1 + uint32(count)%10),
   172  		Weight:       utils.NewUInt32Value(1 + uint32(count)%1000),
   173  		HealthCheck: &apiservice.HealthCheck{
   174  			Type: apiservice.HealthCheck_HEARTBEAT,
   175  			Heartbeat: &apiservice.HeartbeatHealthCheck{
   176  				Ttl: utils.NewUInt32Value(3),
   177  			},
   178  		},
   179  		Healthy:  utils.NewBoolValue(false), // 默认是非健康,因为打开了healthCheck
   180  		Isolate:  utils.NewBoolValue(false),
   181  		LogicSet: utils.NewStringValue(fmt.Sprintf("logic-set-%d", count)),
   182  		Metadata: map[string]string{
   183  			"internal-personal-xxx":        fmt.Sprintf("internal-personal-xxx_%d", count),
   184  			"2my-meta":                     fmt.Sprintf("my-meta-%d", count),
   185  			"my-meta-a1":                   "1111",
   186  			"smy-xmeta-h2":                 "2222",
   187  			"my-1meta-o3":                  "2222",
   188  			"my-2meta-4c":                  "2222",
   189  			"my-3meta-d5":                  "2222",
   190  			"dmy-meta-6p":                  "2222",
   191  			"1my-pmeta-d7":                 "2222",
   192  			"my-dmeta-8c":                  "2222",
   193  			"my-xmeta-9p":                  "2222",
   194  			"other-meta-x":                 "xxx",
   195  			"other-meta-1":                 "xx11",
   196  			"amy-instance":                 "my-instance",
   197  			"very-long-key-data-xxxxxxxxx": "Y",
   198  			"very-long-key-data-uuuuuuuuu": "P",
   199  		},
   200  	}
   201  	if len(instanceID) > 0 {
   202  		instanceReq.Id = utils.NewStringValue(instanceID)
   203  	}
   204  
   205  	resp := d.DiscoverServer().CreateInstances(d.DefaultCtx, []*apiservice.Instance{instanceReq})
   206  	if respSuccess(resp) {
   207  		return instanceReq, resp.Responses[0].GetInstance()
   208  	}
   209  
   210  	if resp.GetCode().GetValue() != api.ExistedResource {
   211  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   212  	}
   213  
   214  	if len(instanceID) == 0 {
   215  		instanceID, _ = utils.CalculateInstanceID(
   216  			instanceReq.GetNamespace().GetValue(), instanceReq.GetService().GetValue(),
   217  			instanceReq.GetVpcId().GetValue(), instanceReq.GetHost().GetValue(), instanceReq.GetPort().GetValue())
   218  	}
   219  	// repeated
   220  	d.cleanInstance(instanceID)
   221  	t.Logf("repeatd create instance(%s)", instanceID)
   222  	resp = d.DiscoverServer().CreateInstances(d.DefaultCtx, []*apiservice.Instance{instanceReq})
   223  	if !respSuccess(resp) {
   224  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   225  	}
   226  
   227  	return instanceReq, resp.Responses[0].GetInstance()
   228  }
   229  
   230  // 新增一个实例
   231  func (d *DiscoverTestSuit) createCommonInstance(t *testing.T, svc *apiservice.Service, count int) (
   232  	*apiservice.Instance, *apiservice.Instance) {
   233  	return d.createCommonInstanceById(t, svc, count, "")
   234  }
   235  
   236  // 指定 IP 和端口为一个服务创建实例
   237  func (d *DiscoverTestSuit) addHostPortInstance(t *testing.T, service *apiservice.Service, host string, port uint32) (
   238  	*apiservice.Instance, *apiservice.Instance) {
   239  	instanceReq := &apiservice.Instance{
   240  		ServiceToken: utils.NewStringValue(service.GetToken().GetValue()),
   241  		Service:      utils.NewStringValue(service.GetName().GetValue()),
   242  		Namespace:    utils.NewStringValue(service.GetNamespace().GetValue()),
   243  		Host:         utils.NewStringValue(host),
   244  		Port:         utils.NewUInt32Value(port),
   245  		Healthy:      utils.NewBoolValue(true),
   246  		Isolate:      utils.NewBoolValue(false),
   247  	}
   248  	resp := d.DiscoverServer().CreateInstances(d.DefaultCtx, []*apiservice.Instance{instanceReq})
   249  	if respSuccess(resp) {
   250  		return instanceReq, resp.Responses[0].GetInstance()
   251  	}
   252  
   253  	if resp.GetCode().GetValue() != api.ExistedResource {
   254  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   255  	}
   256  	return instanceReq, resp.Responses[0].GetInstance()
   257  }
   258  
   259  // 添加一个实例
   260  func (d *DiscoverTestSuit) addInstance(t *testing.T, ins *apiservice.Instance) (
   261  	*apiservice.Instance, *apiservice.Instance) {
   262  	resp := d.DiscoverServer().CreateInstances(d.DefaultCtx, []*apiservice.Instance{ins})
   263  	if !respSuccess(resp) {
   264  		if resp.GetCode().GetValue() == api.ExistedResource {
   265  			id, _ := utils.CalculateInstanceID(ins.GetNamespace().GetValue(), ins.GetService().GetValue(),
   266  				ins.GetHost().GetValue(), ins.GetHost().GetValue(), ins.GetPort().GetValue())
   267  			d.cleanInstance(id)
   268  		}
   269  	} else {
   270  		return ins, resp.Responses[0].GetInstance()
   271  	}
   272  
   273  	resp = d.DiscoverServer().CreateInstances(d.DefaultCtx, []*apiservice.Instance{ins})
   274  	if !respSuccess(resp) {
   275  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   276  	}
   277  
   278  	return ins, resp.Responses[0].GetInstance()
   279  }
   280  
   281  // 删除一个实例
   282  func (d *DiscoverTestSuit) removeCommonInstance(t *testing.T, service *apiservice.Service, instanceID string) {
   283  	req := &apiservice.Instance{
   284  		ServiceToken: utils.NewStringValue(service.GetToken().GetValue()),
   285  		Id:           utils.NewStringValue(instanceID),
   286  	}
   287  
   288  	resp := d.DiscoverServer().DeleteInstances(d.DefaultCtx, []*apiservice.Instance{req})
   289  	if !respSuccess(resp) {
   290  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   291  	}
   292  
   293  }
   294  
   295  // 通过四元组或者五元组删除实例
   296  func (d *DiscoverTestSuit) removeInstanceWithAttrs(
   297  	t *testing.T, service *apiservice.Service, instance *apiservice.Instance) {
   298  	req := &apiservice.Instance{
   299  		ServiceToken: utils.NewStringValue(service.GetToken().GetValue()),
   300  		Service:      utils.NewStringValue(service.GetName().GetValue()),
   301  		Namespace:    utils.NewStringValue(service.GetNamespace().GetValue()),
   302  		VpcId:        utils.NewStringValue(instance.GetVpcId().GetValue()),
   303  		Host:         utils.NewStringValue(instance.GetHost().GetValue()),
   304  		Port:         utils.NewUInt32Value(instance.GetPort().GetValue()),
   305  	}
   306  	if resp := d.DiscoverServer().DeleteInstances(d.DefaultCtx, []*apiservice.Instance{req}); !respSuccess(resp) {
   307  		t.Fatalf("error: %s", resp.GetInfo().GetValue())
   308  	}
   309  }
   310  
   311  // 创建一个路由配置
   312  func (d *DiscoverTestSuit) createCommonRoutingConfig(
   313  	t *testing.T, service *apiservice.Service, inCount int, outCount int) (*apitraffic.Routing, *apitraffic.Routing) {
   314  	inBounds := make([]*apitraffic.Route, 0, inCount)
   315  	for i := 0; i < inCount; i++ {
   316  		matchString := &apimodel.MatchString{
   317  			Type:  apimodel.MatchString_EXACT,
   318  			Value: utils.NewStringValue(fmt.Sprintf("in-meta-value-%d", i)),
   319  		}
   320  		source := &apitraffic.Source{
   321  			Service:   utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)),
   322  			Namespace: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)),
   323  			Metadata: map[string]*apimodel.MatchString{
   324  				fmt.Sprintf("in-metadata-%d", i): matchString,
   325  			},
   326  		}
   327  		destination := &apitraffic.Destination{
   328  			Service:   service.Name,
   329  			Namespace: service.Namespace,
   330  			Metadata: map[string]*apimodel.MatchString{
   331  				fmt.Sprintf("in-metadata-%d", i): matchString,
   332  			},
   333  			Priority: utils.NewUInt32Value(120),
   334  			Weight:   utils.NewUInt32Value(100),
   335  			Transfer: utils.NewStringValue("abcdefg"),
   336  		}
   337  
   338  		entry := &apitraffic.Route{
   339  			Sources:      []*apitraffic.Source{source},
   340  			Destinations: []*apitraffic.Destination{destination},
   341  		}
   342  		inBounds = append(inBounds, entry)
   343  	}
   344  
   345  	conf := &apitraffic.Routing{
   346  		Service:      utils.NewStringValue(service.GetName().GetValue()),
   347  		Namespace:    utils.NewStringValue(service.GetNamespace().GetValue()),
   348  		Inbounds:     inBounds,
   349  		ServiceToken: utils.NewStringValue(service.GetToken().GetValue()),
   350  	}
   351  
   352  	// TODO 是否应该先删除routing
   353  
   354  	resp := d.DiscoverServer().CreateRoutingConfigs(d.DefaultCtx, []*apitraffic.Routing{conf})
   355  	if !respSuccess(resp) {
   356  		t.Fatalf("error: %+v", resp)
   357  	}
   358  
   359  	return conf, resp.Responses[0].GetRouting()
   360  }
   361  
   362  // 创建一个路由配置
   363  func (d *DiscoverTestSuit) createCommonRoutingConfigV1IntoOldStore(t *testing.T, svc *apiservice.Service,
   364  	inCount int, outCount int) (*apitraffic.Routing, *apitraffic.Routing) {
   365  
   366  	inBounds := make([]*apitraffic.Route, 0, inCount)
   367  	for i := 0; i < inCount; i++ {
   368  		matchString := &apimodel.MatchString{
   369  			Type:  apimodel.MatchString_EXACT,
   370  			Value: utils.NewStringValue(fmt.Sprintf("in-meta-value-%d", i)),
   371  		}
   372  		source := &apitraffic.Source{
   373  			Service:   utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)),
   374  			Namespace: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)),
   375  			Metadata: map[string]*apimodel.MatchString{
   376  				fmt.Sprintf("in-metadata-%d", i): matchString,
   377  			},
   378  		}
   379  		destination := &apitraffic.Destination{
   380  			Service:   svc.Name,
   381  			Namespace: svc.Namespace,
   382  			Metadata: map[string]*apimodel.MatchString{
   383  				fmt.Sprintf("in-metadata-%d", i): matchString,
   384  			},
   385  			Priority: utils.NewUInt32Value(120),
   386  			Weight:   utils.NewUInt32Value(100),
   387  			Transfer: utils.NewStringValue("abcdefg"),
   388  		}
   389  
   390  		entry := &apitraffic.Route{
   391  			Sources:      []*apitraffic.Source{source},
   392  			Destinations: []*apitraffic.Destination{destination},
   393  		}
   394  		inBounds = append(inBounds, entry)
   395  	}
   396  
   397  	conf := &apitraffic.Routing{
   398  		Service:      utils.NewStringValue(svc.GetName().GetValue()),
   399  		Namespace:    utils.NewStringValue(svc.GetNamespace().GetValue()),
   400  		Inbounds:     inBounds,
   401  		ServiceToken: utils.NewStringValue(svc.GetToken().GetValue()),
   402  	}
   403  
   404  	resp := d.OriginDiscoverServer().(*service.Server).CreateRoutingConfig(d.DefaultCtx, conf)
   405  	if !respSuccess(resp) {
   406  		t.Fatalf("error: %+v", resp)
   407  	}
   408  
   409  	return conf, resp.GetRouting()
   410  }
   411  
   412  func mockRoutingV1(serviceName, serviceNamespace string, inCount int) *apitraffic.Routing {
   413  	inBounds := make([]*apitraffic.Route, 0, inCount)
   414  	for i := 0; i < inCount; i++ {
   415  		matchString := &apimodel.MatchString{
   416  			Type:  apimodel.MatchString_EXACT,
   417  			Value: utils.NewStringValue(fmt.Sprintf("in-meta-value-%d", i)),
   418  		}
   419  		source := &apitraffic.Source{
   420  			Service:   utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)),
   421  			Namespace: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)),
   422  			Metadata: map[string]*apimodel.MatchString{
   423  				fmt.Sprintf("in-metadata-%d", i): matchString,
   424  			},
   425  		}
   426  		destination := &apitraffic.Destination{
   427  			Service:   utils.NewStringValue(serviceName),
   428  			Namespace: utils.NewStringValue(serviceNamespace),
   429  			Metadata: map[string]*apimodel.MatchString{
   430  				fmt.Sprintf("in-metadata-%d", i): matchString,
   431  			},
   432  			Priority: utils.NewUInt32Value(120),
   433  			Weight:   utils.NewUInt32Value(100),
   434  			Transfer: utils.NewStringValue("abcdefg"),
   435  		}
   436  
   437  		entry := &apitraffic.Route{
   438  			Sources:      []*apitraffic.Source{source},
   439  			Destinations: []*apitraffic.Destination{destination},
   440  		}
   441  		inBounds = append(inBounds, entry)
   442  	}
   443  
   444  	conf := &apitraffic.Routing{
   445  		Service:   utils.NewStringValue(serviceName),
   446  		Namespace: utils.NewStringValue(serviceNamespace),
   447  		Inbounds:  inBounds,
   448  	}
   449  
   450  	return conf
   451  }
   452  
   453  // 创建一个路由配置
   454  func (d *DiscoverTestSuit) createCommonRoutingConfigV2(t *testing.T, cnt int32) []*apitraffic.RouteRule {
   455  	rules := testsuit.MockRoutingV2(t, cnt)
   456  
   457  	return d.createCommonRoutingConfigV2WithReq(t, rules)
   458  }
   459  
   460  // 创建一个路由配置
   461  func (d *DiscoverTestSuit) createCommonRoutingConfigV2WithReq(
   462  	t *testing.T, rules []*apitraffic.RouteRule) []*apitraffic.RouteRule {
   463  	resp := d.DiscoverServer().CreateRoutingConfigsV2(d.DefaultCtx, rules)
   464  	if !respSuccess(resp) {
   465  		t.Fatalf("error: %+v", resp)
   466  	}
   467  
   468  	if len(rules) != len(resp.GetResponses()) {
   469  		t.Fatal("error: create v2 routings not equal resp")
   470  	}
   471  
   472  	ret := []*apitraffic.RouteRule{}
   473  	for i := range resp.GetResponses() {
   474  		item := resp.GetResponses()[i]
   475  		msg := &apitraffic.RouteRule{}
   476  
   477  		if err := ptypes.UnmarshalAny(item.GetData(), msg); err != nil {
   478  			t.Fatal(err)
   479  			return nil
   480  		}
   481  
   482  		ret = append(ret, msg)
   483  	}
   484  
   485  	return ret
   486  }
   487  
   488  // 删除一个路由配置
   489  func (d *DiscoverTestSuit) deleteCommonRoutingConfig(t *testing.T, req *apitraffic.Routing) {
   490  	resp := d.DiscoverServer().DeleteRoutingConfigs(d.DefaultCtx, []*apitraffic.Routing{req})
   491  	if !respSuccess(resp) {
   492  		t.Fatalf("%s", resp.GetInfo().GetValue())
   493  	}
   494  }
   495  
   496  // 删除一个路由配置
   497  func (d *DiscoverTestSuit) deleteCommonRoutingConfigV2(t *testing.T, req *apitraffic.RouteRule) {
   498  	resp := d.DiscoverServer().DeleteRoutingConfigsV2(d.DefaultCtx, []*apitraffic.RouteRule{req})
   499  	if !respSuccess(resp) {
   500  		t.Fatalf("%s", resp.GetInfo())
   501  	}
   502  }
   503  
   504  // 更新一个路由配置
   505  func (d *DiscoverTestSuit) updateCommonRoutingConfig(t *testing.T, req *apitraffic.Routing) {
   506  	resp := d.DiscoverServer().UpdateRoutingConfigs(d.DefaultCtx, []*apitraffic.Routing{req})
   507  	if !respSuccess(resp) {
   508  		t.Fatalf("%s", resp.GetInfo().GetValue())
   509  	}
   510  }
   511  
   512  // 彻底删除一个路由配置
   513  func (d *DiscoverTestSuit) cleanCommonRoutingConfig(service string, namespace string) {
   514  	d.GetTestDataClean().CleanCommonRoutingConfig(service, namespace)
   515  }
   516  
   517  func (d *DiscoverTestSuit) truncateCommonRoutingConfigV2() {
   518  	d.GetTestDataClean().TruncateCommonRoutingConfigV2()
   519  }
   520  
   521  // 彻底删除一个路由配置
   522  func (d *DiscoverTestSuit) cleanCommonRoutingConfigV2(rules []*apitraffic.RouteRule) {
   523  	d.GetTestDataClean().CleanCommonRoutingConfigV2(rules)
   524  }
   525  
   526  func (d *DiscoverTestSuit) CheckGetService(
   527  	t *testing.T, expectReqs []*apiservice.Service, actualReqs []*apiservice.Service) {
   528  	if len(expectReqs) != len(actualReqs) {
   529  		t.Fatalf("error: %d %d", len(expectReqs), len(actualReqs))
   530  	}
   531  
   532  	for _, expect := range expectReqs {
   533  		found := false
   534  		for _, actual := range actualReqs {
   535  			if expect.GetName().GetValue() != actual.GetName().GetValue() ||
   536  				expect.GetNamespace().GetValue() != actual.GetNamespace().GetValue() {
   537  				continue
   538  			}
   539  
   540  			found = true
   541  
   542  			if expect.GetPorts().GetValue() != actual.GetPorts().GetValue() ||
   543  				expect.GetOwners().GetValue() != actual.GetOwners().GetValue() ||
   544  				expect.GetComment().GetValue() != actual.GetComment().GetValue() ||
   545  				actual.GetToken().GetValue() != "" || actual.GetRevision().GetValue() == "" {
   546  				t.Fatalf("error: %+v, %+v", expect, actual)
   547  			}
   548  
   549  			if len(expect.Metadata) != len(actual.Metadata) {
   550  				t.Fatalf("error: %d, %d", len(expect.Metadata), len(actual.Metadata))
   551  			}
   552  			for key, value := range expect.Metadata {
   553  				match, ok := actual.Metadata[key]
   554  				if !ok {
   555  					t.Fatalf("error")
   556  				}
   557  				if value != match {
   558  					t.Fatalf("error")
   559  				}
   560  			}
   561  		}
   562  		if !found {
   563  			t.Fatalf("error: %s, %s", expect.GetName().GetValue(), expect.GetNamespace().GetValue())
   564  		}
   565  
   566  	}
   567  }
   568  
   569  // 检查服务发现的字段是否一致
   570  func (d *DiscoverTestSuit) discoveryCheck(t *testing.T, req *apiservice.Service, resp *apiservice.DiscoverResponse) {
   571  	if resp == nil {
   572  		t.Fatalf("error")
   573  	}
   574  
   575  	if resp.GetService().GetName().GetValue() != req.GetName().GetValue() ||
   576  		resp.GetService().GetNamespace().GetValue() != req.GetNamespace().GetValue() ||
   577  		resp.GetService().GetRevision().GetValue() == "" {
   578  		t.Fatalf("error: %+v", resp)
   579  	}
   580  
   581  	if resp.Service == nil {
   582  		t.Fatalf("error")
   583  	}
   584  	// t.Logf("%+v", resp.Service)
   585  
   586  	if resp.Service.GetName().GetValue() != req.GetName().GetValue() ||
   587  		resp.Service.GetNamespace().GetValue() != req.GetNamespace().GetValue() {
   588  		t.Fatalf("error: %+v", resp.Service)
   589  	}
   590  }
   591  
   592  // 实例校验
   593  func instanceCheck(t *testing.T, expect *apiservice.Instance, actual *apiservice.Instance) {
   594  	// #lizard forgives
   595  	switch {
   596  	case expect.GetService().GetValue() != actual.GetService().GetValue():
   597  		t.Fatalf("error %s---%s", expect.GetService().GetValue(), actual.GetService().GetValue())
   598  	case expect.GetNamespace().GetValue() != actual.GetNamespace().GetValue():
   599  		t.Fatalf("error")
   600  	case expect.GetPort().GetValue() != actual.GetPort().GetValue():
   601  		t.Fatalf("error")
   602  	case expect.GetHost().GetValue() != actual.GetHost().GetValue():
   603  		t.Fatalf("error")
   604  	case expect.GetVpcId().GetValue() != actual.GetVpcId().GetValue():
   605  		t.Fatalf("error")
   606  	case expect.GetProtocol().GetValue() != actual.GetProtocol().GetValue():
   607  		t.Fatalf("error")
   608  	case expect.GetVersion().GetValue() != actual.GetVersion().GetValue():
   609  		t.Fatalf("error")
   610  	case expect.GetWeight().GetValue() != actual.GetWeight().GetValue():
   611  		t.Fatalf("error")
   612  	case expect.GetHealthy().GetValue() != actual.GetHealthy().GetValue():
   613  		t.Fatalf("error")
   614  	case expect.GetIsolate().GetValue() != actual.GetIsolate().GetValue():
   615  		t.Fatalf("error")
   616  	case expect.GetLogicSet().GetValue() != actual.GetLogicSet().GetValue():
   617  		t.Fatalf("error")
   618  	default:
   619  		break
   620  
   621  		// 实例创建,无法指定cmdb信息
   622  		/*case expect.GetCmdbRegion().GetValue() != actual.GetCmdbRegion().GetValue():
   623  		  	t.Fatalf("error")
   624  		  case expect.GetCmdbCampus().GetValue() != actual.GetCmdbRegion().GetValue():
   625  		  	t.Fatalf("error")
   626  		  case expect.GetCmdbZone().GetValue() != actual.GetCmdbZone().GetValue():
   627  		  	t.Fatalf("error")*/
   628  
   629  	}
   630  	for key, value := range expect.GetMetadata() {
   631  		actualValue := actual.GetMetadata()[key]
   632  		if value != actualValue {
   633  			t.Fatalf("error %+v, %+v", expect.Metadata, actual.Metadata)
   634  		}
   635  	}
   636  
   637  	if expect.GetHealthCheck().GetType() != actual.GetHealthCheck().GetType() {
   638  		t.Fatalf("error")
   639  	}
   640  	if expect.GetHealthCheck().GetHeartbeat().GetTtl().GetValue() !=
   641  		actual.GetHealthCheck().GetHeartbeat().GetTtl().GetValue() {
   642  		t.Fatalf("error")
   643  	}
   644  }
   645  
   646  // 完整对比service的各个属性
   647  func serviceCheck(t *testing.T, expect *apiservice.Service, actual *apiservice.Service) {
   648  	switch {
   649  	case expect.GetName().GetValue() != actual.GetName().GetValue():
   650  		t.Fatalf("error")
   651  	case expect.GetNamespace().GetValue() != actual.GetNamespace().GetValue():
   652  		t.Fatalf("error")
   653  	case expect.GetPorts().GetValue() != actual.GetPorts().GetValue():
   654  		t.Fatalf("error")
   655  	case expect.GetBusiness().GetValue() != actual.GetBusiness().GetValue():
   656  		t.Fatalf("error")
   657  	case expect.GetDepartment().GetValue() != actual.GetDepartment().GetValue():
   658  		t.Fatalf("error")
   659  	case expect.GetCmdbMod1().GetValue() != actual.GetCmdbMod1().GetValue():
   660  		t.Fatalf("error")
   661  	case expect.GetCmdbMod2().GetValue() != actual.GetCmdbMod2().GetValue():
   662  		t.Fatalf("error")
   663  	case expect.GetCmdbMod3().GetValue() != actual.GetCmdbMod3().GetValue():
   664  		t.Fatalf("error")
   665  	case expect.GetComment().GetValue() != actual.GetComment().GetValue():
   666  		t.Fatalf("error")
   667  	case expect.GetOwners().GetValue() != actual.GetOwners().GetValue():
   668  		t.Fatalf("error")
   669  	default:
   670  		break
   671  	}
   672  
   673  	for key, value := range expect.GetMetadata() {
   674  		actualValue := actual.GetMetadata()[key]
   675  		if actualValue != value {
   676  			t.Fatalf("error")
   677  		}
   678  	}
   679  }
   680  
   681  // 创建限流规则
   682  func (d *DiscoverTestSuit) createCommonRateLimit(
   683  	t *testing.T, service *apiservice.Service, index int) (*apitraffic.Rule, *apitraffic.Rule) {
   684  	// 先不考虑Cluster
   685  	rateLimit := &apitraffic.Rule{
   686  		Name:      &wrappers.StringValue{Value: fmt.Sprintf("rule_name_%d", index)},
   687  		Service:   service.GetName(),
   688  		Namespace: service.GetNamespace(),
   689  		Priority:  utils.NewUInt32Value(uint32(index)),
   690  		Resource:  apitraffic.Rule_QPS,
   691  		Type:      apitraffic.Rule_GLOBAL,
   692  		Arguments: []*apitraffic.MatchArgument{
   693  			{
   694  				Type: apitraffic.MatchArgument_CUSTOM,
   695  				Key:  fmt.Sprintf("name-%d", index),
   696  				Value: &apimodel.MatchString{
   697  					Type:  apimodel.MatchString_EXACT,
   698  					Value: utils.NewStringValue(fmt.Sprintf("value-%d", index)),
   699  				},
   700  			},
   701  			{
   702  				Type: apitraffic.MatchArgument_CUSTOM,
   703  				Key:  fmt.Sprintf("name-%d", index+1),
   704  				Value: &apimodel.MatchString{
   705  					Type:  apimodel.MatchString_EXACT,
   706  					Value: utils.NewStringValue(fmt.Sprintf("value-%d", index+1)),
   707  				},
   708  			},
   709  		},
   710  		Amounts: []*apitraffic.Amount{
   711  			{
   712  				MaxAmount: utils.NewUInt32Value(uint32(10 * index)),
   713  				ValidDuration: &duration.Duration{
   714  					Seconds: int64(index),
   715  					Nanos:   int32(index),
   716  				},
   717  			},
   718  		},
   719  		Action:  utils.NewStringValue(fmt.Sprintf("behavior-%d", index)),
   720  		Disable: utils.NewBoolValue(false),
   721  		Report: &apitraffic.Report{
   722  			Interval: &duration.Duration{
   723  				Seconds: int64(index),
   724  			},
   725  			AmountPercent: utils.NewUInt32Value(uint32(index)),
   726  		},
   727  	}
   728  
   729  	resp := d.DiscoverServer().CreateRateLimits(d.DefaultCtx, []*apitraffic.Rule{rateLimit})
   730  	if !respSuccess(resp) {
   731  		t.Fatalf("error: %+v", resp)
   732  	}
   733  	return rateLimit, resp.Responses[0].GetRateLimit()
   734  }
   735  
   736  // 删除限流规则
   737  func (d *DiscoverTestSuit) deleteRateLimit(t *testing.T, rateLimit *apitraffic.Rule) {
   738  	if resp := d.DiscoverServer().DeleteRateLimits(d.DefaultCtx, []*apitraffic.Rule{rateLimit}); !respSuccess(resp) {
   739  		t.Fatalf("%s", resp.GetInfo().GetValue())
   740  	}
   741  }
   742  
   743  // 更新单个限流规则
   744  func (d *DiscoverTestSuit) updateRateLimit(t *testing.T, rateLimit *apitraffic.Rule) {
   745  	if resp := d.DiscoverServer().UpdateRateLimits(d.DefaultCtx, []*apitraffic.Rule{rateLimit}); !respSuccess(resp) {
   746  		t.Fatalf("%s", resp.GetInfo().GetValue())
   747  	}
   748  }
   749  
   750  // 彻底删除限流规则
   751  func (d *DiscoverTestSuit) cleanRateLimit(id string) {
   752  	d.GetTestDataClean().CleanRateLimit(id)
   753  }
   754  
   755  // 彻底删除限流规则版本号
   756  func (d *DiscoverTestSuit) cleanRateLimitRevision(service, namespace string) {
   757  }
   758  
   759  // 更新限流规则内容
   760  func updateRateLimitContent(rateLimit *apitraffic.Rule, index int) {
   761  	rateLimit.Priority = utils.NewUInt32Value(uint32(index))
   762  	rateLimit.Resource = apitraffic.Rule_CONCURRENCY
   763  	rateLimit.Type = apitraffic.Rule_LOCAL
   764  	rateLimit.Labels = map[string]*apimodel.MatchString{
   765  		fmt.Sprintf("name-%d", index): {
   766  			Type:  apimodel.MatchString_EXACT,
   767  			Value: utils.NewStringValue(fmt.Sprintf("value-%d", index)),
   768  		},
   769  		fmt.Sprintf("name-%d", index+1): {
   770  			Type:  apimodel.MatchString_REGEX,
   771  			Value: utils.NewStringValue(fmt.Sprintf("value-%d", index+1)),
   772  		},
   773  	}
   774  	rateLimit.Amounts = []*apitraffic.Amount{
   775  		{
   776  			MaxAmount: utils.NewUInt32Value(uint32(index)),
   777  			ValidDuration: &duration.Duration{
   778  				Seconds: int64(index),
   779  			},
   780  		},
   781  	}
   782  	rateLimit.Action = utils.NewStringValue(fmt.Sprintf("value-%d", index))
   783  	rateLimit.Disable = utils.NewBoolValue(true)
   784  	rateLimit.Report = &apitraffic.Report{
   785  		Interval: &duration.Duration{
   786  			Seconds: int64(index),
   787  		},
   788  		AmountPercent: utils.NewUInt32Value(uint32(index)),
   789  	}
   790  }
   791  
   792  /*
   793   * @brief 对比限流规则的各个属性
   794   */
   795  func checkRateLimit(t *testing.T, expect *apitraffic.Rule, actual *apitraffic.Rule) {
   796  	switch {
   797  	case expect.GetId().GetValue() != actual.GetId().GetValue():
   798  		t.Fatalf("error id, expect %s, actual %s", expect.GetId().GetValue(), actual.GetId().GetValue())
   799  	case expect.GetService().GetValue() != actual.GetService().GetValue():
   800  		t.Fatalf(
   801  			"error service, expect %s, actual %s",
   802  			expect.GetService().GetValue(), actual.GetService().GetValue())
   803  	case expect.GetNamespace().GetValue() != actual.GetNamespace().GetValue():
   804  		t.Fatalf("error namespace, expect %s, actual %s",
   805  			expect.GetNamespace().GetValue(), actual.GetNamespace().GetValue())
   806  	case expect.GetPriority().GetValue() != actual.GetPriority().GetValue():
   807  		t.Fatalf("error priority, expect %v, actual %v",
   808  			expect.GetPriority().GetValue(), actual.GetPriority().GetValue())
   809  	case expect.GetResource() != actual.GetResource():
   810  		t.Fatalf("error resource, expect %v, actual %v", expect.GetResource(), actual.GetResource())
   811  	case expect.GetType() != actual.GetType():
   812  		t.Fatalf("error type, expect %v, actual %v", expect.GetType(), actual.GetType())
   813  	case expect.GetDisable().GetValue() != actual.GetDisable().GetValue():
   814  		t.Fatalf("error disable, expect %v, actual %v",
   815  			expect.GetDisable().GetValue(), actual.GetDisable().GetValue())
   816  	case expect.GetAction().GetValue() != actual.GetAction().GetValue():
   817  		t.Fatalf("error action, expect %s, actual %s",
   818  			expect.GetAction().GetValue(), actual.GetAction().GetValue())
   819  	default:
   820  		break
   821  	}
   822  
   823  	expectSubset, err := json.Marshal(expect.GetSubset())
   824  	if err != nil {
   825  		panic(err)
   826  	}
   827  	actualSubset, err := json.Marshal(actual.GetSubset())
   828  	if err != nil {
   829  		panic(err)
   830  	}
   831  	if string(expectSubset) != string(actualSubset) {
   832  		t.Fatal("error subset")
   833  	}
   834  
   835  	expectLabels, err := json.Marshal(expect.GetArguments())
   836  	if err != nil {
   837  		panic(err)
   838  	}
   839  	actualLabels, err := json.Marshal(actual.GetArguments())
   840  	if err != nil {
   841  		panic(err)
   842  	}
   843  	if string(expectLabels) != string(actualLabels) {
   844  		t.Fatal("error labels")
   845  	}
   846  
   847  	expectAmounts, err := json.Marshal(expect.GetAmounts())
   848  	if err != nil {
   849  		panic(err)
   850  	}
   851  	actualAmounts, err := json.Marshal(actual.GetAmounts())
   852  	if err != nil {
   853  		panic(err)
   854  	}
   855  	if string(expectAmounts) != string(actualAmounts) {
   856  		t.Fatal("error amounts")
   857  	}
   858  }
   859  
   860  // 增加熔断规则
   861  func (d *DiscoverTestSuit) createCommonCircuitBreaker(
   862  	t *testing.T, id int) (*apifault.CircuitBreaker, *apifault.CircuitBreaker) {
   863  	circuitBreaker := &apifault.CircuitBreaker{
   864  		Name:       utils.NewStringValue(fmt.Sprintf("name-test-%d", id)),
   865  		Namespace:  utils.NewStringValue(service.DefaultNamespace),
   866  		Owners:     utils.NewStringValue("owner-test"),
   867  		Comment:    utils.NewStringValue("comment-test"),
   868  		Department: utils.NewStringValue("department-test"),
   869  		Business:   utils.NewStringValue("business-test"),
   870  	}
   871  	ruleNum := 1
   872  	// 填充source规则
   873  	sources := make([]*apifault.SourceMatcher, 0, ruleNum)
   874  	for i := 0; i < ruleNum; i++ {
   875  		source := &apifault.SourceMatcher{
   876  			Service:   utils.NewStringValue(fmt.Sprintf("service-test-%d", i)),
   877  			Namespace: utils.NewStringValue(fmt.Sprintf("namespace-test-%d", i)),
   878  			Labels: map[string]*apimodel.MatchString{
   879  				fmt.Sprintf("name-%d", i): {
   880  					Type:  apimodel.MatchString_EXACT,
   881  					Value: utils.NewStringValue(fmt.Sprintf("value-%d", i)),
   882  				},
   883  				fmt.Sprintf("name-%d", i+1): {
   884  					Type:  apimodel.MatchString_REGEX,
   885  					Value: utils.NewStringValue(fmt.Sprintf("value-%d", i+1)),
   886  				},
   887  			},
   888  		}
   889  		sources = append(sources, source)
   890  	}
   891  
   892  	// 填充destination规则
   893  	destinations := make([]*apifault.DestinationSet, 0, ruleNum)
   894  	for i := 0; i < ruleNum; i++ {
   895  		destination := &apifault.DestinationSet{
   896  			Service:   utils.NewStringValue(fmt.Sprintf("service-test-%d", i)),
   897  			Namespace: utils.NewStringValue(fmt.Sprintf("namespace-test-%d", i)),
   898  			Metadata: map[string]*apimodel.MatchString{
   899  				fmt.Sprintf("name-%d", i): {
   900  					Type:  apimodel.MatchString_EXACT,
   901  					Value: utils.NewStringValue(fmt.Sprintf("value-%d", i)),
   902  				},
   903  				fmt.Sprintf("name-%d", i+1): {
   904  					Type:  apimodel.MatchString_REGEX,
   905  					Value: utils.NewStringValue(fmt.Sprintf("value-%d", i+1)),
   906  				},
   907  			},
   908  			Resource: 0,
   909  			Type:     0,
   910  			Scope:    0,
   911  			MetricWindow: &duration.Duration{
   912  				Seconds: int64(i),
   913  			},
   914  			MetricPrecision: utils.NewUInt32Value(uint32(i)),
   915  			UpdateInterval: &duration.Duration{
   916  				Seconds: int64(i),
   917  			},
   918  			Recover: &apifault.RecoverConfig{},
   919  			Policy:  &apifault.CbPolicy{},
   920  		}
   921  		destinations = append(destinations, destination)
   922  	}
   923  
   924  	// 填充inbound规则
   925  	inbounds := make([]*apifault.CbRule, 0, ruleNum)
   926  	for i := 0; i < ruleNum; i++ {
   927  		inbound := &apifault.CbRule{
   928  			Sources:      sources,
   929  			Destinations: destinations,
   930  		}
   931  		inbounds = append(inbounds, inbound)
   932  	}
   933  	// 填充outbound规则
   934  	outbounds := make([]*apifault.CbRule, 0, ruleNum)
   935  	for i := 0; i < ruleNum; i++ {
   936  		outbound := &apifault.CbRule{
   937  			Sources:      sources,
   938  			Destinations: destinations,
   939  		}
   940  		outbounds = append(outbounds, outbound)
   941  	}
   942  	circuitBreaker.Inbounds = inbounds
   943  	circuitBreaker.Outbounds = outbounds
   944  
   945  	resp := d.DiscoverServer().CreateCircuitBreakers(d.DefaultCtx, []*apifault.CircuitBreaker{circuitBreaker})
   946  	if !respSuccess(resp) {
   947  		t.Fatalf("error: %+v", resp)
   948  	}
   949  	return circuitBreaker, resp.Responses[0].GetCircuitBreaker()
   950  }
   951  
   952  // 增加熔断规则版本
   953  func (d *DiscoverTestSuit) createCommonCircuitBreakerVersion(t *testing.T, cb *apifault.CircuitBreaker, index int) (
   954  	*apifault.CircuitBreaker, *apifault.CircuitBreaker) {
   955  	cbVersion := &apifault.CircuitBreaker{
   956  		Id:        cb.GetId(),
   957  		Name:      cb.GetName(),
   958  		Namespace: cb.GetNamespace(),
   959  		Version:   utils.NewStringValue(fmt.Sprintf("test-version-%d", index)),
   960  		Inbounds:  cb.GetInbounds(),
   961  		Outbounds: cb.GetOutbounds(),
   962  		Token:     cb.GetToken(),
   963  	}
   964  
   965  	resp := d.DiscoverServer().CreateCircuitBreakerVersions(d.DefaultCtx, []*apifault.CircuitBreaker{cbVersion})
   966  	if !respSuccess(resp) {
   967  		t.Fatalf("error: %+v", resp)
   968  	}
   969  	return cbVersion, resp.Responses[0].GetCircuitBreaker()
   970  }
   971  
   972  // 删除熔断规则
   973  func (d *DiscoverTestSuit) deleteCircuitBreaker(t *testing.T, circuitBreaker *apifault.CircuitBreaker) {
   974  	if resp := d.DiscoverServer().DeleteCircuitBreakers(
   975  		d.DefaultCtx, []*apifault.CircuitBreaker{circuitBreaker}); !respSuccess(resp) {
   976  		t.Fatalf("%s", resp.GetInfo().GetValue())
   977  	}
   978  }
   979  
   980  // 更新熔断规则内容
   981  func (d *DiscoverTestSuit) updateCircuitBreaker(t *testing.T, circuitBreaker *apifault.CircuitBreaker) {
   982  	if resp := d.DiscoverServer().UpdateCircuitBreakers(
   983  		d.DefaultCtx, []*apifault.CircuitBreaker{circuitBreaker}); !respSuccess(resp) {
   984  		t.Fatalf("%s", resp.GetInfo().GetValue())
   985  	}
   986  }
   987  
   988  // 发布熔断规则
   989  func (d *DiscoverTestSuit) releaseCircuitBreaker(
   990  	t *testing.T, cb *apifault.CircuitBreaker, service *apiservice.Service) {
   991  	release := &apiservice.ConfigRelease{
   992  		Service:        service,
   993  		CircuitBreaker: cb,
   994  	}
   995  
   996  	resp := d.DiscoverServer().ReleaseCircuitBreakers(d.DefaultCtx, []*apiservice.ConfigRelease{release})
   997  	if !respSuccess(resp) {
   998  		t.Fatalf("error: %+v", resp)
   999  	}
  1000  }
  1001  
  1002  // 解绑熔断规则
  1003  func (d *DiscoverTestSuit) unBindCircuitBreaker(
  1004  	t *testing.T, cb *apifault.CircuitBreaker, service *apiservice.Service) {
  1005  	unbind := &apiservice.ConfigRelease{
  1006  		Service:        service,
  1007  		CircuitBreaker: cb,
  1008  	}
  1009  
  1010  	resp := d.DiscoverServer().UnBindCircuitBreakers(d.DefaultCtx, []*apiservice.ConfigRelease{unbind})
  1011  	if !respSuccess(resp) {
  1012  		t.Fatalf("error: %+v", resp)
  1013  	}
  1014  }
  1015  
  1016  // 对比熔断规则的各个属性
  1017  func checkCircuitBreaker(
  1018  	t *testing.T, expect, expectMaster *apifault.CircuitBreaker, actual *apifault.CircuitBreaker) {
  1019  	switch {
  1020  	case expectMaster.GetId().GetValue() != actual.GetId().GetValue():
  1021  		t.Fatal("error id")
  1022  	case expect.GetVersion().GetValue() != actual.GetVersion().GetValue():
  1023  		t.Fatal("error version")
  1024  	case expectMaster.GetName().GetValue() != actual.GetName().GetValue():
  1025  		t.Fatal("error name")
  1026  	case expectMaster.GetNamespace().GetValue() != actual.GetNamespace().GetValue():
  1027  		t.Fatal("error namespace")
  1028  	case expectMaster.GetOwners().GetValue() != actual.GetOwners().GetValue():
  1029  		t.Fatal("error owners")
  1030  	case expectMaster.GetComment().GetValue() != actual.GetComment().GetValue():
  1031  		t.Fatal("error comment")
  1032  	case expectMaster.GetBusiness().GetValue() != actual.GetBusiness().GetValue():
  1033  		t.Fatal("error business")
  1034  	case expectMaster.GetDepartment().GetValue() != actual.GetDepartment().GetValue():
  1035  		t.Fatal("error department")
  1036  	default:
  1037  		break
  1038  	}
  1039  
  1040  	expectInbounds, err := json.Marshal(expect.GetInbounds())
  1041  	if err != nil {
  1042  		panic(err)
  1043  	}
  1044  	inbounds, err := json.Marshal(actual.GetInbounds())
  1045  	if err != nil {
  1046  		panic(err)
  1047  	}
  1048  	if string(expectInbounds) != string(inbounds) {
  1049  		t.Fatal("error inbounds")
  1050  	}
  1051  
  1052  	expectOutbounds, err := json.Marshal(expect.GetOutbounds())
  1053  	if err != nil {
  1054  		panic(err)
  1055  	}
  1056  	outbounds, err := json.Marshal(actual.GetOutbounds())
  1057  	if err != nil {
  1058  		panic(err)
  1059  	}
  1060  	if string(expectOutbounds) != string(outbounds) {
  1061  		t.Fatal("error inbounds")
  1062  	}
  1063  }
  1064  
  1065  func buildCircuitBreakerKey(id, version string) string {
  1066  	return fmt.Sprintf("%s_%s", id, version)
  1067  }
  1068  
  1069  // 彻底删除熔断规则
  1070  func (d *DiscoverTestSuit) cleanCircuitBreaker(id, version string) {
  1071  	d.GetTestDataClean().CleanCircuitBreaker(id, version)
  1072  }
  1073  
  1074  // 彻底删除熔断规则发布记录
  1075  func (d *DiscoverTestSuit) cleanCircuitBreakerRelation(name, namespace, ruleID, ruleVersion string) {
  1076  	d.GetTestDataClean().CleanCircuitBreakerRelation(name, namespace, ruleID, ruleVersion)
  1077  }
  1078  
  1079  func (d *DiscoverTestSuit) cleanReportClient() {
  1080  	d.GetTestDataClean().CleanReportClient()
  1081  }
  1082  
  1083  func (d *DiscoverTestSuit) cleanServices(services []*apiservice.Service) {
  1084  	d.GetTestDataClean().CleanServices(services)
  1085  }
  1086  
  1087  func (d *DiscoverTestSuit) cleanNamespace(n string) {
  1088  	d.GetTestDataClean().CleanNamespace(n)
  1089  }
  1090  
  1091  func (d *DiscoverTestSuit) cleanAllService() {
  1092  	d.GetTestDataClean().CleanAllService()
  1093  }
  1094  
  1095  // 获取指定长度str
  1096  func genSpecialStr(n int) string {
  1097  	str := ""
  1098  	for i := 0; i < n; i++ {
  1099  		str += "a"
  1100  	}
  1101  	return str
  1102  }
  1103  
  1104  // 解析字符串sid为modID和cmdID
  1105  func parseStr2Sid(sid string) (uint32, uint32) {
  1106  	items := strings.Split(sid, ":")
  1107  	if len(items) != 2 {
  1108  		return 0, 0
  1109  	}
  1110  
  1111  	mod, _ := strconv.ParseUint(items[0], 10, 32)
  1112  	cmd, _ := strconv.ParseUint(items[1], 10, 32)
  1113  	return uint32(mod), uint32(cmd)
  1114  }
  1115  
  1116  // 判断一个resp是否执行成功
  1117  func respSuccess(resp api.ResponseMessage) bool {
  1118  
  1119  	ret := api.CalcCode(resp) == 200
  1120  
  1121  	return ret
  1122  }
  1123  
  1124  func respNotFound(resp api.ResponseMessage) bool {
  1125  	res := apimodel.Code(resp.GetCode().GetValue()) == apimodel.Code_NotFoundResource
  1126  
  1127  	return res
  1128  }
  1129  
  1130  func rollbackDbTx(dbTx *sqldb.BaseTx) {
  1131  	if err := dbTx.Rollback(); err != nil {
  1132  		log.Errorf("fail to rollback db tx, err %v", err)
  1133  	}
  1134  }
  1135  
  1136  func commitDbTx(dbTx *sqldb.BaseTx) {
  1137  	if err := dbTx.Commit(); err != nil {
  1138  		log.Errorf("fail to commit db tx, err %v", err)
  1139  	}
  1140  }
  1141  
  1142  func rollbackBoltTx(tx *bolt.Tx) {
  1143  	if err := tx.Rollback(); err != nil {
  1144  		log.Errorf("fail to rollback bolt tx, err %v", err)
  1145  	}
  1146  }
  1147  
  1148  func commitBoltTx(tx *bolt.Tx) {
  1149  	if err := tx.Commit(); err != nil {
  1150  		log.Errorf("fail to commit bolt tx, err %v", err)
  1151  	}
  1152  }