github.com/wreckingballstudiolabs/migrate@v3.5.4+incompatible/migrate_test.go (about)

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