pool_test.go 17 KB

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