github.com/rjgonzale/pop/v5@v5.1.3-dev/dialect_mysql_test.go (about) 1 package pop 2 3 import ( 4 "io/ioutil" 5 "os" 6 "strings" 7 "testing" 8 9 "github.com/gobuffalo/fizz" 10 "github.com/gobuffalo/fizz/translators" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func Test_MySQL_URL_As_Is(t *testing.T) { 15 r := require.New(t) 16 17 cd := &ConnectionDetails{ 18 URL: "mysql://user:pass@(host:port)/dbase?opt=value", 19 } 20 err := cd.Finalize() 21 r.NoError(err) 22 23 m := &mysql{commonDialect{ConnectionDetails: cd}} 24 r.Equal("user:pass@(host:port)/dbase?opt=value", m.URL()) 25 r.Equal("user:pass@(host:port)/?opt=value", m.urlWithoutDb()) 26 r.Equal("user:pass@(host:port)/dbase?opt=value", m.MigrationURL()) 27 } 28 29 func Test_MySQL_URL_Override_withURL(t *testing.T) { 30 r := require.New(t) 31 32 cd := &ConnectionDetails{ 33 Database: "xx", 34 Host: "xx", 35 Port: "xx", 36 User: "xx", 37 Password: "xx", 38 URL: "mysql://user:pass@(host:port)/dbase?opt=value", 39 } 40 err := cd.Finalize() 41 r.NoError(err) 42 43 m := &mysql{commonDialect{ConnectionDetails: cd}} 44 r.Equal("user:pass@(host:port)/dbase?opt=value", m.URL()) 45 r.Equal("user:pass@(host:port)/?opt=value", m.urlWithoutDb()) 46 r.Equal("user:pass@(host:port)/dbase?opt=value", m.MigrationURL()) 47 } 48 49 func Test_MySQL_URL_With_Values(t *testing.T) { 50 r := require.New(t) 51 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{ 52 Database: "dbase", 53 Host: "host", 54 Port: "port", 55 User: "user", 56 Password: "pass", 57 Options: map[string]string{"opt": "value"}, 58 }}} 59 r.Equal("user:pass@(host:port)/dbase?opt=value", m.URL()) 60 r.Equal("user:pass@(host:port)/?opt=value", m.urlWithoutDb()) 61 r.Equal("user:pass@(host:port)/dbase?opt=value", m.MigrationURL()) 62 } 63 64 func Test_MySQL_URL_Without_User(t *testing.T) { 65 r := require.New(t) 66 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{ 67 Password: "pass", 68 Database: "dbase", 69 }}} 70 // finalizerMySQL fills address part in real world. 71 // without user, password cannot live alone 72 r.Equal("(:)/dbase?", m.URL()) 73 } 74 75 func Test_MySQL_URL_Without_Password(t *testing.T) { 76 r := require.New(t) 77 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{ 78 User: "user", 79 Database: "dbase", 80 }}} 81 // finalizerMySQL fills address part in real world. 82 r.Equal("user@(:)/dbase?", m.URL()) 83 } 84 85 func Test_MySQL_URL_urlParserMySQL_Standard(t *testing.T) { 86 r := require.New(t) 87 cd := &ConnectionDetails{ 88 URL: "mysql://user:pass@(host:port)/database?collation=utf8¶m2=value2", 89 } 90 err := urlParserMySQL(cd) 91 r.NoError(err) 92 r.Equal("user", cd.User) 93 r.Equal("pass", cd.Password) 94 r.Equal("host", cd.Host) 95 r.Equal("port", cd.Port) 96 r.Equal("database", cd.Database) 97 // only collation is stored as options by urlParserMySQL() 98 r.Equal("utf8", cd.Options["collation"]) 99 r.Equal("", cd.Options["param2"]) 100 } 101 102 func Test_MySQL_URL_urlParserMySQL_With_Protocol(t *testing.T) { 103 r := require.New(t) 104 cd := &ConnectionDetails{ 105 URL: "user:pass@tcp(host:port)/dbase", 106 } 107 err := urlParserMySQL(cd) 108 r.NoError(err) 109 r.Equal("user", cd.User) 110 r.Equal("pass", cd.Password) 111 r.Equal("host", cd.Host) 112 r.Equal("port", cd.Port) 113 r.Equal("dbase", cd.Database) 114 } 115 116 func Test_MySQL_URL_urlParserMySQL_Socket(t *testing.T) { 117 r := require.New(t) 118 cd := &ConnectionDetails{ 119 URL: "unix(/tmp/socket)/dbase", 120 } 121 err := urlParserMySQL(cd) 122 r.NoError(err) 123 r.Equal("/tmp/socket", cd.Host) 124 r.Equal("socket", cd.Port) 125 126 // additional test without URL 127 cd.URL = "" 128 m := &mysql{commonDialect{ConnectionDetails: cd}} 129 r.True(strings.HasPrefix(m.URL(), "unix(/tmp/socket)/dbase?")) 130 r.True(strings.HasPrefix(m.urlWithoutDb(), "unix(/tmp/socket)/?")) 131 } 132 133 func Test_MySQL_URL_urlParserMySQL_Unsupported(t *testing.T) { 134 r := require.New(t) 135 cd := &ConnectionDetails{ 136 URL: "mysql://user:pass@host:port/dbase?opt=value", 137 } 138 err := urlParserMySQL(cd) 139 r.Error(err) 140 } 141 142 func Test_MySQL_Database_Open_Failure(t *testing.T) { 143 r := require.New(t) 144 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{}}} 145 err := m.CreateDB() 146 r.Error(err) 147 err = m.DropDB() 148 r.Error(err) 149 } 150 151 func Test_MySQL_FizzTranslator(t *testing.T) { 152 r := require.New(t) 153 cd := &ConnectionDetails{} 154 m := &mysql{commonDialect{ConnectionDetails: cd}} 155 ft := m.FizzTranslator() 156 r.IsType(&translators.MySQL{}, ft) 157 r.Implements((*fizz.Translator)(nil), ft) 158 } 159 160 func Test_MySQL_Finalizer_Default_CD(t *testing.T) { 161 r := require.New(t) 162 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{}}} 163 finalizerMySQL(m.ConnectionDetails) 164 r.Equal(hostMySQL, m.ConnectionDetails.Host) 165 r.Equal(portMySQL, m.ConnectionDetails.Port) 166 } 167 168 func Test_MySQL_Finalizer_Default_Options(t *testing.T) { 169 r := require.New(t) 170 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{}}} 171 finalizerMySQL(m.ConnectionDetails) 172 r.Contains(m.URL(), "multiStatements=true") 173 r.Contains(m.URL(), "parseTime=true") 174 r.Contains(m.URL(), "readTimeout=3s") 175 r.Contains(m.URL(), "collation=utf8mb4_general_ci") 176 } 177 178 func Test_MySQL_Finalizer_Preserve_User_Defined_Options(t *testing.T) { 179 r := require.New(t) 180 m := &mysql{commonDialect{ConnectionDetails: &ConnectionDetails{ 181 Options: map[string]string{ 182 "multiStatements": "false", 183 "parseTime": "false", 184 "readTimeout": "1h", 185 "collation": "utf8", 186 }, 187 }}} 188 finalizerMySQL(m.ConnectionDetails) 189 r.Contains(m.URL(), "multiStatements=false") 190 r.Contains(m.URL(), "parseTime=false") 191 r.Contains(m.URL(), "readTimeout=1h") 192 r.Contains(m.URL(), "collation=utf8") 193 } 194 195 func (s *MySQLSuite) Test_MySQL_DDL_Operations() { 196 r := s.Require() 197 198 origDatabase := PDB.Dialect.Details().Database 199 PDB.Dialect.Details().Database = "pop_test_mysql_extra" 200 defer func() { 201 PDB.Dialect.Details().Database = origDatabase 202 }() 203 204 PDB.Dialect.DropDB() // clean up 205 err := PDB.Dialect.CreateDB() 206 r.NoError(err) 207 err = PDB.Dialect.CreateDB() 208 r.Error(err) 209 err = PDB.Dialect.DropDB() 210 r.NoError(err) 211 err = PDB.Dialect.DropDB() 212 r.Error(err) 213 } 214 215 func (s *MySQLSuite) Test_MySQL_DDL_Schema() { 216 r := s.Require() 217 218 f, err := ioutil.TempFile(os.TempDir(), "pop_test_mysql_dump") 219 r.NoError(err) 220 defer func() { 221 f.Close() 222 os.Remove(f.Name()) 223 }() 224 225 // do it against "pop_test" 226 err = PDB.Dialect.DumpSchema(f) 227 r.NoError(err) 228 _, err = f.Seek(0, 0) 229 r.NoError(err) 230 err = PDB.Dialect.LoadSchema(f) 231 r.NoError(err) 232 233 origDatabase := PDB.Dialect.Details().Database 234 PDB.Dialect.Details().Database = "pop_test_not_exist" 235 defer func() { 236 PDB.Dialect.Details().Database = origDatabase 237 }() 238 239 // do it against "pop_test_not_exist" 240 _, err = f.Seek(0, 0) 241 r.NoError(err) 242 err = PDB.Dialect.LoadSchema(f) 243 r.Error(err) 244 err = PDB.Dialect.DumpSchema(f) 245 r.Error(err) 246 }