pool_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2011 Gary Burd
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. package redis
  15. import (
  16. "io"
  17. "testing"
  18. "time"
  19. )
  20. type fakeConn struct {
  21. open *int
  22. err error
  23. }
  24. func (c *fakeConn) Close() error { *c.open -= 1; return nil }
  25. func (c *fakeConn) Err() error { return c.err }
  26. func (c *fakeConn) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
  27. if commandName == "ERR" {
  28. c.err = args[0].(error)
  29. }
  30. return nil, nil
  31. }
  32. func (c *fakeConn) Send(commandName string, args ...interface{}) error {
  33. return nil
  34. }
  35. func (c *fakeConn) Flush() error {
  36. return nil
  37. }
  38. func (c *fakeConn) Receive() (reply interface{}, err error) {
  39. return nil, nil
  40. }
  41. type dialer struct {
  42. t *testing.T
  43. dialed, open int
  44. }
  45. func (d *dialer) dial() (Conn, error) {
  46. d.open += 1
  47. d.dialed += 1
  48. return &fakeConn{open: &d.open}, nil
  49. }
  50. func (d *dialer) check(message string, p *Pool, dialed, open int) {
  51. if d.dialed != dialed {
  52. d.t.Errorf("%s: dialed=%d, want %d", message, d.dialed, dialed)
  53. }
  54. if d.open != open {
  55. d.t.Errorf("%s: open=%d, want %d", message, d.open, open)
  56. }
  57. if active := p.ActiveCount(); active != open {
  58. d.t.Errorf("%s: active=%d, want %d", message, active, open)
  59. }
  60. }
  61. func TestPoolReuse(t *testing.T) {
  62. d := dialer{t: t}
  63. p := &Pool{
  64. MaxIdle: 2,
  65. Dial: d.dial,
  66. }
  67. for i := 0; i < 10; i++ {
  68. c1 := p.Get()
  69. c1.Do("PING")
  70. c2 := p.Get()
  71. c2.Do("PING")
  72. c1.Close()
  73. c2.Close()
  74. }
  75. d.check("before close", p, 2, 2)
  76. p.Close()
  77. d.check("after close", p, 2, 0)
  78. }
  79. func TestPoolMaxIdle(t *testing.T) {
  80. d := dialer{t: t}
  81. p := &Pool{
  82. MaxIdle: 2,
  83. Dial: d.dial,
  84. }
  85. for i := 0; i < 10; i++ {
  86. c1 := p.Get()
  87. c1.Do("PING")
  88. c2 := p.Get()
  89. c2.Do("PING")
  90. c3 := p.Get()
  91. c3.Do("PING")
  92. c1.Close()
  93. c2.Close()
  94. c3.Close()
  95. }
  96. d.check("before close", p, 12, 2)
  97. p.Close()
  98. d.check("after close", p, 12, 0)
  99. }
  100. func TestPoolError(t *testing.T) {
  101. d := dialer{t: t}
  102. p := &Pool{
  103. MaxIdle: 2,
  104. Dial: d.dial,
  105. }
  106. c := p.Get()
  107. c.Do("ERR", io.EOF)
  108. if c.Err() == nil {
  109. t.Errorf("expected c.Err() != nil")
  110. }
  111. c.Close()
  112. c = p.Get()
  113. c.Do("ERR", io.EOF)
  114. c.Close()
  115. d.check(".", p, 2, 0)
  116. }
  117. func TestPoolClose(t *testing.T) {
  118. d := dialer{t: t}
  119. p := &Pool{
  120. MaxIdle: 2,
  121. Dial: d.dial,
  122. }
  123. c1 := p.Get()
  124. c1.Do("PING")
  125. c2 := p.Get()
  126. c2.Do("PING")
  127. c3 := p.Get()
  128. c3.Do("PING")
  129. c1.Close()
  130. if _, err := c1.Do("PING"); err == nil {
  131. t.Errorf("expected error after connection closed")
  132. }
  133. c2.Close()
  134. p.Close()
  135. d.check("after pool close", p, 3, 1)
  136. if _, err := c1.Do("PING"); err == nil {
  137. t.Errorf("expected error after connection and pool closed")
  138. }
  139. c3.Close()
  140. d.check("after channel close", p, 3, 0)
  141. c1 = p.Get()
  142. if _, err := c1.Do("PING"); err == nil {
  143. t.Errorf("expected error after pool closed")
  144. }
  145. }
  146. func TestPoolTimeout(t *testing.T) {
  147. d := dialer{t: t}
  148. p := &Pool{
  149. MaxIdle: 2,
  150. IdleTimeout: 300 * time.Second,
  151. Dial: d.dial,
  152. }
  153. now := time.Now()
  154. nowFunc = func() time.Time { return now }
  155. defer func() { nowFunc = time.Now }()
  156. c := p.Get()
  157. c.Do("PING")
  158. c.Close()
  159. d.check("1", p, 1, 1)
  160. now = now.Add(p.IdleTimeout)
  161. c = p.Get()
  162. c.Do("PING")
  163. c.Close()
  164. d.check("2", p, 2, 1)
  165. }
  166. func TestBorrowCheck(t *testing.T) {
  167. d := dialer{t: t}
  168. p := &Pool{
  169. MaxIdle: 2,
  170. Dial: d.dial,
  171. TestOnBorrow: func(Conn, time.Time) error { return Error("BLAH") },
  172. }
  173. for i := 0; i < 10; i++ {
  174. c := p.Get()
  175. c.Do("PING")
  176. c.Close()
  177. }
  178. d.check("1", p, 10, 1)
  179. }
  180. func TestMaxActive(t *testing.T) {
  181. d := dialer{t: t}
  182. p := &Pool{
  183. MaxIdle: 2,
  184. MaxActive: 2,
  185. Dial: d.dial,
  186. }
  187. c1 := p.Get()
  188. c1.Do("PING")
  189. c2 := p.Get()
  190. c2.Do("PING")
  191. d.check("1", p, 2, 2)
  192. c3 := p.Get()
  193. if _, err := c3.Do("PING"); err != ErrPoolExhausted {
  194. t.Errorf("expected pool exhausted")
  195. }
  196. c3.Close()
  197. d.check("2", p, 2, 2)
  198. c2.Close()
  199. d.check("2", p, 2, 2)
  200. c3 = p.Get()
  201. if _, err := c3.Do("PING"); err != nil {
  202. t.Errorf("expected good channel, err=%v", err)
  203. }
  204. c3.Close()
  205. d.check("2", p, 2, 2)
  206. }