Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(790)

Side by Side Diff: go/database/testutil/testutil.go

Issue 813443002: Overhaul database package (Closed) Base URL: https://skia.googlesource.com/buildbot@master
Patch Set: Add buildbot_migratedb Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 package testutil 1 package testutil
2 2
3 import ( 3 import (
4 "fmt"
5 "os"
6 "strings" 4 "strings"
7 "testing" 5 "testing"
8 ) 6 )
9 7
10 import ( 8 import (
11 // Using 'require' which is like using 'assert' but causes tests to fail . 9 // Using 'require' which is like using 'assert' but causes tests to fail .
12 assert "github.com/stretchr/testify/require" 10 assert "github.com/stretchr/testify/require"
13 11
14 "skia.googlesource.com/buildbot.git/go/database" 12 "skia.googlesource.com/buildbot.git/go/database"
15 ) 13 )
16 14
17 // Connection string to the local MySQL database for testing. 15 // Connection string to the local MySQL database for testing.
18 const ( 16 const (
19 // String to open a local database for testing. The string formatting 17 // String to open a local database for testing. The string formatting
20 // parameters are: username, password, database. 18 // parameters are: username, password, database.
21 MYSQL_DB_OPEN = "%s:%s@tcp(localhost:3306)/%s?parseTime=true" 19 MYSQL_DB_OPEN = "%s:%s@tcp(localhost:3306)/%s?parseTime=true"
22 20
23 // File path to the local SQLite testing databse.
24 SQLITE_DB_PATH = "./testing.db"
25
26 // Name of the MySQL lock 21 // Name of the MySQL lock
27 SQL_LOCK = "mysql_testlock" 22 SQL_LOCK = "mysql_testlock"
28 ) 23 )
29 24
30 // Creates an SQLite test database and runs migration tests against it using the
31 // given migration steps.
32 func SQLiteVersioningTests(t *testing.T, migrationSteps []database.MigrationStep ) {
33 // Initialize without argument to test against SQLite3
34 conf := &database.DatabaseConfig{
35 SQLiteFilePath: SQLITE_DB_PATH,
36 MigrationSteps: migrationSteps,
37 }
38
39 vdb := database.NewVersionedDB(conf)
40 assert.False(t, vdb.IsMySQL)
41 testDBVersioning(t, vdb)
42 }
43
44 // Creates an MySQL test database and runs migration tests against it using the 25 // Creates an MySQL test database and runs migration tests against it using the
45 // given migration steps. See Get for required credentials. 26 // given migration steps. See Get for required credentials.
46 // The test assumes that the database is empty and that the readwrite user is 27 // The test assumes that the database is empty and that the readwrite user is
47 // not allowed to create/drop/alter tables. 28 // not allowed to create/drop/alter tables.
48 func MySQLVersioningTests(t *testing.T, dbName string, migrationSteps []database .MigrationStep) { 29 func MySQLVersioningTests(t *testing.T, dbName string, migrationSteps []database .MigrationStep) {
49 // OpenDB as root user and remove all tables. 30 // OpenDB as root user and remove all tables.
50 » rootConf := &database.DatabaseConfig{ 31 » rootConf := database.LocalTestRootDatabaseConfig(migrationSteps)
51 » » MySQLString: GetTestMySQLConnStr(t, "root", dbName),
52 » » MigrationSteps: migrationSteps,
53 » }
54 lockVdb := GetMySQlLock(t, rootConf) 32 lockVdb := GetMySQlLock(t, rootConf)
55 defer func() { 33 defer func() {
56 ReleaseMySQLLock(t, lockVdb) 34 ReleaseMySQLLock(t, lockVdb)
57 lockVdb.Close() 35 lockVdb.Close()
58 }() 36 }()
59 37
60 rootVdb := database.NewVersionedDB(rootConf) 38 rootVdb := database.NewVersionedDB(rootConf)
61 assert.True(t, rootVdb.IsMySQL)
62 ClearMySQLTables(t, rootVdb) 39 ClearMySQLTables(t, rootVdb)
63 assert.Nil(t, rootVdb.Close()) 40 assert.Nil(t, rootVdb.Close())
64 41
65 // Configuration for the readwrite user without DDL privileges. 42 // Configuration for the readwrite user without DDL privileges.
66 » readWriteConf := &database.DatabaseConfig{ 43 » readWriteConf := database.LocalTestDatabaseConfig(migrationSteps)
67 » » MySQLString: GetTestMySQLConnStr(t, "readwrite", dbName),
68 » » MigrationSteps: migrationSteps,
69 » }
70 44
71 // Open DB as readwrite user and make sure it fails because of a missing 45 // Open DB as readwrite user and make sure it fails because of a missing
72 // version table. 46 // version table.
73 // Note: This requires the database to be empty. 47 // Note: This requires the database to be empty.
74 assert.Panics(t, func() { 48 assert.Panics(t, func() {
75 database.NewVersionedDB(readWriteConf) 49 database.NewVersionedDB(readWriteConf)
76 }) 50 })
77 51
78 rootVdb = database.NewVersionedDB(rootConf) 52 rootVdb = database.NewVersionedDB(rootConf)
79 testDBVersioning(t, rootVdb) 53 testDBVersioning(t, rootVdb)
80 54
81 // Make sure it doesn't panic for readwrite user after the migration 55 // Make sure it doesn't panic for readwrite user after the migration
82 assert.NotPanics(t, func() { 56 assert.NotPanics(t, func() {
83 database.NewVersionedDB(readWriteConf) 57 database.NewVersionedDB(readWriteConf)
84 }) 58 })
85 } 59 }
86 60
87 // Returns a connection string to the local MySQL server and the given database.
88 // The test will be skipped if these environement variables are not set:
89 // MYSQL_TESTING_RWPW (password of readwrite user)
90 // MYSQL_TESTING_ROOTPW (password of the db root user)
91 func GetTestMySQLConnStr(t *testing.T, user string, dbName string) string {
92 rwUserPw, rootPw := os.Getenv("MYSQL_TESTING_RWPW"), os.Getenv("MYSQL_TE STING_ROOTPW")
93 if testing.Short() {
94 t.Skip("Skipping test against MySQL in short mode.")
95 }
96
97 // Skip this test unless there are environment variables with the rwuser and
98 // root password for the local MySQL instance.
99 if (rwUserPw == "") || (rootPw == "") {
100 t.Skip("Skipping test against MySQL. Set 'MYSQL_TESTING_ROOTPW' and 'MYSQL_TESTING_RWPW' to enable tests.")
101 }
102 pw := rwUserPw
103 if user == "root" {
104 pw = rootPw
105 }
106 return fmt.Sprintf(MYSQL_DB_OPEN, user, pw, dbName)
107 }
108
109 // Get a lock from MySQL to serialize DB tests. 61 // Get a lock from MySQL to serialize DB tests.
110 func GetMySQlLock(t *testing.T, conf *database.DatabaseConfig) *database.Version edDB { 62 func GetMySQlLock(t *testing.T, conf *database.DatabaseConfig) *database.Version edDB {
111 vdb := database.NewVersionedDB(conf) 63 vdb := database.NewVersionedDB(conf)
112 _, err := vdb.DB.Exec("SELECT GET_LOCK(?,30)", SQL_LOCK) 64 _, err := vdb.DB.Exec("SELECT GET_LOCK(?,30)", SQL_LOCK)
113 assert.Nil(t, err) 65 assert.Nil(t, err)
114 return vdb 66 return vdb
115 } 67 }
116 68
117 // Release the MySQL lock. 69 // Release the MySQL lock.
118 func ReleaseMySQLLock(t *testing.T, vdb *database.VersionedDB) { 70 func ReleaseMySQLLock(t *testing.T, vdb *database.VersionedDB) {
(...skipping 15 matching lines...) Expand all
134 names = append(names, tableName) 86 names = append(names, tableName)
135 } 87 }
136 88
137 if len(names) > 0 { 89 if len(names) > 0 {
138 stmt = "DROP TABLE " + strings.Join(names, ",") 90 stmt = "DROP TABLE " + strings.Join(names, ",")
139 _, err = vdb.DB.Exec(stmt) 91 _, err = vdb.DB.Exec(stmt)
140 assert.Nil(t, err) 92 assert.Nil(t, err)
141 } 93 }
142 } 94 }
143 95
96 type MySQLTestDatabase struct {
97 rootVdb *database.VersionedDB
98 t *testing.T
99 }
100
101 // SetupMySQLTestDatabase prepares the test database for use. Returns a
102 // VersionedDB which must be closed after use.
103 // Example usage:
104 //
105 // db := SetupMySQLTestDatabase(t, migrationSteps)
106 // defer db.Close()
107 // ... Tests here ...
108 func SetupMySQLTestDatabase(t *testing.T, migrationSteps []database.MigrationSte p) *MySQLTestDatabase {
109 conf := database.LocalTestRootDatabaseConfig(migrationSteps)
110 lockVdb := GetMySQlLock(t, conf)
111 rootVdb := database.NewVersionedDB(conf)
112 ClearMySQLTables(t, rootVdb)
113 if err := rootVdb.Close(); err != nil {
114 t.Fatal(err)
115 }
116 rootVdb = database.NewVersionedDB(conf)
117 if err := rootVdb.Migrate(rootVdb.MaxDBVersion()); err != nil {
118 t.Fatal(err)
119 }
120 if err := rootVdb.Close(); err != nil {
121 t.Fatal(err)
122 }
123 return &MySQLTestDatabase{lockVdb, t}
124 }
125
126 func (d *MySQLTestDatabase) Close() {
127 if err := d.rootVdb.Migrate(0); err != nil {
128 d.t.Fatal(err)
129 }
130 ReleaseMySQLLock(d.t, d.rootVdb)
131 d.rootVdb.Close()
132 }
133
144 // Test wether the migration steps execute correctly. 134 // Test wether the migration steps execute correctly.
145 func testDBVersioning(t *testing.T, vdb *database.VersionedDB) { 135 func testDBVersioning(t *testing.T, vdb *database.VersionedDB) {
146 // get the DB version 136 // get the DB version
147 dbVersion, err := vdb.DBVersion() 137 dbVersion, err := vdb.DBVersion()
148 assert.Nil(t, err) 138 assert.Nil(t, err)
149 maxVersion := vdb.MaxDBVersion() 139 maxVersion := vdb.MaxDBVersion()
150 140
151 // downgrade to 0 141 // downgrade to 0
152 err = vdb.Migrate(0) 142 err = vdb.Migrate(0)
153 assert.Nil(t, err) 143 assert.Nil(t, err)
154 dbVersion, err = vdb.DBVersion() 144 dbVersion, err = vdb.DBVersion()
155 assert.Nil(t, err) 145 assert.Nil(t, err)
156 assert.Equal(t, 0, dbVersion) 146 assert.Equal(t, 0, dbVersion)
157 147
158 // upgrade the the latest version 148 // upgrade the the latest version
159 err = vdb.Migrate(maxVersion) 149 err = vdb.Migrate(maxVersion)
160 assert.Nil(t, err) 150 assert.Nil(t, err)
161 dbVersion, err = vdb.DBVersion() 151 dbVersion, err = vdb.DBVersion()
162 assert.Nil(t, err) 152 assert.Nil(t, err)
163 assert.Equal(t, maxVersion, dbVersion) 153 assert.Equal(t, maxVersion, dbVersion)
164 } 154 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698