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  }