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