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  }