@@ -11,7 +11,9 @@ package mysql
1111import (
1212 "crypto/tls"
1313 "fmt"
14+ "log"
1415 "net/url"
16+ "os"
1517 "reflect"
1618 "testing"
1719 "time"
@@ -33,14 +35,14 @@ var testDSNs = []struct {
3335 "user@unix(/path/to/socket)/dbname?charset=utf8" ,
3436 & Config {User : "user" , Net : "unix" , Addr : "/path/to/socket" , DBName : "dbname" , Params : map [string ]string {"charset" : "utf8" }, Collation : "utf8mb4_general_ci" , Loc : time .UTC , MaxAllowedPacket : defaultMaxAllowedPacket , AllowNativePasswords : true , CheckConnLiveness : true },
3537}, {
36- "user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true" ,
37- & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "localhost:5555" , DBName : "dbname" , Params : map [string ]string {"charset" : "utf8" }, Collation : "utf8mb4_general_ci" , Loc : time .UTC , MaxAllowedPacket : defaultMaxAllowedPacket , AllowNativePasswords : true , CheckConnLiveness : true , TLSConfig : "true" },
38+ "user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true&logging=false " ,
39+ & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "localhost:5555" , DBName : "dbname" , Params : map [string ]string {"charset" : "utf8" }, Collation : "utf8mb4_general_ci" , Loc : time .UTC , MaxAllowedPacket : defaultMaxAllowedPacket , AllowNativePasswords : true , CheckConnLiveness : true , TLSConfig : "true" , LoggingConfig : "false" },
3840}, {
39- "user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify" ,
40- & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "localhost:5555" , DBName : "dbname" , Params : map [string ]string {"charset" : "utf8mb4,utf8" }, Collation : "utf8mb4_general_ci" , Loc : time .UTC , MaxAllowedPacket : defaultMaxAllowedPacket , AllowNativePasswords : true , CheckConnLiveness : true , TLSConfig : "skip-verify" },
41+ "user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify&logging=testLogger " ,
42+ & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "localhost:5555" , DBName : "dbname" , Params : map [string ]string {"charset" : "utf8mb4,utf8" }, Collation : "utf8mb4_general_ci" , Loc : time .UTC , MaxAllowedPacket : defaultMaxAllowedPacket , AllowNativePasswords : true , CheckConnLiveness : true , TLSConfig : "skip-verify" , LoggingConfig : "testLogger" },
4143}, {
42- "user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci&maxAllowedPacket=16777216&tls=false&allowCleartextPasswords=true&parseTime=true&rejectReadOnly=true" ,
43- & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "127.0.0.1:3306" , DBName : "dbname" , Collation : "utf8mb4_unicode_ci" , Loc : time .UTC , TLSConfig : "false" , AllowCleartextPasswords : true , AllowNativePasswords : true , Timeout : 30 * time .Second , ReadTimeout : time .Second , WriteTimeout : time .Second , AllowAllFiles : true , AllowOldPasswords : true , CheckConnLiveness : true , ClientFoundRows : true , MaxAllowedPacket : 16777216 , ParseTime : true , RejectReadOnly : true },
44+ "user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci&maxAllowedPacket=16777216&tls=false&allowCleartextPasswords=true&parseTime=true&rejectReadOnly=true&logging=true " ,
45+ & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "127.0.0.1:3306" , DBName : "dbname" , Collation : "utf8mb4_unicode_ci" , Loc : time .UTC , TLSConfig : "false" , AllowCleartextPasswords : true , AllowNativePasswords : true , Timeout : 30 * time .Second , ReadTimeout : time .Second , WriteTimeout : time .Second , LoggingConfig : "true" , AllowAllFiles : true , AllowOldPasswords : true , CheckConnLiveness : true , ClientFoundRows : true , MaxAllowedPacket : 16777216 , ParseTime : true , RejectReadOnly : true },
4446}, {
4547 "user:password@/dbname?allowNativePasswords=false&checkConnLiveness=false&maxAllowedPacket=0&allowFallbackToPlaintext=true" ,
4648 & Config {User : "user" , Passwd : "password" , Net : "tcp" , Addr : "127.0.0.1:3306" , DBName : "dbname" , Collation : "utf8mb4_general_ci" , Loc : time .UTC , MaxAllowedPacket : 0 , AllowFallbackToPlaintext : true , AllowNativePasswords : false , CheckConnLiveness : false },
@@ -75,6 +77,10 @@ var testDSNs = []struct {
7577}
7678
7779func TestDSNParser (t * testing.T ) {
80+ logger := log .New (os .Stderr , "" , log .LstdFlags )
81+ RegisterLogger ("testLogger" , logger )
82+ defer DeregisterLogger ("testLogger" )
83+
7884 for i , tst := range testDSNs {
7985 cfg , err := ParseDSN (tst .in )
8086 if err != nil {
@@ -83,6 +89,7 @@ func TestDSNParser(t *testing.T) {
8389
8490 // pointer not static
8591 cfg .TLS = nil
92+ cfg .Logger = nil
8693
8794 if ! reflect .DeepEqual (cfg , tst .out ) {
8895 t .Errorf ("%d. ParseDSN(%q) mismatch:\n got %+v\n want %+v" , i , tst .in , cfg , tst .out )
@@ -112,6 +119,10 @@ func TestDSNParserInvalid(t *testing.T) {
112119}
113120
114121func TestDSNReformat (t * testing.T ) {
122+ logger := log .New (os .Stderr , "" , log .LstdFlags )
123+ RegisterLogger ("testLogger" , logger )
124+ defer DeregisterLogger ("testLogger" )
125+
115126 for i , tst := range testDSNs {
116127 dsn1 := tst .in
117128 cfg1 , err := ParseDSN (dsn1 )
@@ -268,6 +279,93 @@ func TestDSNWithCustomTLSQueryEscape(t *testing.T) {
268279 }
269280}
270281
282+ func TestDSNWithCustomLogger (t * testing.T ) {
283+ baseDSN := "User:password@tcp(localhost:5555)/dbname?logging="
284+
285+ t .Run ("custom logger is registered" , func (tt * testing.T ) {
286+ logger := log .New (os .Stderr , "" , log .LstdFlags )
287+
288+ RegisterLogger ("testKey" , logger )
289+ defer DeregisterLogger ("testKey" )
290+
291+ tst := baseDSN + "testKey"
292+
293+ cfg , err := ParseDSN (tst )
294+ if err != nil {
295+ tt .Fatal (err .Error ())
296+ }
297+
298+ if cfg .LoggingConfig != "testKey" {
299+ tt .Errorf ("unexpected cfg.LoggingConfig value: %q" , cfg .LoggingConfig )
300+ }
301+ if cfg .Logger != logger {
302+ tt .Error ("logger pointer doesn't match" )
303+ }
304+ })
305+
306+ t .Run ("custom logger is missing" , func (tt * testing.T ) {
307+ tst := baseDSN + "invalid_name"
308+
309+ cfg , err := ParseDSN (tst )
310+ if err == nil {
311+ tt .Errorf ("invalid name in DSN (%s) but did not error. Got config: %#v" , tst , cfg )
312+ }
313+ })
314+ }
315+
316+ func TestDSNLoggingConfig (t * testing.T ) {
317+ t .Run ("logging=true" , func (tt * testing.T ) {
318+ dsn := "User:password@tcp(localhost:5555)/dbname?logging=true"
319+
320+ cfg , err := ParseDSN (dsn )
321+ if err != nil {
322+ tt .Fatal (err .Error ())
323+ }
324+
325+ if cfg .LoggingConfig != "true" {
326+ tt .Errorf ("unexpected cfg.LoggingConfig value: %q" , cfg .LoggingConfig )
327+ }
328+ if cfg .Logger != nil {
329+ tt .Error ("cfg.Logger should be nil" )
330+ }
331+ })
332+
333+ t .Run ("logging=false" , func (tt * testing.T ) {
334+ dsn := "User:password@tcp(localhost:5555)/dbname?logging=false"
335+
336+ cfg , err := ParseDSN (dsn )
337+ if err != nil {
338+ tt .Fatal (err .Error ())
339+ }
340+
341+ if cfg .LoggingConfig != "false" {
342+ tt .Errorf ("unexpected cfg.LoggingConfig value: %q" , cfg .LoggingConfig )
343+ }
344+ if cfg .Logger != defaultNopLogger {
345+ tt .Error ("logger pointer doesn't match" )
346+ }
347+ })
348+ }
349+
350+ func TestDSNWithCustomLoggerQueryEscape (t * testing.T ) {
351+ const name = "&%!:"
352+ dsn := "User:password@tcp(localhost:5555)/dbname?logging=" + url .QueryEscape (name )
353+
354+ logger := log .New (os .Stderr , "" , log .LstdFlags )
355+
356+ RegisterLogger (name , logger )
357+ defer DeregisterTLSConfig (name )
358+
359+ cfg , err := ParseDSN (dsn )
360+ if err != nil {
361+ t .Fatal (err .Error ())
362+ }
363+
364+ if cfg .Logger != logger {
365+ t .Error ("logger pointer doesn't match" )
366+ }
367+ }
368+
271369func TestDSNUnsafeCollation (t * testing.T ) {
272370 _ , err := ParseDSN ("/dbname?collation=gbk_chinese_ci&interpolateParams=true" )
273371 if err != errInvalidDSNUnsafeCollation {
0 commit comments