github.com/brandonmartin/migrate/v4@v4.14.2/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  }