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&param2=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  }