pool_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  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_test
  15. import (
  16. "context"
  17. "errors"
  18. "io"
  19. "reflect"
  20. "sync"
  21. "testing"
  22. "time"
  23. "github.com/gomodule/redigo/redis"
  24. )
  25. const (
  26. testGoRoutines = 10
  27. )
  28. type poolTestConn struct {
  29. d *poolDialer
  30. err error
  31. redis.Conn
  32. }
  33. func (c *poolTestConn) Close() error {
  34. c.d.mu.Lock()
  35. c.d.open -= 1
  36. c.d.mu.Unlock()
  37. return c.Conn.Close()
  38. }
  39. func (c *poolTestConn) Err() error { return c.err }
  40. func (c *poolTestConn) Do(commandName string, args ...interface{}) (interface{}, error) {
  41. if commandName == "ERR" {
  42. c.err = args[0].(error)
  43. commandName = "PING"
  44. }
  45. if commandName != "" {
  46. c.d.commands = append(c.d.commands, commandName)
  47. }
  48. return c.Conn.Do(commandName, args...)
  49. }
  50. func (c *poolTestConn) Send(commandName string, args ...interface{}) error {
  51. c.d.commands = append(c.d.commands, commandName)
  52. return c.Conn.Send(commandName, args...)
  53. }
  54. type poolDialer struct {
  55. mu sync.Mutex
  56. t *testing.T
  57. dialed int
  58. open int
  59. commands []string
  60. dialErr error
  61. }
  62. func (d *poolDialer) dial() (redis.Conn, error) {
  63. d.mu.Lock()
  64. d.dialed += 1
  65. dialErr := d.dialErr
  66. d.mu.Unlock()
  67. if dialErr != nil {
  68. return nil, d.dialErr
  69. }
  70. c, err := redis.DialDefaultServer()
  71. if err != nil {
  72. return nil, err
  73. }
  74. d.mu.Lock()
  75. d.open += 1
  76. d.mu.Unlock()
  77. return &poolTestConn{d: d, Conn: c}, nil
  78. }
  79. func (d *poolDialer) dialContext(ctx context.Context) (redis.Conn, error) {
  80. return d.dial()
  81. }
  82. func (d *poolDialer) check(message string, p *redis.Pool, dialed, open, inuse int) {
  83. d.checkAll(message, p, dialed, open, inuse, 0, 0)
  84. }
  85. func (d *poolDialer) checkAll(message string, p *redis.Pool, dialed, open, inuse int, waitCountMax int64, waitDurationMax time.Duration) {
  86. d.mu.Lock()
  87. defer d.mu.Unlock()
  88. if d.dialed != dialed {
  89. d.t.Errorf("%s: dialed=%d, want %d", message, d.dialed, dialed)
  90. }
  91. if d.open != open {
  92. d.t.Errorf("%s: open=%d, want %d", message, d.open, open)
  93. }
  94. stats := p.Stats()
  95. if stats.ActiveCount != open {
  96. d.t.Errorf("%s: active=%d, want %d", message, stats.ActiveCount, open)
  97. }
  98. if stats.IdleCount != open-inuse {
  99. d.t.Errorf("%s: idle=%d, want %d", message, stats.IdleCount, open-inuse)
  100. }
  101. if stats.WaitCount > waitCountMax {
  102. d.t.Errorf("%s: unexpected wait=%d want at most %d", message, stats.WaitCount, waitCountMax)
  103. }
  104. if waitCountMax == 0 {
  105. if stats.WaitDuration != 0 {
  106. d.t.Errorf("%s: unexpected waitDuration=%v want %v", message, stats.WaitDuration, 0)
  107. }
  108. return
  109. }
  110. if stats.WaitDuration > waitDurationMax {
  111. d.t.Errorf("%s: unexpected waitDuration=%v want < %v", message, stats.WaitDuration, waitDurationMax)
  112. }
  113. }
  114. func TestPoolReuse(t *testing.T) {
  115. d := poolDialer{t: t}
  116. p := &redis.Pool{
  117. MaxIdle: 2,
  118. Dial: d.dial,
  119. }
  120. for i := 0; i < 10; i++ {
  121. c1 := p.Get()
  122. c1.Do("PING")
  123. c2 := p.Get()
  124. c2.Do("PING")
  125. c1.Close()
  126. c2.Close()
  127. }
  128. d.check("before close", p, 2, 2, 0)
  129. p.Close()
  130. d.check("after close", p, 2, 0, 0)
  131. }
  132. func TestPoolMaxIdle(t *testing.T) {
  133. d := poolDialer{t: t}
  134. p := &redis.Pool{
  135. MaxIdle: 2,
  136. Dial: d.dial,
  137. }
  138. defer p.Close()
  139. for i := 0; i < 10; i++ {
  140. c1 := p.Get()
  141. c1.Do("PING")
  142. c2 := p.Get()
  143. c2.Do("PING")
  144. c3 := p.Get()
  145. c3.Do("PING")
  146. c1.Close()
  147. c2.Close()
  148. c3.Close()
  149. }
  150. d.check("before close", p, 12, 2, 0)
  151. p.Close()
  152. d.check("after close", p, 12, 0, 0)
  153. }
  154. func TestPoolError(t *testing.T) {
  155. d := poolDialer{t: t}
  156. p := &redis.Pool{
  157. MaxIdle: 2,
  158. Dial: d.dial,
  159. }
  160. defer p.Close()
  161. c := p.Get()
  162. c.Do("ERR", io.EOF)
  163. if c.Err() == nil {
  164. t.Errorf("expected c.Err() != nil")
  165. }
  166. c.Close()
  167. c = p.Get()
  168. c.Do("ERR", io.EOF)
  169. c.Close()
  170. d.check(".", p, 2, 0, 0)
  171. }
  172. func TestPoolClose(t *testing.T) {
  173. d := poolDialer{t: t}
  174. p := &redis.Pool{
  175. MaxIdle: 2,
  176. Dial: d.dial,
  177. }
  178. defer p.Close()
  179. c1 := p.Get()
  180. c1.Do("PING")
  181. c2 := p.Get()
  182. c2.Do("PING")
  183. c3 := p.Get()
  184. c3.Do("PING")
  185. c1.Close()
  186. if _, err := c1.Do("PING"); err == nil {
  187. t.Errorf("expected error after connection closed")
  188. }
  189. c2.Close()
  190. c2.Close()
  191. p.Close()
  192. d.check("after pool close", p, 3, 1, 1)
  193. if _, err := c1.Do("PING"); err == nil {
  194. t.Errorf("expected error after connection and pool closed")
  195. }
  196. c3.Close()
  197. d.check("after conn close", p, 3, 0, 0)
  198. c1 = p.Get()
  199. if _, err := c1.Do("PING"); err == nil {
  200. t.Errorf("expected error after pool closed")
  201. }
  202. }
  203. func TestPoolClosedConn(t *testing.T) {
  204. d := poolDialer{t: t}
  205. p := &redis.Pool{
  206. MaxIdle: 2,
  207. IdleTimeout: 300 * time.Second,
  208. Dial: d.dial,
  209. }
  210. defer p.Close()
  211. c := p.Get()
  212. if c.Err() != nil {
  213. t.Fatal("get failed")
  214. }
  215. c.Close()
  216. if err := c.Err(); err == nil {
  217. t.Fatal("Err on closed connection did not return error")
  218. }
  219. if _, err := c.Do("PING"); err == nil {
  220. t.Fatal("Do on closed connection did not return error")
  221. }
  222. if err := c.Send("PING"); err == nil {
  223. t.Fatal("Send on closed connection did not return error")
  224. }
  225. if err := c.Flush(); err == nil {
  226. t.Fatal("Flush on closed connection did not return error")
  227. }
  228. if _, err := c.Receive(); err == nil {
  229. t.Fatal("Receive on closed connection did not return error")
  230. }
  231. }
  232. func TestPoolIdleTimeout(t *testing.T) {
  233. d := poolDialer{t: t}
  234. p := &redis.Pool{
  235. MaxIdle: 2,
  236. IdleTimeout: 300 * time.Second,
  237. Dial: d.dial,
  238. }
  239. defer p.Close()
  240. now := time.Now()
  241. redis.SetNowFunc(func() time.Time { return now })
  242. defer redis.SetNowFunc(time.Now)
  243. c := p.Get()
  244. c.Do("PING")
  245. c.Close()
  246. d.check("1", p, 1, 1, 0)
  247. now = now.Add(p.IdleTimeout + 1)
  248. c = p.Get()
  249. c.Do("PING")
  250. c.Close()
  251. d.check("2", p, 2, 1, 0)
  252. }
  253. func TestPoolMaxLifetime(t *testing.T) {
  254. d := poolDialer{t: t}
  255. p := &redis.Pool{
  256. MaxIdle: 2,
  257. MaxConnLifetime: 300 * time.Second,
  258. Dial: d.dial,
  259. }
  260. defer p.Close()
  261. now := time.Now()
  262. redis.SetNowFunc(func() time.Time { return now })
  263. defer redis.SetNowFunc(time.Now)
  264. c := p.Get()
  265. c.Do("PING")
  266. c.Close()
  267. d.check("1", p, 1, 1, 0)
  268. now = now.Add(p.MaxConnLifetime + 1)
  269. c = p.Get()
  270. c.Do("PING")
  271. c.Close()
  272. d.check("2", p, 2, 1, 0)
  273. }
  274. func TestPoolConcurrenSendReceive(t *testing.T) {
  275. p := &redis.Pool{
  276. Dial: func() (redis.Conn, error) { return redis.DialDefaultServer() },
  277. }
  278. defer p.Close()
  279. c := p.Get()
  280. done := make(chan error, 1)
  281. go func() {
  282. _, err := c.Receive()
  283. done <- err
  284. }()
  285. c.Send("PING")
  286. c.Flush()
  287. err := <-done
  288. if err != nil {
  289. t.Fatalf("Receive() returned error %v", err)
  290. }
  291. _, err = c.Do("")
  292. if err != nil {
  293. t.Fatalf("Do() returned error %v", err)
  294. }
  295. c.Close()
  296. }
  297. func TestPoolBorrowCheck(t *testing.T) {
  298. d := poolDialer{t: t}
  299. p := &redis.Pool{
  300. MaxIdle: 2,
  301. Dial: d.dial,
  302. TestOnBorrow: func(redis.Conn, time.Time) error { return redis.Error("BLAH") },
  303. }
  304. defer p.Close()
  305. for i := 0; i < 10; i++ {
  306. c := p.Get()
  307. c.Do("PING")
  308. c.Close()
  309. }
  310. d.check("1", p, 10, 1, 0)
  311. }
  312. func TestPoolMaxActive(t *testing.T) {
  313. d := poolDialer{t: t}
  314. p := &redis.Pool{
  315. MaxIdle: 2,
  316. MaxActive: 2,
  317. Dial: d.dial,
  318. }
  319. defer p.Close()
  320. c1 := p.Get()
  321. c1.Do("PING")
  322. c2 := p.Get()
  323. c2.Do("PING")
  324. d.check("1", p, 2, 2, 2)
  325. c3 := p.Get()
  326. if _, err := c3.Do("PING"); err != redis.ErrPoolExhausted {
  327. t.Errorf("expected pool exhausted")
  328. }
  329. c3.Close()
  330. d.check("2", p, 2, 2, 2)
  331. c2.Close()
  332. d.check("3", p, 2, 2, 1)
  333. c3 = p.Get()
  334. if _, err := c3.Do("PING"); err != nil {
  335. t.Errorf("expected good channel, err=%v", err)
  336. }
  337. c3.Close()
  338. d.check("4", p, 2, 2, 1)
  339. }
  340. func TestPoolWaitStats(t *testing.T) {
  341. d := poolDialer{t: t}
  342. p := &redis.Pool{
  343. Wait: true,
  344. MaxIdle: 2,
  345. MaxActive: 2,
  346. Dial: d.dial,
  347. }
  348. defer p.Close()
  349. c1 := p.Get()
  350. c1.Do("PING")
  351. c2 := p.Get()
  352. c2.Do("PING")
  353. d.checkAll("1", p, 2, 2, 2, 0, 0)
  354. start := time.Now()
  355. go func() {
  356. time.Sleep(time.Millisecond * 100)
  357. c1.Close()
  358. }()
  359. c3 := p.Get()
  360. d.checkAll("2", p, 2, 2, 2, 1, time.Since(start))
  361. if _, err := c3.Do("PING"); err != nil {
  362. t.Errorf("expected good channel, err=%v", err)
  363. }
  364. }
  365. func TestPoolMonitorCleanup(t *testing.T) {
  366. d := poolDialer{t: t}
  367. p := &redis.Pool{
  368. MaxIdle: 2,
  369. MaxActive: 2,
  370. Dial: d.dial,
  371. }
  372. defer p.Close()
  373. c := p.Get()
  374. c.Send("MONITOR")
  375. c.Close()
  376. d.check("", p, 1, 0, 0)
  377. }
  378. func TestPoolPubSubCleanup(t *testing.T) {
  379. d := poolDialer{t: t}
  380. p := &redis.Pool{
  381. MaxIdle: 2,
  382. MaxActive: 2,
  383. Dial: d.dial,
  384. }
  385. defer p.Close()
  386. c := p.Get()
  387. c.Send("SUBSCRIBE", "x")
  388. c.Close()
  389. want := []string{"SUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"}
  390. if !reflect.DeepEqual(d.commands, want) {
  391. t.Errorf("got commands %v, want %v", d.commands, want)
  392. }
  393. d.commands = nil
  394. c = p.Get()
  395. c.Send("PSUBSCRIBE", "x*")
  396. c.Close()
  397. want = []string{"PSUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"}
  398. if !reflect.DeepEqual(d.commands, want) {
  399. t.Errorf("got commands %v, want %v", d.commands, want)
  400. }
  401. d.commands = nil
  402. }
  403. func TestPoolTransactionCleanup(t *testing.T) {
  404. d := poolDialer{t: t}
  405. p := &redis.Pool{
  406. MaxIdle: 2,
  407. MaxActive: 2,
  408. Dial: d.dial,
  409. }
  410. defer p.Close()
  411. c := p.Get()
  412. c.Do("WATCH", "key")
  413. c.Do("PING")
  414. c.Close()
  415. want := []string{"WATCH", "PING", "UNWATCH"}
  416. if !reflect.DeepEqual(d.commands, want) {
  417. t.Errorf("got commands %v, want %v", d.commands, want)
  418. }
  419. d.commands = nil
  420. c = p.Get()
  421. c.Do("WATCH", "key")
  422. c.Do("UNWATCH")
  423. c.Do("PING")
  424. c.Close()
  425. want = []string{"WATCH", "UNWATCH", "PING"}
  426. if !reflect.DeepEqual(d.commands, want) {
  427. t.Errorf("got commands %v, want %v", d.commands, want)
  428. }
  429. d.commands = nil
  430. c = p.Get()
  431. c.Do("WATCH", "key")
  432. c.Do("MULTI")
  433. c.Do("PING")
  434. c.Close()
  435. want = []string{"WATCH", "MULTI", "PING", "DISCARD"}
  436. if !reflect.DeepEqual(d.commands, want) {
  437. t.Errorf("got commands %v, want %v", d.commands, want)
  438. }
  439. d.commands = nil
  440. c = p.Get()
  441. c.Do("WATCH", "key")
  442. c.Do("MULTI")
  443. c.Do("DISCARD")
  444. c.Do("PING")
  445. c.Close()
  446. want = []string{"WATCH", "MULTI", "DISCARD", "PING"}
  447. if !reflect.DeepEqual(d.commands, want) {
  448. t.Errorf("got commands %v, want %v", d.commands, want)
  449. }
  450. d.commands = nil
  451. c = p.Get()
  452. c.Do("WATCH", "key")
  453. c.Do("MULTI")
  454. c.Do("EXEC")
  455. c.Do("PING")
  456. c.Close()
  457. want = []string{"WATCH", "MULTI", "EXEC", "PING"}
  458. if !reflect.DeepEqual(d.commands, want) {
  459. t.Errorf("got commands %v, want %v", d.commands, want)
  460. }
  461. d.commands = nil
  462. }
  463. func startGoroutines(p *redis.Pool, cmd string, args ...interface{}) chan error {
  464. errs := make(chan error, testGoRoutines)
  465. for i := 0; i < cap(errs); i++ {
  466. go func() {
  467. c := p.Get()
  468. _, err := c.Do(cmd, args...)
  469. c.Close()
  470. errs <- err
  471. }()
  472. }
  473. return errs
  474. }
  475. func TestWaitPool(t *testing.T) {
  476. d := poolDialer{t: t}
  477. p := &redis.Pool{
  478. MaxIdle: 1,
  479. MaxActive: 1,
  480. Dial: d.dial,
  481. Wait: true,
  482. }
  483. defer p.Close()
  484. c := p.Get()
  485. start := time.Now()
  486. errs := startGoroutines(p, "PING")
  487. d.check("before close", p, 1, 1, 1)
  488. c.Close()
  489. timeout := time.After(2 * time.Second)
  490. for i := 0; i < cap(errs); i++ {
  491. select {
  492. case err := <-errs:
  493. if err != nil {
  494. t.Fatal(err)
  495. }
  496. case <-timeout:
  497. t.Fatalf("timeout waiting for blocked goroutine %d", i)
  498. }
  499. }
  500. d.checkAll("done", p, 1, 1, 0, testGoRoutines, time.Since(start)*testGoRoutines)
  501. }
  502. func TestWaitPoolClose(t *testing.T) {
  503. d := poolDialer{t: t}
  504. p := &redis.Pool{
  505. MaxIdle: 1,
  506. MaxActive: 1,
  507. Dial: d.dial,
  508. Wait: true,
  509. }
  510. defer p.Close()
  511. c := p.Get()
  512. if _, err := c.Do("PING"); err != nil {
  513. t.Fatal(err)
  514. }
  515. start := time.Now()
  516. errs := startGoroutines(p, "PING")
  517. d.check("before close", p, 1, 1, 1)
  518. p.Close()
  519. timeout := time.After(2 * time.Second)
  520. for i := 0; i < cap(errs); i++ {
  521. select {
  522. case err := <-errs:
  523. switch err {
  524. case nil:
  525. t.Fatal("blocked goroutine did not get error")
  526. case redis.ErrPoolExhausted:
  527. t.Fatal("blocked goroutine got pool exhausted error")
  528. }
  529. case <-timeout:
  530. t.Fatal("timeout waiting for blocked goroutine")
  531. }
  532. }
  533. c.Close()
  534. d.checkAll("done", p, 1, 0, 0, testGoRoutines, time.Since(start)*testGoRoutines)
  535. }
  536. func TestWaitPoolCommandError(t *testing.T) {
  537. testErr := errors.New("test")
  538. d := poolDialer{t: t}
  539. p := &redis.Pool{
  540. MaxIdle: 1,
  541. MaxActive: 1,
  542. Dial: d.dial,
  543. Wait: true,
  544. }
  545. defer p.Close()
  546. c := p.Get()
  547. start := time.Now()
  548. errs := startGoroutines(p, "ERR", testErr)
  549. d.check("before close", p, 1, 1, 1)
  550. c.Close()
  551. timeout := time.After(2 * time.Second)
  552. for i := 0; i < cap(errs); i++ {
  553. select {
  554. case err := <-errs:
  555. if err != nil {
  556. t.Fatal(err)
  557. }
  558. case <-timeout:
  559. t.Fatalf("timeout waiting for blocked goroutine %d", i)
  560. }
  561. }
  562. d.checkAll("done", p, cap(errs), 0, 0, testGoRoutines, time.Since(start)*testGoRoutines)
  563. }
  564. func TestWaitPoolDialError(t *testing.T) {
  565. testErr := errors.New("test")
  566. d := poolDialer{t: t}
  567. p := &redis.Pool{
  568. MaxIdle: 1,
  569. MaxActive: 1,
  570. Dial: d.dial,
  571. Wait: true,
  572. }
  573. defer p.Close()
  574. c := p.Get()
  575. start := time.Now()
  576. errs := startGoroutines(p, "ERR", testErr)
  577. d.check("before close", p, 1, 1, 1)
  578. d.dialErr = errors.New("dial")
  579. c.Close()
  580. nilCount := 0
  581. errCount := 0
  582. timeout := time.After(2 * time.Second)
  583. for i := 0; i < cap(errs); i++ {
  584. select {
  585. case err := <-errs:
  586. switch err {
  587. case nil:
  588. nilCount++
  589. case d.dialErr:
  590. errCount++
  591. default:
  592. t.Fatalf("expected dial error or nil, got %v", err)
  593. }
  594. case <-timeout:
  595. t.Fatalf("timeout waiting for blocked goroutine %d", i)
  596. }
  597. }
  598. if nilCount != 1 {
  599. t.Errorf("expected one nil error, got %d", nilCount)
  600. }
  601. if errCount != cap(errs)-1 {
  602. t.Errorf("expected %d dial errors, got %d", cap(errs)-1, errCount)
  603. }
  604. d.checkAll("done", p, cap(errs), 0, 0, testGoRoutines, time.Since(start)*testGoRoutines)
  605. }
  606. // Borrowing requires us to iterate over the idle connections, unlock the pool,
  607. // and perform a blocking operation to check the connection still works. If
  608. // TestOnBorrow fails, we must reacquire the lock and continue iteration. This
  609. // test ensures that iteration will work correctly if multiple threads are
  610. // iterating simultaneously.
  611. func TestLocking_TestOnBorrowFails_PoolDoesntCrash(t *testing.T) {
  612. const count = 100
  613. // First we'll Create a pool where the pilfering of idle connections fails.
  614. d := poolDialer{t: t}
  615. p := &redis.Pool{
  616. MaxIdle: count,
  617. MaxActive: count,
  618. Dial: d.dial,
  619. TestOnBorrow: func(c redis.Conn, t time.Time) error {
  620. return errors.New("No way back into the real world.")
  621. },
  622. }
  623. defer p.Close()
  624. // Fill the pool with idle connections.
  625. conns := make([]redis.Conn, count)
  626. for i := range conns {
  627. conns[i] = p.Get()
  628. }
  629. for i := range conns {
  630. conns[i].Close()
  631. }
  632. // Spawn a bunch of goroutines to thrash the pool.
  633. var wg sync.WaitGroup
  634. wg.Add(count)
  635. for i := 0; i < count; i++ {
  636. go func() {
  637. c := p.Get()
  638. if c.Err() != nil {
  639. t.Errorf("pool get failed: %v", c.Err())
  640. }
  641. c.Close()
  642. wg.Done()
  643. }()
  644. }
  645. wg.Wait()
  646. if d.dialed != count*2 {
  647. t.Errorf("Expected %d dials, got %d", count*2, d.dialed)
  648. }
  649. }
  650. func BenchmarkPoolGet(b *testing.B) {
  651. b.StopTimer()
  652. p := redis.Pool{Dial: func() (redis.Conn, error) { return redis.DialDefaultServer() }, MaxIdle: 2}
  653. c := p.Get()
  654. if err := c.Err(); err != nil {
  655. b.Fatal(err)
  656. }
  657. c.Close()
  658. defer p.Close()
  659. b.StartTimer()
  660. for i := 0; i < b.N; i++ {
  661. c = p.Get()
  662. c.Close()
  663. }
  664. }
  665. func BenchmarkPoolGetErr(b *testing.B) {
  666. b.StopTimer()
  667. p := redis.Pool{Dial: func() (redis.Conn, error) { return redis.DialDefaultServer() }, MaxIdle: 2}
  668. c := p.Get()
  669. if err := c.Err(); err != nil {
  670. b.Fatal(err)
  671. }
  672. c.Close()
  673. defer p.Close()
  674. b.StartTimer()
  675. for i := 0; i < b.N; i++ {
  676. c = p.Get()
  677. if err := c.Err(); err != nil {
  678. b.Fatal(err)
  679. }
  680. c.Close()
  681. }
  682. }
  683. func BenchmarkPoolGetPing(b *testing.B) {
  684. b.StopTimer()
  685. p := redis.Pool{Dial: func() (redis.Conn, error) { return redis.DialDefaultServer() }, MaxIdle: 2}
  686. c := p.Get()
  687. if err := c.Err(); err != nil {
  688. b.Fatal(err)
  689. }
  690. c.Close()
  691. defer p.Close()
  692. b.StartTimer()
  693. for i := 0; i < b.N; i++ {
  694. c = p.Get()
  695. if _, err := c.Do("PING"); err != nil {
  696. b.Fatal(err)
  697. }
  698. c.Close()
  699. }
  700. }
  701. func TestWaitPoolGetContext(t *testing.T) {
  702. d := poolDialer{t: t}
  703. p := &redis.Pool{
  704. MaxIdle: 1,
  705. MaxActive: 1,
  706. Dial: d.dial,
  707. Wait: true,
  708. }
  709. defer p.Close()
  710. c, err := p.GetContext(context.Background())
  711. if err != nil {
  712. t.Fatalf("GetContext returned %v", err)
  713. }
  714. defer c.Close()
  715. }
  716. func TestWaitPoolGetContextWithDialContext(t *testing.T) {
  717. d := poolDialer{t: t}
  718. p := &redis.Pool{
  719. MaxIdle: 1,
  720. MaxActive: 1,
  721. DialContext: d.dialContext,
  722. Wait: true,
  723. }
  724. defer p.Close()
  725. c, err := p.GetContext(context.Background())
  726. if err != nil {
  727. t.Fatalf("GetContext returned %v", err)
  728. }
  729. defer c.Close()
  730. }
  731. func TestWaitPoolGetAfterClose(t *testing.T) {
  732. d := poolDialer{t: t}
  733. p := &redis.Pool{
  734. MaxIdle: 1,
  735. MaxActive: 1,
  736. Dial: d.dial,
  737. Wait: true,
  738. }
  739. p.Close()
  740. _, err := p.GetContext(context.Background())
  741. if err == nil {
  742. t.Fatal("expected error")
  743. }
  744. }
  745. func TestWaitPoolGetCanceledContext(t *testing.T) {
  746. d := poolDialer{t: t}
  747. p := &redis.Pool{
  748. MaxIdle: 1,
  749. MaxActive: 1,
  750. Dial: d.dial,
  751. Wait: true,
  752. }
  753. defer p.Close()
  754. ctx, f := context.WithCancel(context.Background())
  755. f()
  756. c := p.Get()
  757. defer c.Close()
  758. _, err := p.GetContext(ctx)
  759. if err != context.Canceled {
  760. t.Fatalf("got error %v, want %v", err, context.Canceled)
  761. }
  762. }