github.com/selaux/migrate/v4@v4.0.0-20220816090517-e1d858e5766d/migrate_test.go (about) 1 package migrate 2 3 import ( 4 "bytes" 5 "database/sql" 6 "errors" 7 "io/ioutil" 8 "log" 9 "os" 10 "strings" 11 "testing" 12 ) 13 14 import ( 15 dStub "github.com/golang-migrate/migrate/v4/database/stub" 16 "github.com/golang-migrate/migrate/v4/source" 17 sStub "github.com/golang-migrate/migrate/v4/source/stub" 18 ) 19 20 // sourceStubMigrations hold the following migrations: 21 // u = up migration, d = down migration, n = version 22 // | 1 | - | 3 | 4 | 5 | - | 7 | 23 // | u d | - | u | u d | d | - | u d | 24 var sourceStubMigrations *source.Migrations 25 26 const ( 27 srcDrvNameStub = "stub" 28 dbDrvNameStub = "stub" 29 ) 30 31 func init() { 32 sourceStubMigrations = source.NewMigrations() 33 sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Up, Identifier: "CREATE 1"}) 34 sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Down, Identifier: "DROP 1"}) 35 sourceStubMigrations.Append(&source.Migration{Version: 3, Direction: source.Up, Identifier: "CREATE 3"}) 36 sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Up, Identifier: "CREATE 4"}) 37 sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Down, Identifier: "DROP 4"}) 38 sourceStubMigrations.Append(&source.Migration{Version: 5, Direction: source.Down, Identifier: "DROP 5"}) 39 sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Up, Identifier: "CREATE 7"}) 40 sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Down, Identifier: "DROP 7"}) 41 } 42 43 type DummyInstance struct{ Name string } 44 45 func TestNew(t *testing.T) { 46 m, err := New("stub://", "stub://") 47 if err != nil { 48 t.Fatal(err) 49 } 50 51 if m.sourceName != srcDrvNameStub { 52 t.Errorf("expected stub, got %v", m.sourceName) 53 } 54 if m.sourceDrv == nil { 55 t.Error("expected sourceDrv not to be nil") 56 } 57 58 if m.databaseName != dbDrvNameStub { 59 t.Errorf("expected stub, got %v", m.databaseName) 60 } 61 if m.databaseDrv == nil { 62 t.Error("expected databaseDrv not to be nil") 63 } 64 } 65 66 func ExampleNew() { 67 // Read migrations from /home/mattes/migrations and connect to a local postgres database. 68 m, err := New("file:///home/mattes/migrations", "postgres://mattes:secret@localhost:5432/database?sslmode=disable") 69 if err != nil { 70 log.Fatal(err) 71 } 72 73 // Migrate all the way up ... 74 if err := m.Up(); err != nil && err != ErrNoChange { 75 log.Fatal(err) 76 } 77 } 78 79 func TestNewWithDatabaseInstance(t *testing.T) { 80 dummyDb := &DummyInstance{"database"} 81 dbInst, err := dStub.WithInstance(dummyDb, &dStub.Config{}) 82 if err != nil { 83 t.Fatal(err) 84 } 85 86 m, err := NewWithDatabaseInstance("stub://", dbDrvNameStub, dbInst) 87 if err != nil { 88 t.Fatal(err) 89 } 90 91 if m.sourceName != srcDrvNameStub { 92 t.Errorf("expected stub, got %v", m.sourceName) 93 } 94 if m.sourceDrv == nil { 95 t.Error("expected sourceDrv not to be nil") 96 } 97 98 if m.databaseName != dbDrvNameStub { 99 t.Errorf("expected stub, got %v", m.databaseName) 100 } 101 if m.databaseDrv == nil { 102 t.Error("expected databaseDrv not to be nil") 103 } 104 } 105 106 func ExampleNewWithDatabaseInstance() { 107 // Create and use an existing database instance. 108 db, err := sql.Open("postgres", "postgres://mattes:secret@localhost:5432/database?sslmode=disable") 109 if err != nil { 110 log.Fatal(err) 111 } 112 defer func() { 113 if err := db.Close(); err != nil { 114 log.Fatal(err) 115 } 116 }() 117 118 // Create driver instance from db. 119 // Check each driver if it supports the WithInstance function. 120 // `import "github.com/golang-migrate/migrate/v4/database/postgres"` 121 instance, err := dStub.WithInstance(db, &dStub.Config{}) 122 if err != nil { 123 log.Fatal(err) 124 } 125 126 // Read migrations from /home/mattes/migrations and connect to a local postgres database. 127 m, err := NewWithDatabaseInstance("file:///home/mattes/migrations", "postgres", instance) 128 if err != nil { 129 log.Fatal(err) 130 } 131 132 // Migrate all the way up ... 133 if err := m.Up(); err != nil { 134 log.Fatal(err) 135 } 136 } 137 138 func TestNewWithSourceInstance(t *testing.T) { 139 dummySource := &DummyInstance{"source"} 140 sInst, err := sStub.WithInstance(dummySource, &sStub.Config{}) 141 if err != nil { 142 t.Fatal(err) 143 } 144 145 m, err := NewWithSourceInstance(srcDrvNameStub, sInst, "stub://") 146 if err != nil { 147 t.Fatal(err) 148 } 149 150 if m.sourceName != srcDrvNameStub { 151 t.Errorf("expected stub, got %v", m.sourceName) 152 } 153 if m.sourceDrv == nil { 154 t.Error("expected sourceDrv not to be nil") 155 } 156 157 if m.databaseName != dbDrvNameStub { 158 t.Errorf("expected stub, got %v", m.databaseName) 159 } 160 if m.databaseDrv == nil { 161 t.Error("expected databaseDrv not to be nil") 162 } 163 } 164 165 func ExampleNewWithSourceInstance() { 166 di := &DummyInstance{"think any client required for a source here"} 167 168 // Create driver instance from DummyInstance di. 169 // Check each driver if it support the WithInstance function. 170 // `import "github.com/golang-migrate/migrate/v4/source/stub"` 171 instance, err := sStub.WithInstance(di, &sStub.Config{}) 172 if err != nil { 173 log.Fatal(err) 174 } 175 176 // Read migrations from Stub and connect to a local postgres database. 177 m, err := NewWithSourceInstance(srcDrvNameStub, instance, "postgres://mattes:secret@localhost:5432/database?sslmode=disable") 178 if err != nil { 179 log.Fatal(err) 180 } 181 182 // Migrate all the way up ... 183 if err := m.Up(); err != nil { 184 log.Fatal(err) 185 } 186 } 187 188 func TestNewWithInstance(t *testing.T) { 189 dummyDb := &DummyInstance{"database"} 190 dbInst, err := dStub.WithInstance(dummyDb, &dStub.Config{}) 191 if err != nil { 192 t.Fatal(err) 193 } 194 195 dummySource := &DummyInstance{"source"} 196 sInst, err := sStub.WithInstance(dummySource, &sStub.Config{}) 197 if err != nil { 198 t.Fatal(err) 199 } 200 201 m, err := NewWithInstance(srcDrvNameStub, sInst, dbDrvNameStub, dbInst) 202 if err != nil { 203 t.Fatal(err) 204 } 205 206 if m.sourceName != srcDrvNameStub { 207 t.Errorf("expected stub, got %v", m.sourceName) 208 } 209 if m.sourceDrv == nil { 210 t.Error("expected sourceDrv not to be nil") 211 } 212 213 if m.databaseName != dbDrvNameStub { 214 t.Errorf("expected stub, got %v", m.databaseName) 215 } 216 if m.databaseDrv == nil { 217 t.Error("expected databaseDrv not to be nil") 218 } 219 } 220 221 func ExampleNewWithInstance() { 222 // See NewWithDatabaseInstance and NewWithSourceInstance for an example. 223 } 224 225 func TestClose(t *testing.T) { 226 m, _ := New("stub://", "stub://") 227 sourceErr, databaseErr := m.Close() 228 if sourceErr != nil { 229 t.Error(sourceErr) 230 } 231 if databaseErr != nil { 232 t.Error(databaseErr) 233 } 234 } 235 236 func TestMigrate(t *testing.T) { 237 m, _ := New("stub://", "stub://") 238 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 239 dbDrv := m.databaseDrv.(*dStub.Stub) 240 241 tt := []struct { 242 version uint 243 expectErr error 244 expectVersion uint 245 expectSeq migrationSequence 246 }{ 247 // migrate all the way Up in single steps 248 { 249 version: 0, 250 expectErr: os.ErrNotExist, 251 }, 252 { 253 version: 1, 254 expectVersion: 1, 255 expectSeq: migrationSequence{ 256 mr("CREATE 1"), 257 }, 258 }, 259 { 260 version: 2, 261 expectErr: os.ErrNotExist, 262 expectSeq: migrationSequence{ 263 mr("CREATE 1"), 264 }, 265 }, 266 { 267 version: 3, 268 expectVersion: 3, 269 expectSeq: migrationSequence{ 270 mr("CREATE 1"), 271 mr("CREATE 3"), 272 }, 273 }, 274 { 275 version: 4, 276 expectVersion: 4, 277 expectSeq: migrationSequence{ 278 mr("CREATE 1"), 279 mr("CREATE 3"), 280 mr("CREATE 4"), 281 }, 282 }, 283 { 284 version: 5, 285 expectVersion: 5, 286 expectSeq: migrationSequence{ // 5 has no up migration 287 mr("CREATE 1"), 288 mr("CREATE 3"), 289 mr("CREATE 4"), 290 }, 291 }, 292 { 293 version: 6, 294 expectErr: os.ErrNotExist, 295 expectSeq: migrationSequence{ 296 mr("CREATE 1"), 297 mr("CREATE 3"), 298 mr("CREATE 4"), 299 }, 300 }, 301 { 302 version: 7, 303 expectVersion: 7, 304 expectSeq: migrationSequence{ 305 mr("CREATE 1"), 306 mr("CREATE 3"), 307 mr("CREATE 4"), 308 mr("CREATE 7"), 309 }, 310 }, 311 { 312 version: 8, 313 expectErr: os.ErrNotExist, 314 expectSeq: migrationSequence{ 315 mr("CREATE 1"), 316 mr("CREATE 3"), 317 mr("CREATE 4"), 318 mr("CREATE 7"), 319 }, 320 }, 321 322 // migrate all the way Down in single steps 323 { 324 version: 6, 325 expectErr: os.ErrNotExist, 326 expectSeq: migrationSequence{ 327 mr("CREATE 1"), 328 mr("CREATE 3"), 329 mr("CREATE 4"), 330 mr("CREATE 7"), 331 }, 332 }, 333 { 334 version: 5, 335 expectVersion: 5, 336 expectSeq: migrationSequence{ 337 mr("CREATE 1"), 338 mr("CREATE 3"), 339 mr("CREATE 4"), 340 mr("CREATE 7"), 341 mr("DROP 7"), 342 }, 343 }, 344 { 345 version: 4, 346 expectVersion: 4, 347 expectSeq: migrationSequence{ 348 mr("CREATE 1"), 349 mr("CREATE 3"), 350 mr("CREATE 4"), 351 mr("CREATE 7"), 352 mr("DROP 7"), 353 mr("DROP 5"), 354 }, 355 }, 356 { 357 version: 3, 358 expectVersion: 3, 359 expectSeq: migrationSequence{ 360 mr("CREATE 1"), 361 mr("CREATE 3"), 362 mr("CREATE 4"), 363 mr("CREATE 7"), 364 mr("DROP 7"), 365 mr("DROP 5"), 366 mr("DROP 4"), 367 }, 368 }, 369 { 370 version: 2, 371 expectErr: os.ErrNotExist, 372 expectSeq: migrationSequence{ 373 mr("CREATE 1"), 374 mr("CREATE 3"), 375 mr("CREATE 4"), 376 mr("CREATE 7"), 377 mr("DROP 7"), 378 mr("DROP 5"), 379 mr("DROP 4"), 380 }, 381 }, 382 { 383 version: 1, 384 expectVersion: 1, 385 expectSeq: migrationSequence{ // 3 has no down migration 386 mr("CREATE 1"), 387 mr("CREATE 3"), 388 mr("CREATE 4"), 389 mr("CREATE 7"), 390 mr("DROP 7"), 391 mr("DROP 5"), 392 mr("DROP 4"), 393 }, 394 }, 395 { 396 version: 0, 397 expectErr: os.ErrNotExist, 398 expectSeq: migrationSequence{ 399 mr("CREATE 1"), 400 mr("CREATE 3"), 401 mr("CREATE 4"), 402 mr("CREATE 7"), 403 mr("DROP 7"), 404 mr("DROP 5"), 405 mr("DROP 4"), 406 }, 407 }, 408 409 // migrate all the way Up in one step 410 { 411 version: 7, 412 expectVersion: 7, 413 expectSeq: migrationSequence{ 414 mr("CREATE 1"), 415 mr("CREATE 3"), 416 mr("CREATE 4"), 417 mr("CREATE 7"), 418 mr("DROP 7"), 419 mr("DROP 5"), 420 mr("DROP 4"), 421 mr("CREATE 3"), 422 mr("CREATE 4"), 423 mr("CREATE 7"), 424 }, 425 }, 426 427 // migrate all the way Down in one step 428 { 429 version: 1, 430 expectVersion: 1, 431 expectSeq: migrationSequence{ 432 mr("CREATE 1"), 433 mr("CREATE 3"), 434 mr("CREATE 4"), 435 mr("CREATE 7"), 436 mr("DROP 7"), 437 mr("DROP 5"), 438 mr("DROP 4"), 439 mr("CREATE 3"), 440 mr("CREATE 4"), 441 mr("CREATE 7"), 442 mr("DROP 7"), 443 mr("DROP 5"), 444 mr("DROP 4"), 445 }, 446 }, 447 448 // can't migrate the same version twice 449 { 450 version: 1, 451 expectErr: ErrNoChange, 452 expectSeq: migrationSequence{ 453 mr("CREATE 1"), 454 mr("CREATE 3"), 455 mr("CREATE 4"), 456 mr("CREATE 7"), 457 mr("DROP 7"), 458 mr("DROP 5"), 459 mr("DROP 4"), 460 mr("CREATE 3"), 461 mr("CREATE 4"), 462 mr("CREATE 7"), 463 mr("DROP 7"), 464 mr("DROP 5"), 465 mr("DROP 4"), 466 }, 467 }, 468 } 469 470 for i, v := range tt { 471 err := m.Migrate(v.version) 472 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 473 (v.expectErr != os.ErrNotExist && err != v.expectErr) { 474 t.Errorf("expected err %v, got %v, in %v", v.expectErr, err, i) 475 476 } else if err == nil { 477 version, _, err := m.Version() 478 if err != nil { 479 t.Error(err) 480 } 481 if version != v.expectVersion { 482 t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i) 483 } 484 } 485 equalDbSeq(t, i, v.expectSeq, dbDrv) 486 } 487 } 488 489 func TestMigrateDirty(t *testing.T) { 490 m, _ := New("stub://", "stub://") 491 dbDrv := m.databaseDrv.(*dStub.Stub) 492 if err := dbDrv.SetVersion(0, true); err != nil { 493 t.Fatal(err) 494 } 495 496 err := m.Migrate(1) 497 if _, ok := err.(ErrDirty); !ok { 498 t.Fatalf("expected ErrDirty, got %v", err) 499 } 500 } 501 502 func TestSteps(t *testing.T) { 503 m, _ := New("stub://", "stub://") 504 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 505 dbDrv := m.databaseDrv.(*dStub.Stub) 506 507 tt := []struct { 508 steps int 509 expectErr error 510 expectVersion int 511 expectSeq migrationSequence 512 }{ 513 // step must be != 0 514 { 515 steps: 0, 516 expectErr: ErrNoChange, 517 }, 518 519 // can't go Down if ErrNilVersion 520 { 521 steps: -1, 522 expectErr: os.ErrNotExist, 523 }, 524 525 // migrate all the way Up 526 { 527 steps: 1, 528 expectVersion: 1, 529 expectSeq: migrationSequence{ 530 mr("CREATE 1")}, 531 }, 532 { 533 steps: 1, 534 expectVersion: 3, 535 expectSeq: migrationSequence{ 536 mr("CREATE 1"), 537 mr("CREATE 3"), 538 }, 539 }, 540 { 541 steps: 1, 542 expectVersion: 4, 543 expectSeq: migrationSequence{ 544 mr("CREATE 1"), 545 mr("CREATE 3"), 546 mr("CREATE 4"), 547 }, 548 }, 549 { 550 steps: 1, 551 expectVersion: 5, 552 expectSeq: migrationSequence{ 553 mr("CREATE 1"), 554 mr("CREATE 3"), 555 mr("CREATE 4"), 556 }, 557 }, 558 { 559 steps: 1, 560 expectVersion: 7, 561 expectSeq: migrationSequence{ 562 mr("CREATE 1"), 563 mr("CREATE 3"), 564 mr("CREATE 4"), 565 mr("CREATE 7"), 566 }, 567 }, 568 { 569 steps: 1, 570 expectErr: os.ErrNotExist, 571 expectSeq: migrationSequence{ 572 mr("CREATE 1"), 573 mr("CREATE 3"), 574 mr("CREATE 4"), 575 mr("CREATE 7"), 576 }, 577 }, 578 579 // migrate all the way Down 580 { 581 steps: -1, 582 expectVersion: 5, 583 expectSeq: migrationSequence{ 584 mr("CREATE 1"), 585 mr("CREATE 3"), 586 mr("CREATE 4"), 587 mr("CREATE 7"), 588 mr("DROP 7"), 589 }, 590 }, 591 { 592 steps: -1, 593 expectVersion: 4, 594 expectSeq: migrationSequence{ 595 mr("CREATE 1"), 596 mr("CREATE 3"), 597 mr("CREATE 4"), 598 mr("CREATE 7"), 599 mr("DROP 7"), 600 mr("DROP 5"), 601 }, 602 }, 603 { 604 steps: -1, 605 expectVersion: 3, 606 expectSeq: migrationSequence{ 607 mr("CREATE 1"), 608 mr("CREATE 3"), 609 mr("CREATE 4"), 610 mr("CREATE 7"), 611 mr("DROP 7"), 612 mr("DROP 5"), 613 mr("DROP 4"), 614 }, 615 }, 616 { 617 steps: -1, 618 expectVersion: 1, 619 expectSeq: migrationSequence{ 620 mr("CREATE 1"), 621 mr("CREATE 3"), 622 mr("CREATE 4"), 623 mr("CREATE 7"), 624 mr("DROP 7"), 625 mr("DROP 5"), 626 mr("DROP 4"), 627 }, 628 }, 629 { 630 steps: -1, 631 expectVersion: -1, 632 expectSeq: migrationSequence{ 633 mr("CREATE 1"), 634 mr("CREATE 3"), 635 mr("CREATE 4"), 636 mr("CREATE 7"), 637 mr("DROP 7"), 638 mr("DROP 5"), 639 mr("DROP 4"), 640 mr("DROP 1"), 641 }, 642 }, 643 644 // migrate Up in bigger step 645 { 646 steps: 4, 647 expectVersion: 5, 648 expectSeq: migrationSequence{ 649 mr("CREATE 1"), 650 mr("CREATE 3"), 651 mr("CREATE 4"), 652 mr("CREATE 7"), 653 mr("DROP 7"), 654 mr("DROP 5"), 655 mr("DROP 4"), 656 mr("DROP 1"), 657 mr("CREATE 1"), 658 mr("CREATE 3"), 659 mr("CREATE 4"), 660 }, 661 }, 662 663 // apply one migration, then reaches out of boundary 664 { 665 steps: 2, 666 expectErr: ErrShortLimit{1}, 667 expectVersion: 7, 668 expectSeq: migrationSequence{ 669 mr("CREATE 1"), 670 mr("CREATE 3"), 671 mr("CREATE 4"), 672 mr("CREATE 7"), 673 mr("DROP 7"), 674 mr("DROP 5"), 675 mr("DROP 4"), 676 mr("DROP 1"), 677 mr("CREATE 1"), 678 mr("CREATE 3"), 679 mr("CREATE 4"), 680 mr("CREATE 7"), 681 }, 682 }, 683 684 // migrate Down in bigger step 685 { 686 steps: -4, 687 expectVersion: 1, 688 expectSeq: migrationSequence{ 689 mr("CREATE 1"), 690 mr("CREATE 3"), 691 mr("CREATE 4"), 692 mr("CREATE 7"), 693 mr("DROP 7"), 694 mr("DROP 5"), 695 mr("DROP 4"), 696 mr("DROP 1"), 697 mr("CREATE 1"), 698 mr("CREATE 3"), 699 mr("CREATE 4"), 700 mr("CREATE 7"), 701 mr("DROP 7"), 702 mr("DROP 5"), 703 mr("DROP 4"), 704 }, 705 }, 706 707 // apply one migration, then reaches out of boundary 708 { 709 steps: -2, 710 expectErr: ErrShortLimit{1}, 711 expectVersion: -1, 712 expectSeq: migrationSequence{ 713 mr("CREATE 1"), 714 mr("CREATE 3"), 715 mr("CREATE 4"), 716 mr("CREATE 7"), 717 mr("DROP 7"), 718 mr("DROP 5"), 719 mr("DROP 4"), 720 mr("DROP 1"), 721 mr("CREATE 1"), 722 mr("CREATE 3"), 723 mr("CREATE 4"), 724 mr("CREATE 7"), 725 mr("DROP 7"), 726 mr("DROP 5"), 727 mr("DROP 4"), 728 mr("DROP 1"), 729 }, 730 }, 731 } 732 733 for i, v := range tt { 734 err := m.Steps(v.steps) 735 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 736 (v.expectErr != os.ErrNotExist && err != v.expectErr) { 737 t.Errorf("expected err %v, got %v, in %v", v.expectErr, err, i) 738 739 } else if err == nil { 740 version, _, err := m.Version() 741 if err != ErrNilVersion && err != nil { 742 t.Error(err) 743 } 744 if v.expectVersion == -1 && err != ErrNilVersion { 745 t.Errorf("expected ErrNilVersion, got %v, in %v", version, i) 746 747 } else if v.expectVersion >= 0 && version != uint(v.expectVersion) { 748 t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i) 749 } 750 } 751 equalDbSeq(t, i, v.expectSeq, dbDrv) 752 } 753 } 754 755 func TestStepsDirty(t *testing.T) { 756 m, _ := New("stub://", "stub://") 757 dbDrv := m.databaseDrv.(*dStub.Stub) 758 if err := dbDrv.SetVersion(0, true); err != nil { 759 t.Fatal(err) 760 } 761 762 err := m.Steps(1) 763 if _, ok := err.(ErrDirty); !ok { 764 t.Fatalf("expected ErrDirty, got %v", err) 765 } 766 } 767 768 func TestUpAndDown(t *testing.T) { 769 m, _ := New("stub://", "stub://") 770 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 771 dbDrv := m.databaseDrv.(*dStub.Stub) 772 773 // go Up first 774 if err := m.Up(); err != nil { 775 t.Fatal(err) 776 } 777 expectedSequence := migrationSequence{ 778 mr("CREATE 1"), 779 mr("CREATE 3"), 780 mr("CREATE 4"), 781 mr("CREATE 7"), 782 } 783 equalDbSeq(t, 0, expectedSequence, dbDrv) 784 785 // go Down 786 if err := m.Down(); err != nil { 787 t.Fatal(err) 788 } 789 expectedSequence = migrationSequence{ 790 mr("CREATE 1"), 791 mr("CREATE 3"), 792 mr("CREATE 4"), 793 mr("CREATE 7"), 794 mr("DROP 7"), 795 mr("DROP 5"), 796 mr("DROP 4"), 797 mr("DROP 1"), 798 } 799 equalDbSeq(t, 1, expectedSequence, dbDrv) 800 801 // go 1 Up and then all the way Up 802 if err := m.Steps(1); err != nil { 803 t.Fatal(err) 804 } 805 expectedSequence = migrationSequence{ 806 mr("CREATE 1"), 807 mr("CREATE 3"), 808 mr("CREATE 4"), 809 mr("CREATE 7"), 810 mr("DROP 7"), 811 mr("DROP 5"), 812 mr("DROP 4"), 813 mr("DROP 1"), 814 mr("CREATE 1"), 815 } 816 equalDbSeq(t, 2, expectedSequence, dbDrv) 817 818 if err := m.Up(); err != nil { 819 t.Fatal(err) 820 } 821 expectedSequence = migrationSequence{ 822 mr("CREATE 1"), 823 mr("CREATE 3"), 824 mr("CREATE 4"), 825 mr("CREATE 7"), 826 mr("DROP 7"), 827 mr("DROP 5"), 828 mr("DROP 4"), 829 mr("DROP 1"), 830 mr("CREATE 1"), 831 mr("CREATE 3"), 832 mr("CREATE 4"), 833 mr("CREATE 7"), 834 } 835 equalDbSeq(t, 3, expectedSequence, dbDrv) 836 837 // go 1 Down and then all the way Down 838 if err := m.Steps(-1); err != nil { 839 t.Fatal(err) 840 } 841 expectedSequence = migrationSequence{ 842 mr("CREATE 1"), 843 mr("CREATE 3"), 844 mr("CREATE 4"), 845 mr("CREATE 7"), 846 mr("DROP 7"), 847 mr("DROP 5"), 848 mr("DROP 4"), 849 mr("DROP 1"), 850 mr("CREATE 1"), 851 mr("CREATE 3"), 852 mr("CREATE 4"), 853 mr("CREATE 7"), 854 mr("DROP 7"), 855 } 856 equalDbSeq(t, 1, expectedSequence, dbDrv) 857 858 if err := m.Down(); err != nil { 859 t.Fatal(err) 860 } 861 expectedSequence = migrationSequence{ 862 mr("CREATE 1"), 863 mr("CREATE 3"), 864 mr("CREATE 4"), 865 mr("CREATE 7"), 866 mr("DROP 7"), 867 mr("DROP 5"), 868 mr("DROP 4"), 869 mr("DROP 1"), 870 mr("CREATE 1"), 871 mr("CREATE 3"), 872 mr("CREATE 4"), 873 mr("CREATE 7"), 874 mr("DROP 7"), 875 mr("DROP 5"), 876 mr("DROP 4"), 877 mr("DROP 1"), 878 } 879 equalDbSeq(t, 1, expectedSequence, dbDrv) 880 } 881 882 func TestUpDirty(t *testing.T) { 883 m, _ := New("stub://", "stub://") 884 dbDrv := m.databaseDrv.(*dStub.Stub) 885 if err := dbDrv.SetVersion(0, true); err != nil { 886 t.Fatal(err) 887 } 888 889 err := m.Up() 890 if _, ok := err.(ErrDirty); !ok { 891 t.Fatalf("expected ErrDirty, got %v", err) 892 } 893 } 894 895 func TestDownDirty(t *testing.T) { 896 m, _ := New("stub://", "stub://") 897 dbDrv := m.databaseDrv.(*dStub.Stub) 898 if err := dbDrv.SetVersion(0, true); err != nil { 899 t.Fatal(err) 900 } 901 902 err := m.Down() 903 if _, ok := err.(ErrDirty); !ok { 904 t.Fatalf("expected ErrDirty, got %v", err) 905 } 906 } 907 908 func TestDrop(t *testing.T) { 909 m, _ := New("stub://", "stub://") 910 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 911 dbDrv := m.databaseDrv.(*dStub.Stub) 912 913 if err := m.Drop(); err != nil { 914 t.Fatal(err) 915 } 916 917 if dbDrv.MigrationSequence[len(dbDrv.MigrationSequence)-1] != dStub.DROP { 918 t.Fatalf("expected database to DROP, got sequence %v", dbDrv.MigrationSequence) 919 } 920 } 921 922 func TestVersion(t *testing.T) { 923 m, _ := New("stub://", "stub://") 924 dbDrv := m.databaseDrv.(*dStub.Stub) 925 926 _, _, err := m.Version() 927 if err != ErrNilVersion { 928 t.Fatalf("expected ErrNilVersion, got %v", err) 929 } 930 931 if err := dbDrv.Run(bytes.NewBufferString("1_up")); err != nil { 932 t.Fatal(err) 933 } 934 935 if err := dbDrv.SetVersion(1, false); err != nil { 936 t.Fatal(err) 937 } 938 939 v, _, err := m.Version() 940 if err != nil { 941 t.Fatal(err) 942 } 943 944 if v != 1 { 945 t.Fatalf("expected version 1, got %v", v) 946 } 947 } 948 949 func TestRun(t *testing.T) { 950 m, _ := New("stub://", "stub://") 951 952 mx, err := NewMigration(nil, "", 1, 2) 953 if err != nil { 954 t.Fatal(err) 955 } 956 957 if err := m.Run(mx); err != nil { 958 t.Fatal(err) 959 } 960 961 v, _, err := m.Version() 962 if err != nil { 963 t.Fatal(err) 964 } 965 966 if v != 2 { 967 t.Errorf("expected version 2, got %v", v) 968 } 969 } 970 971 func TestRunDirty(t *testing.T) { 972 m, _ := New("stub://", "stub://") 973 dbDrv := m.databaseDrv.(*dStub.Stub) 974 if err := dbDrv.SetVersion(0, true); err != nil { 975 t.Fatal(err) 976 } 977 978 migr, err := NewMigration(nil, "", 1, 2) 979 if err != nil { 980 t.Fatal(err) 981 } 982 983 err = m.Run(migr) 984 if _, ok := err.(ErrDirty); !ok { 985 t.Fatalf("expected ErrDirty, got %v", err) 986 } 987 } 988 989 func TestForce(t *testing.T) { 990 m, _ := New("stub://", "stub://") 991 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 992 993 if err := m.Force(7); err != nil { 994 t.Fatal(err) 995 } 996 997 v, dirty, err := m.Version() 998 if err != nil { 999 t.Fatal(err) 1000 } 1001 if dirty { 1002 t.Errorf("expected dirty to be false") 1003 } 1004 if v != 7 { 1005 t.Errorf("expected version to be 7") 1006 } 1007 } 1008 1009 func TestForceDirty(t *testing.T) { 1010 m, _ := New("stub://", "stub://") 1011 dbDrv := m.databaseDrv.(*dStub.Stub) 1012 if err := dbDrv.SetVersion(0, true); err != nil { 1013 t.Fatal(err) 1014 } 1015 1016 if err := m.Force(1); err != nil { 1017 t.Fatal(err) 1018 } 1019 } 1020 1021 func TestRead(t *testing.T) { 1022 m, _ := New("stub://", "stub://") 1023 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1024 1025 tt := []struct { 1026 from int 1027 to int 1028 expectErr error 1029 expectMigrations migrationSequence 1030 }{ 1031 {from: -1, to: -1, expectErr: ErrNoChange}, 1032 {from: -1, to: 0, expectErr: os.ErrNotExist}, 1033 {from: -1, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(1))}, 1034 {from: -1, to: 2, expectErr: os.ErrNotExist}, 1035 {from: -1, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3))}, 1036 {from: -1, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4))}, 1037 {from: -1, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5))}, 1038 {from: -1, to: 6, expectErr: os.ErrNotExist}, 1039 {from: -1, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5), M(7))}, 1040 {from: -1, to: 8, expectErr: os.ErrNotExist}, 1041 1042 {from: 0, to: -1, expectErr: os.ErrNotExist}, 1043 {from: 0, to: 0, expectErr: os.ErrNotExist}, 1044 {from: 0, to: 1, expectErr: os.ErrNotExist}, 1045 {from: 0, to: 2, expectErr: os.ErrNotExist}, 1046 {from: 0, to: 3, expectErr: os.ErrNotExist}, 1047 {from: 0, to: 4, expectErr: os.ErrNotExist}, 1048 {from: 0, to: 5, expectErr: os.ErrNotExist}, 1049 {from: 0, to: 6, expectErr: os.ErrNotExist}, 1050 {from: 0, to: 7, expectErr: os.ErrNotExist}, 1051 {from: 0, to: 8, expectErr: os.ErrNotExist}, 1052 1053 {from: 1, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))}, 1054 {from: 1, to: 0, expectErr: os.ErrNotExist}, 1055 {from: 1, to: 1, expectErr: ErrNoChange}, 1056 {from: 1, to: 2, expectErr: os.ErrNotExist}, 1057 {from: 1, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(3))}, 1058 {from: 1, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4))}, 1059 {from: 1, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5))}, 1060 {from: 1, to: 6, expectErr: os.ErrNotExist}, 1061 {from: 1, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5), M(7))}, 1062 {from: 1, to: 8, expectErr: os.ErrNotExist}, 1063 1064 {from: 2, to: -1, expectErr: os.ErrNotExist}, 1065 {from: 2, to: 0, expectErr: os.ErrNotExist}, 1066 {from: 2, to: 1, expectErr: os.ErrNotExist}, 1067 {from: 2, to: 2, expectErr: os.ErrNotExist}, 1068 {from: 2, to: 3, expectErr: os.ErrNotExist}, 1069 {from: 2, to: 4, expectErr: os.ErrNotExist}, 1070 {from: 2, to: 5, expectErr: os.ErrNotExist}, 1071 {from: 2, to: 6, expectErr: os.ErrNotExist}, 1072 {from: 2, to: 7, expectErr: os.ErrNotExist}, 1073 {from: 2, to: 8, expectErr: os.ErrNotExist}, 1074 1075 {from: 3, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))}, 1076 {from: 3, to: 0, expectErr: os.ErrNotExist}, 1077 {from: 3, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1))}, 1078 {from: 3, to: 2, expectErr: os.ErrNotExist}, 1079 {from: 3, to: 3, expectErr: ErrNoChange}, 1080 {from: 3, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(4))}, 1081 {from: 3, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5))}, 1082 {from: 3, to: 6, expectErr: os.ErrNotExist}, 1083 {from: 3, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5), M(7))}, 1084 {from: 3, to: 8, expectErr: os.ErrNotExist}, 1085 1086 {from: 4, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1), M(1, -1))}, 1087 {from: 4, to: 0, expectErr: os.ErrNotExist}, 1088 {from: 4, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1))}, 1089 {from: 4, to: 2, expectErr: os.ErrNotExist}, 1090 {from: 4, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(4, 3))}, 1091 {from: 4, to: 4, expectErr: ErrNoChange}, 1092 {from: 4, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(5))}, 1093 {from: 4, to: 6, expectErr: os.ErrNotExist}, 1094 {from: 4, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))}, 1095 {from: 4, to: 8, expectErr: os.ErrNotExist}, 1096 1097 {from: 5, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1098 {from: 5, to: 0, expectErr: os.ErrNotExist}, 1099 {from: 5, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1))}, 1100 {from: 5, to: 2, expectErr: os.ErrNotExist}, 1101 {from: 5, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3))}, 1102 {from: 5, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(5, 4))}, 1103 {from: 5, to: 5, expectErr: ErrNoChange}, 1104 {from: 5, to: 6, expectErr: os.ErrNotExist}, 1105 {from: 5, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(7))}, 1106 {from: 5, to: 8, expectErr: os.ErrNotExist}, 1107 1108 {from: 6, to: -1, expectErr: os.ErrNotExist}, 1109 {from: 6, to: 0, expectErr: os.ErrNotExist}, 1110 {from: 6, to: 1, expectErr: os.ErrNotExist}, 1111 {from: 6, to: 2, expectErr: os.ErrNotExist}, 1112 {from: 6, to: 3, expectErr: os.ErrNotExist}, 1113 {from: 6, to: 4, expectErr: os.ErrNotExist}, 1114 {from: 6, to: 5, expectErr: os.ErrNotExist}, 1115 {from: 6, to: 6, expectErr: os.ErrNotExist}, 1116 {from: 6, to: 7, expectErr: os.ErrNotExist}, 1117 {from: 6, to: 8, expectErr: os.ErrNotExist}, 1118 1119 {from: 7, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1120 {from: 7, to: 0, expectErr: os.ErrNotExist}, 1121 {from: 7, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1))}, 1122 {from: 7, to: 2, expectErr: os.ErrNotExist}, 1123 {from: 7, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3))}, 1124 {from: 7, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4))}, 1125 {from: 7, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(7, 5))}, 1126 {from: 7, to: 6, expectErr: os.ErrNotExist}, 1127 {from: 7, to: 7, expectErr: ErrNoChange}, 1128 {from: 7, to: 8, expectErr: os.ErrNotExist}, 1129 1130 {from: 8, to: -1, expectErr: os.ErrNotExist}, 1131 {from: 8, to: 0, expectErr: os.ErrNotExist}, 1132 {from: 8, to: 1, expectErr: os.ErrNotExist}, 1133 {from: 8, to: 2, expectErr: os.ErrNotExist}, 1134 {from: 8, to: 3, expectErr: os.ErrNotExist}, 1135 {from: 8, to: 4, expectErr: os.ErrNotExist}, 1136 {from: 8, to: 5, expectErr: os.ErrNotExist}, 1137 {from: 8, to: 6, expectErr: os.ErrNotExist}, 1138 {from: 8, to: 7, expectErr: os.ErrNotExist}, 1139 {from: 8, to: 8, expectErr: os.ErrNotExist}, 1140 } 1141 1142 for i, v := range tt { 1143 ret := make(chan interface{}) 1144 go m.read(v.from, v.to, ret) 1145 migrations, err := migrationsFromChannel(ret) 1146 1147 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 1148 (v.expectErr != os.ErrNotExist && v.expectErr != err) { 1149 t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i) 1150 t.Logf("%v, in %v", migrations, i) 1151 } 1152 if len(v.expectMigrations) > 0 { 1153 equalMigSeq(t, i, v.expectMigrations, migrations) 1154 } 1155 } 1156 } 1157 1158 func TestReadUp(t *testing.T) { 1159 m, _ := New("stub://", "stub://") 1160 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1161 1162 tt := []struct { 1163 from int 1164 limit int // -1 means no limit 1165 expectErr error 1166 expectMigrations migrationSequence 1167 }{ 1168 {from: -1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5), M(7))}, 1169 {from: -1, limit: 0, expectErr: ErrNoChange}, 1170 {from: -1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(1))}, 1171 {from: -1, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3))}, 1172 1173 {from: 0, limit: -1, expectErr: os.ErrNotExist}, 1174 {from: 0, limit: 0, expectErr: os.ErrNotExist}, 1175 {from: 0, limit: 1, expectErr: os.ErrNotExist}, 1176 {from: 0, limit: 2, expectErr: os.ErrNotExist}, 1177 1178 {from: 1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5), M(7))}, 1179 {from: 1, limit: 0, expectErr: ErrNoChange}, 1180 {from: 1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(3))}, 1181 {from: 1, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4))}, 1182 1183 {from: 2, limit: -1, expectErr: os.ErrNotExist}, 1184 {from: 2, limit: 0, expectErr: os.ErrNotExist}, 1185 {from: 2, limit: 1, expectErr: os.ErrNotExist}, 1186 {from: 2, limit: 2, expectErr: os.ErrNotExist}, 1187 1188 {from: 3, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5), M(7))}, 1189 {from: 3, limit: 0, expectErr: ErrNoChange}, 1190 {from: 3, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(4))}, 1191 {from: 3, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5))}, 1192 1193 {from: 4, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))}, 1194 {from: 4, limit: 0, expectErr: ErrNoChange}, 1195 {from: 4, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(5))}, 1196 {from: 4, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))}, 1197 1198 {from: 5, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(7))}, 1199 {from: 5, limit: 0, expectErr: ErrNoChange}, 1200 {from: 5, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(7))}, 1201 {from: 5, limit: 2, expectErr: ErrShortLimit{1}, expectMigrations: newMigSeq(M(7))}, 1202 1203 {from: 6, limit: -1, expectErr: os.ErrNotExist}, 1204 {from: 6, limit: 0, expectErr: os.ErrNotExist}, 1205 {from: 6, limit: 1, expectErr: os.ErrNotExist}, 1206 {from: 6, limit: 2, expectErr: os.ErrNotExist}, 1207 1208 {from: 7, limit: -1, expectErr: ErrNoChange}, 1209 {from: 7, limit: 0, expectErr: ErrNoChange}, 1210 {from: 7, limit: 1, expectErr: os.ErrNotExist}, 1211 {from: 7, limit: 2, expectErr: os.ErrNotExist}, 1212 1213 {from: 8, limit: -1, expectErr: os.ErrNotExist}, 1214 {from: 8, limit: 0, expectErr: os.ErrNotExist}, 1215 {from: 8, limit: 1, expectErr: os.ErrNotExist}, 1216 {from: 8, limit: 2, expectErr: os.ErrNotExist}, 1217 } 1218 1219 for i, v := range tt { 1220 ret := make(chan interface{}) 1221 go m.readUp(v.from, v.limit, ret) 1222 migrations, err := migrationsFromChannel(ret) 1223 1224 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 1225 (v.expectErr != os.ErrNotExist && v.expectErr != err) { 1226 t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i) 1227 t.Logf("%v, in %v", migrations, i) 1228 } 1229 if len(v.expectMigrations) > 0 { 1230 equalMigSeq(t, i, v.expectMigrations, migrations) 1231 } 1232 } 1233 } 1234 1235 func TestReadDown(t *testing.T) { 1236 m, _ := New("stub://", "stub://") 1237 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1238 1239 tt := []struct { 1240 from int 1241 limit int // -1 means no limit 1242 expectErr error 1243 expectMigrations migrationSequence 1244 }{ 1245 {from: -1, limit: -1, expectErr: ErrNoChange}, 1246 {from: -1, limit: 0, expectErr: ErrNoChange}, 1247 {from: -1, limit: 1, expectErr: os.ErrNotExist}, 1248 {from: -1, limit: 2, expectErr: os.ErrNotExist}, 1249 1250 {from: 0, limit: -1, expectErr: os.ErrNotExist}, 1251 {from: 0, limit: 0, expectErr: os.ErrNotExist}, 1252 {from: 0, limit: 1, expectErr: os.ErrNotExist}, 1253 {from: 0, limit: 2, expectErr: os.ErrNotExist}, 1254 1255 {from: 1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))}, 1256 {from: 1, limit: 0, expectErr: ErrNoChange}, 1257 {from: 1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))}, 1258 {from: 1, limit: 2, expectErr: ErrShortLimit{1}, expectMigrations: newMigSeq(M(1, -1))}, 1259 1260 {from: 2, limit: -1, expectErr: os.ErrNotExist}, 1261 {from: 2, limit: 0, expectErr: os.ErrNotExist}, 1262 {from: 2, limit: 1, expectErr: os.ErrNotExist}, 1263 {from: 2, limit: 2, expectErr: os.ErrNotExist}, 1264 1265 {from: 3, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))}, 1266 {from: 3, limit: 0, expectErr: ErrNoChange}, 1267 {from: 3, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1))}, 1268 {from: 3, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))}, 1269 1270 {from: 4, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1), M(1, -1))}, 1271 {from: 4, limit: 0, expectErr: ErrNoChange}, 1272 {from: 4, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3))}, 1273 {from: 4, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1))}, 1274 1275 {from: 5, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1276 {from: 5, limit: 0, expectErr: ErrNoChange}, 1277 {from: 5, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4))}, 1278 {from: 5, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3))}, 1279 1280 {from: 6, limit: -1, expectErr: os.ErrNotExist}, 1281 {from: 6, limit: 0, expectErr: os.ErrNotExist}, 1282 {from: 6, limit: 1, expectErr: os.ErrNotExist}, 1283 {from: 6, limit: 2, expectErr: os.ErrNotExist}, 1284 1285 {from: 7, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1286 {from: 7, limit: 0, expectErr: ErrNoChange}, 1287 {from: 7, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5))}, 1288 {from: 7, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4))}, 1289 1290 {from: 8, limit: -1, expectErr: os.ErrNotExist}, 1291 {from: 8, limit: 0, expectErr: os.ErrNotExist}, 1292 {from: 8, limit: 1, expectErr: os.ErrNotExist}, 1293 {from: 8, limit: 2, expectErr: os.ErrNotExist}, 1294 } 1295 1296 for i, v := range tt { 1297 ret := make(chan interface{}) 1298 go m.readDown(v.from, v.limit, ret) 1299 migrations, err := migrationsFromChannel(ret) 1300 1301 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 1302 (v.expectErr != os.ErrNotExist && v.expectErr != err) { 1303 t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i) 1304 t.Logf("%v, in %v", migrations, i) 1305 } 1306 if len(v.expectMigrations) > 0 { 1307 equalMigSeq(t, i, v.expectMigrations, migrations) 1308 } 1309 } 1310 } 1311 1312 func TestLock(t *testing.T) { 1313 m, _ := New("stub://", "stub://") 1314 if err := m.lock(); err != nil { 1315 t.Fatal(err) 1316 } 1317 1318 if err := m.lock(); err == nil { 1319 t.Fatal("should be locked already") 1320 } 1321 } 1322 1323 func migrationsFromChannel(ret chan interface{}) ([]*Migration, error) { 1324 slice := make([]*Migration, 0) 1325 for r := range ret { 1326 switch t := r.(type) { 1327 case error: 1328 return slice, t 1329 1330 case *Migration: 1331 slice = append(slice, t) 1332 } 1333 } 1334 return slice, nil 1335 } 1336 1337 type migrationSequence []*Migration 1338 1339 func newMigSeq(migr ...*Migration) migrationSequence { 1340 return migr 1341 } 1342 1343 func (m *migrationSequence) add(migr ...*Migration) migrationSequence { // nolint:unused 1344 *m = append(*m, migr...) 1345 return *m 1346 } 1347 1348 func (m *migrationSequence) bodySequence() []string { 1349 r := make([]string, 0) 1350 for _, v := range *m { 1351 if v.Body != nil { 1352 body, err := ioutil.ReadAll(v.Body) 1353 if err != nil { 1354 panic(err) // that should never happen 1355 } 1356 1357 // reset body reader 1358 // TODO: is there a better/nicer way? 1359 v.Body = ioutil.NopCloser(bytes.NewReader(body)) 1360 1361 r = append(r, string(body[:])) 1362 } else { 1363 r = append(r, "<empty>") 1364 } 1365 } 1366 return r 1367 } 1368 1369 // M is a convenience func to create a new *Migration 1370 func M(version uint, targetVersion ...int) *Migration { 1371 if len(targetVersion) > 1 { 1372 panic("only one targetVersion allowed") 1373 } 1374 ts := int(version) 1375 if len(targetVersion) == 1 { 1376 ts = targetVersion[0] 1377 } 1378 1379 m, _ := New("stub://", "stub://") 1380 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1381 migr, err := m.newMigration(version, ts) 1382 if err != nil { 1383 panic(err) 1384 } 1385 return migr 1386 } 1387 1388 // mr is a convenience func to create a new *Migration from the raw database query 1389 func mr(value string) *Migration { 1390 return &Migration{ 1391 Body: ioutil.NopCloser(strings.NewReader(value)), 1392 } 1393 } 1394 1395 func equalMigSeq(t *testing.T, i int, expected, got migrationSequence) { 1396 if len(expected) != len(got) { 1397 t.Errorf("expected migrations %v, got %v, in %v", expected, got, i) 1398 1399 } else { 1400 for ii := 0; ii < len(expected); ii++ { 1401 if expected[ii].Version != got[ii].Version { 1402 t.Errorf("expected version %v, got %v, in %v", expected[ii].Version, got[ii].Version, i) 1403 } 1404 1405 if expected[ii].TargetVersion != got[ii].TargetVersion { 1406 t.Errorf("expected targetVersion %v, got %v, in %v", expected[ii].TargetVersion, got[ii].TargetVersion, i) 1407 } 1408 } 1409 } 1410 } 1411 1412 func equalDbSeq(t *testing.T, i int, expected migrationSequence, got *dStub.Stub) { 1413 bs := expected.bodySequence() 1414 if !got.EqualSequence(bs) { 1415 t.Fatalf("\nexpected sequence %v,\ngot %v, in %v", bs, got.MigrationSequence, i) 1416 } 1417 }