github.com/polarismesh/polaris@v1.17.8/config/client_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 config_test
    19  
    20  import (
    21  	"fmt"
    22  	"strconv"
    23  	"testing"
    24  	"time"
    25  
    26  	apiconfig "github.com/polarismesh/specification/source/go/api/v1/config_manage"
    27  	"github.com/stretchr/testify/assert"
    28  	"google.golang.org/protobuf/types/known/wrapperspb"
    29  
    30  	api "github.com/polarismesh/polaris/common/api/v1"
    31  	commonlog "github.com/polarismesh/polaris/common/log"
    32  	"github.com/polarismesh/polaris/common/model"
    33  	"github.com/polarismesh/polaris/common/utils"
    34  	"github.com/polarismesh/polaris/config"
    35  	testsuit "github.com/polarismesh/polaris/test/suit"
    36  )
    37  
    38  // TestClientSetupAndFileNotExisted 测试客户端启动时(version=0),并且配置不存在的情况下拉取配置
    39  func TestClientSetupAndFileNotExisted(t *testing.T) {
    40  	testSuit := &ConfigCenterTest{}
    41  	if err := testSuit.Initialize(); err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	t.Cleanup(func() {
    45  		if err := testSuit.clearTestData(); err != nil {
    46  			t.Fatal(err)
    47  		}
    48  		testSuit.Destroy()
    49  	})
    50  
    51  	fileInfo := &apiconfig.ClientConfigFileInfo{
    52  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
    53  		Group:     &wrapperspb.StringValue{Value: testGroup},
    54  		FileName:  &wrapperspb.StringValue{Value: testFile},
    55  		Version:   &wrapperspb.UInt64Value{Value: 0},
    56  	}
    57  
    58  	rsp := testSuit.ConfigServer().GetConfigFileForClient(testSuit.DefaultCtx, fileInfo)
    59  	assert.Equal(t, uint32(api.NotFoundResource), rsp.Code.GetValue(), "GetConfigFileForClient must notfound")
    60  
    61  	originSvr := testSuit.OriginConfigServer()
    62  	rsp2, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByVersion)
    63  	assert.Equal(t, uint32(api.DataNoChange), rsp2.Code.GetValue(), "checkClientConfigFileByVersion must nochange")
    64  	assert.Nil(t, rsp2.ConfigFile)
    65  
    66  	rsp3, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByMD5)
    67  	assert.Equal(t, uint32(api.DataNoChange), rsp3.Code.GetValue())
    68  	assert.Nil(t, rsp3.ConfigFile)
    69  }
    70  
    71  // TestClientSetupAndFileExisted 测试客户端启动时(version=0),并且配置存在的情况下拉取配置
    72  func TestClientSetupAndFileExisted(t *testing.T) {
    73  	testSuit := &ConfigCenterTest{}
    74  	if err := testSuit.Initialize(); err != nil {
    75  		t.Fatal(err)
    76  	}
    77  	t.Cleanup(func() {
    78  		if err := testSuit.clearTestData(); err != nil {
    79  			t.Fatal(err)
    80  		}
    81  		testSuit.Destroy()
    82  	})
    83  
    84  	// 创建并发布一个配置文件
    85  	configFile := assembleConfigFile()
    86  	rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
    87  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue(), rsp.GetInfo().GetValue())
    88  
    89  	rsp2 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, assembleConfigFileRelease(configFile))
    90  	assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue(), rsp.GetInfo().GetValue())
    91  
    92  	fileInfo := &apiconfig.ClientConfigFileInfo{
    93  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
    94  		Group:     &wrapperspb.StringValue{Value: testGroup},
    95  		FileName:  &wrapperspb.StringValue{Value: testFile},
    96  		Version:   &wrapperspb.UInt64Value{Value: 0},
    97  	}
    98  
    99  	// 强制 Cache 层 load 到本地
   100  	_ = testSuit.DiscoverServer().Cache().ConfigFile().Update()
   101  
   102  	// 拉取配置接口
   103  	rsp3 := testSuit.ConfigServer().GetConfigFileForClient(testSuit.DefaultCtx, fileInfo)
   104  	assert.Equalf(t, api.ExecuteSuccess, rsp3.Code.GetValue(), "GetConfigFileForClient must success, acutal code : %d", rsp3.Code.GetValue())
   105  	assert.NotNil(t, rsp3.ConfigFile)
   106  	assert.Equal(t, uint64(1), rsp3.ConfigFile.Version.GetValue())
   107  	assert.Equal(t, configFile.Content.GetValue(), rsp3.ConfigFile.Content.GetValue())
   108  	assert.Equal(t, config.CalMd5(configFile.Content.GetValue()), rsp3.ConfigFile.Md5.GetValue())
   109  
   110  	// 比较客户端配置是否落后
   111  	originSvr := testSuit.OriginConfigServer()
   112  	rsp4, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByVersion)
   113  	assert.Equal(t, api.ExecuteSuccess, rsp4.Code.GetValue(), rsp4.GetInfo().GetValue())
   114  	assert.NotNil(t, rsp4.ConfigFile)
   115  	assert.Equal(t, config.CalMd5(configFile.Content.GetValue()), rsp4.ConfigFile.Md5.GetValue())
   116  
   117  	rsp5, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByMD5)
   118  	assert.Equal(t, api.ExecuteSuccess, rsp5.Code.GetValue(), rsp5.GetInfo().GetValue())
   119  	assert.NotNil(t, rsp5.ConfigFile)
   120  	assert.Equal(t, uint64(1), rsp5.ConfigFile.Version.GetValue())
   121  	assert.Equal(t, config.CalMd5(configFile.Content.GetValue()), rsp5.ConfigFile.Md5.GetValue())
   122  }
   123  
   124  // TestClientSetupAndCreateNewFile 测试客户端启动时(version=0),并且配置不存在的情况下创建新的配置
   125  func TestClientSetupAndCreateNewFile(t *testing.T) {
   126  	testSuit := &ConfigCenterTest{}
   127  	if err := testSuit.Initialize(); err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	t.Cleanup(func() {
   131  		if err := testSuit.clearTestData(); err != nil {
   132  			t.Fatal(err)
   133  		}
   134  		testSuit.Destroy()
   135  	})
   136  
   137  	fileInfo := &apiconfig.ConfigFile{
   138  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   139  		Group:     &wrapperspb.StringValue{Value: testGroup},
   140  		Name:      &wrapperspb.StringValue{Value: testFile},
   141  		Content:   &wrapperspb.StringValue{Value: testContent},
   142  	}
   143  
   144  	rsp := testSuit.ConfigServer().CreateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   145  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue(), rsp.GetInfo().GetValue())
   146  
   147  	originSvr := testSuit.OriginConfigServer()
   148  	rsp2, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByVersion)
   149  	assert.Equal(t, api.DataNoChange, rsp2.Code.GetValue(), rsp2.GetInfo().GetValue())
   150  	assert.Nil(t, rsp2.ConfigFile)
   151  
   152  	rsp3, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByMD5)
   153  	assert.Equal(t, api.DataNoChange, rsp3.Code.GetValue(), rsp3.GetInfo().GetValue())
   154  	assert.Nil(t, rsp3.ConfigFile)
   155  }
   156  
   157  // TestClientSetupAndCreateExistFile 测试客户端启动时(version=0),并且配置存在的情况下重复创建配置
   158  func TestClientSetupAndCreateExistFile(t *testing.T) {
   159  	testSuit := &ConfigCenterTest{}
   160  	if err := testSuit.Initialize(); err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	t.Cleanup(func() {
   164  		if err := testSuit.clearTestData(); err != nil {
   165  			t.Fatal(err)
   166  		}
   167  		testSuit.Destroy()
   168  	})
   169  
   170  	fileInfo := &apiconfig.ConfigFile{
   171  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   172  		Group:     &wrapperspb.StringValue{Value: testGroup},
   173  		Name:      &wrapperspb.StringValue{Value: testFile},
   174  		Content:   &wrapperspb.StringValue{Value: testContent},
   175  	}
   176  
   177  	// 第一次创建
   178  	rsp := testSuit.ConfigServer().CreateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   179  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue(), "First CreateConfigFileFromClient must success")
   180  
   181  	// 第二次创建
   182  	rsp1 := testSuit.ConfigServer().CreateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   183  	assert.Equal(t, api.ExistedResource, rsp1.Code.GetValue(), "CreateConfigFileFromClient again must error")
   184  
   185  	originSvr := testSuit.OriginConfigServer()
   186  	rsp2, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByVersion)
   187  	assert.Equal(t, api.DataNoChange, rsp2.Code.GetValue(), "checkClientConfigFileByVersion must nochange")
   188  	assert.Nil(t, rsp2.ConfigFile)
   189  
   190  	rsp3, _ := originSvr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(0), config.TestCompareByMD5)
   191  	assert.Equal(t, api.DataNoChange, rsp3.Code.GetValue())
   192  	assert.Nil(t, rsp3.ConfigFile)
   193  }
   194  
   195  // TestClientSetupAndUpdateNewFile 测试客户端启动时(version=0),更新不存在的配置
   196  func TestClientSetupAndUpdateNewFile(t *testing.T) {
   197  	testSuit := &ConfigCenterTest{}
   198  	if err := testSuit.Initialize(); err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	t.Cleanup(func() {
   202  		if err := testSuit.clearTestData(); err != nil {
   203  			t.Fatal(err)
   204  		}
   205  		testSuit.Destroy()
   206  	})
   207  
   208  	fileInfo := &apiconfig.ConfigFile{
   209  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   210  		Group:     &wrapperspb.StringValue{Value: testGroup},
   211  		Name:      &wrapperspb.StringValue{Value: testFile},
   212  		Content:   &wrapperspb.StringValue{Value: testContent},
   213  	}
   214  
   215  	// 直接更新
   216  	rsp := testSuit.ConfigServer().UpdateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   217  	assert.Equal(t, api.NotFoundResource, rsp.Code.GetValue(), "UpdateConfigFileFromClient with no exist file must error")
   218  }
   219  
   220  // TestClientSetupAndUpdateExistFile 测试客户端启动时(version=0),更新存在的配置
   221  func TestClientSetupAndUpdateExistFile(t *testing.T) {
   222  	testSuit := &ConfigCenterTest{}
   223  	if err := testSuit.Initialize(); err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	t.Cleanup(func() {
   227  		if err := testSuit.clearTestData(); err != nil {
   228  			t.Fatal(err)
   229  		}
   230  		testSuit.Destroy()
   231  	})
   232  
   233  	fileInfo := &apiconfig.ConfigFile{
   234  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   235  		Group:     &wrapperspb.StringValue{Value: testGroup},
   236  		Name:      &wrapperspb.StringValue{Value: testFile},
   237  		Content:   &wrapperspb.StringValue{Value: testContent},
   238  	}
   239  
   240  	// 先创建
   241  	rsp := testSuit.ConfigServer().CreateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   242  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue(), "CreateConfigFileFromClient must success")
   243  
   244  	// 再更新
   245  	fileInfo.Content = &wrapperspb.StringValue{Value: testContent + "1"}
   246  	rsp1 := testSuit.ConfigServer().UpdateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   247  	assert.Equal(t, api.ExecuteSuccess, rsp1.Code.GetValue(), "UpdateConfigFileFromClient must success")
   248  
   249  }
   250  
   251  // TestClientSetupAndPublishNewFile 测试客户端启动时(version=0),发布不存在的配置
   252  func TestClientSetupAndPublishNewFile(t *testing.T) {
   253  	testSuit := &ConfigCenterTest{}
   254  	if err := testSuit.Initialize(); err != nil {
   255  		t.Fatal(err)
   256  	}
   257  	t.Cleanup(func() {
   258  		if err := testSuit.clearTestData(); err != nil {
   259  			t.Fatal(err)
   260  		}
   261  		testSuit.Destroy()
   262  	})
   263  
   264  	fileReleaseInfo := &apiconfig.ConfigFileRelease{
   265  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   266  		Group:     &wrapperspb.StringValue{Value: testGroup},
   267  		FileName:  &wrapperspb.StringValue{Value: testFile},
   268  		Content:   &wrapperspb.StringValue{Value: testContent},
   269  	}
   270  
   271  	// 直接发布
   272  	rsp := testSuit.ConfigServer().PublishConfigFileFromClient(testSuit.DefaultCtx, fileReleaseInfo)
   273  	assert.Equal(t, api.NotFoundNamespace, rsp.Code.GetValue(), "PublishConfigFileFromClient with no exist file must error")
   274  }
   275  
   276  // TestClientSetupAndPublishExistFile 测试客户端启动时(version=0),发布存在的配置
   277  func TestClientSetupAndPublishExistFile(t *testing.T) {
   278  	testSuit := &ConfigCenterTest{}
   279  	if err := testSuit.Initialize(); err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	t.Cleanup(func() {
   283  		if err := testSuit.clearTestData(); err != nil {
   284  			t.Fatal(err)
   285  		}
   286  		testSuit.Destroy()
   287  	})
   288  
   289  	fileInfo := &apiconfig.ConfigFile{
   290  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   291  		Group:     &wrapperspb.StringValue{Value: testGroup},
   292  		Name:      &wrapperspb.StringValue{Value: testFile},
   293  		Content:   &wrapperspb.StringValue{Value: testContent},
   294  	}
   295  
   296  	// 先创建
   297  	rsp := testSuit.ConfigServer().CreateConfigFileFromClient(testSuit.DefaultCtx, fileInfo)
   298  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue(), "CreateConfigFileFromClient must success")
   299  
   300  	// 再发布
   301  	fileReleaseInfo := &apiconfig.ConfigFileRelease{
   302  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   303  		Group:     &wrapperspb.StringValue{Value: testGroup},
   304  		FileName:  &wrapperspb.StringValue{Value: testFile},
   305  		Content:   &wrapperspb.StringValue{Value: testContent},
   306  	}
   307  	rsp1 := testSuit.ConfigServer().PublishConfigFileFromClient(testSuit.DefaultCtx, fileReleaseInfo)
   308  	assert.Equal(t, api.ExecuteSuccess, rsp1.Code.GetValue(), "PublishConfigFileFromClient must success")
   309  
   310  }
   311  
   312  // TestClientVersionBehindServer 测试客户端版本落后服务端
   313  func TestClientVersionBehindServer(t *testing.T) {
   314  	testSuit := &ConfigCenterTest{}
   315  	if err := testSuit.Initialize(); err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	t.Cleanup(func() {
   319  		if err := testSuit.clearTestData(); err != nil {
   320  			t.Fatal(err)
   321  		}
   322  		testSuit.Destroy()
   323  	})
   324  
   325  	// 创建并连续发布5次
   326  	configFile := assembleConfigFile()
   327  	rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   328  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   329  
   330  	for i := 0; i < 5; i++ {
   331  		configFile.Content = utils.NewStringValue("content" + strconv.Itoa(i))
   332  		// 更新
   333  		rsp2 := testSuit.ConfigServer().UpdateConfigFile(testSuit.DefaultCtx, configFile)
   334  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   335  		// 发布
   336  		rsp3 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, assembleConfigFileRelease(configFile))
   337  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue(), rsp3.GetInfo().GetValue())
   338  	}
   339  
   340  	// 客户端版本号为4, 服务端由于连续发布5次,所以版本号为5
   341  	clientVersion := uint64(4)
   342  	latestContent := "content4"
   343  
   344  	fileInfo := &apiconfig.ClientConfigFileInfo{
   345  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   346  		Group:     &wrapperspb.StringValue{Value: testGroup},
   347  		FileName:  &wrapperspb.StringValue{Value: testFile},
   348  		Version:   &wrapperspb.UInt64Value{Value: clientVersion},
   349  	}
   350  
   351  	_ = testSuit.DiscoverServer().Cache().ConfigFile().Update()
   352  
   353  	// 拉取配置接口
   354  	rsp4 := testSuit.ConfigServer().GetConfigFileForClient(testSuit.DefaultCtx, fileInfo)
   355  	assert.Equal(t, api.ExecuteSuccess, rsp4.Code.GetValue())
   356  	assert.NotNil(t, rsp4.ConfigFile)
   357  	assert.Equal(t, uint64(5), rsp4.ConfigFile.Version.GetValue())
   358  	assert.Equal(t, latestContent, rsp4.ConfigFile.Content.GetValue())
   359  	assert.Equal(t, config.CalMd5(latestContent), rsp4.ConfigFile.Md5.GetValue())
   360  
   361  	svr := testSuit.OriginConfigServer()
   362  	// 比较客户端配置是否落后
   363  	rsp5, _ := svr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(clientVersion), config.TestCompareByVersion)
   364  	assert.Equal(t, api.ExecuteSuccess, rsp5.Code.GetValue())
   365  	assert.NotNil(t, rsp5.ConfigFile)
   366  	assert.Equal(t, config.CalMd5(latestContent), rsp5.ConfigFile.Md5.GetValue())
   367  
   368  	rsp6, _ := svr.TestCheckClientConfigFile(testSuit.DefaultCtx, assembleDefaultClientConfigFile(clientVersion), config.TestCompareByMD5)
   369  	assert.Equal(t, api.ExecuteSuccess, rsp6.Code.GetValue())
   370  	assert.NotNil(t, rsp6.ConfigFile)
   371  	assert.Equal(t, uint64(5), rsp6.ConfigFile.Version.GetValue())
   372  	assert.Equal(t, config.CalMd5(latestContent), rsp6.ConfigFile.Md5.GetValue())
   373  }
   374  
   375  // TestWatchConfigFileAtFirstPublish 测试监听配置,并且第一次发布配置
   376  func TestWatchConfigFileAtFirstPublish(t *testing.T) {
   377  	testSuit := &ConfigCenterTest{}
   378  	if err := testSuit.Initialize(func(cfg *testsuit.TestConfig) {
   379  		for _, v := range cfg.Bootstrap.Logger {
   380  			v.SetOutputLevel(commonlog.DebugLevel.Name())
   381  		}
   382  	}); err != nil {
   383  		t.Fatal(err)
   384  	}
   385  
   386  	t.Cleanup(func() {
   387  		if err := testSuit.clearTestData(); err != nil {
   388  			t.Fatal(err)
   389  		}
   390  		testSuit.Destroy()
   391  	})
   392  
   393  	// 创建并发布配置文件
   394  	configFile := assembleConfigFile()
   395  
   396  	t.Run("第一次订阅发布", func(t *testing.T) {
   397  		received := make(chan uint64)
   398  
   399  		watchConfigFiles := assembleDefaultClientConfigFile(0)
   400  		clientId := "TestWatchConfigFileAtFirstPublish-first"
   401  
   402  		defer func() {
   403  			testSuit.OriginConfigServer().WatchCenter().RemoveWatcher(clientId, watchConfigFiles)
   404  		}()
   405  
   406  		testSuit.OriginConfigServer().WatchCenter().AddWatcher(clientId, watchConfigFiles,
   407  			func(clientId string, rsp *apiconfig.ConfigClientResponse) bool {
   408  				t.Logf("clientId=[%s] receive config publish msg", clientId)
   409  				received <- rsp.ConfigFile.Version.GetValue()
   410  				return true
   411  			})
   412  
   413  		rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   414  		t.Log("create config file success")
   415  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   416  
   417  		rsp2 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, assembleConfigFileRelease(configFile))
   418  		t.Log("publish config file success")
   419  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   420  
   421  		saveData, err := testSuit.Storage.GetConfigFileActiveRelease(&model.ConfigFileKey{
   422  			Name:      configFile.GetName().GetValue(),
   423  			Namespace: configFile.GetNamespace().GetValue(),
   424  			Group:     configFile.GetGroup().GetValue(),
   425  		})
   426  		assert.NoError(t, err)
   427  		assert.Equal(t, configFile.GetContent().GetValue(), saveData.Content)
   428  
   429  		select {
   430  		case receivedVersion := <-received:
   431  			assert.Equal(t, uint64(1), receivedVersion)
   432  		case <-time.After(10 * time.Second):
   433  			t.Fatal("time out")
   434  		}
   435  	})
   436  
   437  	t.Run("第二次订阅发布", func(t *testing.T) {
   438  
   439  		received := make(chan uint64)
   440  
   441  		// 版本号由于发布过一次,所以是1
   442  		watchConfigFiles := assembleDefaultClientConfigFile(1)
   443  
   444  		clientId := "TestWatchConfigFileAtFirstPublish-second"
   445  
   446  		testSuit.OriginConfigServer().WatchCenter().AddWatcher(clientId, watchConfigFiles,
   447  			func(clientId string, rsp *apiconfig.ConfigClientResponse) bool {
   448  				t.Logf("clientId=[%s] receive config publish msg", clientId)
   449  				received <- rsp.ConfigFile.Version.GetValue()
   450  				return true
   451  			})
   452  
   453  		rsp3 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, assembleConfigFileRelease(configFile))
   454  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
   455  
   456  		// 等待回调
   457  		select {
   458  		case receivedVersion := <-received:
   459  			assert.Equal(t, uint64(2), receivedVersion)
   460  		case <-time.After(10 * time.Second):
   461  			t.Fatal("time out")
   462  		}
   463  
   464  		// 为了避免影响其它 case,删除订阅
   465  		testSuit.OriginConfigServer().WatchCenter().RemoveWatcher(clientId, watchConfigFiles)
   466  	})
   467  }
   468  
   469  // Test10000ClientWatchConfigFile 测试 10000 个客户端同时监听配置变更,配置发布所有客户端都收到通知
   470  func Test10000ClientWatchConfigFile(t *testing.T) {
   471  	testSuit := &ConfigCenterTest{}
   472  	if err := testSuit.Initialize(); err != nil {
   473  		t.Fatal(err)
   474  	}
   475  	t.Cleanup(func() {
   476  		if err := testSuit.clearTestData(); err != nil {
   477  			t.Fatal(err)
   478  		}
   479  		testSuit.Destroy()
   480  	})
   481  
   482  	clientSize := 10000
   483  	received := make(map[string]bool)
   484  	receivedVersion := make(map[string]uint64)
   485  	watchConfigFiles := assembleDefaultClientConfigFile(0)
   486  	for i := 0; i < clientSize; i++ {
   487  		clientId := fmt.Sprintf("Test10000ClientWatchConfigFile-client-id=%d", i)
   488  		received[clientId] = false
   489  		receivedVersion[clientId] = uint64(0)
   490  		testSuit.OriginConfigServer().WatchCenter().AddWatcher(clientId, watchConfigFiles, func(clientId string, rsp *apiconfig.ConfigClientResponse) bool {
   491  			received[clientId] = true
   492  			receivedVersion[clientId] = rsp.ConfigFile.Version.GetValue()
   493  			return true
   494  		})
   495  	}
   496  
   497  	// 创建并发布配置文件
   498  	configFile := assembleConfigFile()
   499  	rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   500  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   501  
   502  	rsp2 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, assembleConfigFileRelease(configFile))
   503  	assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   504  
   505  	// 等待回调
   506  	time.Sleep(2000 * time.Millisecond)
   507  
   508  	// 校验是否所有客户端都收到推送通知
   509  	receivedCnt := 0
   510  	for _, v := range received {
   511  		if v {
   512  			receivedCnt++
   513  		}
   514  	}
   515  	assert.Equal(t, len(received), receivedCnt)
   516  
   517  	receivedVerCnt := uint64(0)
   518  	for _, v := range receivedVersion {
   519  		receivedVerCnt += v
   520  	}
   521  	assert.Equal(t, uint64(len(receivedVersion)), uint64(receivedVerCnt))
   522  
   523  	// 为了避免影响其它case,删除订阅
   524  	for clientId := range received {
   525  		testSuit.OriginConfigServer().WatchCenter().RemoveWatcher(clientId, watchConfigFiles)
   526  	}
   527  }
   528  
   529  // TestDeleteConfigFile 测试删除配置,删除配置会通知客户端,并且重新拉取配置会返回 NotFoundResourceConfigFile 状态码
   530  func TestDeleteConfigFile(t *testing.T) {
   531  	testSuit := &ConfigCenterTest{}
   532  	if err := testSuit.Initialize(); err != nil {
   533  		t.Fatal(err)
   534  	}
   535  	t.Cleanup(func() {
   536  		if err := testSuit.clearTestData(); err != nil {
   537  			t.Fatal(err)
   538  		}
   539  		testSuit.Destroy()
   540  	})
   541  
   542  	// 创建并发布一个配置文件
   543  	configFile := assembleConfigFile()
   544  	rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   545  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   546  
   547  	rsp2 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, assembleConfigFileRelease(configFile))
   548  	assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   549  
   550  	time.Sleep(1200 * time.Millisecond)
   551  
   552  	// 客户端订阅
   553  	clientId := randomStr()
   554  	received := make(chan uint64)
   555  	watchConfigFiles := assembleDefaultClientConfigFile(0)
   556  
   557  	t.Log("add config watcher")
   558  
   559  	testSuit.OriginConfigServer().WatchCenter().AddWatcher(clientId, watchConfigFiles, func(clientId string, rsp *apiconfig.ConfigClientResponse) bool {
   560  		received <- rsp.GetConfigFile().GetVersion().GetValue()
   561  		return true
   562  	})
   563  
   564  	// 删除配置文件
   565  	t.Log("remove config file")
   566  	rsp3 := testSuit.ConfigServer().DeleteConfigFile(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   567  		Namespace: utils.NewStringValue(testNamespace),
   568  		Group:     utils.NewStringValue(testGroup),
   569  		Name:      utils.NewStringValue(testFile),
   570  	})
   571  	assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
   572  
   573  	// 客户端收到推送通知
   574  	t.Log("wait receive config change msg")
   575  	select {
   576  	case receivedVersion := <-received:
   577  		assert.Equal(t, uint64(2), receivedVersion)
   578  		assert.Equal(t, uint64(2), receivedVersion)
   579  	case <-time.After(10 * time.Second):
   580  		t.Fatal("time out")
   581  	}
   582  
   583  	fileInfo := &apiconfig.ClientConfigFileInfo{
   584  		Namespace: &wrapperspb.StringValue{Value: testNamespace},
   585  		Group:     &wrapperspb.StringValue{Value: testGroup},
   586  		FileName:  &wrapperspb.StringValue{Value: testFile},
   587  		Version:   &wrapperspb.UInt64Value{Value: 2},
   588  	}
   589  
   590  	// 重新拉取配置,获取不到配置文件
   591  	rsp4 := testSuit.ConfigServer().GetConfigFileForClient(testSuit.DefaultCtx, fileInfo)
   592  	assert.Equal(t, uint32(api.NotFoundResource), rsp4.Code.GetValue())
   593  }