github.com/pupizoid/migrate@v3.5.4+incompatible/database/mysql/mysql_test.go (about) 1 package mysql 2 3 import ( 4 "database/sql" 5 sqldriver "database/sql/driver" 6 "fmt" 7 "net/url" 8 "testing" 9 ) 10 11 import ( 12 "github.com/go-sql-driver/mysql" 13 ) 14 15 import ( 16 dt "github.com/golang-migrate/migrate/database/testing" 17 mt "github.com/golang-migrate/migrate/testing" 18 ) 19 20 var versions = []mt.Version{ 21 {Image: "mysql:8", ENV: []string{"MYSQL_ROOT_PASSWORD=root", "MYSQL_DATABASE=public"}}, 22 {Image: "mysql:5.7", ENV: []string{"MYSQL_ROOT_PASSWORD=root", "MYSQL_DATABASE=public"}}, 23 {Image: "mysql:5.6", ENV: []string{"MYSQL_ROOT_PASSWORD=root", "MYSQL_DATABASE=public"}}, 24 {Image: "mysql:5.5", ENV: []string{"MYSQL_ROOT_PASSWORD=root", "MYSQL_DATABASE=public"}}, 25 } 26 27 func isReady(i mt.Instance) bool { 28 db, err := sql.Open("mysql", fmt.Sprintf("root:root@tcp(%v:%v)/public", i.Host(), i.Port())) 29 if err != nil { 30 return false 31 } 32 defer db.Close() 33 if err = db.Ping(); err != nil { 34 switch err { 35 case sqldriver.ErrBadConn, mysql.ErrInvalidConn: 36 return false 37 default: 38 fmt.Println(err) 39 } 40 return false 41 } 42 43 return true 44 } 45 46 func Test(t *testing.T) { 47 // mysql.SetLogger(mysql.Logger(log.New(ioutil.Discard, "", log.Ltime))) 48 49 mt.ParallelTest(t, versions, isReady, 50 func(t *testing.T, i mt.Instance) { 51 p := &Mysql{} 52 addr := fmt.Sprintf("mysql://root:root@tcp(%v:%v)/public", i.Host(), i.Port()) 53 d, err := p.Open(addr) 54 if err != nil { 55 t.Fatalf("%v", err) 56 } 57 defer d.Close() 58 dt.Test(t, d, []byte("SELECT 1")) 59 60 // check ensureVersionTable 61 if err := d.(*Mysql).ensureVersionTable(); err != nil { 62 t.Fatal(err) 63 } 64 // check again 65 if err := d.(*Mysql).ensureVersionTable(); err != nil { 66 t.Fatal(err) 67 } 68 }) 69 } 70 71 func TestLockWorks(t *testing.T) { 72 mt.ParallelTest(t, versions, isReady, 73 func(t *testing.T, i mt.Instance) { 74 p := &Mysql{} 75 addr := fmt.Sprintf("mysql://root:root@tcp(%v:%v)/public", i.Host(), i.Port()) 76 d, err := p.Open(addr) 77 if err != nil { 78 t.Fatalf("%v", err) 79 } 80 dt.Test(t, d, []byte("SELECT 1")) 81 82 ms := d.(*Mysql) 83 84 err = ms.Lock() 85 if err != nil { 86 t.Fatal(err) 87 } 88 err = ms.Unlock() 89 if err != nil { 90 t.Fatal(err) 91 } 92 93 // make sure the 2nd lock works (RELEASE_LOCK is very finicky) 94 err = ms.Lock() 95 if err != nil { 96 t.Fatal(err) 97 } 98 err = ms.Unlock() 99 if err != nil { 100 t.Fatal(err) 101 } 102 }) 103 } 104 105 func TestURLToMySQLConfig(t *testing.T) { 106 testcases := []struct { 107 name string 108 urlStr string 109 expectedDSN string // empty string signifies that an error is expected 110 }{ 111 {name: "no user/password", urlStr: "mysql://tcp(127.0.0.1:3306)/myDB?multiStatements=true", 112 expectedDSN: "tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 113 {name: "only user", urlStr: "mysql://username@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 114 expectedDSN: "username@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 115 {name: "only user - with encoded :", 116 urlStr: "mysql://username%3A@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 117 expectedDSN: "username:@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 118 {name: "only user - with encoded @", 119 urlStr: "mysql://username%40@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 120 expectedDSN: "username@@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 121 {name: "user/password", urlStr: "mysql://username:password@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 122 expectedDSN: "username:password@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 123 // Not supported yet: https://github.com/go-sql-driver/mysql/issues/591 124 // {name: "user/password - user with encoded :", 125 // urlStr: "mysql://username%3A:password@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 126 // expectedDSN: "username::pasword@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 127 {name: "user/password - user with encoded @", 128 urlStr: "mysql://username%40:password@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 129 expectedDSN: "username@:password@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 130 {name: "user/password - password with encoded :", 131 urlStr: "mysql://username:password%3A@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 132 expectedDSN: "username:password:@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 133 {name: "user/password - password with encoded @", 134 urlStr: "mysql://username:password%40@tcp(127.0.0.1:3306)/myDB?multiStatements=true", 135 expectedDSN: "username:password@@tcp(127.0.0.1:3306)/myDB?multiStatements=true"}, 136 } 137 for _, tc := range testcases { 138 t.Run(tc.name, func(t *testing.T) { 139 u, err := url.Parse(tc.urlStr) 140 if err != nil { 141 t.Fatal("Failed to parse url string:", tc.urlStr, "error:", err) 142 } 143 if config, err := urlToMySQLConfig(*u); err == nil { 144 dsn := config.FormatDSN() 145 if dsn != tc.expectedDSN { 146 t.Error("Got unexpected DSN:", dsn, "!=", tc.expectedDSN) 147 } 148 } else { 149 if tc.expectedDSN != "" { 150 t.Error("Got unexpected error:", err, "urlStr:", tc.urlStr) 151 } 152 } 153 }) 154 } 155 }