From b9111a3f44d3900a322f8b6bb3db13c6e5d08ba0 Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Mon, 17 Mar 2014 11:24:23 +0000 Subject: [PATCH 1/4] Add test for mysql --- pkg/database/testing/testing.go | 46 ++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/pkg/database/testing/testing.go b/pkg/database/testing/testing.go index c252204c5..4d6a32cb2 100644 --- a/pkg/database/testing/testing.go +++ b/pkg/database/testing/testing.go @@ -2,7 +2,11 @@ package database import ( "crypto/aes" + "database/sql" + "fmt" "log" + "os" + "strings" "github.com/drone/drone/pkg/database" "github.com/drone/drone/pkg/database/encrypt" @@ -12,6 +16,11 @@ import ( "github.com/russross/meddler" ) +var ( + dbname, driver, dsn, login string + db *sql.DB +) + func init() { // create a cipher for ecnrypting and decrypting // database fields @@ -24,11 +33,31 @@ func init() { // decrypt database fields. meddler.Register("gobencrypt", &encrypt.EncryptedField{cipher}) + // Check for $DB_ENV + dbenv := os.Getenv("DB_ENV") + if dbenv == "mysql" { + driver = dbenv + dbname = "drone_test" + login = os.Getenv("MYSQL_LOGIN") + if len(login) == 0 { + login = "root" + } + log.Println("Using mysql database ...") + } else { + driver = "sqlite3" + dsn = ":memory:" + log.Println("Using sqlite3 database ...") + } + } func Setup() { // create an in-memory database - database.Init("sqlite3", ":memory:") + if driver == "mysql" { + idsn := fmt.Sprintf("%s@/?parseTime=true", login) + db, dsn = createDB(dbname, idsn) + } + database.Init(driver, dsn) // create dummy user data user1 := User{ @@ -197,4 +226,19 @@ func Setup() { func Teardown() { database.Close() + if driver == "mysql" { + db.Exec(fmt.Sprintf("DROP DATABASE %s", dbname)) + } +} + +func createDB(name, datasource string) (*sql.DB, string) { + db, err := sql.Open(driver, datasource) + if err != nil { + panic("Can't connect to database") + } + if _, err := db.Exec(fmt.Sprintf("CREATE DATABASE %s", name)); err != nil { + panic("Can't create database") + } + dsn := strings.Replace(datasource, "/", fmt.Sprintf("/%s", name), 1) + return db, dsn } From fe58917a7ca6920f654c246c87c04659ad340834 Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Tue, 25 Mar 2014 01:15:02 +0000 Subject: [PATCH 2/4] Add stub for mysql test at migration --- pkg/database/migrate/sqlite_test.go | 40 ++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/pkg/database/migrate/sqlite_test.go b/pkg/database/migrate/sqlite_test.go index 37bc15b45..cb6c6775d 100644 --- a/pkg/database/migrate/sqlite_test.go +++ b/pkg/database/migrate/sqlite_test.go @@ -2,6 +2,7 @@ package migrate_test import ( "database/sql" + "fmt" "os" "strings" "testing" @@ -38,9 +39,9 @@ type revision1 struct{} func (r *revision1) Up(mg *MigrationDriver) error { _, err := mg.CreateTable("samples", []string{ - "id INTEGER PRIMARY KEY AUTOINCREMENT", - "imel VARCHAR(255) UNIQUE", - "name VARCHAR(255)", + mg.T.Integer("id", PRIMARYKEY, AUTOINCREMENT), + mg.T.String("imel", UNIQUE), + mg.T.String("name"), }) return err } @@ -253,7 +254,12 @@ func (r *revision10) Down(mg *MigrationDriver) error { // ---------- end of revision 10 -var db *sql.DB +var ( + db *sql.DB + driver, dsn string + + dbname = "drone_test" +) var testSchema = ` CREATE TABLE samples ( @@ -554,16 +560,38 @@ func TestChangeColumnType(t *testing.T) { } } +func init() { + if driver = os.Getenv("DB_ENV"); len(driver) == 0 { + driver = "sqlite3" + } + if dsn = os.Getenv("MYSQL_LOGIN"); len(dsn) == 0 { + dsn = ":memory:" + } +} + func setUp() error { var err error Driver = SQLite - db, err = sql.Open("sqlite3", "migration_tests.sqlite") + if db, err = sql.Open(driver, dsn); err != nil { + panic("Can't connect to database: ") + } + if driver == "mysql" { + Driver = MySQL + if _, err := db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbname)); err != nil { + panic("Can't create database: ") + } + if _, err := db.Exec(fmt.Sprintf("USE %s", dbname)); err != nil { + panic("Can't use database: ") + } + } return err } func tearDown() { + if driver == "mysql" { + db.Exec(fmt.Sprintf("DROP DATABASE %s", dbname)) + } db.Close() - os.Remove("migration_tests.sqlite") } func loadFixture(t *testing.T) { From 202ea9536801454622e4ae1ded7663bb90a831dd Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Thu, 27 Mar 2014 13:57:53 +0000 Subject: [PATCH 3/4] Move testing related code --- .../migrate/{ => testing}/sqlite_test.go | 125 +++++++++++------- 1 file changed, 76 insertions(+), 49 deletions(-) rename pkg/database/migrate/{ => testing}/sqlite_test.go (80%) diff --git a/pkg/database/migrate/sqlite_test.go b/pkg/database/migrate/testing/sqlite_test.go similarity index 80% rename from pkg/database/migrate/sqlite_test.go rename to pkg/database/migrate/testing/sqlite_test.go index cb6c6775d..5d7bf51c0 100644 --- a/pkg/database/migrate/sqlite_test.go +++ b/pkg/database/migrate/testing/sqlite_test.go @@ -3,12 +3,14 @@ package migrate_test import ( "database/sql" "fmt" + "log" "os" "strings" "testing" . "github.com/drone/drone/pkg/database/migrate" + _ "github.com/go-sql-driver/mysql" _ "github.com/mattn/go-sqlite3" "github.com/russross/meddler" ) @@ -476,43 +478,48 @@ func TestIndexOperations(t *testing.T) { } var esquel []*sqliteMaster - // Query sqlite_master, check if index is exists. - query := `SELECT sql FROM sqlite_master WHERE type='index' and tbl_name='samples'` - if err := meddler.QueryAll(db, &esquel, query); err != nil { - t.Fatalf("Can not find index: %q", err) - } + switch { + case driver == "mysql": - indexStatement := `CREATE INDEX idx_samples_on_url_and_name ON samples (url, name)` - if string(esquel[1].Sql.([]byte)) != indexStatement { - t.Errorf("Can not find index, got: %q", esquel[1]) - } + default: + // Query sqlite_master, check if index is exists. + query := `SELECT sql FROM sqlite_master WHERE type='index' and tbl_name='samples'` + if err := meddler.QueryAll(db, &esquel, query); err != nil { + t.Fatalf("Can not find index: %q", err) + } - // Migrate, rename indexed columns - if err := mgr.Add(&revision6{}).Migrate(); err != nil { - t.Fatalf("Can not migrate: %q", err) - } + indexStatement := `CREATE INDEX idx_samples_on_url_and_name ON samples (url, name)` + if string(esquel[1].Sql.([]byte)) != indexStatement { + t.Errorf("Can not find index, got: %q", esquel[1]) + } - var esquel1 []*sqliteMaster - if err := meddler.QueryAll(db, &esquel1, query); err != nil { - t.Fatalf("Can not find index: %q", err) - } + // Migrate, rename indexed columns + if err := mgr.Add(&revision6{}).Migrate(); err != nil { + t.Fatalf("Can not migrate: %q", err) + } - indexStatement = `CREATE INDEX idx_samples_on_host_and_name ON samples (host, name)` - if string(esquel1[1].Sql.([]byte)) != indexStatement { - t.Errorf("Can not find index, got: %q", esquel1[1]) - } + var esquel1 []*sqliteMaster + if err := meddler.QueryAll(db, &esquel1, query); err != nil { + t.Fatalf("Can not find index: %q", err) + } - if err := mgr.Add(&revision7{}).Migrate(); err != nil { - t.Fatalf("Can not migrate: %q", err) - } + indexStatement = `CREATE INDEX idx_samples_on_host_and_name ON samples (host, name)` + if string(esquel1[1].Sql.([]byte)) != indexStatement { + t.Errorf("Can not find index, got: %q", esquel1[1]) + } - var esquel2 []*sqliteMaster - if err := meddler.QueryAll(db, &esquel2, query); err != nil { - t.Fatalf("Can not find index: %q", err) - } + if err := mgr.Add(&revision7{}).Migrate(); err != nil { + t.Fatalf("Can not migrate: %q", err) + } - if len(esquel2) != 1 { - t.Errorf("Expect row length equal to %d, got %d", 1, len(esquel2)) + var esquel2 []*sqliteMaster + if err := meddler.QueryAll(db, &esquel2, query); err != nil { + t.Fatalf("Can not find index: %q", err) + } + + if len(esquel2) != 1 { + t.Errorf("Expect row length equal to %d, got %d", 1, len(esquel2)) + } } } @@ -527,14 +534,24 @@ func TestColumnRedundancy(t *testing.T) { t.Fatalf("Can not migrate: %q", err) } - var tableSql string - query := `SELECT sql FROM sqlite_master where type='table' and name='samples'` - if err := db.QueryRow(query).Scan(&tableSql); err != nil { - t.Fatalf("Can not query sqlite_master: %q", err) - } - - if !strings.Contains(tableSql, "repository ") { - t.Errorf("Expect column with name repository") + var dummy, query, tableSql string + switch { + case driver == "mysql": + query = `SHOW CREATE TABLE samples` + if err := db.QueryRow(query).Scan(&dummy, &tableSql); err != nil { + t.Fatalf("Can not query table's definition: %q", err) + } + if !strings.Contains(tableSql, "`repository`") { + t.Errorf("Expect column with name repository") + } + default: + query = `SELECT sql FROM sqlite_master where type='table' and name='samples'` + if err := db.QueryRow(query).Scan(&tableSql); err != nil { + t.Fatalf("Can not query sqlite_master: %q", err) + } + if !strings.Contains(tableSql, "repository ") { + t.Errorf("Expect column with name repository") + } } } @@ -549,14 +566,24 @@ func TestChangeColumnType(t *testing.T) { t.Fatalf("Can not migrate: %q", err) } - var tableSql string - query := `SELECT sql FROM sqlite_master where type='table' and name='samples'` - if err := db.QueryRow(query).Scan(&tableSql); err != nil { - t.Fatalf("Can not query sqlite_master: %q", err) - } - - if !strings.Contains(tableSql, "email varchar(512) UNIQUE") { - t.Errorf("Expect email type to changed: %q", tableSql) + var dummy, tableSql, query string + switch { + case driver == "mysql": + query = `SHOW CREATE TABLE samples` + if err := db.QueryRow(query).Scan(&dummy, &tableSql); err != nil { + t.Fatalf("Can not query table's definition: %q", err) + } + if !strings.Contains(tableSql, "`email` varchar(512)") { + t.Errorf("Expect email type to changed: %q", tableSql) + } + default: + query = `SELECT sql FROM sqlite_master where type='table' and name='samples'` + if err := db.QueryRow(query).Scan(&tableSql); err != nil { + t.Fatalf("Can not query sqlite_master: %q", err) + } + if !strings.Contains(tableSql, "email varchar(512) UNIQUE") { + t.Errorf("Expect email type to changed: %q", tableSql) + } } } @@ -573,15 +600,15 @@ func setUp() error { var err error Driver = SQLite if db, err = sql.Open(driver, dsn); err != nil { - panic("Can't connect to database: ") + log.Fatalf("Can't connect to database: %q", err) } if driver == "mysql" { Driver = MySQL if _, err := db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbname)); err != nil { - panic("Can't create database: ") + panic("Can't create database") } if _, err := db.Exec(fmt.Sprintf("USE %s", dbname)); err != nil { - panic("Can't use database: ") + panic("Can't use database") } } return err From 1736716baae07d42cf21b063f455a4b44f9f5242 Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Tue, 8 Apr 2014 01:13:13 +0000 Subject: [PATCH 4/4] Migration tests for mysql invoke: export DB_ENV=mysql export MYSQL_LOGIN='root:psswd@/' go test -v github.com/drone/drone/pkg/database/migrate/testing --- Makefile | 2 +- .../{sqlite_test.go => migrate_test.go} | 379 ++++++------------ pkg/database/migrate/testing/revisions.go | 246 ++++++++++++ pkg/database/testing/repos_test.go | 12 +- pkg/database/testing/testing.go | 45 ++- 5 files changed, 407 insertions(+), 277 deletions(-) rename pkg/database/migrate/testing/{sqlite_test.go => migrate_test.go} (62%) create mode 100644 pkg/database/migrate/testing/revisions.go diff --git a/Makefile b/Makefile index bfe9d94cd..b2d50e5e4 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ build/script \ channel \ database \ database/encrypt \ -database/migrate \ +database/migrate/testing \ database/testing \ mail \ model \ diff --git a/pkg/database/migrate/testing/sqlite_test.go b/pkg/database/migrate/testing/migrate_test.go similarity index 62% rename from pkg/database/migrate/testing/sqlite_test.go rename to pkg/database/migrate/testing/migrate_test.go index 5d7bf51c0..0dee1b98c 100644 --- a/pkg/database/migrate/testing/sqlite_test.go +++ b/pkg/database/migrate/testing/migrate_test.go @@ -1,4 +1,4 @@ -package migrate_test +package migrate import ( "database/sql" @@ -15,247 +15,6 @@ import ( "github.com/russross/meddler" ) -type Sample struct { - ID int64 `meddler:"id,pk"` - Imel string `meddler:"imel"` - Name string `meddler:"name"` -} - -type RenameSample struct { - ID int64 `meddler:"id,pk"` - Email string `meddler:"email"` - Name string `meddler:"name"` -} - -type AddColumnSample struct { - ID int64 `meddler:"id,pk"` - Imel string `meddler:"imel"` - Name string `meddler:"name"` - Url string `meddler:"url"` - Num int64 `meddler:"num"` -} - -// ---------- revision 1 - -type revision1 struct{} - -func (r *revision1) Up(mg *MigrationDriver) error { - _, err := mg.CreateTable("samples", []string{ - mg.T.Integer("id", PRIMARYKEY, AUTOINCREMENT), - mg.T.String("imel", UNIQUE), - mg.T.String("name"), - }) - return err -} - -func (r *revision1) Down(mg *MigrationDriver) error { - _, err := mg.DropTable("samples") - return err -} - -func (r *revision1) Revision() int64 { - return 1 -} - -// ---------- end of revision 1 - -// ---------- revision 2 - -type revision2 struct{} - -func (r *revision2) Up(mg *MigrationDriver) error { - _, err := mg.RenameTable("samples", "examples") - return err -} - -func (r *revision2) Down(mg *MigrationDriver) error { - _, err := mg.RenameTable("examples", "samples") - return err -} - -func (r *revision2) Revision() int64 { - return 2 -} - -// ---------- end of revision 2 - -// ---------- revision 3 - -type revision3 struct{} - -func (r *revision3) Up(mg *MigrationDriver) error { - if _, err := mg.AddColumn("samples", "url VARCHAR(255)"); err != nil { - return err - } - _, err := mg.AddColumn("samples", "num INTEGER") - return err -} - -func (r *revision3) Down(mg *MigrationDriver) error { - _, err := mg.DropColumns("samples", "num", "url") - return err -} - -func (r *revision3) Revision() int64 { - return 3 -} - -// ---------- end of revision 3 - -// ---------- revision 4 - -type revision4 struct{} - -func (r *revision4) Up(mg *MigrationDriver) error { - _, err := mg.RenameColumns("samples", map[string]string{ - "imel": "email", - }) - return err -} - -func (r *revision4) Down(mg *MigrationDriver) error { - _, err := mg.RenameColumns("samples", map[string]string{ - "email": "imel", - }) - return err -} - -func (r *revision4) Revision() int64 { - return 4 -} - -// ---------- end of revision 4 - -// ---------- revision 5 - -type revision5 struct{} - -func (r *revision5) Up(mg *MigrationDriver) error { - _, err := mg.AddIndex("samples", []string{"url", "name"}) - return err -} - -func (r *revision5) Down(mg *MigrationDriver) error { - _, err := mg.DropIndex("samples", []string{"url", "name"}) - return err -} - -func (r *revision5) Revision() int64 { - return 5 -} - -// ---------- end of revision 5 - -// ---------- revision 6 -type revision6 struct{} - -func (r *revision6) Up(mg *MigrationDriver) error { - _, err := mg.RenameColumns("samples", map[string]string{ - "url": "host", - }) - return err -} - -func (r *revision6) Down(mg *MigrationDriver) error { - _, err := mg.RenameColumns("samples", map[string]string{ - "host": "url", - }) - return err -} - -func (r *revision6) Revision() int64 { - return 6 -} - -// ---------- end of revision 6 - -// ---------- revision 7 -type revision7 struct{} - -func (r *revision7) Up(mg *MigrationDriver) error { - _, err := mg.DropColumns("samples", "host", "num") - return err -} - -func (r *revision7) Down(mg *MigrationDriver) error { - if _, err := mg.AddColumn("samples", "host VARCHAR(255)"); err != nil { - return err - } - _, err := mg.AddColumn("samples", "num INSTEGER") - return err -} - -func (r *revision7) Revision() int64 { - return 7 -} - -// ---------- end of revision 7 - -// ---------- revision 8 -type revision8 struct{} - -func (r *revision8) Up(mg *MigrationDriver) error { - if _, err := mg.AddColumn("samples", "repo_id INTEGER"); err != nil { - return err - } - _, err := mg.AddColumn("samples", "repo VARCHAR(255)") - return err -} - -func (r *revision8) Down(mg *MigrationDriver) error { - _, err := mg.DropColumns("samples", "repo", "repo_id") - return err -} - -func (r *revision8) Revision() int64 { - return 8 -} - -// ---------- end of revision 8 - -// ---------- revision 9 -type revision9 struct{} - -func (r *revision9) Up(mg *MigrationDriver) error { - _, err := mg.RenameColumns("samples", map[string]string{ - "repo": "repository", - }) - return err -} - -func (r *revision9) Down(mg *MigrationDriver) error { - _, err := mg.RenameColumns("samples", map[string]string{ - "repository": "repo", - }) - return err -} - -func (r *revision9) Revision() int64 { - return 9 -} - -// ---------- end of revision 9 - -// ---------- revision 10 - -type revision10 struct{} - -func (r *revision10) Revision() int64 { - return 10 -} - -func (r *revision10) Up(mg *MigrationDriver) error { - _, err := mg.ChangeColumn("samples", "email", "varchar(512) UNIQUE") - return err -} - -func (r *revision10) Down(mg *MigrationDriver) error { - _, err := mg.ChangeColumn("samples", "email", "varchar(255) unique") - return err -} - -// ---------- end of revision 10 - var ( db *sql.DB driver, dsn string @@ -263,7 +22,7 @@ var ( dbname = "drone_test" ) -var testSchema = ` +var sqliteTestSchema = ` CREATE TABLE samples ( id INTEGER PRIMARY KEY AUTOINCREMENT, imel VARCHAR(255) UNIQUE, @@ -271,6 +30,14 @@ CREATE TABLE samples ( ); ` +var mysqlTestSchema = ` +CREATE TABLE samples ( + id INTEGER PRIMARY KEY AUTO_INCREMENT, + imel VARCHAR(255) UNIQUE, + name VARCHAR(255) +) +` + var dataDump = []string{ `INSERT INTO samples (imel, name) VALUES ('test@example.com', 'Test Tester');`, `INSERT INTO samples (imel, name) VALUES ('foo@bar.com', 'Foo Bar');`, @@ -304,6 +71,13 @@ func TestMigrateExistingCreateTable(t *testing.T) { t.Fatalf("Error preparing database: %q", err) } + var testSchema string + if driver == "mysql" { + testSchema = mysqlTestSchema + } else { + testSchema = sqliteTestSchema + } + if _, err := db.Exec(testSchema); err != nil { t.Fatalf("Can not create database: %q", err) } @@ -357,6 +131,15 @@ type TableInfo struct { PK bool `meddler:"pk"` } +type MysqlTableInfo struct { + Field string `meddler:"Field"` + Type string `meddler:"Type"` + Null string `meddler:"Null"` + Key interface{} `meddler:"Key"` + Default interface{} `meddler:"Default"` + Extra interface{} `meddler:"Extra"` +} + func TestMigrateAddRemoveColumns(t *testing.T) { defer tearDown() if err := setUp(); err != nil { @@ -368,13 +151,25 @@ func TestMigrateAddRemoveColumns(t *testing.T) { t.Fatalf("Can not migrate: %q", err) } - var columns []*TableInfo - if err := meddler.QueryAll(db, &columns, `PRAGMA table_info(samples);`); err != nil { - t.Fatalf("Can not access table info: %q", err) - } + switch driver { + case "mysql": + var columns []*MysqlTableInfo + if err := meddler.QueryAll(db, &columns, `SHOW COLUMNS FROM samples`); err != nil { + t.Fatalf("Can not access table infor: %q", err) + } - if len(columns) < 5 { - t.Errorf("Expect length columns: %d\nGot: %d", 5, len(columns)) + if len(columns) < 5 { + t.Errorf("Expect length columns: %d\nGot: %d", 5, len(columns)) + } + default: + var columns []*TableInfo + if err := meddler.QueryAll(db, &columns, `PRAGMA table_info(samples);`); err != nil { + t.Fatalf("Can not access table info: %q", err) + } + + if len(columns) < 5 { + t.Errorf("Expect length columns: %d\nGot: %d", 5, len(columns)) + } } var row = AddColumnSample{ @@ -392,14 +187,27 @@ func TestMigrateAddRemoveColumns(t *testing.T) { t.Fatalf("Can not migrate: %q", err) } - var another_columns []*TableInfo - if err := meddler.QueryAll(db, &another_columns, `PRAGMA table_info(samples);`); err != nil { - t.Fatalf("Can not access table info: %q", err) + switch driver { + case "mysql": + var columns []*MysqlTableInfo + if err := meddler.QueryAll(db, &columns, `SHOW COLUMNS FROM samples`); err != nil { + t.Fatalf("Can not access table infor: %q", err) + } + + if len(columns) != 3 { + t.Errorf("Expect length columns: %d\nGot: %d", 3, len(columns)) + } + default: + var columns []*TableInfo + if err := meddler.QueryAll(db, &columns, `PRAGMA table_info(samples);`); err != nil { + t.Fatalf("Can not access table info: %q", err) + } + + if len(columns) != 3 { + t.Errorf("Expect length columns: %d\nGot: %d", 3, len(columns)) + } } - if len(another_columns) != 3 { - t.Errorf("Expect length columns = %d, got: %d", 3, len(columns)) - } } func TestRenameColumn(t *testing.T) { @@ -435,6 +243,13 @@ func TestMigrateExistingTable(t *testing.T) { t.Fatalf("Error preparing database: %q", err) } + var testSchema string + if driver == "mysql" { + testSchema = mysqlTestSchema + } else { + testSchema = sqliteTestSchema + } + if _, err := db.Exec(testSchema); err != nil { t.Fatalf("Can not create database: %q", err) } @@ -478,8 +293,44 @@ func TestIndexOperations(t *testing.T) { } var esquel []*sqliteMaster - switch { - case driver == "mysql": + var mysquel struct { + Table string `meddler:"Table"` + CreateTable string `meddler:"Create Table"` + } + switch driver { + case "mysql": + query := `SHOW CREATE TABLE samples` + if err := meddler.QueryRow(db, &mysquel, query); err != nil { + t.Fatalf("Can not fetch table definition: %q", err) + } + + if !strings.Contains(mysquel.CreateTable, "KEY `idx_samples_on_url_and_name` (`url`,`name`)") { + t.Errorf("Can not find index, got: %q", mysquel.CreateTable) + } + + if err := mgr.Add(&revision6{}).Migrate(); err != nil { + t.Fatalf("Can not migrate: %q", err) + } + + if err := meddler.QueryRow(db, &mysquel, query); err != nil { + t.Fatalf("Can not find index: %q", err) + } + + if !strings.Contains(mysquel.CreateTable, "KEY `idx_samples_on_url_and_name` (`host`,`name`)") { + t.Errorf("Can not find index, got: %q", mysquel.CreateTable) + } + + if err := mgr.Add(&revision7{}).Migrate(); err != nil { + t.Fatalf("Can not migrate: %q", err) + } + + if err := meddler.QueryRow(db, &mysquel, query); err != nil { + t.Fatalf("Can not find index: %q", err) + } + + if strings.Contains(mysquel.CreateTable, "KEY `idx_samples_on_url_and_name` (`host`,`name`)") { + t.Errorf("Expect index to be deleted.") + } default: // Query sqlite_master, check if index is exists. @@ -535,8 +386,8 @@ func TestColumnRedundancy(t *testing.T) { } var dummy, query, tableSql string - switch { - case driver == "mysql": + switch driver { + case "mysql": query = `SHOW CREATE TABLE samples` if err := db.QueryRow(query).Scan(&dummy, &tableSql); err != nil { t.Fatalf("Can not query table's definition: %q", err) @@ -567,8 +418,8 @@ func TestChangeColumnType(t *testing.T) { } var dummy, tableSql, query string - switch { - case driver == "mysql": + switch driver { + case "mysql": query = `SHOW CREATE TABLE samples` if err := db.QueryRow(query).Scan(&dummy, &tableSql); err != nil { t.Fatalf("Can not query table's definition: %q", err) @@ -593,6 +444,8 @@ func init() { } if dsn = os.Getenv("MYSQL_LOGIN"); len(dsn) == 0 { dsn = ":memory:" + } else { + dsn = fmt.Sprintf("%s@/?parseTime=true", dsn) } } @@ -605,10 +458,10 @@ func setUp() error { if driver == "mysql" { Driver = MySQL if _, err := db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbname)); err != nil { - panic("Can't create database") + log.Fatalf("Can't create database: %q", err) } if _, err := db.Exec(fmt.Sprintf("USE %s", dbname)); err != nil { - panic("Can't use database") + log.Fatalf("Can't use database: %q", dbname) } } return err diff --git a/pkg/database/migrate/testing/revisions.go b/pkg/database/migrate/testing/revisions.go new file mode 100644 index 000000000..508af8437 --- /dev/null +++ b/pkg/database/migrate/testing/revisions.go @@ -0,0 +1,246 @@ +package migrate + +import ( + . "github.com/drone/drone/pkg/database/migrate" +) + +type Sample struct { + ID int64 `meddler:"id,pk"` + Imel string `meddler:"imel"` + Name string `meddler:"name"` +} + +type RenameSample struct { + ID int64 `meddler:"id,pk"` + Email string `meddler:"email"` + Name string `meddler:"name"` +} + +type AddColumnSample struct { + ID int64 `meddler:"id,pk"` + Imel string `meddler:"imel"` + Name string `meddler:"name"` + Url string `meddler:"url"` + Num int64 `meddler:"num"` +} + +// ---------- revision 1 + +type revision1 struct{} + +func (r *revision1) Up(mg *MigrationDriver) error { + _, err := mg.CreateTable("samples", []string{ + mg.T.Integer("id", PRIMARYKEY, AUTOINCREMENT), + mg.T.String("imel", UNIQUE), + mg.T.String("name"), + }) + return err +} + +func (r *revision1) Down(mg *MigrationDriver) error { + _, err := mg.DropTable("samples") + return err +} + +func (r *revision1) Revision() int64 { + return 1 +} + +// ---------- end of revision 1 + +// ---------- revision 2 + +type revision2 struct{} + +func (r *revision2) Up(mg *MigrationDriver) error { + _, err := mg.RenameTable("samples", "examples") + return err +} + +func (r *revision2) Down(mg *MigrationDriver) error { + _, err := mg.RenameTable("examples", "samples") + return err +} + +func (r *revision2) Revision() int64 { + return 2 +} + +// ---------- end of revision 2 + +// ---------- revision 3 + +type revision3 struct{} + +func (r *revision3) Up(mg *MigrationDriver) error { + if _, err := mg.AddColumn("samples", "url VARCHAR(255)"); err != nil { + return err + } + _, err := mg.AddColumn("samples", "num INTEGER") + return err +} + +func (r *revision3) Down(mg *MigrationDriver) error { + _, err := mg.DropColumns("samples", "num", "url") + return err +} + +func (r *revision3) Revision() int64 { + return 3 +} + +// ---------- end of revision 3 + +// ---------- revision 4 + +type revision4 struct{} + +func (r *revision4) Up(mg *MigrationDriver) error { + _, err := mg.RenameColumns("samples", map[string]string{ + "imel": "email", + }) + return err +} + +func (r *revision4) Down(mg *MigrationDriver) error { + _, err := mg.RenameColumns("samples", map[string]string{ + "email": "imel", + }) + return err +} + +func (r *revision4) Revision() int64 { + return 4 +} + +// ---------- end of revision 4 + +// ---------- revision 5 + +type revision5 struct{} + +func (r *revision5) Up(mg *MigrationDriver) error { + _, err := mg.AddIndex("samples", []string{"url", "name"}) + return err +} + +func (r *revision5) Down(mg *MigrationDriver) error { + _, err := mg.DropIndex("samples", []string{"url", "name"}) + return err +} + +func (r *revision5) Revision() int64 { + return 5 +} + +// ---------- end of revision 5 + +// ---------- revision 6 +type revision6 struct{} + +func (r *revision6) Up(mg *MigrationDriver) error { + _, err := mg.RenameColumns("samples", map[string]string{ + "url": "host", + }) + return err +} + +func (r *revision6) Down(mg *MigrationDriver) error { + _, err := mg.RenameColumns("samples", map[string]string{ + "host": "url", + }) + return err +} + +func (r *revision6) Revision() int64 { + return 6 +} + +// ---------- end of revision 6 + +// ---------- revision 7 +type revision7 struct{} + +func (r *revision7) Up(mg *MigrationDriver) error { + _, err := mg.DropColumns("samples", "host", "num") + return err +} + +func (r *revision7) Down(mg *MigrationDriver) error { + if _, err := mg.AddColumn("samples", "host VARCHAR(255)"); err != nil { + return err + } + _, err := mg.AddColumn("samples", "num INSTEGER") + return err +} + +func (r *revision7) Revision() int64 { + return 7 +} + +// ---------- end of revision 7 + +// ---------- revision 8 +type revision8 struct{} + +func (r *revision8) Up(mg *MigrationDriver) error { + if _, err := mg.AddColumn("samples", "repo_id INTEGER"); err != nil { + return err + } + _, err := mg.AddColumn("samples", "repo VARCHAR(255)") + return err +} + +func (r *revision8) Down(mg *MigrationDriver) error { + _, err := mg.DropColumns("samples", "repo", "repo_id") + return err +} + +func (r *revision8) Revision() int64 { + return 8 +} + +// ---------- end of revision 8 + +// ---------- revision 9 +type revision9 struct{} + +func (r *revision9) Up(mg *MigrationDriver) error { + _, err := mg.RenameColumns("samples", map[string]string{ + "repo": "repository", + }) + return err +} + +func (r *revision9) Down(mg *MigrationDriver) error { + _, err := mg.RenameColumns("samples", map[string]string{ + "repository": "repo", + }) + return err +} + +func (r *revision9) Revision() int64 { + return 9 +} + +// ---------- end of revision 9 + +// ---------- revision 10 + +type revision10 struct{} + +func (r *revision10) Revision() int64 { + return 10 +} + +func (r *revision10) Up(mg *MigrationDriver) error { + _, err := mg.ChangeColumn("samples", "email", "varchar(512) UNIQUE") + return err +} + +func (r *revision10) Down(mg *MigrationDriver) error { + _, err := mg.ChangeColumn("samples", "email", "varchar(255) unique") + return err +} + +// ---------- end of revision 10 diff --git a/pkg/database/testing/repos_test.go b/pkg/database/testing/repos_test.go index a6420184b..515b99b3b 100644 --- a/pkg/database/testing/repos_test.go +++ b/pkg/database/testing/repos_test.go @@ -63,11 +63,11 @@ func TestGetRepo(t *testing.T) { t.Errorf("Exepected Password %s, got %s", "no password", repo.Password) } - if repo.PublicKey != "public key" { + if repo.PublicKey != pubkey { t.Errorf("Exepected PublicKey %s, got %s", "public key", repo.PublicKey) } - if repo.PrivateKey != "private key" { + if repo.PrivateKey != privkey { t.Errorf("Exepected PrivateKey %s, got %s", "private key", repo.PrivateKey) } @@ -135,11 +135,11 @@ func TestGetRepoSlug(t *testing.T) { t.Errorf("Exepected Password %s, got %s", "no password", repo.Password) } - if repo.PublicKey != "public key" { + if repo.PublicKey != pubkey { t.Errorf("Exepected PublicKey %s, got %s", "public key", repo.PublicKey) } - if repo.PrivateKey != "private key" { + if repo.PrivateKey != privkey { t.Errorf("Exepected PrivateKey %s, got %s", "private key", repo.PrivateKey) } @@ -385,11 +385,11 @@ func TestListReposTeam(t *testing.T) { t.Errorf("Exepected Password %s, got %s", "no password", repo.Password) } - if repo.PublicKey != "public key" { + if repo.PublicKey != pubkey { t.Errorf("Exepected PublicKey %s, got %s", "public key", repo.PublicKey) } - if repo.PrivateKey != "private key" { + if repo.PrivateKey != privkey { t.Errorf("Exepected PrivateKey %s, got %s", "private key", repo.PrivateKey) } diff --git a/pkg/database/testing/testing.go b/pkg/database/testing/testing.go index 4d6a32cb2..9330ca6cb 100644 --- a/pkg/database/testing/testing.go +++ b/pkg/database/testing/testing.go @@ -16,9 +16,40 @@ import ( "github.com/russross/meddler" ) +const ( + pubkey = `sh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQClp9+xjhYj2Wz0nwLNhUiR1RkqfoVZwlJoxdubQy8GskZtY7C7YGa/PeKfdfaKOWtVgg37r/OYS3kc7bIKVup4sx/oW59FMwCZYQ2nxoaPZpPwUJs8D0Wy0b2VSP+vAnJ6jZQEIEiClrzyYafSfqN6L9T/BTkn28ktWalOHqWVKejKeD6M0uhlpyIZFsQ1K2wNt32ACwT/rbanx/r/jfczqxSkLzvIKXXs/RdKQgwRRUYnKkl4Lh6r22n9n3m2VwRor5wdsPK8sr57OsqdRpnvsFs3lxwM8w5ZiAZV3T0xTMGVs3W8Uy5HexAD6TgWBWFjSrgdXF1pE83wmUtJtVBf` + privkey = `-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApaffsY4WI9ls9J8CzYVIkdUZKn6FWcJSaMXbm0MvBrJGbWOw +u2Bmvz3in3X2ijlrVYIN+6/zmEt5HO2yClbqeLMf6FufRTMAmWENp8aGj2aT8FCb +PA9FstG9lUj/rwJyeo2UBCBIgpa88mGn0n6jei/U/wU5J9vJLVmpTh6llSnoyng+ +jNLoZaciGRbENStsDbd9gAsE/622p8f6/433M6sUpC87yCl17P0XSkIMEUVGJypJ +eC4eq9tp/Z95tlcEaK+cHbDyvLK+ezrKnUaZ77BbN5ccDPMOWYgGVd09MUzBlbN1 +vFMuR3sQA+k4FgVhY0q4HVxdaRPN8JlLSbVQXwIDAQABAoIBAA3EqSPxwkdSf+rI ++IuqY0CzrHbKszylmQHaSAlciSEOWionWf4I4iFM/HPycv5EDXa663yawC1NQJC1 +9NFFLhHAGYvPaapvtcIJvf/O0UpD5VHY8T4JqupU4mPxAEdEdc1XzRCWulAYRTYE +BdXJ7r5uEU7s2TZF3y+kvxyeEXcXNWK1I4kGBSgH4KI5WIODtNJ6vaIk5Yugqt1N +cg5Sprk4bUMRTBH6GmSiJUleA0f/k6MCCmhETKXGt9mmfJ1PXpVlfDn5m26MX6vZ +XgaoIHUCy4sh1Fq6vbEI831JcO4kdvl4TtX90SzSadHjewNHy0V2gjAysvqbEDhw +Hn8D+MkCgYEA00tTKPp3AUTxT9ZgfPBD3DY7tk7+xp2R2lA6H9TUWe79TRfncFtS +8bCfEXd8xALL5cFyzi4q4YJ77mJjlWE7AMYdsFoAW1l3Q71JRRBSwsyIwp4hU8AV +K48SDjqecDzY42UvuKGp3opPWb0PzJixJNUgawU/ZGPxqN8jlr0o+K0CgYEAyLSO +rZqOvyE5wu8yadHLlQC4usoYtnyDC8PG2SgnZnlnZnkgNy3yLmHYvTvYSQsAv7rA +fFsKMt2MJhlclx+sTds/LLHKj/RfVDFenFf6ajBNZ1k+KRcwrV1A4iWinWmBxiEi +A8aM9rGs7WRBkqaCONSUQHcmLRRz7hqDtsBpkrsCgYBY2FJ2Z6LEmN2zCVx3DHws +S22eQeclUroyhwt5uP81daVy1jtN5kihMfgg2xJORTLBQC9q/MSxIDHGUf63oDO0 +JpnzPlTqFFtu01fMv4ldOa3Dz8QJuDnun/EipIlcfmlgbHq9ctS/q36kKDhNemL6 +Lte7yHAYYWIK9RC84Hsq3QKBgAfDbC1s6A6ek2Rl6jZLpitKTtryzEfqwwrmdL+b +nQKKuaQuFT/tKAwBPuf685/HrCy+ZYmp39gd17j1jC5QTFLqoyPwcJxm4HUaP8We +ZZJL8gKIYi4mtnxOOh9FQ2gBV8K5L16kBHnaX40DLsIkbK8UEfP4Z+Kggud34RZl +lO/XAoGAFFZdolsVbSieFhJt7ypzp/19dKJ8Sk6QGCk3uQpTuLJMvwcBT8X5XCTD +zFfYARarx87mbD2k5GZ7F0fmGYTUV14qlxJCGMythLM/xZ6EJuJWBz69puNj4yhn +exWM7t1BDHy2zIoPfIQLDH2h1zNTRjismMeErOCy0Uha7jrZhW8= +-----END RSA PRIVATE KEY-----` +) + var ( dbname, driver, dsn, login string - db *sql.DB + db *sql.DB ) func init() { @@ -131,8 +162,8 @@ func Setup() { URL: "git@github.com:drone/drone.git", Username: "no username", Password: "no password", - PublicKey: "public key", - PrivateKey: "private key", + PublicKey: pubkey, + PrivateKey: privkey, UserID: user1.ID, TeamID: team1.ID, } @@ -147,8 +178,8 @@ func Setup() { URL: "https://bitbucket.org/drone/test", Username: "no username", Password: "no password", - PublicKey: "public key", - PrivateKey: "private key", + PublicKey: pubkey, + PrivateKey: privkey, UserID: user1.ID, TeamID: team1.ID, } @@ -163,8 +194,8 @@ func Setup() { URL: "https://bitbucket.org/brydzewski/test", Username: "no username", Password: "no password", - PublicKey: "public key", - PrivateKey: "private key", + PublicKey: pubkey, + PrivateKey: privkey, UserID: user2.ID, }