github.com/polarismesh/polaris@v1.17.8/apiserver/eurekaserver/applications_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 eurekaserver
    19  
    20  import (
    21  	"strconv"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/golang/protobuf/ptypes/wrappers"
    27  	"github.com/google/uuid"
    28  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    29  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    30  	"github.com/stretchr/testify/assert"
    31  
    32  	"github.com/polarismesh/polaris/common/model"
    33  	"github.com/polarismesh/polaris/service"
    34  )
    35  
    36  const (
    37  	defaultSvcCount     = 10
    38  	productionSvcCount  = 5
    39  	unhealthySvcCount   = 5
    40  	instanceCount       = 20
    41  	namespaceDefault    = "default"
    42  	namespaceProduction = "production"
    43  	hostPrefix          = "127.0.0."
    44  	port                = 10011
    45  )
    46  
    47  type svcName struct {
    48  	name      string
    49  	namespace string
    50  }
    51  
    52  var (
    53  	mockServices           = map[svcName]*model.Service{}
    54  	mockInstances          = map[string]map[string]*model.Instance{}
    55  	mockUnhealthyServices  = map[svcName]*model.Service{}
    56  	mockUnhealthyInstances = map[string]map[string]*model.Instance{}
    57  )
    58  
    59  func buildServices(count int, namespace string, services map[svcName]*model.Service) {
    60  	for i := 0; i < count; i++ {
    61  		name := svcName{
    62  			name:      namespace + "_svc_" + strconv.Itoa(i),
    63  			namespace: namespace,
    64  		}
    65  		services[name] = &model.Service{
    66  			ID:        uuid.NewString(),
    67  			Name:      name.name,
    68  			Namespace: name.namespace,
    69  		}
    70  	}
    71  }
    72  
    73  func buildMockInstance(idx int, svc *model.Service, healthy bool, vipAddresses string, svipAddresses string) *model.Instance {
    74  	instance := &model.Instance{
    75  		Proto: &apiservice.Instance{
    76  			Id:                &wrappers.StringValue{Value: uuid.NewString()},
    77  			Service:           &wrappers.StringValue{Value: svc.Name},
    78  			Namespace:         &wrappers.StringValue{Value: svc.Namespace},
    79  			Host:              &wrappers.StringValue{Value: hostPrefix + strconv.Itoa(idx)},
    80  			Port:              &wrappers.UInt32Value{Value: port},
    81  			Protocol:          &wrappers.StringValue{Value: InsecureProtocol},
    82  			Version:           &wrappers.StringValue{Value: "1.0.0"},
    83  			Weight:            &wrappers.UInt32Value{Value: 100},
    84  			EnableHealthCheck: &wrappers.BoolValue{Value: true},
    85  			HealthCheck: &apiservice.HealthCheck{Type: apiservice.HealthCheck_HEARTBEAT, Heartbeat: &apiservice.HeartbeatHealthCheck{
    86  				Ttl: nil,
    87  			}},
    88  			Healthy: &wrappers.BoolValue{Value: healthy},
    89  			Isolate: &wrappers.BoolValue{Value: false},
    90  			Location: &apimodel.Location{
    91  				Region: &wrappers.StringValue{Value: "South China"},
    92  				Zone:   &wrappers.StringValue{Value: "ShangHai"},
    93  				Campus: &wrappers.StringValue{Value: "CampusOne"},
    94  			},
    95  			Metadata: map[string]string{
    96  				MetadataRegisterFrom:        ServerEureka,
    97  				MetadataCountryId:           DefaultCountryId,
    98  				MetadataHostName:            svc.Namespace + "." + svc.Name + "." + strconv.Itoa(port) + "." + strconv.Itoa(idx),
    99  				MetadataInsecurePort:        strconv.Itoa(port),
   100  				MetadataInsecurePortEnabled: "true",
   101  				MetadataSecurePortEnabled:   "false",
   102  			},
   103  		},
   104  		ServiceID:  svc.ID,
   105  		Valid:      true,
   106  		ModifyTime: time.Now(),
   107  	}
   108  	if len(vipAddresses) > 0 {
   109  		instance.Proto.Metadata[MetadataVipAddress] = vipAddresses
   110  	}
   111  	if len(svipAddresses) > 0 {
   112  		instance.Proto.Metadata[MetadataSecureVipAddress] = svipAddresses
   113  	}
   114  	return instance
   115  }
   116  
   117  func buildMockSvcInstances() {
   118  	buildServices(defaultSvcCount, namespaceDefault, mockServices)
   119  	buildServices(productionSvcCount, namespaceProduction, mockServices)
   120  	idx := 0
   121  	for _, svc := range mockServices {
   122  		instances := make(map[string]*model.Instance, instanceCount)
   123  		for i := 0; i < instanceCount; i++ {
   124  			idx++
   125  			instance := buildMockInstance(idx, svc, true, "", "")
   126  			instances[instance.ID()] = instance
   127  		}
   128  		mockInstances[svc.ID] = instances
   129  	}
   130  }
   131  
   132  func buildMockUnhealthyInstances() {
   133  	buildServices(unhealthySvcCount, namespaceDefault, mockUnhealthyServices)
   134  	idx := 0
   135  	for _, svc := range mockUnhealthyServices {
   136  		var allUnhealthy bool
   137  		if idx%(3*instanceCount) == 0 {
   138  			allUnhealthy = true
   139  		}
   140  		instances := make(map[string]*model.Instance, instanceCount)
   141  		for i := 0; i < instanceCount; i++ {
   142  			idx++
   143  			instance := buildMockInstance(idx, svc, !allUnhealthy, "", "")
   144  			instances[instance.ID()] = instance
   145  		}
   146  		mockUnhealthyInstances[svc.ID] = instances
   147  	}
   148  
   149  }
   150  
   151  func mockGetCacheServices(namingServer service.DiscoverServer, namespace string) map[string]*model.Service {
   152  	var newServices = make(map[string]*model.Service)
   153  	for _, svc := range mockServices {
   154  		if namespace == svc.Namespace {
   155  			newServices[svc.ID] = svc
   156  		}
   157  	}
   158  	return newServices
   159  }
   160  
   161  func mockGetCacheInstances(namingServer service.DiscoverServer, svcId string) ([]*model.Instance, string, error) {
   162  	instances := mockInstances[svcId]
   163  	var retValue = make([]*model.Instance, 0, len(instances))
   164  	if len(instances) == 0 {
   165  		return retValue, uuid.NewString(), nil
   166  	}
   167  	for _, instance := range instances {
   168  		retValue = append(retValue, instance)
   169  	}
   170  	return retValue, uuid.NewString(), nil
   171  }
   172  
   173  func doFunctionMock() {
   174  	buildMockSvcInstances()
   175  	getCacheServicesFunc = mockGetCacheServices
   176  	getCacheInstancesFunc = mockGetCacheInstances
   177  }
   178  
   179  // TestApplicationsBuilder_BuildApplications testing method for application builder
   180  func TestApplicationsBuilder_BuildApplications(t *testing.T) {
   181  	doFunctionMock()
   182  	builder := &ApplicationsBuilder{
   183  		namespace:              DefaultNamespace,
   184  		enableSelfPreservation: true,
   185  	}
   186  	appResCache := builder.BuildApplications(nil)
   187  	applications := appResCache.AppsResp.Applications.Application
   188  	assert.Equal(t, defaultSvcCount, len(applications))
   189  	for _, application := range applications {
   190  		serviceName := svcName{
   191  			name:      strings.ToLower(application.Name),
   192  			namespace: DefaultNamespace,
   193  		}
   194  		svc, ok := mockServices[serviceName]
   195  		assert.True(t, ok)
   196  		instances := application.Instance
   197  		mInstances := mockInstances[svc.ID]
   198  		for _, instance := range instances {
   199  			mInstance, ok := mInstances[instance.InstanceId]
   200  			assert.True(t, ok)
   201  			assert.Equal(t, instance.Port.Port, int(mInstance.Port()))
   202  			assert.Equal(t, instance.IpAddr, mInstance.Host())
   203  			assert.Equal(t, mInstance.Location().GetRegion().GetValue(), instance.Metadata.Meta[KeyRegion])
   204  			assert.Equal(t, mInstance.Location().GetZone().GetValue(), instance.Metadata.Meta[keyZone])
   205  			assert.Equal(t, mInstance.Location().GetCampus().GetValue(), instance.Metadata.Meta[keyCampus])
   206  		}
   207  	}
   208  }
   209  
   210  func doUnhealthyFunctionMock() {
   211  	buildMockUnhealthyInstances()
   212  	getCacheServicesFunc = mockGetUnhealthyServices
   213  	getCacheInstancesFunc = mockGetUnhealthyInstances
   214  }
   215  
   216  func mockGetUnhealthyServices(namingServer service.DiscoverServer, namespace string) map[string]*model.Service {
   217  	var newServices = make(map[string]*model.Service)
   218  	for _, svc := range mockUnhealthyServices {
   219  		if namespace == svc.Namespace {
   220  			newServices[svc.ID] = svc
   221  		}
   222  	}
   223  	return newServices
   224  }
   225  
   226  func mockGetUnhealthyInstances(namingServer service.DiscoverServer, svcId string) ([]*model.Instance, string, error) {
   227  	instances := mockUnhealthyInstances[svcId]
   228  	var retValue = make([]*model.Instance, 0, len(instances))
   229  	if len(instances) == 0 {
   230  		return retValue, uuid.NewString(), nil
   231  	}
   232  	for _, instance := range instances {
   233  		retValue = append(retValue, instance)
   234  	}
   235  	return retValue, uuid.NewString(), nil
   236  }
   237  
   238  // TestBuildDataCenterInfo test to build dci info
   239  func TestBuildDataCenterInfo(t *testing.T) {
   240  	CustomEurekaParameters[CustomKeyDciClass] = "com.netflix.appinfo.AmazonInfo"
   241  	CustomEurekaParameters[CustomKeyDciName] = "testOwn"
   242  	dciInfo := buildDataCenterInfo()
   243  	assert.Equal(t, CustomEurekaParameters[CustomKeyDciClass], dciInfo.Clazz)
   244  	assert.Equal(t, CustomEurekaParameters[CustomKeyDciName], dciInfo.Name)
   245  	delete(CustomEurekaParameters, CustomKeyDciName)
   246  	dciInfo = buildDataCenterInfo()
   247  	assert.Equal(t, CustomEurekaParameters[CustomKeyDciClass], dciInfo.Clazz)
   248  	assert.Equal(t, DefaultDciName, dciInfo.Name)
   249  	delete(CustomEurekaParameters, CustomKeyDciClass)
   250  	CustomEurekaParameters[CustomKeyDciName] = "testOwn"
   251  	dciInfo = buildDataCenterInfo()
   252  	assert.Equal(t, DefaultDciClazz, dciInfo.Clazz)
   253  	assert.Equal(t, CustomEurekaParameters[CustomKeyDciName], dciInfo.Name)
   254  	delete(CustomEurekaParameters, CustomKeyDciName)
   255  	dciInfo = buildDataCenterInfo()
   256  	assert.Equal(t, DefaultDciClazz, dciInfo.Clazz)
   257  	assert.Equal(t, DefaultDciName, dciInfo.Name)
   258  }
   259  
   260  // TestBuildInstance test to build the instance
   261  func TestBuildInstance(t *testing.T) {
   262  	CustomEurekaParameters[CustomKeyDciClass] = "com.netflix.appinfo.AmazonInfo"
   263  	svc := &model.Service{ID: "111", Name: "testInst0", Namespace: "test"}
   264  	instance := buildMockInstance(0, svc, true, "xxx.com", "yyyy.com")
   265  	instanceInfo := buildInstance(svc.Name, instance.Proto, 123345550)
   266  	assert.Equal(t, CustomEurekaParameters[CustomKeyDciClass], instanceInfo.DataCenterInfo.Clazz)
   267  }