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

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: Comments/readme cleanup 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"
23
24 // Name of the shared test database.
25 TEST_DB = "sk_testing"
28 ) 26 )
29 27
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 28 // Creates an MySQL test database and runs migration tests against it using the
45 // given migration steps. See Get for required credentials. 29 // given migration steps. See Get for required credentials.
46 // The test assumes that the database is empty and that the readwrite user is 30 // The test assumes that the database is empty and that the readwrite user is
47 // not allowed to create/drop/alter tables. 31 // not allowed to create/drop/alter tables.
48 func MySQLVersioningTests(t *testing.T, dbName string, migrationSteps []database .MigrationStep) { 32 func MySQLVersioningTests(t *testing.T, dbName string, migrationSteps []database .MigrationStep) {
49 // OpenDB as root user and remove all tables. 33 // OpenDB as root user and remove all tables.
50 » rootConf := &database.DatabaseConfig{ 34 » rootConf := database.LocalTestRootDatabaseConfig(TEST_DB, migrationSteps )
51 » » MySQLString: GetTestMySQLConnStr(t, "root", dbName),
52 » » MigrationSteps: migrationSteps,
53 » }
54 lockVdb := GetMySQlLock(t, rootConf) 35 lockVdb := GetMySQlLock(t, rootConf)
55 defer func() { 36 defer func() {
56 ReleaseMySQLLock(t, lockVdb) 37 ReleaseMySQLLock(t, lockVdb)
57 lockVdb.Close() 38 lockVdb.Close()
58 }() 39 }()
59 40
60 rootVdb := database.NewVersionedDB(rootConf) 41 rootVdb := database.NewVersionedDB(rootConf)
61 assert.True(t, rootVdb.IsMySQL)
62 ClearMySQLTables(t, rootVdb) 42 ClearMySQLTables(t, rootVdb)
63 assert.Nil(t, rootVdb.Close()) 43 assert.Nil(t, rootVdb.Close())
64 44
65 // Configuration for the readwrite user without DDL privileges. 45 // Configuration for the readwrite user without DDL privileges.
66 » readWriteConf := &database.DatabaseConfig{ 46 » readWriteConf := database.LocalTestDatabaseConfig(TEST_DB, migrationStep s)
67 » » MySQLString: GetTestMySQLConnStr(t, "readwrite", dbName),
68 » » MigrationSteps: migrationSteps,
69 » }
70 47
71 // Open DB as readwrite user and make sure it fails because of a missing 48 // Open DB as readwrite user and make sure it fails because of a missing
72 // version table. 49 // version table.
73 // Note: This requires the database to be empty. 50 // Note: This requires the database to be empty.
74 assert.Panics(t, func() { 51 assert.Panics(t, func() {
75 database.NewVersionedDB(readWriteConf) 52 database.NewVersionedDB(readWriteConf)
76 }) 53 })
77 54
78 rootVdb = database.NewVersionedDB(rootConf) 55 rootVdb = database.NewVersionedDB(rootConf)
79 testDBVersioning(t, rootVdb) 56 testDBVersioning(t, rootVdb)
80 57
81 // Make sure it doesn't panic for readwrite user after the migration 58 // Make sure it doesn't panic for readwrite user after the migration
82 assert.NotPanics(t, func() { 59 assert.NotPanics(t, func() {
83 database.NewVersionedDB(readWriteConf) 60 database.NewVersionedDB(readWriteConf)
84 }) 61 })
85 } 62 }
86 63
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. 64 // Get a lock from MySQL to serialize DB tests.
110 func GetMySQlLock(t *testing.T, conf *database.DatabaseConfig) *database.Version edDB { 65 func GetMySQlLock(t *testing.T, conf *database.DatabaseConfig) *database.Version edDB {
111 vdb := database.NewVersionedDB(conf) 66 vdb := database.NewVersionedDB(conf)
112 _, err := vdb.DB.Exec("SELECT GET_LOCK(?,30)", SQL_LOCK) 67 _, err := vdb.DB.Exec("SELECT GET_LOCK(?,30)", SQL_LOCK)
113 assert.Nil(t, err) 68 assert.Nil(t, err)
114 return vdb 69 return vdb
115 } 70 }
116 71
117 // Release the MySQL lock. 72 // Release the MySQL lock.
118 func ReleaseMySQLLock(t *testing.T, vdb *database.VersionedDB) { 73 func ReleaseMySQLLock(t *testing.T, vdb *database.VersionedDB) {
(...skipping 15 matching lines...) Expand all
134 names = append(names, tableName) 89 names = append(names, tableName)
135 } 90 }
136 91
137 if len(names) > 0 { 92 if len(names) > 0 {
138 stmt = "DROP TABLE " + strings.Join(names, ",") 93 stmt = "DROP TABLE " + strings.Join(names, ",")
139 _, err = vdb.DB.Exec(stmt) 94 _, err = vdb.DB.Exec(stmt)
140 assert.Nil(t, err) 95 assert.Nil(t, err)
141 } 96 }
142 } 97 }
143 98
99 // MySQLTestDatabase is a convenience struct for using a test database which
100 // starts in a clean state.
101 type MySQLTestDatabase struct {
102 rootVdb *database.VersionedDB
103 t *testing.T
104 }
105
106 // SetupMySQLTestDatabase returns a MySQLTestDatabase in a clean state. It must
107 // be closed after use.
108 //
109 // Example usage:
110 //
111 // db := SetupMySQLTestDatabase(t, migrationSteps)
112 // defer db.Close()
113 // ... Tests here ...
114 func SetupMySQLTestDatabase(t *testing.T, migrationSteps []database.MigrationSte p) *MySQLTestDatabase {
115 conf := database.LocalTestRootDatabaseConfig(TEST_DB, migrationSteps)
116 lockVdb := GetMySQlLock(t, conf)
117 rootVdb := database.NewVersionedDB(conf)
118 ClearMySQLTables(t, rootVdb)
119 if err := rootVdb.Close(); err != nil {
120 t.Fatal(err)
121 }
122 rootVdb = database.NewVersionedDB(conf)
123 if err := rootVdb.Migrate(rootVdb.MaxDBVersion()); err != nil {
124 t.Fatal(err)
125 }
126 if err := rootVdb.Close(); err != nil {
127 t.Fatal(err)
128 }
129 return &MySQLTestDatabase{lockVdb, t}
130 }
131
132 func (d *MySQLTestDatabase) Close() {
133 if err := d.rootVdb.Migrate(0); err != nil {
134 d.t.Fatal(err)
135 }
136 ReleaseMySQLLock(d.t, d.rootVdb)
137 d.rootVdb.Close()
138 }
139
144 // Test wether the migration steps execute correctly. 140 // Test wether the migration steps execute correctly.
145 func testDBVersioning(t *testing.T, vdb *database.VersionedDB) { 141 func testDBVersioning(t *testing.T, vdb *database.VersionedDB) {
146 // get the DB version 142 // get the DB version
147 dbVersion, err := vdb.DBVersion() 143 dbVersion, err := vdb.DBVersion()
148 assert.Nil(t, err) 144 assert.Nil(t, err)
149 maxVersion := vdb.MaxDBVersion() 145 maxVersion := vdb.MaxDBVersion()
150 146
151 // downgrade to 0 147 // downgrade to 0
152 err = vdb.Migrate(0) 148 err = vdb.Migrate(0)
153 assert.Nil(t, err) 149 assert.Nil(t, err)
154 dbVersion, err = vdb.DBVersion() 150 dbVersion, err = vdb.DBVersion()
155 assert.Nil(t, err) 151 assert.Nil(t, err)
156 assert.Equal(t, 0, dbVersion) 152 assert.Equal(t, 0, dbVersion)
157 153
158 // upgrade the the latest version 154 // upgrade the the latest version
159 err = vdb.Migrate(maxVersion) 155 err = vdb.Migrate(maxVersion)
160 assert.Nil(t, err) 156 assert.Nil(t, err)
161 dbVersion, err = vdb.DBVersion() 157 dbVersion, err = vdb.DBVersion()
162 assert.Nil(t, err) 158 assert.Nil(t, err)
163 assert.Equal(t, maxVersion, dbVersion) 159 assert.Equal(t, maxVersion, dbVersion)
164 } 160 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698