github.com/bishtawi/migrate/v4@v4.8.11/migrate_test.go (about)

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