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