github.com/basekit/migrate@v3.2.1-0.20180724125854-2fc69c806a45+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/basekit/migrate/database/stub"
    12  	"github.com/basekit/migrate/source"
    13  	sStub "github.com/basekit/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})
    25  	sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Down})
    26  	sourceStubMigrations.Append(&source.Migration{Version: 3, Direction: source.Up})
    27  	sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Up})
    28  	sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Down})
    29  	sourceStubMigrations.Append(&source.Migration{Version: 5, Direction: source.Down})
    30  	sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Up})
    31  	sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Down})
    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(false); 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/basekit/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(false); 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/basekit/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(false); 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  	seq := newMigSeq()
   228  
   229  	tt := []struct {
   230  		version       uint
   231  		expectErr     error
   232  		expectVersion uint
   233  		expectSeq     migrationSequence
   234  	}{
   235  		// migrate all the way Up in single steps
   236  		{version: 0, expectErr: os.ErrNotExist},
   237  		{version: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(1))},
   238  		{version: 2, expectErr: os.ErrNotExist},
   239  		{version: 3, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(3))},
   240  		{version: 4, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(4))},
   241  		{version: 5, expectErr: nil, expectVersion: 5, expectSeq: seq.add()}, // 5 has no up migration
   242  		{version: 6, expectErr: os.ErrNotExist},
   243  		{version: 7, expectErr: nil, expectVersion: 7, expectSeq: seq.add(M(7))},
   244  		{version: 8, expectErr: os.ErrNotExist},
   245  
   246  		// migrate all the way Down in single steps
   247  		{version: 6, expectErr: os.ErrNotExist},
   248  		{version: 5, expectErr: nil, expectVersion: 5, expectSeq: seq.add(M(7, 5))},
   249  		{version: 4, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(5, 4))},
   250  		{version: 3, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(4, 3))},
   251  		{version: 2, expectErr: os.ErrNotExist},
   252  		{version: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add()}, // 3 has no down migration
   253  		{version: 0, expectErr: os.ErrNotExist},
   254  
   255  		// migrate all the way Up in one step
   256  		{version: 7, expectErr: nil, expectVersion: 7, expectSeq: seq.add(M(3), M(4), M(7))},
   257  
   258  		// migrate all the way Down in one step
   259  		{version: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1))},
   260  
   261  		// can't migrate the same version twice
   262  		{version: 1, expectErr: ErrNoChange},
   263  	}
   264  
   265  	for i, v := range tt {
   266  		err := m.Migrate(v.version)
   267  		if (v.expectErr == os.ErrNotExist && !os.IsNotExist(err)) ||
   268  			(v.expectErr != os.ErrNotExist && err != v.expectErr) {
   269  			t.Errorf("expected err %v, got %v, in %v", v.expectErr, err, i)
   270  
   271  		} else if err == nil {
   272  			version, _, err := m.Version()
   273  			if err != nil {
   274  				t.Error(err)
   275  			}
   276  			if version != v.expectVersion {
   277  				t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i)
   278  			}
   279  			equalDbSeq(t, i, v.expectSeq, dbDrv)
   280  		}
   281  	}
   282  }
   283  
   284  func TestMigrateDirty(t *testing.T) {
   285  	m, _ := New("stub://", "stub://")
   286  	dbDrv := m.databaseDrv.(*dStub.Stub)
   287  	if err := dbDrv.SetVersion(0, true); err != nil {
   288  		t.Fatal(err)
   289  	}
   290  
   291  	err := m.Migrate(1)
   292  	if _, ok := err.(ErrDirty); !ok {
   293  		t.Fatalf("expected ErrDirty, got %v", err)
   294  	}
   295  }
   296  
   297  func TestSteps(t *testing.T) {
   298  	m, _ := New("stub://", "stub://")
   299  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   300  	dbDrv := m.databaseDrv.(*dStub.Stub)
   301  	seq := newMigSeq()
   302  
   303  	tt := []struct {
   304  		n             int
   305  		expectErr     error
   306  		expectVersion int
   307  		expectSeq     migrationSequence
   308  	}{
   309  		// step must be != 0
   310  		{n: 0, expectErr: ErrNoChange},
   311  
   312  		// can't go Down if ErrNilVersion
   313  		{n: -1, expectErr: os.ErrNotExist},
   314  
   315  		// migrate all the way Up
   316  		{n: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(1))},
   317  		{n: 1, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(3))},
   318  		{n: 1, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(4))},
   319  		{n: 1, expectErr: nil, expectVersion: 5, expectSeq: seq.add()},
   320  		{n: 1, expectErr: nil, expectVersion: 7, expectSeq: seq.add(M(7))},
   321  		{n: 1, expectErr: os.ErrNotExist},
   322  
   323  		// migrate all the way Down
   324  		{n: -1, expectErr: nil, expectVersion: 5, expectSeq: seq.add(M(7, 5))},
   325  		{n: -1, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(5, 4))},
   326  		{n: -1, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(4, 3))},
   327  		{n: -1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(3, 1))},
   328  		{n: -1, expectErr: nil, expectVersion: -1, expectSeq: seq.add(M(1, -1))},
   329  
   330  		// migrate Up in bigger step
   331  		{n: 4, expectErr: nil, expectVersion: 5, expectSeq: seq.add(M(1), M(3), M(4), M(5))},
   332  
   333  		// apply one migration, then reaches out of boundary
   334  		{n: 2, expectErr: ErrShortLimit{1}, expectVersion: 7, expectSeq: seq.add(M(7))},
   335  
   336  		// migrate Down in bigger step
   337  		{n: -4, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1))},
   338  
   339  		// apply one migration, then reaches out of boundary
   340  		{n: -2, expectErr: ErrShortLimit{1}, expectVersion: -1, expectSeq: seq.add(M(1, -1))},
   341  	}
   342  
   343  	for i, v := range tt {
   344  		err := m.Steps(v.n)
   345  		if (v.expectErr == os.ErrNotExist && !os.IsNotExist(err)) ||
   346  			(v.expectErr != os.ErrNotExist && err != v.expectErr) {
   347  			t.Errorf("expected err %v, got %v, in %v", v.expectErr, err, i)
   348  
   349  		} else if err == nil {
   350  			version, _, err := m.Version()
   351  			if err != ErrNilVersion && err != nil {
   352  				t.Error(err)
   353  			}
   354  			if v.expectVersion == -1 && err != ErrNilVersion {
   355  				t.Errorf("expected ErrNilVersion, got %v, in %v", version, i)
   356  
   357  			} else if v.expectVersion >= 0 && version != uint(v.expectVersion) {
   358  				t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i)
   359  			}
   360  			equalDbSeq(t, i, v.expectSeq, dbDrv)
   361  		}
   362  	}
   363  }
   364  
   365  func TestStepsDirty(t *testing.T) {
   366  	m, _ := New("stub://", "stub://")
   367  	dbDrv := m.databaseDrv.(*dStub.Stub)
   368  	if err := dbDrv.SetVersion(0, true); err != nil {
   369  		t.Fatal(err)
   370  	}
   371  
   372  	err := m.Steps(1)
   373  	if _, ok := err.(ErrDirty); !ok {
   374  		t.Fatalf("expected ErrDirty, got %v", err)
   375  	}
   376  }
   377  
   378  func TestUpAndDown(t *testing.T) {
   379  	m, _ := New("stub://", "stub://")
   380  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   381  	dbDrv := m.databaseDrv.(*dStub.Stub)
   382  	seq := newMigSeq()
   383  
   384  	// go Up first
   385  	if err := m.Up(false); err != nil {
   386  		t.Fatal(err)
   387  	}
   388  	equalDbSeq(t, 0, seq.add(M(1), M(3), M(4), M(5), M(7)), dbDrv)
   389  
   390  	// go Down
   391  	if err := m.Down(); err != nil {
   392  		t.Fatal(err)
   393  	}
   394  	equalDbSeq(t, 1, seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1)), dbDrv)
   395  
   396  	// go 1 Up and then all the way Up
   397  	if err := m.Steps(1); err != nil {
   398  		t.Fatal(err)
   399  	}
   400  	if err := m.Up(false); err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	equalDbSeq(t, 2, seq.add(M(1), M(3), M(4), M(5), M(7)), dbDrv)
   404  
   405  	// go 1 Down and then all the way Down
   406  	if err := m.Steps(-1); err != nil {
   407  		t.Fatal(err)
   408  	}
   409  	if err := m.Down(); err != nil {
   410  		t.Fatal(err)
   411  	}
   412  	equalDbSeq(t, 0, seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1)), dbDrv)
   413  }
   414  
   415  func TestUpDirty(t *testing.T) {
   416  	m, _ := New("stub://", "stub://")
   417  	dbDrv := m.databaseDrv.(*dStub.Stub)
   418  	if err := dbDrv.SetVersion(0, true); err != nil {
   419  		t.Fatal(err)
   420  	}
   421  
   422  	err := m.Up(false)
   423  	if _, ok := err.(ErrDirty); !ok {
   424  		t.Fatalf("expected ErrDirty, got %v", err)
   425  	}
   426  }
   427  
   428  func TestDownDirty(t *testing.T) {
   429  	m, _ := New("stub://", "stub://")
   430  	dbDrv := m.databaseDrv.(*dStub.Stub)
   431  	if err := dbDrv.SetVersion(0, true); err != nil {
   432  		t.Fatal(err)
   433  	}
   434  
   435  	err := m.Down()
   436  	if _, ok := err.(ErrDirty); !ok {
   437  		t.Fatalf("expected ErrDirty, got %v", err)
   438  	}
   439  }
   440  
   441  func TestDrop(t *testing.T) {
   442  	m, _ := New("stub://", "stub://")
   443  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   444  	dbDrv := m.databaseDrv.(*dStub.Stub)
   445  
   446  	if err := m.Drop(); err != nil {
   447  		t.Fatal(err)
   448  	}
   449  
   450  	if dbDrv.MigrationSequence[len(dbDrv.MigrationSequence)-1] != dStub.DROP {
   451  		t.Fatalf("expected database to DROP, got sequence %v", dbDrv.MigrationSequence)
   452  	}
   453  }
   454  
   455  func TestVersion(t *testing.T) {
   456  	m, _ := New("stub://", "stub://")
   457  	dbDrv := m.databaseDrv.(*dStub.Stub)
   458  
   459  	_, _, err := m.Version()
   460  	if err != ErrNilVersion {
   461  		t.Fatalf("expected ErrNilVersion, got %v", err)
   462  	}
   463  
   464  	if err := dbDrv.Run(bytes.NewBufferString("1_up")); err != nil {
   465  		t.Fatal(err)
   466  	}
   467  
   468  	if err := dbDrv.SetVersion(1, false); err != nil {
   469  		t.Fatal(err)
   470  	}
   471  
   472  	v, _, err := m.Version()
   473  	if err != nil {
   474  		t.Fatal(err)
   475  	}
   476  
   477  	if v != 1 {
   478  		t.Fatalf("expected version 1, got %v", v)
   479  	}
   480  }
   481  
   482  func TestRun(t *testing.T) {
   483  	m, _ := New("stub://", "stub://")
   484  
   485  	mx, err := NewMigration(nil, "", 1, 2)
   486  	if err != nil {
   487  		t.Fatal(err)
   488  	}
   489  
   490  	if err := m.Run(mx); err != nil {
   491  		t.Fatal(err)
   492  	}
   493  
   494  	v, _, err := m.Version()
   495  	if err != nil {
   496  		t.Fatal(err)
   497  	}
   498  
   499  	if v != 2 {
   500  		t.Errorf("expected version 2, got %v", v)
   501  	}
   502  }
   503  
   504  func TestRunDirty(t *testing.T) {
   505  	m, _ := New("stub://", "stub://")
   506  	dbDrv := m.databaseDrv.(*dStub.Stub)
   507  	if err := dbDrv.SetVersion(0, true); err != nil {
   508  		t.Fatal(err)
   509  	}
   510  
   511  	migr, err := NewMigration(nil, "", 1, 2)
   512  	if err != nil {
   513  		t.Fatal(err)
   514  	}
   515  
   516  	err = m.Run(migr)
   517  	if _, ok := err.(ErrDirty); !ok {
   518  		t.Fatalf("expected ErrDirty, got %v", err)
   519  	}
   520  }
   521  
   522  func TestForce(t *testing.T) {
   523  	m, _ := New("stub://", "stub://")
   524  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   525  
   526  	if err := m.Force(7); err != nil {
   527  		t.Fatal(err)
   528  	}
   529  
   530  	v, dirty, err := m.Version()
   531  	if err != nil {
   532  		t.Fatal(err)
   533  	}
   534  	if dirty {
   535  		t.Errorf("expected dirty to be false")
   536  	}
   537  	if v != 7 {
   538  		t.Errorf("expected version to be 7")
   539  	}
   540  }
   541  
   542  func TestForceDirty(t *testing.T) {
   543  	m, _ := New("stub://", "stub://")
   544  	dbDrv := m.databaseDrv.(*dStub.Stub)
   545  	if err := dbDrv.SetVersion(0, true); err != nil {
   546  		t.Fatal(err)
   547  	}
   548  
   549  	if err := m.Force(1); err != nil {
   550  		t.Fatal(err)
   551  	}
   552  }
   553  
   554  func TestRead(t *testing.T) {
   555  	m, _ := New("stub://", "stub://")
   556  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   557  
   558  	tt := []struct {
   559  		from             int
   560  		to               int
   561  		expectErr        error
   562  		expectMigrations migrationSequence
   563  	}{
   564  		{from: -1, to: -1, expectErr: ErrNoChange},
   565  		{from: -1, to: 0, expectErr: os.ErrNotExist},
   566  		{from: -1, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(1))},
   567  		{from: -1, to: 2, expectErr: os.ErrNotExist},
   568  		{from: -1, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3))},
   569  		{from: -1, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4))},
   570  		{from: -1, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5))},
   571  		{from: -1, to: 6, expectErr: os.ErrNotExist},
   572  		{from: -1, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5), M(7))},
   573  		{from: -1, to: 8, expectErr: os.ErrNotExist},
   574  
   575  		{from: 0, to: -1, expectErr: os.ErrNotExist},
   576  		{from: 0, to: 0, expectErr: os.ErrNotExist},
   577  		{from: 0, to: 1, expectErr: os.ErrNotExist},
   578  		{from: 0, to: 2, expectErr: os.ErrNotExist},
   579  		{from: 0, to: 3, expectErr: os.ErrNotExist},
   580  		{from: 0, to: 4, expectErr: os.ErrNotExist},
   581  		{from: 0, to: 5, expectErr: os.ErrNotExist},
   582  		{from: 0, to: 6, expectErr: os.ErrNotExist},
   583  		{from: 0, to: 7, expectErr: os.ErrNotExist},
   584  		{from: 0, to: 8, expectErr: os.ErrNotExist},
   585  
   586  		{from: 1, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))},
   587  		{from: 1, to: 0, expectErr: os.ErrNotExist},
   588  		{from: 1, to: 1, expectErr: ErrNoChange},
   589  		{from: 1, to: 2, expectErr: os.ErrNotExist},
   590  		{from: 1, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(3))},
   591  		{from: 1, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4))},
   592  		{from: 1, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5))},
   593  		{from: 1, to: 6, expectErr: os.ErrNotExist},
   594  		{from: 1, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5), M(7))},
   595  		{from: 1, to: 8, expectErr: os.ErrNotExist},
   596  
   597  		{from: 2, to: -1, expectErr: os.ErrNotExist},
   598  		{from: 2, to: 0, expectErr: os.ErrNotExist},
   599  		{from: 2, to: 1, expectErr: os.ErrNotExist},
   600  		{from: 2, to: 2, expectErr: os.ErrNotExist},
   601  		{from: 2, to: 3, expectErr: os.ErrNotExist},
   602  		{from: 2, to: 4, expectErr: os.ErrNotExist},
   603  		{from: 2, to: 5, expectErr: os.ErrNotExist},
   604  		{from: 2, to: 6, expectErr: os.ErrNotExist},
   605  		{from: 2, to: 7, expectErr: os.ErrNotExist},
   606  		{from: 2, to: 8, expectErr: os.ErrNotExist},
   607  
   608  		{from: 3, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))},
   609  		{from: 3, to: 0, expectErr: os.ErrNotExist},
   610  		{from: 3, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1))},
   611  		{from: 3, to: 2, expectErr: os.ErrNotExist},
   612  		{from: 3, to: 3, expectErr: ErrNoChange},
   613  		{from: 3, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(4))},
   614  		{from: 3, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5))},
   615  		{from: 3, to: 6, expectErr: os.ErrNotExist},
   616  		{from: 3, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5), M(7))},
   617  		{from: 3, to: 8, expectErr: os.ErrNotExist},
   618  
   619  		{from: 4, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1), M(1, -1))},
   620  		{from: 4, to: 0, expectErr: os.ErrNotExist},
   621  		{from: 4, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1))},
   622  		{from: 4, to: 2, expectErr: os.ErrNotExist},
   623  		{from: 4, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(4, 3))},
   624  		{from: 4, to: 4, expectErr: ErrNoChange},
   625  		{from: 4, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(5))},
   626  		{from: 4, to: 6, expectErr: os.ErrNotExist},
   627  		{from: 4, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))},
   628  		{from: 4, to: 8, expectErr: os.ErrNotExist},
   629  
   630  		{from: 5, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1), M(1, -1))},
   631  		{from: 5, to: 0, expectErr: os.ErrNotExist},
   632  		{from: 5, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1))},
   633  		{from: 5, to: 2, expectErr: os.ErrNotExist},
   634  		{from: 5, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3))},
   635  		{from: 5, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(5, 4))},
   636  		{from: 5, to: 5, expectErr: ErrNoChange},
   637  		{from: 5, to: 6, expectErr: os.ErrNotExist},
   638  		{from: 5, to: 7, expectErr: nil, expectMigrations: newMigSeq(M(7))},
   639  		{from: 5, to: 8, expectErr: os.ErrNotExist},
   640  
   641  		{from: 6, to: -1, expectErr: os.ErrNotExist},
   642  		{from: 6, to: 0, expectErr: os.ErrNotExist},
   643  		{from: 6, to: 1, expectErr: os.ErrNotExist},
   644  		{from: 6, to: 2, expectErr: os.ErrNotExist},
   645  		{from: 6, to: 3, expectErr: os.ErrNotExist},
   646  		{from: 6, to: 4, expectErr: os.ErrNotExist},
   647  		{from: 6, to: 5, expectErr: os.ErrNotExist},
   648  		{from: 6, to: 6, expectErr: os.ErrNotExist},
   649  		{from: 6, to: 7, expectErr: os.ErrNotExist},
   650  		{from: 6, to: 8, expectErr: os.ErrNotExist},
   651  
   652  		{from: 7, to: -1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1))},
   653  		{from: 7, to: 0, expectErr: os.ErrNotExist},
   654  		{from: 7, to: 1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1))},
   655  		{from: 7, to: 2, expectErr: os.ErrNotExist},
   656  		{from: 7, to: 3, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3))},
   657  		{from: 7, to: 4, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4))},
   658  		{from: 7, to: 5, expectErr: nil, expectMigrations: newMigSeq(M(7, 5))},
   659  		{from: 7, to: 6, expectErr: os.ErrNotExist},
   660  		{from: 7, to: 7, expectErr: ErrNoChange},
   661  		{from: 7, to: 8, expectErr: os.ErrNotExist},
   662  
   663  		{from: 8, to: -1, expectErr: os.ErrNotExist},
   664  		{from: 8, to: 0, expectErr: os.ErrNotExist},
   665  		{from: 8, to: 1, expectErr: os.ErrNotExist},
   666  		{from: 8, to: 2, expectErr: os.ErrNotExist},
   667  		{from: 8, to: 3, expectErr: os.ErrNotExist},
   668  		{from: 8, to: 4, expectErr: os.ErrNotExist},
   669  		{from: 8, to: 5, expectErr: os.ErrNotExist},
   670  		{from: 8, to: 6, expectErr: os.ErrNotExist},
   671  		{from: 8, to: 7, expectErr: os.ErrNotExist},
   672  		{from: 8, to: 8, expectErr: os.ErrNotExist},
   673  	}
   674  
   675  	for i, v := range tt {
   676  		ret := make(chan interface{})
   677  		go m.read(v.from, v.to, ret)
   678  		migrations, err := migrationsFromChannel(ret)
   679  
   680  		if (v.expectErr == os.ErrNotExist && !os.IsNotExist(err)) ||
   681  			(v.expectErr != os.ErrNotExist && v.expectErr != err) {
   682  			t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i)
   683  			t.Logf("%v, in %v", migrations, i)
   684  		}
   685  		if len(v.expectMigrations) > 0 {
   686  			equalMigSeq(t, i, v.expectMigrations, migrations)
   687  		}
   688  	}
   689  }
   690  
   691  func TestReadUp(t *testing.T) {
   692  	m, _ := New("stub://", "stub://")
   693  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   694  
   695  	tt := []struct {
   696  		from             int
   697  		limit            int // -1 means no limit
   698  		expectErr        error
   699  		expectMigrations migrationSequence
   700  	}{
   701  		{from: -1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3), M(4), M(5), M(7))},
   702  		{from: -1, limit: 0, expectErr: ErrNoChange},
   703  		{from: -1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(1))},
   704  		{from: -1, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(1), M(3))},
   705  
   706  		{from: 0, limit: -1, expectErr: os.ErrNotExist},
   707  		{from: 0, limit: 0, expectErr: os.ErrNotExist},
   708  		{from: 0, limit: 1, expectErr: os.ErrNotExist},
   709  		{from: 0, limit: 2, expectErr: os.ErrNotExist},
   710  
   711  		{from: 1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4), M(5), M(7))},
   712  		{from: 1, limit: 0, expectErr: ErrNoChange},
   713  		{from: 1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(3))},
   714  		{from: 1, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(3), M(4))},
   715  
   716  		{from: 2, limit: -1, expectErr: os.ErrNotExist},
   717  		{from: 2, limit: 0, expectErr: os.ErrNotExist},
   718  		{from: 2, limit: 1, expectErr: os.ErrNotExist},
   719  		{from: 2, limit: 2, expectErr: os.ErrNotExist},
   720  
   721  		{from: 3, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5), M(7))},
   722  		{from: 3, limit: 0, expectErr: ErrNoChange},
   723  		{from: 3, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(4))},
   724  		{from: 3, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(4), M(5))},
   725  
   726  		{from: 4, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))},
   727  		{from: 4, limit: 0, expectErr: ErrNoChange},
   728  		{from: 4, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(5))},
   729  		{from: 4, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(5), M(7))},
   730  
   731  		{from: 5, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(7))},
   732  		{from: 5, limit: 0, expectErr: ErrNoChange},
   733  		{from: 5, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(7))},
   734  		{from: 5, limit: 2, expectErr: ErrShortLimit{1}, expectMigrations: newMigSeq(M(7))},
   735  
   736  		{from: 6, limit: -1, expectErr: os.ErrNotExist},
   737  		{from: 6, limit: 0, expectErr: os.ErrNotExist},
   738  		{from: 6, limit: 1, expectErr: os.ErrNotExist},
   739  		{from: 6, limit: 2, expectErr: os.ErrNotExist},
   740  
   741  		{from: 7, limit: -1, expectErr: ErrNoChange},
   742  		{from: 7, limit: 0, expectErr: ErrNoChange},
   743  		{from: 7, limit: 1, expectErr: os.ErrNotExist},
   744  		{from: 7, limit: 2, expectErr: os.ErrNotExist},
   745  
   746  		{from: 8, limit: -1, expectErr: os.ErrNotExist},
   747  		{from: 8, limit: 0, expectErr: os.ErrNotExist},
   748  		{from: 8, limit: 1, expectErr: os.ErrNotExist},
   749  		{from: 8, limit: 2, expectErr: os.ErrNotExist},
   750  	}
   751  
   752  	for i, v := range tt {
   753  		ret := make(chan interface{})
   754  		go m.readUp(v.from, v.limit, ret, false)
   755  		migrations, err := migrationsFromChannel(ret)
   756  
   757  		if (v.expectErr == os.ErrNotExist && !os.IsNotExist(err)) ||
   758  			(v.expectErr != os.ErrNotExist && v.expectErr != err) {
   759  			t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i)
   760  			t.Logf("%v, in %v", migrations, i)
   761  		}
   762  		if len(v.expectMigrations) > 0 {
   763  			equalMigSeq(t, i, v.expectMigrations, migrations)
   764  		}
   765  	}
   766  }
   767  
   768  func TestReadDown(t *testing.T) {
   769  	m, _ := New("stub://", "stub://")
   770  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   771  
   772  	tt := []struct {
   773  		from             int
   774  		limit            int // -1 means no limit
   775  		expectErr        error
   776  		expectMigrations migrationSequence
   777  	}{
   778  		{from: -1, limit: -1, expectErr: ErrNoChange},
   779  		{from: -1, limit: 0, expectErr: ErrNoChange},
   780  		{from: -1, limit: 1, expectErr: os.ErrNotExist},
   781  		{from: -1, limit: 2, expectErr: os.ErrNotExist},
   782  
   783  		{from: 0, limit: -1, expectErr: os.ErrNotExist},
   784  		{from: 0, limit: 0, expectErr: os.ErrNotExist},
   785  		{from: 0, limit: 1, expectErr: os.ErrNotExist},
   786  		{from: 0, limit: 2, expectErr: os.ErrNotExist},
   787  
   788  		{from: 1, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))},
   789  		{from: 1, limit: 0, expectErr: ErrNoChange},
   790  		{from: 1, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(1, -1))},
   791  		{from: 1, limit: 2, expectErr: ErrShortLimit{1}, expectMigrations: newMigSeq(M(1, -1))},
   792  
   793  		{from: 2, limit: -1, expectErr: os.ErrNotExist},
   794  		{from: 2, limit: 0, expectErr: os.ErrNotExist},
   795  		{from: 2, limit: 1, expectErr: os.ErrNotExist},
   796  		{from: 2, limit: 2, expectErr: os.ErrNotExist},
   797  
   798  		{from: 3, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))},
   799  		{from: 3, limit: 0, expectErr: ErrNoChange},
   800  		{from: 3, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(3, 1))},
   801  		{from: 3, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(3, 1), M(1, -1))},
   802  
   803  		{from: 4, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1), M(1, -1))},
   804  		{from: 4, limit: 0, expectErr: ErrNoChange},
   805  		{from: 4, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(4, 3))},
   806  		{from: 4, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(4, 3), M(3, 1))},
   807  
   808  		{from: 5, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3), M(3, 1), M(1, -1))},
   809  		{from: 5, limit: 0, expectErr: ErrNoChange},
   810  		{from: 5, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(5, 4))},
   811  		{from: 5, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(5, 4), M(4, 3))},
   812  
   813  		{from: 6, limit: -1, expectErr: os.ErrNotExist},
   814  		{from: 6, limit: 0, expectErr: os.ErrNotExist},
   815  		{from: 6, limit: 1, expectErr: os.ErrNotExist},
   816  		{from: 6, limit: 2, expectErr: os.ErrNotExist},
   817  
   818  		{from: 7, limit: -1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1))},
   819  		{from: 7, limit: 0, expectErr: ErrNoChange},
   820  		{from: 7, limit: 1, expectErr: nil, expectMigrations: newMigSeq(M(7, 5))},
   821  		{from: 7, limit: 2, expectErr: nil, expectMigrations: newMigSeq(M(7, 5), M(5, 4))},
   822  
   823  		{from: 8, limit: -1, expectErr: os.ErrNotExist},
   824  		{from: 8, limit: 0, expectErr: os.ErrNotExist},
   825  		{from: 8, limit: 1, expectErr: os.ErrNotExist},
   826  		{from: 8, limit: 2, expectErr: os.ErrNotExist},
   827  	}
   828  
   829  	for i, v := range tt {
   830  		ret := make(chan interface{})
   831  		go m.readDown(v.from, v.limit, ret)
   832  		migrations, err := migrationsFromChannel(ret)
   833  
   834  		if (v.expectErr == os.ErrNotExist && !os.IsNotExist(err)) ||
   835  			(v.expectErr != os.ErrNotExist && v.expectErr != err) {
   836  			t.Errorf("expected %v, got %v, in %v", v.expectErr, err, i)
   837  			t.Logf("%v, in %v", migrations, i)
   838  		}
   839  		if len(v.expectMigrations) > 0 {
   840  			equalMigSeq(t, i, v.expectMigrations, migrations)
   841  		}
   842  	}
   843  }
   844  
   845  func TestLock(t *testing.T) {
   846  	m, _ := New("stub://", "stub://")
   847  	if err := m.lock(); err != nil {
   848  		t.Fatal(err)
   849  	}
   850  
   851  	if err := m.lock(); err == nil {
   852  		t.Fatal("should be locked already")
   853  	}
   854  }
   855  
   856  func migrationsFromChannel(ret chan interface{}) ([]*Migration, error) {
   857  	slice := make([]*Migration, 0)
   858  	for r := range ret {
   859  		switch r.(type) {
   860  		case error:
   861  			return slice, r.(error)
   862  
   863  		case *Migration:
   864  			slice = append(slice, r.(*Migration))
   865  		}
   866  	}
   867  	return slice, nil
   868  }
   869  
   870  type migrationSequence []*Migration
   871  
   872  func newMigSeq(migr ...*Migration) migrationSequence {
   873  	return migr
   874  }
   875  
   876  func (m *migrationSequence) add(migr ...*Migration) migrationSequence {
   877  	*m = append(*m, migr...)
   878  	return *m
   879  }
   880  
   881  func (m *migrationSequence) bodySequence() []string {
   882  	r := make([]string, 0)
   883  	for _, v := range *m {
   884  		if v.Body != nil {
   885  			body, err := ioutil.ReadAll(v.Body)
   886  			if err != nil {
   887  				panic(err) // that should never happen
   888  			}
   889  
   890  			// reset body reader
   891  			// TODO: is there a better/nicer way?
   892  			v.Body = ioutil.NopCloser(bytes.NewReader(body))
   893  
   894  			r = append(r, string(body[:]))
   895  		}
   896  	}
   897  	return r
   898  }
   899  
   900  // M is a convenience func to create a new *Migration
   901  func M(version uint, targetVersion ...int) *Migration {
   902  	if len(targetVersion) > 1 {
   903  		panic("only one targetVersion allowed")
   904  	}
   905  	ts := int(version)
   906  	if len(targetVersion) == 1 {
   907  		ts = targetVersion[0]
   908  	}
   909  
   910  	m, _ := New("stub://", "stub://")
   911  	m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
   912  	migr, err := m.newMigration(version, ts)
   913  	if err != nil {
   914  		panic(err)
   915  	}
   916  	return migr
   917  }
   918  
   919  func equalMigSeq(t *testing.T, i int, expected, got migrationSequence) {
   920  	if len(expected) != len(got) {
   921  		t.Errorf("expected migrations %v, got %v, in %v", expected, got, i)
   922  
   923  	} else {
   924  		for ii := 0; ii < len(expected); ii++ {
   925  			if expected[ii].Version != got[ii].Version {
   926  				t.Errorf("expected version %v, got %v, in %v", expected[ii].Version, got[ii].Version, i)
   927  			}
   928  
   929  			if expected[ii].TargetVersion != got[ii].TargetVersion {
   930  				t.Errorf("expected targetVersion %v, got %v, in %v", expected[ii].TargetVersion, got[ii].TargetVersion, i)
   931  			}
   932  		}
   933  	}
   934  }
   935  
   936  func equalDbSeq(t *testing.T, i int, expected migrationSequence, got *dStub.Stub) {
   937  	bs := expected.bodySequence()
   938  	if !got.EqualSequence(bs) {
   939  		t.Fatalf("\nexpected sequence %v,\ngot               %v, in %v", bs, got.MigrationSequence, i)
   940  	}
   941  }