github.com/quanghm/crate-migrate/v4@v4.0.0-20240506141318-8f1d4a2ddb6c/migrate_test.go (about) 1 package migrate 2 3 import ( 4 "bytes" 5 "database/sql" 6 "errors" 7 "io" 8 "log" 9 "os" 10 "strings" 11 "testing" 12 13 dStub "github.com/quanghm/crate-migrate/v4/database/stub" 14 "github.com/quanghm/crate-migrate/v4/source" 15 sStub "github.com/quanghm/crate-migrate/v4/source/stub" 16 ) 17 18 // sourceStubMigrations hold the following migrations: 19 // u = up migration, d = down migration, n = version 20 // 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/quanghm/crate-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/quanghm/crate-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 475 } else if err == nil { 476 version, _, err := m.Version() 477 if err != nil { 478 t.Error(err) 479 } 480 if version != v.expectVersion { 481 t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i) 482 } 483 } 484 equalDbSeq(t, i, v.expectSeq, dbDrv) 485 } 486 } 487 488 func TestMigrateDirty(t *testing.T) { 489 m, _ := New("stub://", "stub://") 490 dbDrv := m.databaseDrv.(*dStub.Stub) 491 if err := dbDrv.SetVersion(0, true); err != nil { 492 t.Fatal(err) 493 } 494 495 err := m.Migrate(1) 496 if _, ok := err.(ErrDirty); !ok { 497 t.Fatalf("expected ErrDirty, got %v", err) 498 } 499 } 500 501 func TestSteps(t *testing.T) { 502 m, _ := New("stub://", "stub://") 503 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 504 dbDrv := m.databaseDrv.(*dStub.Stub) 505 506 tt := []struct { 507 steps int 508 expectErr error 509 expectVersion int 510 expectSeq migrationSequence 511 }{ 512 // step must be != 0 513 { 514 steps: 0, 515 expectErr: ErrNoChange, 516 }, 517 518 // can't go Down if ErrNilVersion 519 { 520 steps: -1, 521 expectErr: os.ErrNotExist, 522 }, 523 524 // migrate all the way Up 525 { 526 steps: 1, 527 expectVersion: 1, 528 expectSeq: migrationSequence{ 529 mr("CREATE 1")}, 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 738 } else if err == nil { 739 version, _, err := m.Version() 740 if err != ErrNilVersion && err != nil { 741 t.Error(err) 742 } 743 if v.expectVersion == -1 && err != ErrNilVersion { 744 t.Errorf("expected ErrNilVersion, got %v, in %v", version, i) 745 746 } else if v.expectVersion >= 0 && version != uint(v.expectVersion) { 747 t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i) 748 } 749 } 750 equalDbSeq(t, i, v.expectSeq, dbDrv) 751 } 752 } 753 754 func TestStepsDirty(t *testing.T) { 755 m, _ := New("stub://", "stub://") 756 dbDrv := m.databaseDrv.(*dStub.Stub) 757 if err := dbDrv.SetVersion(0, true); err != nil { 758 t.Fatal(err) 759 } 760 761 err := m.Steps(1) 762 if _, ok := err.(ErrDirty); !ok { 763 t.Fatalf("expected ErrDirty, got %v", err) 764 } 765 } 766 767 func TestUpAndDown(t *testing.T) { 768 m, _ := New("stub://", "stub://") 769 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 770 dbDrv := m.databaseDrv.(*dStub.Stub) 771 772 // go Up first 773 if err := m.Up(); err != nil { 774 t.Fatal(err) 775 } 776 expectedSequence := migrationSequence{ 777 mr("CREATE 1"), 778 mr("CREATE 3"), 779 mr("CREATE 4"), 780 mr("CREATE 7"), 781 } 782 equalDbSeq(t, 0, expectedSequence, dbDrv) 783 784 // go Down 785 if err := m.Down(); err != nil { 786 t.Fatal(err) 787 } 788 expectedSequence = migrationSequence{ 789 mr("CREATE 1"), 790 mr("CREATE 3"), 791 mr("CREATE 4"), 792 mr("CREATE 7"), 793 mr("DROP 7"), 794 mr("DROP 5"), 795 mr("DROP 4"), 796 mr("DROP 1"), 797 } 798 equalDbSeq(t, 1, expectedSequence, dbDrv) 799 800 // go 1 Up and then all the way Up 801 if err := m.Steps(1); err != nil { 802 t.Fatal(err) 803 } 804 expectedSequence = migrationSequence{ 805 mr("CREATE 1"), 806 mr("CREATE 3"), 807 mr("CREATE 4"), 808 mr("CREATE 7"), 809 mr("DROP 7"), 810 mr("DROP 5"), 811 mr("DROP 4"), 812 mr("DROP 1"), 813 mr("CREATE 1"), 814 } 815 equalDbSeq(t, 2, expectedSequence, dbDrv) 816 817 if err := m.Up(); err != nil { 818 t.Fatal(err) 819 } 820 expectedSequence = migrationSequence{ 821 mr("CREATE 1"), 822 mr("CREATE 3"), 823 mr("CREATE 4"), 824 mr("CREATE 7"), 825 mr("DROP 7"), 826 mr("DROP 5"), 827 mr("DROP 4"), 828 mr("DROP 1"), 829 mr("CREATE 1"), 830 mr("CREATE 3"), 831 mr("CREATE 4"), 832 mr("CREATE 7"), 833 } 834 equalDbSeq(t, 3, expectedSequence, dbDrv) 835 836 // go 1 Down and then all the way Down 837 if err := m.Steps(-1); err != nil { 838 t.Fatal(err) 839 } 840 expectedSequence = migrationSequence{ 841 mr("CREATE 1"), 842 mr("CREATE 3"), 843 mr("CREATE 4"), 844 mr("CREATE 7"), 845 mr("DROP 7"), 846 mr("DROP 5"), 847 mr("DROP 4"), 848 mr("DROP 1"), 849 mr("CREATE 1"), 850 mr("CREATE 3"), 851 mr("CREATE 4"), 852 mr("CREATE 7"), 853 mr("DROP 7"), 854 } 855 equalDbSeq(t, 1, expectedSequence, dbDrv) 856 857 if err := m.Down(); err != nil { 858 t.Fatal(err) 859 } 860 expectedSequence = migrationSequence{ 861 mr("CREATE 1"), 862 mr("CREATE 3"), 863 mr("CREATE 4"), 864 mr("CREATE 7"), 865 mr("DROP 7"), 866 mr("DROP 5"), 867 mr("DROP 4"), 868 mr("DROP 1"), 869 mr("CREATE 1"), 870 mr("CREATE 3"), 871 mr("CREATE 4"), 872 mr("CREATE 7"), 873 mr("DROP 7"), 874 mr("DROP 5"), 875 mr("DROP 4"), 876 mr("DROP 1"), 877 } 878 equalDbSeq(t, 1, expectedSequence, dbDrv) 879 } 880 881 func TestUpDirty(t *testing.T) { 882 m, _ := New("stub://", "stub://") 883 dbDrv := m.databaseDrv.(*dStub.Stub) 884 if err := dbDrv.SetVersion(0, true); err != nil { 885 t.Fatal(err) 886 } 887 888 err := m.Up() 889 if _, ok := err.(ErrDirty); !ok { 890 t.Fatalf("expected ErrDirty, got %v", err) 891 } 892 } 893 894 func TestDownDirty(t *testing.T) { 895 m, _ := New("stub://", "stub://") 896 dbDrv := m.databaseDrv.(*dStub.Stub) 897 if err := dbDrv.SetVersion(0, true); err != nil { 898 t.Fatal(err) 899 } 900 901 err := m.Down() 902 if _, ok := err.(ErrDirty); !ok { 903 t.Fatalf("expected ErrDirty, got %v", err) 904 } 905 } 906 907 func TestDrop(t *testing.T) { 908 m, _ := New("stub://", "stub://") 909 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 910 dbDrv := m.databaseDrv.(*dStub.Stub) 911 912 if err := m.Drop(); err != nil { 913 t.Fatal(err) 914 } 915 916 if dbDrv.MigrationSequence[len(dbDrv.MigrationSequence)-1] != dStub.DROP { 917 t.Fatalf("expected database to DROP, got sequence %v", dbDrv.MigrationSequence) 918 } 919 } 920 921 func TestVersion(t *testing.T) { 922 m, _ := New("stub://", "stub://") 923 dbDrv := m.databaseDrv.(*dStub.Stub) 924 925 _, _, err := m.Version() 926 if err != ErrNilVersion { 927 t.Fatalf("expected ErrNilVersion, got %v", err) 928 } 929 930 if err := dbDrv.Run(bytes.NewBufferString("1_up")); err != nil { 931 t.Fatal(err) 932 } 933 934 if err := dbDrv.SetVersion(1, false); err != nil { 935 t.Fatal(err) 936 } 937 938 v, _, err := m.Version() 939 if err != nil { 940 t.Fatal(err) 941 } 942 943 if v != 1 { 944 t.Fatalf("expected version 1, got %v", v) 945 } 946 } 947 948 func TestRun(t *testing.T) { 949 m, _ := New("stub://", "stub://") 950 951 mx, err := NewMigration(nil, "", 1, 2) 952 if err != nil { 953 t.Fatal(err) 954 } 955 956 if err := m.Run(mx); err != nil { 957 t.Fatal(err) 958 } 959 960 v, _, err := m.Version() 961 if err != nil { 962 t.Fatal(err) 963 } 964 965 if v != 2 { 966 t.Errorf("expected version 2, got %v", v) 967 } 968 } 969 970 func TestRunDirty(t *testing.T) { 971 m, _ := New("stub://", "stub://") 972 dbDrv := m.databaseDrv.(*dStub.Stub) 973 if err := dbDrv.SetVersion(0, true); err != nil { 974 t.Fatal(err) 975 } 976 977 migr, err := NewMigration(nil, "", 1, 2) 978 if err != nil { 979 t.Fatal(err) 980 } 981 982 err = m.Run(migr) 983 if _, ok := err.(ErrDirty); !ok { 984 t.Fatalf("expected ErrDirty, got %v", err) 985 } 986 } 987 988 func TestForce(t *testing.T) { 989 m, _ := New("stub://", "stub://") 990 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 991 992 if err := m.Force(7); err != nil { 993 t.Fatal(err) 994 } 995 996 v, dirty, err := m.Version() 997 if err != nil { 998 t.Fatal(err) 999 } 1000 if dirty { 1001 t.Errorf("expected dirty to be false") 1002 } 1003 if v != 7 { 1004 t.Errorf("expected version to be 7") 1005 } 1006 } 1007 1008 func TestForceDirty(t *testing.T) { 1009 m, _ := New("stub://", "stub://") 1010 dbDrv := m.databaseDrv.(*dStub.Stub) 1011 if err := dbDrv.SetVersion(0, true); err != nil { 1012 t.Fatal(err) 1013 } 1014 1015 if err := m.Force(1); err != nil { 1016 t.Fatal(err) 1017 } 1018 } 1019 1020 func TestRead(t *testing.T) { 1021 m, _ := New("stub://", "stub://") 1022 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1023 1024 tt := []struct { 1025 from int 1026 to int 1027 expectErr error 1028 expectMigrations migrationSequence 1029 }{ 1030 {from: -1, to: -1, expectErr: ErrNoChange}, 1031 {from: -1, to: 0, expectErr: os.ErrNotExist}, 1032 {from: -1, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(1))}, 1033 {from: -1, to: 2, expectErr: os.ErrNotExist}, 1034 {from: -1, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3))}, 1035 {from: -1, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4))}, 1036 {from: -1, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5))}, 1037 {from: -1, to: 6, expectErr: os.ErrNotExist}, 1038 {from: -1, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5), M(7))}, 1039 {from: -1, to: 8, expectErr: os.ErrNotExist}, 1040 1041 {from: 0, to: -1, expectErr: os.ErrNotExist}, 1042 {from: 0, to: 0, expectErr: os.ErrNotExist}, 1043 {from: 0, to: 1, expectErr: os.ErrNotExist}, 1044 {from: 0, to: 2, expectErr: os.ErrNotExist}, 1045 {from: 0, to: 3, expectErr: os.ErrNotExist}, 1046 {from: 0, to: 4, expectErr: os.ErrNotExist}, 1047 {from: 0, to: 5, expectErr: os.ErrNotExist}, 1048 {from: 0, to: 6, expectErr: os.ErrNotExist}, 1049 {from: 0, to: 7, expectErr: os.ErrNotExist}, 1050 {from: 0, to: 8, expectErr: os.ErrNotExist}, 1051 1052 {from: 1, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))}, 1053 {from: 1, to: 0, expectErr: os.ErrNotExist}, 1054 {from: 1, to: 1, expectErr: ErrNoChange}, 1055 {from: 1, to: 2, expectErr: os.ErrNotExist}, 1056 {from: 1, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(3))}, 1057 {from: 1, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4))}, 1058 {from: 1, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5))}, 1059 {from: 1, to: 6, expectErr: os.ErrNotExist}, 1060 {from: 1, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5), M(7))}, 1061 {from: 1, to: 8, expectErr: os.ErrNotExist}, 1062 1063 {from: 2, to: -1, expectErr: os.ErrNotExist}, 1064 {from: 2, to: 0, expectErr: os.ErrNotExist}, 1065 {from: 2, to: 1, expectErr: os.ErrNotExist}, 1066 {from: 2, to: 2, expectErr: os.ErrNotExist}, 1067 {from: 2, to: 3, expectErr: os.ErrNotExist}, 1068 {from: 2, to: 4, expectErr: os.ErrNotExist}, 1069 {from: 2, to: 5, expectErr: os.ErrNotExist}, 1070 {from: 2, to: 6, expectErr: os.ErrNotExist}, 1071 {from: 2, to: 7, expectErr: os.ErrNotExist}, 1072 {from: 2, to: 8, expectErr: os.ErrNotExist}, 1073 1074 {from: 3, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))}, 1075 {from: 3, to: 0, expectErr: os.ErrNotExist}, 1076 {from: 3, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1))}, 1077 {from: 3, to: 2, expectErr: os.ErrNotExist}, 1078 {from: 3, to: 3, expectErr: ErrNoChange}, 1079 {from: 3, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(4))}, 1080 {from: 3, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5))}, 1081 {from: 3, to: 6, expectErr: os.ErrNotExist}, 1082 {from: 3, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5), M(7))}, 1083 {from: 3, to: 8, expectErr: os.ErrNotExist}, 1084 1085 {from: 4, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1), M(1, -1))}, 1086 {from: 4, to: 0, expectErr: os.ErrNotExist}, 1087 {from: 4, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1))}, 1088 {from: 4, to: 2, expectErr: os.ErrNotExist}, 1089 {from: 4, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(4, 3))}, 1090 {from: 4, to: 4, expectErr: ErrNoChange}, 1091 {from: 4, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(5))}, 1092 {from: 4, to: 6, expectErr: os.ErrNotExist}, 1093 {from: 4, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))}, 1094 {from: 4, to: 8, expectErr: os.ErrNotExist}, 1095 1096 {from: 5, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1097 {from: 5, to: 0, expectErr: os.ErrNotExist}, 1098 {from: 5, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1))}, 1099 {from: 5, to: 2, expectErr: os.ErrNotExist}, 1100 {from: 5, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3))}, 1101 {from: 5, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(5, 4))}, 1102 {from: 5, to: 5, expectErr: ErrNoChange}, 1103 {from: 5, to: 6, expectErr: os.ErrNotExist}, 1104 {from: 5, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(7))}, 1105 {from: 5, to: 8, expectErr: os.ErrNotExist}, 1106 1107 {from: 6, to: -1, expectErr: os.ErrNotExist}, 1108 {from: 6, to: 0, expectErr: os.ErrNotExist}, 1109 {from: 6, to: 1, expectErr: os.ErrNotExist}, 1110 {from: 6, to: 2, expectErr: os.ErrNotExist}, 1111 {from: 6, to: 3, expectErr: os.ErrNotExist}, 1112 {from: 6, to: 4, expectErr: os.ErrNotExist}, 1113 {from: 6, to: 5, expectErr: os.ErrNotExist}, 1114 {from: 6, to: 6, expectErr: os.ErrNotExist}, 1115 {from: 6, to: 7, expectErr: os.ErrNotExist}, 1116 {from: 6, to: 8, expectErr: os.ErrNotExist}, 1117 1118 {from: 7, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1119 {from: 7, to: 0, expectErr: os.ErrNotExist}, 1120 {from: 7, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1))}, 1121 {from: 7, to: 2, expectErr: os.ErrNotExist}, 1122 {from: 7, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3))}, 1123 {from: 7, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4))}, 1124 {from: 7, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(7, 5))}, 1125 {from: 7, to: 6, expectErr: os.ErrNotExist}, 1126 {from: 7, to: 7, expectErr: ErrNoChange}, 1127 {from: 7, to: 8, expectErr: os.ErrNotExist}, 1128 1129 {from: 8, to: -1, expectErr: os.ErrNotExist}, 1130 {from: 8, to: 0, expectErr: os.ErrNotExist}, 1131 {from: 8, to: 1, expectErr: os.ErrNotExist}, 1132 {from: 8, to: 2, expectErr: os.ErrNotExist}, 1133 {from: 8, to: 3, expectErr: os.ErrNotExist}, 1134 {from: 8, to: 4, expectErr: os.ErrNotExist}, 1135 {from: 8, to: 5, expectErr: os.ErrNotExist}, 1136 {from: 8, to: 6, expectErr: os.ErrNotExist}, 1137 {from: 8, to: 7, expectErr: os.ErrNotExist}, 1138 {from: 8, to: 8, expectErr: os.ErrNotExist}, 1139 } 1140 1141 for i, v := range tt { 1142 ret := make(chan interface{}) 1143 go m.read(v.from, v.to, ret) 1144 migrations, err := migrationsFromChannel(ret) 1145 1146 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 1147 (v.expectErr != os.ErrNotExist && v.expectErr != err) { 1148 t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i) 1149 t.Logf("%v, in %v", migrations, i) 1150 } 1151 if len(v.expectMigrations) > 0 { 1152 equalMigSeq(t, i, v.expectMigrations, migrations) 1153 } 1154 } 1155 } 1156 1157 func TestReadUp(t *testing.T) { 1158 m, _ := New("stub://", "stub://") 1159 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1160 1161 tt := []struct { 1162 from int 1163 limit int // -1 means no limit 1164 expectErr error 1165 expectMigrations migrationSequence 1166 }{ 1167 {from: -1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5), M(7))}, 1168 {from: -1, limit: 0, expectErr: ErrNoChange}, 1169 {from: -1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(1))}, 1170 {from: -1, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3))}, 1171 1172 {from: 0, limit: -1, expectErr: os.ErrNotExist}, 1173 {from: 0, limit: 0, expectErr: os.ErrNotExist}, 1174 {from: 0, limit: 1, expectErr: os.ErrNotExist}, 1175 {from: 0, limit: 2, expectErr: os.ErrNotExist}, 1176 1177 {from: 1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5), M(7))}, 1178 {from: 1, limit: 0, expectErr: ErrNoChange}, 1179 {from: 1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(3))}, 1180 {from: 1, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4))}, 1181 1182 {from: 2, limit: -1, expectErr: os.ErrNotExist}, 1183 {from: 2, limit: 0, expectErr: os.ErrNotExist}, 1184 {from: 2, limit: 1, expectErr: os.ErrNotExist}, 1185 {from: 2, limit: 2, expectErr: os.ErrNotExist}, 1186 1187 {from: 3, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5), M(7))}, 1188 {from: 3, limit: 0, expectErr: ErrNoChange}, 1189 {from: 3, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(4))}, 1190 {from: 3, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5))}, 1191 1192 {from: 4, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))}, 1193 {from: 4, limit: 0, expectErr: ErrNoChange}, 1194 {from: 4, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(5))}, 1195 {from: 4, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))}, 1196 1197 {from: 5, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(7))}, 1198 {from: 5, limit: 0, expectErr: ErrNoChange}, 1199 {from: 5, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(7))}, 1200 {from: 5, limit: 2, expectErr: ErrShortLimit{1}, expectMigrations: newMigSeq(M(7))}, 1201 1202 {from: 6, limit: -1, expectErr: os.ErrNotExist}, 1203 {from: 6, limit: 0, expectErr: os.ErrNotExist}, 1204 {from: 6, limit: 1, expectErr: os.ErrNotExist}, 1205 {from: 6, limit: 2, expectErr: os.ErrNotExist}, 1206 1207 {from: 7, limit: -1, expectErr: ErrNoChange}, 1208 {from: 7, limit: 0, expectErr: ErrNoChange}, 1209 {from: 7, limit: 1, expectErr: os.ErrNotExist}, 1210 {from: 7, limit: 2, expectErr: os.ErrNotExist}, 1211 1212 {from: 8, limit: -1, expectErr: os.ErrNotExist}, 1213 {from: 8, limit: 0, expectErr: os.ErrNotExist}, 1214 {from: 8, limit: 1, expectErr: os.ErrNotExist}, 1215 {from: 8, limit: 2, expectErr: os.ErrNotExist}, 1216 } 1217 1218 for i, v := range tt { 1219 ret := make(chan interface{}) 1220 go m.readUp(v.from, v.limit, ret) 1221 migrations, err := migrationsFromChannel(ret) 1222 1223 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 1224 (v.expectErr != os.ErrNotExist && v.expectErr != err) { 1225 t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i) 1226 t.Logf("%v, in %v", migrations, i) 1227 } 1228 if len(v.expectMigrations) > 0 { 1229 equalMigSeq(t, i, v.expectMigrations, migrations) 1230 } 1231 } 1232 } 1233 1234 func TestReadDown(t *testing.T) { 1235 m, _ := New("stub://", "stub://") 1236 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1237 1238 tt := []struct { 1239 from int 1240 limit int // -1 means no limit 1241 expectErr error 1242 expectMigrations migrationSequence 1243 }{ 1244 {from: -1, limit: -1, expectErr: ErrNoChange}, 1245 {from: -1, limit: 0, expectErr: ErrNoChange}, 1246 {from: -1, limit: 1, expectErr: os.ErrNotExist}, 1247 {from: -1, limit: 2, expectErr: os.ErrNotExist}, 1248 1249 {from: 0, limit: -1, expectErr: os.ErrNotExist}, 1250 {from: 0, limit: 0, expectErr: os.ErrNotExist}, 1251 {from: 0, limit: 1, expectErr: os.ErrNotExist}, 1252 {from: 0, limit: 2, expectErr: os.ErrNotExist}, 1253 1254 {from: 1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))}, 1255 {from: 1, limit: 0, expectErr: ErrNoChange}, 1256 {from: 1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))}, 1257 {from: 1, limit: 2, expectErr: ErrShortLimit{1}, expectMigrations: newMigSeq(M(1, -1))}, 1258 1259 {from: 2, limit: -1, expectErr: os.ErrNotExist}, 1260 {from: 2, limit: 0, expectErr: os.ErrNotExist}, 1261 {from: 2, limit: 1, expectErr: os.ErrNotExist}, 1262 {from: 2, limit: 2, expectErr: os.ErrNotExist}, 1263 1264 {from: 3, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))}, 1265 {from: 3, limit: 0, expectErr: ErrNoChange}, 1266 {from: 3, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1))}, 1267 {from: 3, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))}, 1268 1269 {from: 4, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1), M(1, -1))}, 1270 {from: 4, limit: 0, expectErr: ErrNoChange}, 1271 {from: 4, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3))}, 1272 {from: 4, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1))}, 1273 1274 {from: 5, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1275 {from: 5, limit: 0, expectErr: ErrNoChange}, 1276 {from: 5, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4))}, 1277 {from: 5, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3))}, 1278 1279 {from: 6, limit: -1, expectErr: os.ErrNotExist}, 1280 {from: 6, limit: 0, expectErr: os.ErrNotExist}, 1281 {from: 6, limit: 1, expectErr: os.ErrNotExist}, 1282 {from: 6, limit: 2, expectErr: os.ErrNotExist}, 1283 1284 {from: 7, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1))}, 1285 {from: 7, limit: 0, expectErr: ErrNoChange}, 1286 {from: 7, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5))}, 1287 {from: 7, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4))}, 1288 1289 {from: 8, limit: -1, expectErr: os.ErrNotExist}, 1290 {from: 8, limit: 0, expectErr: os.ErrNotExist}, 1291 {from: 8, limit: 1, expectErr: os.ErrNotExist}, 1292 {from: 8, limit: 2, expectErr: os.ErrNotExist}, 1293 } 1294 1295 for i, v := range tt { 1296 ret := make(chan interface{}) 1297 go m.readDown(v.from, v.limit, ret) 1298 migrations, err := migrationsFromChannel(ret) 1299 1300 if (v.expectErr == os.ErrNotExist && !errors.Is(err, os.ErrNotExist)) || 1301 (v.expectErr != os.ErrNotExist && v.expectErr != err) { 1302 t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i) 1303 t.Logf("%v, in %v", migrations, i) 1304 } 1305 if len(v.expectMigrations) > 0 { 1306 equalMigSeq(t, i, v.expectMigrations, migrations) 1307 } 1308 } 1309 } 1310 1311 func TestLock(t *testing.T) { 1312 m, _ := New("stub://", "stub://") 1313 if err := m.lock(); err != nil { 1314 t.Fatal(err) 1315 } 1316 1317 if err := m.lock(); err == nil { 1318 t.Fatal("should be locked already") 1319 } 1320 } 1321 1322 func migrationsFromChannel(ret chan interface{}) ([]*Migration, error) { 1323 slice := make([]*Migration, 0) 1324 for r := range ret { 1325 switch t := r.(type) { 1326 case error: 1327 return slice, t 1328 1329 case *Migration: 1330 slice = append(slice, t) 1331 } 1332 } 1333 return slice, nil 1334 } 1335 1336 type migrationSequence []*Migration 1337 1338 func newMigSeq(migr ...*Migration) migrationSequence { 1339 return migr 1340 } 1341 1342 func (m *migrationSequence) add(migr ...*Migration) migrationSequence { // nolint:unused 1343 *m = append(*m, migr...) 1344 return *m 1345 } 1346 1347 func (m *migrationSequence) bodySequence() []string { 1348 r := make([]string, 0) 1349 for _, v := range *m { 1350 if v.Body != nil { 1351 body, err := io.ReadAll(v.Body) 1352 if err != nil { 1353 panic(err) // that should never happen 1354 } 1355 1356 // reset body reader 1357 // TODO: is there a better/nicer way? 1358 v.Body = io.NopCloser(bytes.NewReader(body)) 1359 1360 r = append(r, string(body[:])) 1361 } else { 1362 r = append(r, "<empty>") 1363 } 1364 } 1365 return r 1366 } 1367 1368 // M is a convenience func to create a new *Migration 1369 func M(version uint, targetVersion ...int) *Migration { 1370 if len(targetVersion) > 1 { 1371 panic("only one targetVersion allowed") 1372 } 1373 ts := int(version) 1374 if len(targetVersion) == 1 { 1375 ts = targetVersion[0] 1376 } 1377 1378 m, _ := New("stub://", "stub://") 1379 m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations 1380 migr, err := m.newMigration(version, ts) 1381 if err != nil { 1382 panic(err) 1383 } 1384 return migr 1385 } 1386 1387 // mr is a convenience func to create a new *Migration from the raw database query 1388 func mr(value string) *Migration { 1389 return &Migration{ 1390 Body: io.NopCloser(strings.NewReader(value)), 1391 } 1392 } 1393 1394 func equalMigSeq(t *testing.T, i int, expected, got migrationSequence) { 1395 if len(expected) != len(got) { 1396 t.Errorf("expected migrations %v, got %v, in %v", expected, got, i) 1397 1398 } else { 1399 for ii := 0; ii < len(expected); ii++ { 1400 if expected[ii].Version != got[ii].Version { 1401 t.Errorf("expected version %v, got %v, in %v", expected[ii].Version, got[ii].Version, i) 1402 } 1403 1404 if expected[ii].TargetVersion != got[ii].TargetVersion { 1405 t.Errorf("expected targetVersion %v, got %v, in %v", expected[ii].TargetVersion, got[ii].TargetVersion, i) 1406 } 1407 } 1408 } 1409 } 1410 1411 func equalDbSeq(t *testing.T, i int, expected migrationSequence, got *dStub.Stub) { 1412 bs := expected.bodySequence() 1413 if !got.EqualSequence(bs) { 1414 t.Fatalf("\nexpected sequence %v,\ngot %v, in %v", bs, got.MigrationSequence, i) 1415 } 1416 }