github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/cmd/server/server_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "fmt" 18 "math" 19 "os" 20 "path/filepath" 21 "testing" 22 "time" 23 24 ticonfig "github.com/pingcap/tidb/pkg/config" 25 "github.com/pingcap/tiflow/pkg/config" 26 "github.com/pingcap/tiflow/pkg/security" 27 "github.com/spf13/cobra" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestPatchTiDBConf(t *testing.T) { 32 t.TempDir() 33 patchTiDBConf() 34 cfg := ticonfig.GetGlobalConfig() 35 require.Equal(t, uint(0), cfg.TiKVClient.MaxBatchSize) 36 } 37 38 func TestValidateWithEmptyPdAddress(t *testing.T) { 39 cmd := new(cobra.Command) 40 o := newOptions() 41 o.addFlags(cmd) 42 43 require.Nil(t, cmd.ParseFlags([]string{"--pd="})) 44 err := o.complete(cmd) 45 require.Nil(t, err) 46 err = o.validate() 47 require.Regexp(t, ".*empty PD address.*", err.Error()) 48 } 49 50 func TestValidateWithInvalidPdAddress(t *testing.T) { 51 cmd := new(cobra.Command) 52 o := newOptions() 53 o.addFlags(cmd) 54 55 require.Nil(t, cmd.ParseFlags([]string{"--pd=aa"})) 56 err := o.complete(cmd) 57 require.Nil(t, err) 58 err = o.validate() 59 require.Regexp(t, ".*PD endpoint should be a valid http or https URL.*", err.Error()) 60 } 61 62 func TestValidateWithInvalidPdAddressWithoutHost(t *testing.T) { 63 cmd := new(cobra.Command) 64 o := newOptions() 65 o.addFlags(cmd) 66 67 require.Nil(t, cmd.ParseFlags([]string{"--pd=http://"})) 68 err := o.complete(cmd) 69 require.Nil(t, err) 70 err = o.validate() 71 require.Regexp(t, ".*PD endpoint should be a valid http or https URL.*", err.Error()) 72 } 73 74 func TestValidateWithHttpsPdAddressWithoutCertificate(t *testing.T) { 75 cmd := new(cobra.Command) 76 o := newOptions() 77 o.addFlags(cmd) 78 79 require.Nil(t, cmd.ParseFlags([]string{"--pd=https://aa"})) 80 err := o.complete(cmd) 81 require.Nil(t, err) 82 err = o.validate() 83 require.Regexp(t, ".*PD endpoint scheme is https, please provide certificate.*", err.Error()) 84 } 85 86 func TestAddUnknownFlag(t *testing.T) { 87 cmd := new(cobra.Command) 88 o := newOptions() 89 o.addFlags(cmd) 90 91 require.Regexp(t, ".*unknown flag: --PD.*", cmd.ParseFlags([]string{"--PD="}).Error()) 92 } 93 94 func TestDefaultCfg(t *testing.T) { 95 cmd := new(cobra.Command) 96 o := newOptions() 97 o.addFlags(cmd) 98 99 require.Nil(t, cmd.ParseFlags([]string{})) 100 err := o.complete(cmd) 101 require.Nil(t, err) 102 103 defaultCfg := config.GetDefaultServerConfig() 104 require.Nil(t, defaultCfg.ValidateAndAdjust()) 105 require.Equal(t, defaultCfg, o.serverConfig) 106 require.Equal(t, "http://127.0.0.1:2379", o.serverPdAddr) 107 } 108 109 func TestParseCfg(t *testing.T) { 110 dataDir := t.TempDir() 111 cmd := new(cobra.Command) 112 o := newOptions() 113 o.addFlags(cmd) 114 115 require.Nil(t, cmd.ParseFlags([]string{ 116 "--addr", "127.5.5.1:8833", 117 "--advertise-addr", "127.5.5.1:7777", 118 "--log-file", "/root/cdc.log", 119 "--log-level", "debug", 120 "--data-dir", dataDir, 121 "--gc-ttl", "10", 122 "--tz", "UTC", 123 "--owner-flush-interval", "150ms", 124 "--processor-flush-interval", "150ms", 125 "--cert", "bb", 126 "--key", "cc", 127 "--cert-allowed-cn", "dd,ee", 128 "--sort-dir", "/tmp/just_a_test", 129 })) 130 131 err := o.complete(cmd) 132 require.Nil(t, err) 133 err = o.validate() 134 require.Nil(t, err) 135 require.Equal(t, &config.ServerConfig{ 136 Addr: "127.5.5.1:8833", 137 AdvertiseAddr: "127.5.5.1:7777", 138 LogFile: "/root/cdc.log", 139 LogLevel: "debug", 140 Log: &config.LogConfig{ 141 File: &config.LogFileConfig{ 142 MaxSize: 300, 143 MaxDays: 0, 144 MaxBackups: 0, 145 }, 146 InternalErrOutput: "stderr", 147 }, 148 DataDir: dataDir, 149 GcTTL: 10, 150 TZ: "UTC", 151 CaptureSessionTTL: 10, 152 OwnerFlushInterval: config.TomlDuration(150 * time.Millisecond), 153 ProcessorFlushInterval: config.TomlDuration(150 * time.Millisecond), 154 Sorter: &config.SorterConfig{ 155 SortDir: config.DefaultSortDir, 156 CacheSizeInMB: 128, 157 }, 158 Security: &security.Credential{ 159 CertPath: "bb", 160 KeyPath: "cc", 161 CertAllowedCN: []string{"dd", "ee"}, 162 }, 163 KVClient: &config.KVClientConfig{ 164 EnableMultiplexing: true, 165 WorkerConcurrent: 8, 166 GrpcStreamConcurrent: 1, 167 AdvanceIntervalInMs: 300, 168 FrontierConcurrent: 8, 169 WorkerPoolSize: 0, 170 RegionScanLimit: 40, 171 RegionRetryDuration: config.TomlDuration(time.Minute), 172 }, 173 Debug: &config.DebugConfig{ 174 DB: &config.DBConfig{ 175 Count: 8, 176 MaxOpenFiles: 10000, 177 BlockSize: 65536, 178 WriterBufferSize: 8388608, 179 Compression: "snappy", 180 WriteL0PauseTrigger: math.MaxInt32, 181 CompactionL0Trigger: 16, 182 }, 183 // We expect the default configuration here. 184 Messages: &config.MessagesConfig{ 185 ClientMaxBatchInterval: config.TomlDuration(time.Millisecond * 10), 186 ClientMaxBatchSize: 8 * 1024 * 1024, 187 ClientMaxBatchCount: 128, 188 ClientRetryRateLimit: 1.0, 189 ServerMaxPendingMessageCount: 102400, 190 ServerAckInterval: config.TomlDuration(time.Millisecond * 100), 191 ServerWorkerPoolSize: 4, 192 MaxRecvMsgSize: 256 * 1024 * 1024, 193 KeepAliveTimeout: config.TomlDuration(time.Second * 10), 194 KeepAliveTime: config.TomlDuration(time.Second * 30), 195 }, 196 Scheduler: &config.SchedulerConfig{ 197 HeartbeatTick: 2, 198 CollectStatsTick: 200, 199 MaxTaskConcurrency: 10, 200 CheckBalanceInterval: 60000000000, 201 AddTableBatchSize: 50, 202 }, 203 CDCV2: &config.CDCV2{ 204 Enable: false, 205 MetaStoreConfig: config.MetaStoreConfiguration{}, 206 }, 207 Puller: &config.PullerConfig{ 208 EnableResolvedTsStuckDetection: false, 209 ResolvedTsStuckInterval: config.TomlDuration(5 * time.Minute), 210 }, 211 }, 212 ClusterID: "default", 213 }, o.serverConfig) 214 } 215 216 func TestDecodeCfg(t *testing.T) { 217 dataDir := t.TempDir() 218 tmpDir := t.TempDir() 219 configPath := filepath.Join(tmpDir, "ticdc.toml") 220 configContent := fmt.Sprintf(` 221 addr = "128.0.0.1:1234" 222 advertise-addr = "127.0.0.1:1111" 223 224 log-file = "/root/cdc1.log" 225 log-level = "warn" 226 227 data-dir = "%+v" 228 gc-ttl = 500 229 tz = "US" 230 capture-session-ttl = 10 231 232 owner-flush-interval = "600ms" 233 processor-flush-interval = "600ms" 234 235 [log.file] 236 max-size = 200 237 max-days = 1 238 max-backups = 1 239 240 [sorter] 241 sort-dir = "/tmp/just_a_test" 242 cache-size-in-mb = 8 243 244 [kv-client] 245 region-retry-duration = "3s" 246 247 [debug] 248 [debug.db] 249 count = 5 250 max-open-files = 7 251 block-size = 32768 # 32 KB 252 block-cache-size = 8 253 writer-buffer-size = 9 254 compression = "none" 255 target-file-size-base = 10 256 compaction-l0-trigger = 11 257 write-l0-pause-trigger = 13 258 259 [debug.messages] 260 client-max-batch-interval = "500ms" 261 client-max-batch-size = 999 262 client-max-batch-count = 888 263 client-retry-rate-limit = 100.0 264 server-max-pending-message-count = 1024 265 server-ack-interval = "1s" 266 server-worker-pool-size = 16 267 max-recv-msg-size = 4 268 [debug.scheduler] 269 heartbeat-tick = 3 270 collect-stats-tick = 201 271 max-task-concurrency = 11 272 check-balance-interval = "10s" 273 `, dataDir) 274 err := os.WriteFile(configPath, []byte(configContent), 0o644) 275 require.Nil(t, err) 276 277 cmd := new(cobra.Command) 278 o := newOptions() 279 o.addFlags(cmd) 280 281 require.Nil(t, cmd.ParseFlags([]string{"--config", configPath})) 282 283 err = o.complete(cmd) 284 require.Nil(t, err) 285 err = o.validate() 286 require.Nil(t, err) 287 require.Equal(t, &config.ServerConfig{ 288 Addr: "128.0.0.1:1234", 289 AdvertiseAddr: "127.0.0.1:1111", 290 LogFile: "/root/cdc1.log", 291 LogLevel: "warn", 292 Log: &config.LogConfig{ 293 File: &config.LogFileConfig{ 294 MaxSize: 200, 295 MaxDays: 1, 296 MaxBackups: 1, 297 }, 298 InternalErrOutput: "stderr", 299 }, 300 DataDir: dataDir, 301 GcTTL: 500, 302 TZ: "US", 303 CaptureSessionTTL: 10, 304 OwnerFlushInterval: config.TomlDuration(600 * time.Millisecond), 305 ProcessorFlushInterval: config.TomlDuration(600 * time.Millisecond), 306 Sorter: &config.SorterConfig{ 307 SortDir: config.DefaultSortDir, 308 CacheSizeInMB: 8, 309 }, 310 Security: &security.Credential{}, 311 KVClient: &config.KVClientConfig{ 312 EnableMultiplexing: true, 313 WorkerConcurrent: 8, 314 GrpcStreamConcurrent: 1, 315 AdvanceIntervalInMs: 300, 316 FrontierConcurrent: 8, 317 WorkerPoolSize: 0, 318 RegionScanLimit: 40, 319 RegionRetryDuration: config.TomlDuration(3 * time.Second), 320 }, 321 Debug: &config.DebugConfig{ 322 DB: &config.DBConfig{ 323 Count: 5, 324 MaxOpenFiles: 7, 325 BlockSize: 32768, 326 WriterBufferSize: 9, 327 Compression: "none", 328 CompactionL0Trigger: 11, 329 WriteL0PauseTrigger: 13, 330 }, 331 Messages: &config.MessagesConfig{ 332 ClientMaxBatchInterval: config.TomlDuration(500 * time.Millisecond), 333 ClientMaxBatchSize: 999, 334 ClientMaxBatchCount: 888, 335 ClientRetryRateLimit: 100.0, 336 ServerMaxPendingMessageCount: 1024, 337 ServerAckInterval: config.TomlDuration(1 * time.Second), 338 ServerWorkerPoolSize: 16, 339 MaxRecvMsgSize: 4, 340 KeepAliveTimeout: config.TomlDuration(time.Second * 10), 341 KeepAliveTime: config.TomlDuration(time.Second * 30), 342 }, 343 Scheduler: &config.SchedulerConfig{ 344 HeartbeatTick: 3, 345 CollectStatsTick: 201, 346 MaxTaskConcurrency: 11, 347 CheckBalanceInterval: config.TomlDuration(10 * time.Second), 348 AddTableBatchSize: 50, 349 }, 350 CDCV2: &config.CDCV2{ 351 Enable: false, 352 MetaStoreConfig: config.MetaStoreConfiguration{}, 353 }, 354 Puller: &config.PullerConfig{ 355 EnableResolvedTsStuckDetection: false, 356 ResolvedTsStuckInterval: config.TomlDuration(5 * time.Minute), 357 }, 358 }, 359 ClusterID: "default", 360 }, o.serverConfig) 361 } 362 363 func TestDecodeCfgWithFlags(t *testing.T) { 364 dataDir := t.TempDir() 365 tmpDir := t.TempDir() 366 configPath := filepath.Join(tmpDir, "ticdc.toml") 367 configContent := fmt.Sprintf(` 368 addr = "128.0.0.1:1234" 369 advertise-addr = "127.0.0.1:1111" 370 371 log-file = "/root/cdc1.log" 372 log-level = "warn" 373 374 data-dir = "%+v" 375 gc-ttl = 500 376 tz = "US" 377 capture-session-ttl = 10 378 379 owner-flush-interval = "600ms" 380 processor-flush-interval = "600ms" 381 382 [log.file] 383 max-size = 200 384 max-days = 1 385 max-backups = 1 386 387 [sorter] 388 sort-dir = "/tmp/just_a_test" 389 cache-size-in-mb = 8 390 391 [security] 392 ca-path = "aa" 393 cert-path = "bb" 394 key-path = "cc" 395 cert-allowed-cn = ["dd","ee"] 396 `, dataDir) 397 err := os.WriteFile(configPath, []byte(configContent), 0o644) 398 require.Nil(t, err) 399 400 cmd := new(cobra.Command) 401 o := newOptions() 402 o.addFlags(cmd) 403 404 require.Nil(t, cmd.ParseFlags([]string{ 405 "--addr", "127.5.5.1:8833", 406 "--log-file", "/root/cdc.log", 407 "--log-level", "debug", 408 "--data-dir", dataDir, 409 "--gc-ttl", "10", 410 "--tz", "UTC", 411 "--owner-flush-interval", "150ms", 412 "--processor-flush-interval", "150ms", 413 "--ca", "", 414 "--config", configPath, 415 })) 416 417 err = o.complete(cmd) 418 require.Nil(t, err) 419 err = o.validate() 420 require.Nil(t, err) 421 require.Equal(t, &config.ServerConfig{ 422 Addr: "127.5.5.1:8833", 423 AdvertiseAddr: "127.0.0.1:1111", 424 LogFile: "/root/cdc.log", 425 LogLevel: "debug", 426 Log: &config.LogConfig{ 427 File: &config.LogFileConfig{ 428 MaxSize: 200, 429 MaxDays: 1, 430 MaxBackups: 1, 431 }, 432 InternalErrOutput: "stderr", 433 }, 434 DataDir: dataDir, 435 GcTTL: 10, 436 TZ: "UTC", 437 CaptureSessionTTL: 10, 438 OwnerFlushInterval: config.TomlDuration(150 * time.Millisecond), 439 ProcessorFlushInterval: config.TomlDuration(150 * time.Millisecond), 440 Sorter: &config.SorterConfig{ 441 SortDir: config.DefaultSortDir, 442 CacheSizeInMB: 8, 443 }, 444 Security: &security.Credential{ 445 CertPath: "bb", 446 KeyPath: "cc", 447 CertAllowedCN: []string{"dd", "ee"}, 448 }, 449 KVClient: &config.KVClientConfig{ 450 EnableMultiplexing: true, 451 WorkerConcurrent: 8, 452 GrpcStreamConcurrent: 1, 453 AdvanceIntervalInMs: 300, 454 FrontierConcurrent: 8, 455 WorkerPoolSize: 0, 456 RegionScanLimit: 40, 457 RegionRetryDuration: config.TomlDuration(time.Minute), 458 }, 459 Debug: &config.DebugConfig{ 460 DB: &config.DBConfig{ 461 Count: 8, 462 MaxOpenFiles: 10000, 463 BlockSize: 65536, 464 WriterBufferSize: 8388608, 465 Compression: "snappy", 466 WriteL0PauseTrigger: math.MaxInt32, 467 CompactionL0Trigger: 16, 468 }, 469 // We expect the default configuration here. 470 Messages: &config.MessagesConfig{ 471 ClientMaxBatchInterval: config.TomlDuration(time.Millisecond * 10), 472 ClientMaxBatchSize: 8 * 1024 * 1024, 473 ClientMaxBatchCount: 128, 474 ClientRetryRateLimit: 1.0, 475 ServerMaxPendingMessageCount: 102400, 476 ServerAckInterval: config.TomlDuration(time.Millisecond * 100), 477 ServerWorkerPoolSize: 4, 478 MaxRecvMsgSize: 256 * 1024 * 1024, 479 KeepAliveTimeout: config.TomlDuration(time.Second * 10), 480 KeepAliveTime: config.TomlDuration(time.Second * 30), 481 }, 482 Scheduler: &config.SchedulerConfig{ 483 HeartbeatTick: 2, 484 CollectStatsTick: 200, 485 MaxTaskConcurrency: 10, 486 CheckBalanceInterval: 60000000000, 487 AddTableBatchSize: 50, 488 }, 489 CDCV2: &config.CDCV2{ 490 Enable: false, 491 MetaStoreConfig: config.MetaStoreConfiguration{}, 492 }, 493 Puller: &config.PullerConfig{ 494 EnableResolvedTsStuckDetection: false, 495 ResolvedTsStuckInterval: config.TomlDuration(5 * time.Minute), 496 }, 497 }, 498 ClusterID: "default", 499 }, o.serverConfig) 500 } 501 502 func TestDecodeUnknownDebugCfg(t *testing.T) { 503 tmpDir := t.TempDir() 504 configPath := filepath.Join(tmpDir, "ticdc.toml") 505 configContent := ` 506 [debug] 507 unknown1 = 1 508 [debug.unknown2] 509 unknown3 = 3 510 ` 511 err := os.WriteFile(configPath, []byte(configContent), 0o644) 512 require.Nil(t, err) 513 514 cmd := new(cobra.Command) 515 o := newOptions() 516 o.addFlags(cmd) 517 518 require.Nil(t, cmd.ParseFlags([]string{"--config", configPath})) 519 520 err = o.complete(cmd) 521 require.Nil(t, err) 522 err = o.validate() 523 require.Nil(t, err) 524 require.Equal(t, &config.DebugConfig{ 525 DB: &config.DBConfig{ 526 Count: 8, 527 MaxOpenFiles: 10000, 528 BlockSize: 65536, 529 WriterBufferSize: 8388608, 530 Compression: "snappy", 531 WriteL0PauseTrigger: math.MaxInt32, 532 CompactionL0Trigger: 16, 533 }, 534 // We expect the default configuration here. 535 Messages: &config.MessagesConfig{ 536 ClientMaxBatchInterval: config.TomlDuration(time.Millisecond * 10), 537 ClientMaxBatchSize: 8 * 1024 * 1024, 538 ClientMaxBatchCount: 128, 539 ClientRetryRateLimit: 1.0, 540 ServerMaxPendingMessageCount: 102400, 541 ServerAckInterval: config.TomlDuration(time.Millisecond * 100), 542 ServerWorkerPoolSize: 4, 543 MaxRecvMsgSize: 256 * 1024 * 1024, 544 KeepAliveTimeout: config.TomlDuration(time.Second * 10), 545 KeepAliveTime: config.TomlDuration(time.Second * 30), 546 }, 547 Scheduler: &config.SchedulerConfig{ 548 HeartbeatTick: 2, 549 CollectStatsTick: 200, 550 MaxTaskConcurrency: 10, 551 CheckBalanceInterval: 60000000000, 552 AddTableBatchSize: 50, 553 }, 554 CDCV2: &config.CDCV2{ 555 Enable: false, 556 MetaStoreConfig: config.MetaStoreConfiguration{}, 557 }, 558 Puller: &config.PullerConfig{ 559 EnableResolvedTsStuckDetection: false, 560 ResolvedTsStuckInterval: config.TomlDuration(5 * time.Minute), 561 }, 562 }, o.serverConfig.Debug) 563 }