| // Package testing has the database tests. |
| // All database drivers must pass the Test function. |
| // This lives in it's own package so it stays a test dependency. |
| package testing |
| |
| import ( |
| "bytes" |
| "fmt" |
| "io" |
| "testing" |
| "time" |
| |
| "github.com/mattes/migrate/database" |
| ) |
| |
| // Test runs tests against database implementations. |
| func Test(t *testing.T, d database.Driver, migration []byte) { |
| if migration == nil { |
| panic("test must provide migration reader") |
| } |
| |
| TestNilVersion(t, d) // test first |
| TestLockAndUnlock(t, d) |
| TestRun(t, d, bytes.NewReader(migration)) |
| TestDrop(t, d) |
| TestSetVersion(t, d) // also tests Version() |
| } |
| |
| func TestNilVersion(t *testing.T, d database.Driver) { |
| v, _, err := d.Version() |
| if err != nil { |
| t.Fatal(err) |
| } |
| if v != database.NilVersion { |
| t.Fatalf("Version: expected version to be NilVersion (-1), got %v", v) |
| } |
| } |
| |
| func TestLockAndUnlock(t *testing.T, d database.Driver) { |
| // add a timeout, in case there is a deadlock |
| done := make(chan bool, 1) |
| go func() { |
| timeout := time.After(15 * time.Second) |
| for { |
| select { |
| case <-done: |
| return |
| case <-timeout: |
| panic(fmt.Sprintf("Timeout after 15 seconds. Looks like a deadlock in Lock/UnLock.\n%#v", d)) |
| } |
| } |
| }() |
| defer func() { |
| done <- true |
| }() |
| |
| // run the locking test ... |
| |
| if err := d.Lock(); err != nil { |
| t.Fatal(err) |
| } |
| |
| // try to acquire lock again |
| if err := d.Lock(); err == nil { |
| t.Fatal("Lock: expected err not to be nil") |
| } |
| |
| // unlock |
| if err := d.Unlock(); err != nil { |
| t.Fatal(err) |
| } |
| |
| // try to lock |
| if err := d.Lock(); err != nil { |
| t.Fatal(err) |
| } |
| if err := d.Unlock(); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| func TestRun(t *testing.T, d database.Driver, migration io.Reader) { |
| if migration == nil { |
| panic("migration can't be nil") |
| } |
| |
| if err := d.Run(migration); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| func TestDrop(t *testing.T, d database.Driver) { |
| if err := d.Drop(); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| func TestSetVersion(t *testing.T, d database.Driver) { |
| if err := d.SetVersion(1, true); err != nil { |
| t.Fatal(err) |
| } |
| |
| // call again |
| if err := d.SetVersion(1, true); err != nil { |
| t.Fatal(err) |
| } |
| |
| v, dirty, err := d.Version() |
| if err != nil { |
| t.Fatal(err) |
| } |
| if !dirty { |
| t.Fatal("expected dirty") |
| } |
| if v != 1 { |
| t.Fatal("expected version to be 1") |
| } |
| |
| if err := d.SetVersion(2, false); err != nil { |
| t.Fatal(err) |
| } |
| |
| // call again |
| if err := d.SetVersion(2, false); err != nil { |
| t.Fatal(err) |
| } |
| |
| v, dirty, err = d.Version() |
| if err != nil { |
| t.Fatal(err) |
| } |
| if dirty { |
| t.Fatal("expected not dirty") |
| } |
| if v != 2 { |
| t.Fatal("expected version to be 2") |
| } |
| } |