github.com/nacos-group/nacos-sdk-go@v1.1.4/clients/config_client/config_client_test.go (about) 1 /* 2 * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package config_client 18 19 import ( 20 "errors" 21 "fmt" 22 "net/http" 23 "runtime" 24 "testing" 25 "time" 26 27 "github.com/golang/mock/gomock" 28 "github.com/nacos-group/nacos-sdk-go/clients/cache" 29 "github.com/nacos-group/nacos-sdk-go/clients/nacos_client" 30 "github.com/nacos-group/nacos-sdk-go/common/constant" 31 "github.com/nacos-group/nacos-sdk-go/common/http_agent" 32 "github.com/nacos-group/nacos-sdk-go/mock" 33 "github.com/nacos-group/nacos-sdk-go/util" 34 "github.com/nacos-group/nacos-sdk-go/vo" 35 "github.com/stretchr/testify/assert" 36 ) 37 38 var goVersion = runtime.Version() 39 40 var clientConfigTest = constant.ClientConfig{ 41 TimeoutMs: 10000, 42 BeatInterval: 10000, 43 } 44 45 var serverConfigTest = constant.ServerConfig{ 46 ContextPath: "/nacos", 47 Port: 80, 48 IpAddr: "console.nacos.io", 49 } 50 51 var serverConfigWithOptions = constant.NewServerConfig("console.nacos.io", 80, constant.WithContextPath("/nacos")) 52 53 var clientConfigWithOptions = constant.NewClientConfig( 54 constant.WithCustomLogger(mockLogger{}), 55 constant.WithTimeoutMs(10*1000), 56 constant.WithBeatInterval(2*1000), 57 constant.WithNotLoadCacheAtStart(true), 58 ) 59 60 var ( 61 dataIdKey = goVersion + "dataId" 62 groupKey = goVersion + "group:env" 63 configNoChangeKey = goVersion + "ConfigNoChange" 64 multipleClientsKey = goVersion + "MultipleClients" 65 multipleClientsMultipleConfigsKey = goVersion + "MultipleClientsMultipleConfig" 66 specialSymbolKey = goVersion + "special_symbol" 67 ) 68 69 var configParamMapTest = map[string]string{ 70 "dataId": dataIdKey, 71 "group": groupKey, 72 } 73 74 var configParamTest = vo.ConfigParam{ 75 DataId: dataIdKey, 76 Group: groupKey, 77 } 78 79 var localConfigTest = vo.ConfigParam{ 80 DataId: dataIdKey, 81 Group: groupKey, 82 Content: "content", 83 } 84 85 var localConfigMapTest = map[string]string{ 86 "dataId": dataIdKey, 87 "group": groupKey, 88 "content": "content", 89 } 90 var client *ConfigClient 91 92 func TestMain(m *testing.M) { 93 nc := nacos_client.NacosClient{} 94 nc.SetServerConfig([]constant.ServerConfig{*serverConfigWithOptions}) 95 nc.SetClientConfig(*clientConfigWithOptions) 96 nc.SetHttpAgent(&http_agent.HttpAgent{}) 97 client, _ = NewConfigClient(&nc) 98 m.Run() 99 } 100 101 func createConfigClientHttpTest(mockHttpAgent http_agent.IHttpAgent) *ConfigClient { 102 nc := nacos_client.NacosClient{} 103 nc.SetServerConfig([]constant.ServerConfig{serverConfigTest}) 104 nc.SetClientConfig(clientConfigTest) 105 nc.SetHttpAgent(mockHttpAgent) 106 client, _ := NewConfigClient(&nc) 107 return client 108 } 109 110 func Test_GetConfig(t *testing.T) { 111 success, err := client.PublishConfig(vo.ConfigParam{ 112 DataId: dataIdKey, 113 Group: "group", 114 Content: "hello world!222222"}) 115 116 assert.Nil(t, err) 117 assert.True(t, success) 118 119 content, err := client.GetConfig(vo.ConfigParam{ 120 DataId: dataIdKey, 121 Group: "group"}) 122 123 assert.Nil(t, err) 124 assert.Equal(t, "hello world!222222", content) 125 } 126 127 func Test_SearchConfig(t *testing.T) { 128 client.PublishConfig(vo.ConfigParam{ 129 DataId: dataIdKey, 130 Group: "groDEFAULT_GROUPup", 131 Content: "hello world!222222"}) 132 configPage, err := client.SearchConfig(vo.SearchConfigParam{ 133 Search: "accurate", 134 DataId: dataIdKey, 135 Group: "groDEFAULT_GROUPup", 136 PageNo: 1, 137 PageSize: 10, 138 }) 139 assert.Nil(t, err) 140 assert.NotEmpty(t, configPage) 141 } 142 143 // PublishConfig 144 func Test_PublishConfigWithoutDataId(t *testing.T) { 145 _, err := client.PublishConfig(vo.ConfigParam{ 146 DataId: "", 147 Group: "group", 148 Content: "content", 149 }) 150 assert.NotNil(t, err) 151 } 152 153 func Test_PublishConfigWithoutGroup(t *testing.T) { 154 _, err := client.PublishConfig(vo.ConfigParam{ 155 DataId: dataIdKey, 156 Group: "", 157 Content: "content", 158 }) 159 assert.NotNil(t, err) 160 } 161 162 func Test_PublishConfigWithoutContent(t *testing.T) { 163 _, err := client.PublishConfig(vo.ConfigParam{ 164 DataId: dataIdKey, 165 Group: "group", 166 Content: "", 167 }) 168 assert.NotNil(t, err) 169 } 170 171 func Test_PublishConfig(t *testing.T) { 172 success, err := client.PublishConfig(vo.ConfigParam{ 173 DataId: dataIdKey, 174 Group: "group", 175 Content: "hello world2!"}) 176 177 assert.Nil(t, err) 178 assert.True(t, success) 179 } 180 181 func Test_PublishConfigWithType(t *testing.T) { 182 success, err := client.PublishConfig(vo.ConfigParam{ 183 DataId: dataIdKey, 184 Group: "group", 185 Content: "foo", 186 Type: vo.YAML, 187 }) 188 189 assert.Nil(t, err) 190 assert.True(t, success) 191 } 192 193 func Test_PublishConfigWithErrorResponse(t *testing.T) { 194 controller := gomock.NewController(t) 195 defer controller.Finish() 196 197 mockHttpAgent := mock.NewMockIHttpAgent(controller) 198 clientHttp := createConfigClientHttpTest(mockHttpAgent) 199 mockHttpAgent.EXPECT().Request(gomock.Eq(http.MethodPost), 200 gomock.Eq("http://console.nacos.io:80/nacos/v1/cs/configs"), 201 gomock.AssignableToTypeOf(http.Header{}), 202 gomock.Eq(clientConfigTest.TimeoutMs), 203 gomock.Eq(localConfigMapTest), 204 ).Times(3).Return(http_agent.FakeHttpResponse(401, "no security"), nil) 205 success, err := clientHttp.PublishConfig(localConfigTest) 206 assert.NotNil(t, err) 207 assert.True(t, !success) 208 } 209 210 func Test_PublishConfigWithErrorResponse_200(t *testing.T) { 211 controller := gomock.NewController(t) 212 defer controller.Finish() 213 214 mockHttpAgent := mock.NewMockIHttpAgent(controller) 215 clientHttp := createConfigClientHttpTest(mockHttpAgent) 216 mockHttpAgent.EXPECT().Request(gomock.Eq(http.MethodPost), 217 gomock.Eq("http://console.nacos.io:80/nacos/v1/cs/configs"), 218 gomock.AssignableToTypeOf(http.Header{}), 219 gomock.Eq(clientConfigTest.TimeoutMs), 220 gomock.Eq(localConfigMapTest), 221 ).Times(1).Return(http_agent.FakeHttpResponse(200, "false"), nil) 222 success, err := clientHttp.PublishConfig(localConfigTest) 223 assert.NotNil(t, err) 224 assert.True(t, !success) 225 } 226 227 // DeleteConfig 228 229 func Test_DeleteConfig(t *testing.T) { 230 success, err := client.PublishConfig(vo.ConfigParam{ 231 DataId: dataIdKey, 232 Group: "group", 233 Content: "hello world!"}) 234 235 assert.Nil(t, err) 236 assert.True(t, success) 237 238 success, err = client.DeleteConfig(vo.ConfigParam{ 239 DataId: dataIdKey, 240 Group: "group"}) 241 242 assert.Nil(t, err) 243 assert.True(t, success) 244 } 245 246 func Test_DeleteConfigWithErrorResponse_200(t *testing.T) { 247 controller := gomock.NewController(t) 248 defer controller.Finish() 249 250 mockHttpAgent := mock.NewMockIHttpAgent(controller) 251 clientHttp := createConfigClientHttpTest(mockHttpAgent) 252 253 mockHttpAgent.EXPECT().Request(gomock.Eq(http.MethodDelete), 254 gomock.Eq("http://console.nacos.io:80/nacos/v1/cs/configs"), 255 gomock.AssignableToTypeOf(http.Header{}), 256 gomock.Eq(clientConfigTest.TimeoutMs), 257 gomock.Eq(configParamMapTest), 258 ).Times(1).Return(http_agent.FakeHttpResponse(200, "false"), nil) 259 success, err := clientHttp.DeleteConfig(configParamTest) 260 assert.NotNil(t, err) 261 assert.Equal(t, false, success) 262 } 263 264 func Test_DeleteConfigWithErrorResponse_401(t *testing.T) { 265 controller := gomock.NewController(t) 266 defer controller.Finish() 267 268 mockHttpAgent := mock.NewMockIHttpAgent(controller) 269 clientHttp := createConfigClientHttpTest(mockHttpAgent) 270 271 mockHttpAgent.EXPECT().Request(gomock.Eq(http.MethodDelete), 272 gomock.Eq("http://console.nacos.io:80/nacos/v1/cs/configs"), 273 gomock.AssignableToTypeOf(http.Header{}), 274 gomock.Eq(clientConfigTest.TimeoutMs), 275 gomock.Eq(configParamMapTest), 276 ).Times(3).Return(http_agent.FakeHttpResponse(401, "no security"), nil) 277 success, err := clientHttp.DeleteConfig(configParamTest) 278 assert.NotNil(t, err) 279 assert.Equal(t, false, success) 280 } 281 282 func Test_DeleteConfigWithoutDataId(t *testing.T) { 283 success, err := client.DeleteConfig(vo.ConfigParam{ 284 DataId: "", 285 Group: "group", 286 }) 287 assert.NotNil(t, err) 288 assert.Equal(t, false, success) 289 } 290 291 func Test_DeleteConfigWithoutGroup(t *testing.T) { 292 success, err := client.DeleteConfig(vo.ConfigParam{ 293 DataId: dataIdKey, 294 Group: "", 295 }) 296 assert.NotNil(t, err) 297 assert.Equal(t, false, success) 298 } 299 300 // ListenConfig 301 func TestListen(t *testing.T) { 302 // ListenConfig 303 t.Run("TestListenConfig", func(t *testing.T) { 304 key := util.GetConfigCacheKey(localConfigTest.DataId, localConfigTest.Group, clientConfigTest.NamespaceId) 305 cache.WriteConfigToFile(key, client.configCacheDir, "") 306 var err error 307 var success bool 308 ch := make(chan string) 309 err = client.ListenConfig(vo.ConfigParam{ 310 DataId: localConfigTest.DataId, 311 Group: localConfigTest.Group, 312 OnChange: func(namespace, group, dataId, data string) { 313 ch <- data 314 }, 315 }) 316 assert.Nil(t, err) 317 318 success, err = client.PublishConfig(vo.ConfigParam{ 319 DataId: localConfigTest.DataId, 320 Group: localConfigTest.Group, 321 Content: localConfigTest.Content}) 322 323 assert.Nil(t, err) 324 assert.Equal(t, true, success) 325 select { 326 case c := <-ch: 327 assert.Equal(t, c, localConfigTest.Content) 328 case <-time.After(10 * time.Second): 329 assert.Errorf(t, errors.New("timeout"), "timeout") 330 } 331 }) 332 // ListenConfig no dataId 333 t.Run("TestListenConfigNoDataId", func(t *testing.T) { 334 listenConfigParam := vo.ConfigParam{ 335 Group: "gateway", 336 OnChange: func(namespace, group, dataId, data string) { 337 }, 338 } 339 err := client.ListenConfig(listenConfigParam) 340 assert.Error(t, err) 341 }) 342 // ListenConfig no change 343 t.Run("TestListenConfigNoChange", func(t *testing.T) { 344 key := util.GetConfigCacheKey(configNoChangeKey, localConfigTest.Group, clientConfigTest.NamespaceId) 345 cache.WriteConfigToFile(key, client.configCacheDir, localConfigTest.Content) 346 var err error 347 var success bool 348 var content string 349 350 err = client.ListenConfig(vo.ConfigParam{ 351 DataId: configNoChangeKey, 352 Group: localConfigTest.Group, 353 OnChange: func(namespace, group, dataId, data string) { 354 content = "data" 355 }, 356 }) 357 assert.Nil(t, err) 358 359 success, err = client.PublishConfig(vo.ConfigParam{ 360 DataId: configNoChangeKey, 361 Group: localConfigTest.Group, 362 Content: localConfigTest.Content}) 363 364 assert.Nil(t, err) 365 assert.Equal(t, true, success) 366 assert.Equal(t, content, "") 367 }) 368 // Multiple clients listen to the same configuration file 369 t.Run("TestListenConfigWithMultipleClients", func(t *testing.T) { 370 ch := make(chan string) 371 listenConfigParam := vo.ConfigParam{ 372 DataId: multipleClientsKey, 373 Group: localConfigTest.Group, 374 OnChange: func(namespace, group, dataId, data string) { 375 ch <- data 376 }, 377 } 378 key := util.GetConfigCacheKey(listenConfigParam.DataId, listenConfigParam.Group, clientConfigTest.NamespaceId) 379 cache.WriteConfigToFile(key, client.configCacheDir, "") 380 client.ListenConfig(listenConfigParam) 381 382 nc := nacos_client.NacosClient{} 383 nc.SetServerConfig([]constant.ServerConfig{*serverConfigWithOptions}) 384 nc.SetClientConfig(*clientConfigWithOptions) 385 nc.SetHttpAgent(&http_agent.HttpAgent{}) 386 client1, _ := NewConfigClient(&nc) 387 client1.ListenConfig(listenConfigParam) 388 389 success, err := client.PublishConfig(vo.ConfigParam{ 390 DataId: multipleClientsKey, 391 Group: localConfigTest.Group, 392 Content: localConfigTest.Content}) 393 394 assert.Nil(t, err) 395 assert.Equal(t, true, success) 396 select { 397 case c := <-ch: 398 assert.Equal(t, localConfigTest.Content, c) 399 case <-time.After(10 * time.Second): 400 assert.Errorf(t, errors.New("timeout"), "timeout") 401 } 402 403 }) 404 // Multiple clients listen to multiple configuration files 405 t.Run("TestListenConfigWithMultipleClientsMultipleConfig", func(t *testing.T) { 406 ch := make(chan string) 407 listenConfigParam := vo.ConfigParam{ 408 DataId: multipleClientsMultipleConfigsKey, 409 Group: localConfigTest.Group, 410 OnChange: func(namespace, group, dataId, data string) { 411 ch <- data 412 }, 413 } 414 key := util.GetConfigCacheKey(listenConfigParam.DataId, listenConfigParam.Group, clientConfigTest.NamespaceId) 415 cache.WriteConfigToFile(key, client.configCacheDir, "") 416 client.ListenConfig(listenConfigParam) 417 418 nc := nacos_client.NacosClient{} 419 nc.SetServerConfig([]constant.ServerConfig{*serverConfigWithOptions}) 420 nc.SetClientConfig(*clientConfigWithOptions) 421 nc.SetHttpAgent(&http_agent.HttpAgent{}) 422 client1, _ := NewConfigClient(&nc) 423 client1.ListenConfig(listenConfigParam) 424 425 success, err := client.PublishConfig(vo.ConfigParam{ 426 DataId: multipleClientsMultipleConfigsKey, 427 Group: localConfigTest.Group, 428 Content: localConfigTest.Content}) 429 430 assert.Nil(t, err) 431 assert.Equal(t, true, success) 432 select { 433 case c := <-ch: 434 assert.Equal(t, localConfigTest.Content, c) 435 case <-time.After(10 * time.Second): 436 assert.Errorf(t, errors.New("timeout"), "timeout") 437 } 438 439 }) 440 } 441 442 func TestGetConfigWithSpecialSymbol(t *testing.T) { 443 contentStr := "hello world!!@#$%^&&*()" 444 success, err := client.PublishConfig(vo.ConfigParam{ 445 DataId: specialSymbolKey, 446 Group: localConfigTest.Group, 447 Content: contentStr}) 448 449 assert.Nil(t, err) 450 assert.True(t, success) 451 452 content, err := client.GetConfig(vo.ConfigParam{ 453 DataId: specialSymbolKey, 454 Group: localConfigTest.Group}) 455 456 assert.Nil(t, err) 457 assert.Equal(t, contentStr, content) 458 } 459 460 type mockLogger struct { 461 } 462 463 func (m mockLogger) Info(args ...interface{}) { 464 fmt.Println(args...) 465 } 466 467 func (m mockLogger) Warn(args ...interface{}) { 468 fmt.Println(args...) 469 } 470 471 func (m mockLogger) Error(args ...interface{}) { 472 fmt.Println(args...) 473 } 474 475 func (m mockLogger) Debug(args ...interface{}) { 476 fmt.Println(args...) 477 } 478 479 func (m mockLogger) Infof(format string, args ...interface{}) { 480 fmt.Println(fmt.Sprintf(format, args...)) 481 } 482 483 func (m mockLogger) Warnf(format string, args ...interface{}) { 484 fmt.Println(fmt.Sprintf(format, args...)) 485 } 486 487 func (m mockLogger) Errorf(format string, args ...interface{}) { 488 fmt.Println(fmt.Sprintf(format, args...)) 489 } 490 491 func (m mockLogger) Debugf(format string, args ...interface{}) { 492 fmt.Println("implement me") 493 }