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

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: Rebase Created 5 years, 11 months 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"
23
24 // Name of the shared test database.
25 TEST_DB_HOST = "localhost"
26 TEST_DB_PORT = 3306
27 TEST_DB_NAME = "sk_testing"
28
29 // Names of test users. These users should have no password and be
30 // limited to accessing the sk_testing database.
31 USER_ROOT = "test_root"
32 USER_RW = "test_rw"
33
34 // Empty password for testing.
35 TEST_PASSWORD = ""
28 ) 36 )
29 37
30 // Creates an SQLite test database and runs migration tests against it using the 38 // LocalTestDatabaseConfig returns a DatabaseConfig appropriate for local
31 // given migration steps. 39 // testing.
32 func SQLiteVersioningTests(t *testing.T, migrationSteps []database.MigrationStep ) { 40 func LocalTestDatabaseConfig(m []database.MigrationStep) *database.DatabaseConfi g {
33 » // Initialize without argument to test against SQLite3 41 » return database.NewDatabaseConfig(USER_RW, "", TEST_DB_HOST, TEST_DB_POR T, TEST_DB_NAME, m)
34 » conf := &database.DatabaseConfig{ 42 }
35 » » SQLiteFilePath: SQLITE_DB_PATH,
36 » » MigrationSteps: migrationSteps,
37 » }
38 43
39 » vdb := database.NewVersionedDB(conf) 44 // LocalTestRootDatabaseConfig returns a DatabaseConfig appropriate for local
40 » assert.False(t, vdb.IsMySQL) 45 // testing, with root access.
41 » testDBVersioning(t, vdb) 46 func LocalTestRootDatabaseConfig(m []database.MigrationStep) *database.DatabaseC onfig {
47 » return database.NewDatabaseConfig(USER_ROOT, "", TEST_DB_HOST, TEST_DB_P ORT, TEST_DB_NAME, m)
42 } 48 }
43 49
44 // Creates an MySQL test database and runs migration tests against it using the 50 // Creates an MySQL test database and runs migration tests against it using the
45 // given migration steps. See Get for required credentials. 51 // given migration steps. See Get for required credentials.
46 // The test assumes that the database is empty and that the readwrite user is 52 // The test assumes that the database is empty and that the readwrite user is
47 // not allowed to create/drop/alter tables. 53 // not allowed to create/drop/alter tables.
48 func MySQLVersioningTests(t *testing.T, dbName string, migrationSteps []database .MigrationStep) { 54 func MySQLVersioningTests(t *testing.T, dbName string, migrationSteps []database .MigrationStep) {
49 // OpenDB as root user and remove all tables. 55 // OpenDB as root user and remove all tables.
50 » rootConf := &database.DatabaseConfig{ 56 » rootConf := LocalTestRootDatabaseConfig(migrationSteps)
51 » » MySQLString: GetTestMySQLConnStr(t, "root", dbName),
52 » » MigrationSteps: migrationSteps,
53 » }
54 lockVdb := GetMySQlLock(t, rootConf) 57 lockVdb := GetMySQlLock(t, rootConf)
55 defer func() { 58 defer func() {
56 ReleaseMySQLLock(t, lockVdb) 59 ReleaseMySQLLock(t, lockVdb)
57 lockVdb.Close() 60 lockVdb.Close()
58 }() 61 }()
59 62
60 rootVdb := database.NewVersionedDB(rootConf) 63 rootVdb := database.NewVersionedDB(rootConf)
61 assert.True(t, rootVdb.IsMySQL)
62 ClearMySQLTables(t, rootVdb) 64 ClearMySQLTables(t, rootVdb)
63 assert.Nil(t, rootVdb.Close()) 65 assert.Nil(t, rootVdb.Close())
64 66
65 // Configuration for the readwrite user without DDL privileges. 67 // Configuration for the readwrite user without DDL privileges.
66 » readWriteConf := &database.DatabaseConfig{ 68 » readWriteConf := LocalTestDatabaseConfig(migrationSteps)
67 » » MySQLString: GetTestMySQLConnStr(t, "readwrite", dbName),
68 » » MigrationSteps: migrationSteps,
69 » }
70 69
71 // Open DB as readwrite user and make sure it fails because of a missing 70 // Open DB as readwrite user and make sure it fails because of a missing
72 // version table. 71 // version table.
73 // Note: This requires the database to be empty. 72 // Note: This requires the database to be empty.
74 assert.Panics(t, func() { 73 assert.Panics(t, func() {
75 database.NewVersionedDB(readWriteConf) 74 database.NewVersionedDB(readWriteConf)
76 }) 75 })
77 76
78 rootVdb = database.NewVersionedDB(rootConf) 77 rootVdb = database.NewVersionedDB(rootConf)
79 testDBVersioning(t, rootVdb) 78 testDBVersioning(t, rootVdb)
80 79
81 // Make sure it doesn't panic for readwrite user after the migration 80 // Make sure it doesn't panic for readwrite user after the migration
82 assert.NotPanics(t, func() { 81 assert.NotPanics(t, func() {
83 database.NewVersionedDB(readWriteConf) 82 database.NewVersionedDB(readWriteConf)
84 }) 83 })
85 } 84 }
86 85
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. 86 // Get a lock from MySQL to serialize DB tests.
110 func GetMySQlLock(t *testing.T, conf *database.DatabaseConfig) *database.Version edDB { 87 func GetMySQlLock(t *testing.T, conf *database.DatabaseConfig) *database.Version edDB {
111 vdb := database.NewVersionedDB(conf) 88 vdb := database.NewVersionedDB(conf)
112 _, err := vdb.DB.Exec("SELECT GET_LOCK(?,30)", SQL_LOCK) 89 _, err := vdb.DB.Exec("SELECT GET_LOCK(?,30)", SQL_LOCK)
113 assert.Nil(t, err) 90 assert.Nil(t, err)
114 return vdb 91 return vdb
115 } 92 }
116 93
117 // Release the MySQL lock. 94 // Release the MySQL lock.
118 func ReleaseMySQLLock(t *testing.T, vdb *database.VersionedDB) { 95 func ReleaseMySQLLock(t *testing.T, vdb *database.VersionedDB) {
(...skipping 15 matching lines...) Expand all
134 names = append(names, tableName) 111 names = append(names, tableName)
135 } 112 }
136 113
137 if len(names) > 0 { 114 if len(names) > 0 {
138 stmt = "DROP TABLE " + strings.Join(names, ",") 115 stmt = "DROP TABLE " + strings.Join(names, ",")
139 _, err = vdb.DB.Exec(stmt) 116 _, err = vdb.DB.Exec(stmt)
140 assert.Nil(t, err) 117 assert.Nil(t, err)
141 } 118 }
142 } 119 }
143 120
121 // MySQLTestDatabase is a convenience struct for using a test database which
122 // starts in a clean state.
123 type MySQLTestDatabase struct {
124 rootVdb *database.VersionedDB
125 t *testing.T
126 }
127
128 // SetupMySQLTestDatabase returns a MySQLTestDatabase in a clean state. It must
129 // be closed after use.
130 //
131 // Example usage:
132 //
133 // db := SetupMySQLTestDatabase(t, migrationSteps)
134 // defer db.Close()
135 // ... Tests here ...
136 func SetupMySQLTestDatabase(t *testing.T, migrationSteps []database.MigrationSte p) *MySQLTestDatabase {
137 conf := LocalTestRootDatabaseConfig(migrationSteps)
138 lockVdb := GetMySQlLock(t, conf)
139 rootVdb := database.NewVersionedDB(conf)
140 ClearMySQLTables(t, rootVdb)
141 if err := rootVdb.Close(); err != nil {
142 t.Fatal(err)
143 }
144 rootVdb = database.NewVersionedDB(conf)
145 if err := rootVdb.Migrate(rootVdb.MaxDBVersion()); err != nil {
146 t.Fatal(err)
147 }
148 if err := rootVdb.Close(); err != nil {
149 t.Fatal(err)
150 }
151 return &MySQLTestDatabase{lockVdb, t}
152 }
153
154 func (d *MySQLTestDatabase) Close() {
155 if err := d.rootVdb.Migrate(0); err != nil {
156 d.t.Fatal(err)
157 }
158 ReleaseMySQLLock(d.t, d.rootVdb)
159 d.rootVdb.Close()
160 }
161
144 // Test wether the migration steps execute correctly. 162 // Test wether the migration steps execute correctly.
145 func testDBVersioning(t *testing.T, vdb *database.VersionedDB) { 163 func testDBVersioning(t *testing.T, vdb *database.VersionedDB) {
146 // get the DB version 164 // get the DB version
147 dbVersion, err := vdb.DBVersion() 165 dbVersion, err := vdb.DBVersion()
148 assert.Nil(t, err) 166 assert.Nil(t, err)
149 maxVersion := vdb.MaxDBVersion() 167 maxVersion := vdb.MaxDBVersion()
150 168
151 // downgrade to 0 169 // downgrade to 0
152 err = vdb.Migrate(0) 170 err = vdb.Migrate(0)
153 assert.Nil(t, err) 171 assert.Nil(t, err)
154 dbVersion, err = vdb.DBVersion() 172 dbVersion, err = vdb.DBVersion()
155 assert.Nil(t, err) 173 assert.Nil(t, err)
156 assert.Equal(t, 0, dbVersion) 174 assert.Equal(t, 0, dbVersion)
157 175
158 // upgrade the the latest version 176 // upgrade the the latest version
159 err = vdb.Migrate(maxVersion) 177 err = vdb.Migrate(maxVersion)
160 assert.Nil(t, err) 178 assert.Nil(t, err)
161 dbVersion, err = vdb.DBVersion() 179 dbVersion, err = vdb.DBVersion()
162 assert.Nil(t, err) 180 assert.Nil(t, err)
163 assert.Equal(t, maxVersion, dbVersion) 181 assert.Equal(t, maxVersion, dbVersion)
164 } 182 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698