github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/config/config_test.go (about) 1 // Copyright 2019 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 config_test 15 16 import ( 17 "bytes" 18 "context" 19 "flag" 20 "fmt" 21 "net" 22 "net/http" 23 "net/http/httptest" 24 "net/url" 25 "path/filepath" 26 "regexp" 27 "strconv" 28 "testing" 29 "time" 30 31 "github.com/BurntSushi/toml" 32 . "github.com/pingcap/check" 33 "github.com/pingcap/parser/mysql" 34 35 "github.com/pingcap/br/pkg/lightning/config" 36 ) 37 38 func Test(t *testing.T) { 39 TestingT(t) 40 } 41 42 var _ = Suite(&configTestSuite{}) 43 44 type configTestSuite struct{} 45 46 func startMockServer(c *C, statusCode int, content string) (*httptest.Server, string, int) { 47 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 48 w.WriteHeader(statusCode) 49 fmt.Fprint(w, content) 50 })) 51 52 url, err := url.Parse(ts.URL) 53 c.Assert(err, IsNil) 54 host, portString, err := net.SplitHostPort(url.Host) 55 c.Assert(err, IsNil) 56 port, err := strconv.Atoi(portString) 57 c.Assert(err, IsNil) 58 59 return ts, host, port 60 } 61 62 func assignMinimalLegalValue(cfg *config.Config) { 63 cfg.TiDB.Host = "123.45.67.89" 64 cfg.TiDB.Port = 4567 65 cfg.TiDB.StatusPort = 8901 66 cfg.TiDB.PdAddr = "234.56.78.90:12345" 67 cfg.Mydumper.SourceDir = "file://." 68 cfg.TikvImporter.Backend = config.BackendLocal 69 cfg.TikvImporter.SortedKVDir = "." 70 cfg.TikvImporter.DiskQuota = 1 71 } 72 73 func (s *configTestSuite) TestAdjustPdAddrAndPort(c *C) { 74 ts, host, port := startMockServer(c, http.StatusOK, 75 `{"port":4444,"advertise-address":"","path":"123.45.67.89:1234,56.78.90.12:3456"}`, 76 ) 77 defer ts.Close() 78 79 cfg := config.NewConfig() 80 cfg.TiDB.Host = host 81 cfg.TiDB.StatusPort = port 82 cfg.Mydumper.SourceDir = "." 83 cfg.TikvImporter.Backend = config.BackendLocal 84 cfg.TikvImporter.SortedKVDir = "." 85 cfg.TiDB.DistSQLScanConcurrency = 1 86 87 err := cfg.Adjust(context.Background()) 88 c.Assert(err, IsNil) 89 c.Assert(cfg.TiDB.Port, Equals, 4444) 90 c.Assert(cfg.TiDB.PdAddr, Equals, "123.45.67.89:1234") 91 } 92 93 func (s *configTestSuite) TestAdjustPdAddrAndPortViaAdvertiseAddr(c *C) { 94 ts, host, port := startMockServer(c, http.StatusOK, 95 `{"port":6666,"advertise-address":"121.212.121.212:5555","path":"34.34.34.34:3434"}`, 96 ) 97 defer ts.Close() 98 99 cfg := config.NewConfig() 100 cfg.TiDB.Host = host 101 cfg.TiDB.StatusPort = port 102 cfg.Mydumper.SourceDir = "." 103 cfg.TikvImporter.Backend = config.BackendLocal 104 cfg.TikvImporter.SortedKVDir = "." 105 cfg.TiDB.DistSQLScanConcurrency = 1 106 107 err := cfg.Adjust(context.Background()) 108 c.Assert(err, IsNil) 109 c.Assert(cfg.TiDB.Port, Equals, 6666) 110 c.Assert(cfg.TiDB.PdAddr, Equals, "34.34.34.34:3434") 111 } 112 113 func (s *configTestSuite) TestAdjustPageNotFound(c *C) { 114 ts, host, port := startMockServer(c, http.StatusNotFound, "{}") 115 defer ts.Close() 116 117 cfg := config.NewConfig() 118 cfg.TiDB.Host = host 119 cfg.TiDB.StatusPort = port 120 cfg.TikvImporter.Backend = config.BackendLocal 121 cfg.TikvImporter.SortedKVDir = "." 122 cfg.TiDB.DistSQLScanConcurrency = 1 123 124 err := cfg.Adjust(context.Background()) 125 c.Assert(err, ErrorMatches, "cannot fetch settings from TiDB.*") 126 } 127 128 func (s *configTestSuite) TestAdjustConnectRefused(c *C) { 129 ts, host, port := startMockServer(c, http.StatusOK, "{}") 130 131 cfg := config.NewConfig() 132 cfg.TiDB.Host = host 133 cfg.TiDB.StatusPort = port 134 cfg.TikvImporter.Backend = config.BackendLocal 135 cfg.TikvImporter.SortedKVDir = "." 136 cfg.TiDB.DistSQLScanConcurrency = 1 137 138 ts.Close() // immediately close to ensure connection refused. 139 140 err := cfg.Adjust(context.Background()) 141 c.Assert(err, ErrorMatches, "cannot fetch settings from TiDB.*") 142 } 143 144 func (s *configTestSuite) TestAdjustBackendNotSet(c *C) { 145 cfg := config.NewConfig() 146 cfg.TiDB.DistSQLScanConcurrency = 1 147 err := cfg.Adjust(context.Background()) 148 c.Assert(err, ErrorMatches, "tikv-importer.backend must not be empty!") 149 } 150 151 func (s *configTestSuite) TestAdjustInvalidBackend(c *C) { 152 cfg := config.NewConfig() 153 cfg.TikvImporter.Backend = "no_such_backend" 154 cfg.TiDB.DistSQLScanConcurrency = 1 155 err := cfg.Adjust(context.Background()) 156 c.Assert(err, ErrorMatches, "invalid config: unsupported `tikv-importer\\.backend` \\(no_such_backend\\)") 157 } 158 159 func (s *configTestSuite) TestAdjustFileRoutePath(c *C) { 160 cfg := config.NewConfig() 161 assignMinimalLegalValue(cfg) 162 163 ctx := context.Background() 164 tmpDir := c.MkDir() 165 cfg.Mydumper.SourceDir = tmpDir 166 invalidPath := filepath.Join(tmpDir, "../test123/1.sql") 167 rule := &config.FileRouteRule{Path: invalidPath, Type: "sql", Schema: "test", Table: "tbl"} 168 cfg.Mydumper.FileRouters = []*config.FileRouteRule{rule} 169 cfg.TiDB.DistSQLScanConcurrency = 1 170 err := cfg.Adjust(ctx) 171 c.Assert(err, ErrorMatches, fmt.Sprintf("\\Qfile route path '%s' is not in source dir '%s'\\E", invalidPath, tmpDir)) 172 173 relPath := filepath.FromSlash("test_dir/1.sql") 174 rule.Path = filepath.Join(tmpDir, relPath) 175 err = cfg.Adjust(ctx) 176 c.Assert(err, IsNil) 177 c.Assert(cfg.Mydumper.FileRouters[0].Path, Equals, relPath) 178 } 179 180 func (s *configTestSuite) TestDecodeError(c *C) { 181 ts, host, port := startMockServer(c, http.StatusOK, "invalid-string") 182 defer ts.Close() 183 184 cfg := config.NewConfig() 185 cfg.TiDB.Host = host 186 cfg.TiDB.StatusPort = port 187 cfg.TikvImporter.Backend = config.BackendLocal 188 cfg.TikvImporter.SortedKVDir = "." 189 cfg.TiDB.DistSQLScanConcurrency = 1 190 191 err := cfg.Adjust(context.Background()) 192 c.Assert(err, ErrorMatches, "cannot fetch settings from TiDB.*") 193 } 194 195 func (s *configTestSuite) TestInvalidSetting(c *C) { 196 ts, host, port := startMockServer(c, http.StatusOK, `{"port": 0}`) 197 defer ts.Close() 198 199 cfg := config.NewConfig() 200 cfg.TiDB.Host = host 201 cfg.TiDB.StatusPort = port 202 cfg.TikvImporter.Backend = config.BackendLocal 203 cfg.TikvImporter.SortedKVDir = "." 204 cfg.TiDB.DistSQLScanConcurrency = 1 205 206 err := cfg.Adjust(context.Background()) 207 c.Assert(err, ErrorMatches, "invalid `tidb.port` setting") 208 } 209 210 func (s *configTestSuite) TestInvalidPDAddr(c *C) { 211 ts, host, port := startMockServer(c, http.StatusOK, `{"port": 1234, "path": ",,"}`) 212 defer ts.Close() 213 214 cfg := config.NewConfig() 215 cfg.TiDB.Host = host 216 cfg.TiDB.StatusPort = port 217 cfg.TikvImporter.Backend = config.BackendLocal 218 cfg.TikvImporter.SortedKVDir = "." 219 cfg.TiDB.DistSQLScanConcurrency = 1 220 221 err := cfg.Adjust(context.Background()) 222 c.Assert(err, ErrorMatches, "invalid `tidb.pd-addr` setting") 223 } 224 225 func (s *configTestSuite) TestAdjustWillNotContactServerIfEverythingIsDefined(c *C) { 226 cfg := config.NewConfig() 227 assignMinimalLegalValue(cfg) 228 cfg.TiDB.DistSQLScanConcurrency = 1 229 230 err := cfg.Adjust(context.Background()) 231 c.Assert(err, IsNil) 232 c.Assert(cfg.TiDB.Port, Equals, 4567) 233 c.Assert(cfg.TiDB.PdAddr, Equals, "234.56.78.90:12345") 234 } 235 236 func (s *configTestSuite) TestAdjustWillBatchImportRatioInvalid(c *C) { 237 cfg := config.NewConfig() 238 assignMinimalLegalValue(cfg) 239 cfg.Mydumper.BatchImportRatio = -1 240 cfg.TiDB.DistSQLScanConcurrency = 1 241 err := cfg.Adjust(context.Background()) 242 c.Assert(err, IsNil) 243 c.Assert(cfg.Mydumper.BatchImportRatio, Equals, 0.75) 244 } 245 246 func (s *configTestSuite) TestAdjustSecuritySection(c *C) { 247 testCases := []struct { 248 input string 249 expectedCA string 250 expectedTLS string 251 }{ 252 { 253 input: ``, 254 expectedCA: "", 255 expectedTLS: "false", 256 }, 257 { 258 input: ` 259 [security] 260 `, 261 expectedCA: "", 262 expectedTLS: "false", 263 }, 264 { 265 input: ` 266 [security] 267 ca-path = "/path/to/ca.pem" 268 `, 269 expectedCA: "/path/to/ca.pem", 270 expectedTLS: "cluster", 271 }, 272 { 273 input: ` 274 [security] 275 ca-path = "/path/to/ca.pem" 276 [tidb.security] 277 `, 278 expectedCA: "", 279 expectedTLS: "false", 280 }, 281 { 282 input: ` 283 [security] 284 ca-path = "/path/to/ca.pem" 285 [tidb.security] 286 ca-path = "/path/to/ca2.pem" 287 `, 288 expectedCA: "/path/to/ca2.pem", 289 expectedTLS: "cluster", 290 }, 291 { 292 input: ` 293 [security] 294 [tidb.security] 295 ca-path = "/path/to/ca2.pem" 296 `, 297 expectedCA: "/path/to/ca2.pem", 298 expectedTLS: "cluster", 299 }, 300 { 301 input: ` 302 [security] 303 [tidb] 304 tls = "skip-verify" 305 [tidb.security] 306 `, 307 expectedCA: "", 308 expectedTLS: "skip-verify", 309 }, 310 } 311 312 for _, tc := range testCases { 313 comment := Commentf("input = %s", tc.input) 314 315 cfg := config.NewConfig() 316 assignMinimalLegalValue(cfg) 317 cfg.TiDB.DistSQLScanConcurrency = 1 318 err := cfg.LoadFromTOML([]byte(tc.input)) 319 c.Assert(err, IsNil, comment) 320 321 err = cfg.Adjust(context.Background()) 322 c.Assert(err, IsNil, comment) 323 c.Assert(cfg.TiDB.Security.CAPath, Equals, tc.expectedCA, comment) 324 c.Assert(cfg.TiDB.TLS, Equals, tc.expectedTLS, comment) 325 } 326 } 327 328 func (s *configTestSuite) TestInvalidCSV(c *C) { 329 testCases := []struct { 330 input string 331 err string 332 }{ 333 { 334 input: ` 335 [mydumper.csv] 336 separator = '' 337 `, 338 err: "invalid config: `mydumper.csv.separator` must not be empty", 339 }, 340 { 341 input: ` 342 [mydumper.csv] 343 separator = 'hello' 344 delimiter = 'hel' 345 `, 346 err: "invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", 347 }, 348 { 349 input: ` 350 [mydumper.csv] 351 separator = 'hel' 352 delimiter = 'hello' 353 `, 354 err: "invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", 355 }, 356 { 357 input: ` 358 [mydumper.csv] 359 separator = '\' 360 backslash-escape = false 361 `, 362 err: "", 363 }, 364 { 365 input: ` 366 [mydumper.csv] 367 separator = ',' 368 `, 369 err: "", 370 }, 371 { 372 input: ` 373 [mydumper.csv] 374 delimiter = '' 375 `, 376 err: "", 377 }, 378 { 379 input: ` 380 [mydumper.csv] 381 delimiter = 'hello' 382 `, 383 err: "", 384 }, 385 { 386 input: ` 387 [mydumper.csv] 388 delimiter = '\' 389 backslash-escape = false 390 `, 391 err: "", 392 }, 393 { 394 input: ` 395 [mydumper.csv] 396 separator = '\s' 397 delimiter = '\d' 398 `, 399 err: "", 400 }, 401 { 402 input: ` 403 [mydumper.csv] 404 separator = '|' 405 delimiter = '|' 406 `, 407 err: "invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", 408 }, 409 { 410 input: ` 411 [mydumper.csv] 412 separator = '\' 413 backslash-escape = true 414 `, 415 err: "invalid config: cannot use '\\' as CSV separator when `mydumper.csv.backslash-escape` is true", 416 }, 417 { 418 input: ` 419 [mydumper.csv] 420 delimiter = '\' 421 backslash-escape = true 422 `, 423 err: "invalid config: cannot use '\\' as CSV delimiter when `mydumper.csv.backslash-escape` is true", 424 }, 425 { 426 input: ` 427 [tidb] 428 sql-mode = "invalid-sql-mode" 429 `, 430 err: "invalid config: `mydumper.tidb.sql_mode` must be a valid SQL_MODE: ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'invalid-sql-mode'", 431 }, 432 { 433 input: ` 434 [[routes]] 435 schema-pattern = "" 436 table-pattern = "shard_table_*" 437 `, 438 err: "schema pattern of table route rule should not be empty", 439 }, 440 { 441 input: ` 442 [[routes]] 443 schema-pattern = "schema_*" 444 table-pattern = "" 445 `, 446 err: "target schema of table route rule should not be empty", 447 }, 448 } 449 450 for _, tc := range testCases { 451 comment := Commentf("input = %s", tc.input) 452 453 cfg := config.NewConfig() 454 cfg.Mydumper.SourceDir = "file://." 455 cfg.TiDB.Port = 4000 456 cfg.TiDB.PdAddr = "test.invalid:2379" 457 cfg.TikvImporter.Backend = config.BackendLocal 458 cfg.TikvImporter.SortedKVDir = "." 459 cfg.TiDB.DistSQLScanConcurrency = 1 460 err := cfg.LoadFromTOML([]byte(tc.input)) 461 c.Assert(err, IsNil) 462 463 err = cfg.Adjust(context.Background()) 464 if tc.err != "" { 465 c.Assert(err, ErrorMatches, regexp.QuoteMeta(tc.err), comment) 466 } else { 467 c.Assert(err, IsNil, comment) 468 } 469 } 470 } 471 472 func (s *configTestSuite) TestInvalidTOML(c *C) { 473 cfg := &config.Config{} 474 err := cfg.LoadFromTOML([]byte(` 475 invalid[mydumper.csv] 476 delimiter = '\' 477 backslash-escape = true 478 `)) 479 c.Assert(err, ErrorMatches, regexp.QuoteMeta("Near line 0 (last key parsed ''): bare keys cannot contain '['")) 480 } 481 482 func (s *configTestSuite) TestTOMLUnusedKeys(c *C) { 483 cfg := &config.Config{} 484 err := cfg.LoadFromTOML([]byte(` 485 [lightning] 486 typo = 123 487 `)) 488 c.Assert(err, ErrorMatches, regexp.QuoteMeta("config file contained unknown configuration options: lightning.typo")) 489 } 490 491 func (s *configTestSuite) TestDurationUnmarshal(c *C) { 492 duration := config.Duration{} 493 err := duration.UnmarshalText([]byte("13m20s")) 494 c.Assert(err, IsNil) 495 c.Assert(duration.Duration.Seconds(), Equals, 13*60+20.0) 496 err = duration.UnmarshalText([]byte("13x20s")) 497 c.Assert(err, ErrorMatches, "time: unknown unit .?x.? in duration .?13x20s.?") 498 } 499 500 func (s *configTestSuite) TestDurationMarshalJSON(c *C) { 501 duration := config.Duration{} 502 err := duration.UnmarshalText([]byte("13m20s")) 503 c.Assert(err, IsNil) 504 c.Assert(duration.Duration.Seconds(), Equals, 13*60+20.0) 505 result, err := duration.MarshalJSON() 506 c.Assert(err, IsNil) 507 c.Assert(string(result), Equals, `"13m20s"`) 508 } 509 510 func (s *configTestSuite) TestLoadConfig(c *C) { 511 cfg, err := config.LoadGlobalConfig([]string{"-tidb-port", "sss"}, nil) 512 c.Assert(err, ErrorMatches, `invalid value "sss" for flag -tidb-port: parse error`) 513 c.Assert(cfg, IsNil) 514 515 cfg, err = config.LoadGlobalConfig([]string{"-V"}, nil) 516 c.Assert(err, Equals, flag.ErrHelp) 517 c.Assert(cfg, IsNil) 518 519 cfg, err = config.LoadGlobalConfig([]string{"-config", "not-exists"}, nil) 520 c.Assert(err, ErrorMatches, ".*(no such file or directory|The system cannot find the file specified).*") 521 c.Assert(cfg, IsNil) 522 523 cfg, err = config.LoadGlobalConfig([]string{"--server-mode"}, nil) 524 c.Assert(err, ErrorMatches, "If server-mode is enabled, the status-addr must be a valid listen address") 525 c.Assert(cfg, IsNil) 526 527 path, _ := filepath.Abs(".") 528 cfg, err = config.LoadGlobalConfig([]string{ 529 "-L", "debug", 530 "-log-file", "/path/to/file.log", 531 "-tidb-host", "172.16.30.11", 532 "-tidb-port", "4001", 533 "-tidb-user", "guest", 534 "-tidb-password", "12345", 535 "-pd-urls", "172.16.30.11:2379,172.16.30.12:2379", 536 "-d", path, 537 "-backend", config.BackendLocal, 538 "-sorted-kv-dir", ".", 539 "-checksum=false", 540 }, nil) 541 c.Assert(err, IsNil) 542 c.Assert(cfg.App.Config.Level, Equals, "debug") 543 c.Assert(cfg.App.Config.File, Equals, "/path/to/file.log") 544 c.Assert(cfg.TiDB.Host, Equals, "172.16.30.11") 545 c.Assert(cfg.TiDB.Port, Equals, 4001) 546 c.Assert(cfg.TiDB.User, Equals, "guest") 547 c.Assert(cfg.TiDB.Psw, Equals, "12345") 548 c.Assert(cfg.TiDB.PdAddr, Equals, "172.16.30.11:2379,172.16.30.12:2379") 549 c.Assert(cfg.Mydumper.SourceDir, Equals, path) 550 c.Assert(cfg.TikvImporter.Backend, Equals, config.BackendLocal) 551 c.Assert(cfg.TikvImporter.SortedKVDir, Equals, ".") 552 c.Assert(cfg.PostRestore.Checksum, Equals, config.OpLevelOff) 553 c.Assert(cfg.PostRestore.Analyze, Equals, config.OpLevelOptional) 554 555 taskCfg := config.NewConfig() 556 err = taskCfg.LoadFromGlobal(cfg) 557 c.Assert(err, IsNil) 558 c.Assert(taskCfg.PostRestore.Checksum, Equals, config.OpLevelOff) 559 c.Assert(taskCfg.PostRestore.Analyze, Equals, config.OpLevelOptional) 560 561 taskCfg.Checkpoint.DSN = "" 562 taskCfg.Checkpoint.Driver = config.CheckpointDriverMySQL 563 taskCfg.TiDB.DistSQLScanConcurrency = 1 564 err = taskCfg.Adjust(context.Background()) 565 c.Assert(err, IsNil) 566 c.Assert(taskCfg.Checkpoint.DSN, Equals, "guest:12345@tcp(172.16.30.11:4001)/?charset=utf8mb4&sql_mode='"+mysql.DefaultSQLMode+"'&maxAllowedPacket=67108864&tls=false") 567 568 result := taskCfg.String() 569 c.Assert(result, Matches, `.*"pd-addr":"172.16.30.11:2379,172.16.30.12:2379".*`) 570 } 571 572 func (s *configTestSuite) TestDefaultImporterBackendValue(c *C) { 573 cfg := config.NewConfig() 574 assignMinimalLegalValue(cfg) 575 cfg.TikvImporter.Backend = "importer" 576 cfg.TiDB.DistSQLScanConcurrency = 1 577 err := cfg.Adjust(context.Background()) 578 c.Assert(err, IsNil) 579 c.Assert(cfg.App.IndexConcurrency, Equals, 2) 580 c.Assert(cfg.App.TableConcurrency, Equals, 6) 581 } 582 583 func (s *configTestSuite) TestDefaultTidbBackendValue(c *C) { 584 cfg := config.NewConfig() 585 assignMinimalLegalValue(cfg) 586 cfg.TikvImporter.Backend = "tidb" 587 cfg.App.RegionConcurrency = 123 588 cfg.TiDB.DistSQLScanConcurrency = 1 589 err := cfg.Adjust(context.Background()) 590 c.Assert(err, IsNil) 591 c.Assert(cfg.App.TableConcurrency, Equals, 123) 592 } 593 594 func (s *configTestSuite) TestDefaultCouldBeOverwritten(c *C) { 595 cfg := config.NewConfig() 596 assignMinimalLegalValue(cfg) 597 cfg.TikvImporter.Backend = "importer" 598 cfg.App.IndexConcurrency = 20 599 cfg.App.TableConcurrency = 60 600 cfg.TiDB.DistSQLScanConcurrency = 1 601 err := cfg.Adjust(context.Background()) 602 c.Assert(err, IsNil) 603 c.Assert(cfg.App.IndexConcurrency, Equals, 20) 604 c.Assert(cfg.App.TableConcurrency, Equals, 60) 605 } 606 607 func (s *configTestSuite) TestLoadFromInvalidConfig(c *C) { 608 taskCfg := config.NewConfig() 609 err := taskCfg.LoadFromGlobal(&config.GlobalConfig{ 610 ConfigFileContent: []byte("invalid toml"), 611 }) 612 c.Assert(err, ErrorMatches, "Near line 1.*") 613 } 614 615 func (s *configTestSuite) TestTomlPostRestore(c *C) { 616 cfg := &config.Config{} 617 err := cfg.LoadFromTOML([]byte(` 618 [post-restore] 619 checksum = "req" 620 `)) 621 c.Assert(err, ErrorMatches, regexp.QuoteMeta("invalid op level 'req', please choose valid option between ['off', 'optional', 'required']")) 622 623 err = cfg.LoadFromTOML([]byte(` 624 [post-restore] 625 analyze = 123 626 `)) 627 c.Assert(err, ErrorMatches, regexp.QuoteMeta("invalid op level '123', please choose valid option between ['off', 'optional', 'required']")) 628 629 kvMap := map[string]config.PostOpLevel{ 630 `"off"`: config.OpLevelOff, 631 `"required"`: config.OpLevelRequired, 632 `"optional"`: config.OpLevelOptional, 633 "true": config.OpLevelRequired, 634 "false": config.OpLevelOff, 635 } 636 637 var b bytes.Buffer 638 enc := toml.NewEncoder(&b) 639 640 for k, v := range kvMap { 641 cfg := &config.Config{} 642 confStr := fmt.Sprintf("[post-restore]\r\nchecksum= %s\r\n", k) 643 err := cfg.LoadFromTOML([]byte(confStr)) 644 c.Assert(err, IsNil) 645 c.Assert(cfg.PostRestore.Checksum, Equals, v) 646 647 b.Reset() 648 c.Assert(enc.Encode(cfg.PostRestore), IsNil) 649 c.Assert(&b, Matches, fmt.Sprintf(`(?s).*checksum = "\Q%s\E".*`, v)) 650 } 651 652 for k, v := range kvMap { 653 cfg := &config.Config{} 654 confStr := fmt.Sprintf("[post-restore]\r\nanalyze= %s\r\n", k) 655 err := cfg.LoadFromTOML([]byte(confStr)) 656 c.Assert(err, IsNil) 657 c.Assert(cfg.PostRestore.Analyze, Equals, v) 658 659 b.Reset() 660 c.Assert(enc.Encode(cfg.PostRestore), IsNil) 661 c.Assert(&b, Matches, fmt.Sprintf(`(?s).*analyze = "\Q%s\E".*`, v)) 662 } 663 } 664 665 func (s *configTestSuite) TestCronEncodeDecode(c *C) { 666 cfg := &config.Config{} 667 cfg.Cron.SwitchMode.Duration = 1 * time.Minute 668 cfg.Cron.LogProgress.Duration = 2 * time.Minute 669 cfg.Cron.CheckDiskQuota.Duration = 3 * time.Second 670 var b bytes.Buffer 671 c.Assert(toml.NewEncoder(&b).Encode(cfg.Cron), IsNil) 672 c.Assert(b.String(), Equals, "switch-mode = \"1m0s\"\nlog-progress = \"2m0s\"\ncheck-disk-quota = \"3s\"\n") 673 674 confStr := "[cron]\r\n" + b.String() 675 cfg2 := &config.Config{} 676 c.Assert(cfg2.LoadFromTOML([]byte(confStr)), IsNil) 677 c.Assert(cfg2.Cron, DeepEquals, cfg.Cron) 678 } 679 680 func (s *configTestSuite) TestAdjustWithLegacyBlackWhiteList(c *C) { 681 cfg := config.NewConfig() 682 assignMinimalLegalValue(cfg) 683 c.Assert(cfg.Mydumper.Filter, DeepEquals, config.DefaultFilter) 684 c.Assert(cfg.HasLegacyBlackWhiteList(), IsFalse) 685 686 ctx := context.Background() 687 cfg.Mydumper.Filter = []string{"test.*"} 688 cfg.TiDB.DistSQLScanConcurrency = 1 689 c.Assert(cfg.Adjust(ctx), IsNil) 690 c.Assert(cfg.HasLegacyBlackWhiteList(), IsFalse) 691 692 cfg.BWList.DoDBs = []string{"test"} 693 c.Assert(cfg.Adjust(ctx), ErrorMatches, "invalid config: `mydumper\\.filter` and `black-white-list` cannot be simultaneously defined") 694 695 cfg.Mydumper.Filter = config.DefaultFilter 696 c.Assert(cfg.Adjust(ctx), IsNil) 697 c.Assert(cfg.HasLegacyBlackWhiteList(), IsTrue) 698 } 699 700 func (s *configTestSuite) TestAdjustDiskQuota(c *C) { 701 cfg := config.NewConfig() 702 assignMinimalLegalValue(cfg) 703 704 base := c.MkDir() 705 ctx := context.Background() 706 cfg.TikvImporter.Backend = config.BackendLocal 707 cfg.TikvImporter.DiskQuota = 0 708 cfg.TikvImporter.SortedKVDir = base 709 cfg.TiDB.DistSQLScanConcurrency = 1 710 c.Assert(cfg.Adjust(ctx), IsNil) 711 c.Assert(int64(cfg.TikvImporter.DiskQuota), Equals, int64(0)) 712 }