github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-sql-driver/mysql/dsn_test.go (about) 1 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 // 3 // Copyright 2016 The Go-MySQL-Driver Authors. All rights reserved. 4 // 5 // This Source Code Form is subject to the terms of the Mozilla Public 6 // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 // You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 package mysql 10 11 import ( 12 "crypto/tls" 13 "fmt" 14 "net/url" 15 "testing" 16 ) 17 18 var testDSNs = []struct { 19 in string 20 out string 21 }{ 22 {"username:password@protocol(address)/dbname?param=value", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 23 {"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:true InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 24 {"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true&multiStatements=true", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:true InterpolateParams:false MultiStatements:true ParseTime:false Strict:false}"}, 25 {"user@unix(/path/to/socket)/dbname?charset=utf8", "&{User:user Passwd: Net:unix Addr:/path/to/socket DBName:dbname Params:map[charset:utf8] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 26 {"user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", "&{User:user Passwd:password Net:tcp Addr:localhost:5555 DBName:dbname Params:map[charset:utf8] Collation:utf8_general_ci Loc:UTC TLSConfig:true tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 27 {"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", "&{User:user Passwd:password Net:tcp Addr:localhost:5555 DBName:dbname Params:map[charset:utf8mb4,utf8] Collation:utf8_general_ci Loc:UTC TLSConfig:skip-verify tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 28 {"user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{User:user Passwd:password Net:tcp Addr:127.0.0.1:3306 DBName:dbname Params:map[] Collation:utf8mb4_unicode_ci Loc:UTC TLSConfig: tls:<nil> Timeout:30s ReadTimeout:1s WriteTimeout:1s AllowAllFiles:true AllowCleartextPasswords:false AllowOldPasswords:true ClientFoundRows:true ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 29 {"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", "&{User:user Passwd:p@ss(word) Net:tcp Addr:[de:ad:be:ef::ca:fe]:80 DBName:dbname Params:map[] Collation:utf8_general_ci Loc:Local TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 30 {"/dbname", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName:dbname Params:map[] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 31 {"@/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 32 {"/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 33 {"", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 34 {"user:p@/ssword@/", "&{User:user Passwd:p@/ssword Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 35 {"unix/?arg=%2Fsome%2Fpath.ext", "&{User: Passwd: Net:unix Addr:/tmp/mysql.sock DBName: Params:map[arg:/some/path.ext] Collation:utf8_general_ci Loc:UTC TLSConfig: tls:<nil> Timeout:0 ReadTimeout:0 WriteTimeout:0 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false MultiStatements:false ParseTime:false Strict:false}"}, 36 } 37 38 func TestDSNParser(t *testing.T) { 39 var cfg *Config 40 var err error 41 var res string 42 43 for i, tst := range testDSNs { 44 cfg, err = ParseDSN(tst.in) 45 if err != nil { 46 t.Error(err.Error()) 47 } 48 49 // pointer not static 50 cfg.tls = nil 51 52 res = fmt.Sprintf("%+v", cfg) 53 if res != tst.out { 54 t.Errorf("%d. ParseDSN(%q) => %q, want %q", i, tst.in, res, tst.out) 55 } 56 } 57 } 58 59 func TestDSNParserInvalid(t *testing.T) { 60 var invalidDSNs = []string{ 61 "@net(addr/", // no closing brace 62 "@tcp(/", // no closing brace 63 "tcp(/", // no closing brace 64 "(/", // no closing brace 65 "net(addr)//", // unescaped 66 "User:pass@tcp(1.2.3.4:3306)", // no trailing slash 67 //"/dbname?arg=/some/unescaped/path", 68 } 69 70 for i, tst := range invalidDSNs { 71 if _, err := ParseDSN(tst); err == nil { 72 t.Errorf("invalid DSN #%d. (%s) didn't error!", i, tst) 73 } 74 } 75 } 76 77 func TestDSNReformat(t *testing.T) { 78 for i, tst := range testDSNs { 79 dsn1 := tst.in 80 cfg1, err := ParseDSN(dsn1) 81 if err != nil { 82 t.Error(err.Error()) 83 continue 84 } 85 cfg1.tls = nil // pointer not static 86 res1 := fmt.Sprintf("%+v", cfg1) 87 88 dsn2 := cfg1.FormatDSN() 89 cfg2, err := ParseDSN(dsn2) 90 if err != nil { 91 t.Error(err.Error()) 92 continue 93 } 94 cfg2.tls = nil // pointer not static 95 res2 := fmt.Sprintf("%+v", cfg2) 96 97 if res1 != res2 { 98 t.Errorf("%d. %q does not match %q", i, res2, res1) 99 } 100 } 101 } 102 103 func TestDSNWithCustomTLS(t *testing.T) { 104 baseDSN := "User:password@tcp(localhost:5555)/dbname?tls=" 105 tlsCfg := tls.Config{} 106 107 RegisterTLSConfig("utils_test", &tlsCfg) 108 109 // Custom TLS is missing 110 tst := baseDSN + "invalid_tls" 111 cfg, err := ParseDSN(tst) 112 if err == nil { 113 t.Errorf("invalid custom TLS in DSN (%s) but did not error. Got config: %#v", tst, cfg) 114 } 115 116 tst = baseDSN + "utils_test" 117 118 // Custom TLS with a server name 119 name := "foohost" 120 tlsCfg.ServerName = name 121 cfg, err = ParseDSN(tst) 122 123 if err != nil { 124 t.Error(err.Error()) 125 } else if cfg.tls.ServerName != name { 126 t.Errorf("did not get the correct TLS ServerName (%s) parsing DSN (%s).", name, tst) 127 } 128 129 // Custom TLS without a server name 130 name = "localhost" 131 tlsCfg.ServerName = "" 132 cfg, err = ParseDSN(tst) 133 134 if err != nil { 135 t.Error(err.Error()) 136 } else if cfg.tls.ServerName != name { 137 t.Errorf("did not get the correct ServerName (%s) parsing DSN (%s).", name, tst) 138 } 139 140 DeregisterTLSConfig("utils_test") 141 } 142 143 func TestDSNWithCustomTLSQueryEscape(t *testing.T) { 144 const configKey = "&%!:" 145 dsn := "User:password@tcp(localhost:5555)/dbname?tls=" + url.QueryEscape(configKey) 146 name := "foohost" 147 tlsCfg := tls.Config{ServerName: name} 148 149 RegisterTLSConfig(configKey, &tlsCfg) 150 151 cfg, err := ParseDSN(dsn) 152 153 if err != nil { 154 t.Error(err.Error()) 155 } else if cfg.tls.ServerName != name { 156 t.Errorf("did not get the correct TLS ServerName (%s) parsing DSN (%s).", name, dsn) 157 } 158 } 159 160 func TestDSNUnsafeCollation(t *testing.T) { 161 _, err := ParseDSN("/dbname?collation=gbk_chinese_ci&interpolateParams=true") 162 if err != errInvalidDSNUnsafeCollation { 163 t.Errorf("expected %v, got %v", errInvalidDSNUnsafeCollation, err) 164 } 165 166 _, err = ParseDSN("/dbname?collation=gbk_chinese_ci&interpolateParams=false") 167 if err != nil { 168 t.Errorf("expected %v, got %v", nil, err) 169 } 170 171 _, err = ParseDSN("/dbname?collation=gbk_chinese_ci") 172 if err != nil { 173 t.Errorf("expected %v, got %v", nil, err) 174 } 175 176 _, err = ParseDSN("/dbname?collation=ascii_bin&interpolateParams=true") 177 if err != nil { 178 t.Errorf("expected %v, got %v", nil, err) 179 } 180 181 _, err = ParseDSN("/dbname?collation=latin1_german1_ci&interpolateParams=true") 182 if err != nil { 183 t.Errorf("expected %v, got %v", nil, err) 184 } 185 186 _, err = ParseDSN("/dbname?collation=utf8_general_ci&interpolateParams=true") 187 if err != nil { 188 t.Errorf("expected %v, got %v", nil, err) 189 } 190 191 _, err = ParseDSN("/dbname?collation=utf8mb4_general_ci&interpolateParams=true") 192 if err != nil { 193 t.Errorf("expected %v, got %v", nil, err) 194 } 195 } 196 197 func BenchmarkParseDSN(b *testing.B) { 198 b.ReportAllocs() 199 200 for i := 0; i < b.N; i++ { 201 for _, tst := range testDSNs { 202 if _, err := ParseDSN(tst.in); err != nil { 203 b.Error(err.Error()) 204 } 205 } 206 } 207 }