driver_go110_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2018 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. // +build go1.10
  9. package mysql
  10. import (
  11. "context"
  12. "database/sql"
  13. "database/sql/driver"
  14. "fmt"
  15. "net"
  16. "testing"
  17. "time"
  18. )
  19. var _ driver.DriverContext = &MySQLDriver{}
  20. type dialCtxKey struct{}
  21. func TestConnectorObeysDialTimeouts(t *testing.T) {
  22. if !available {
  23. t.Skipf("MySQL server not running on %s", netAddr)
  24. }
  25. RegisterDialContext("dialctxtest", func(ctx context.Context, addr string) (net.Conn, error) {
  26. var d net.Dialer
  27. if !ctx.Value(dialCtxKey{}).(bool) {
  28. return nil, fmt.Errorf("test error: query context is not propagated to our dialer")
  29. }
  30. return d.DialContext(ctx, prot, addr)
  31. })
  32. db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@dialctxtest(%s)/%s?timeout=30s", user, pass, addr, dbname))
  33. if err != nil {
  34. t.Fatalf("error connecting: %s", err.Error())
  35. }
  36. defer db.Close()
  37. ctx := context.WithValue(context.Background(), dialCtxKey{}, true)
  38. _, err = db.ExecContext(ctx, "DO 1")
  39. if err != nil {
  40. t.Fatal(err)
  41. }
  42. }
  43. func configForTests(t *testing.T) *Config {
  44. if !available {
  45. t.Skipf("MySQL server not running on %s", netAddr)
  46. }
  47. mycnf := NewConfig()
  48. mycnf.User = user
  49. mycnf.Passwd = pass
  50. mycnf.Addr = addr
  51. mycnf.Net = prot
  52. mycnf.DBName = dbname
  53. return mycnf
  54. }
  55. func TestNewConnector(t *testing.T) {
  56. mycnf := configForTests(t)
  57. conn, err := NewConnector(mycnf)
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. db := sql.OpenDB(conn)
  62. defer db.Close()
  63. if err := db.Ping(); err != nil {
  64. t.Fatal(err)
  65. }
  66. }
  67. type slowConnection struct {
  68. net.Conn
  69. slowdown time.Duration
  70. }
  71. func (sc *slowConnection) Read(b []byte) (int, error) {
  72. time.Sleep(sc.slowdown)
  73. return sc.Conn.Read(b)
  74. }
  75. type connectorHijack struct {
  76. driver.Connector
  77. connErr error
  78. }
  79. func (cw *connectorHijack) Connect(ctx context.Context) (driver.Conn, error) {
  80. var conn driver.Conn
  81. conn, cw.connErr = cw.Connector.Connect(ctx)
  82. return conn, cw.connErr
  83. }
  84. func TestConnectorTimeoutsDuringOpen(t *testing.T) {
  85. RegisterDialContext("slowconn", func(ctx context.Context, addr string) (net.Conn, error) {
  86. var d net.Dialer
  87. conn, err := d.DialContext(ctx, prot, addr)
  88. if err != nil {
  89. return nil, err
  90. }
  91. return &slowConnection{Conn: conn, slowdown: 100 * time.Millisecond}, nil
  92. })
  93. mycnf := configForTests(t)
  94. mycnf.Net = "slowconn"
  95. conn, err := NewConnector(mycnf)
  96. if err != nil {
  97. t.Fatal(err)
  98. }
  99. hijack := &connectorHijack{Connector: conn}
  100. db := sql.OpenDB(hijack)
  101. defer db.Close()
  102. ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
  103. defer cancel()
  104. _, err = db.ExecContext(ctx, "DO 1")
  105. if err != context.DeadlineExceeded {
  106. t.Fatalf("ExecContext should have timed out")
  107. }
  108. if hijack.connErr != context.DeadlineExceeded {
  109. t.Fatalf("(*Connector).Connect should have timed out")
  110. }
  111. }