github.com/yuukihogo/migrate@v3.0.0+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/mattes/migrate/database/stub" 12 "github.com/mattes/migrate/source" 13 sStub "github.com/mattes/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(); 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/mattes/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/mattes/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 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(); 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(); 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() 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) 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 }