pool_test.go 16 KB

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