conn_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. // Copyright 2012 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. "bytes"
  17. "crypto/tls"
  18. "crypto/x509"
  19. "fmt"
  20. "io"
  21. "math"
  22. "net"
  23. "os"
  24. "reflect"
  25. "strings"
  26. "testing"
  27. "time"
  28. "github.com/gomodule/redigo/redis"
  29. )
  30. type testConn struct {
  31. io.Reader
  32. io.Writer
  33. readDeadline time.Time
  34. writeDeadline time.Time
  35. }
  36. func (*testConn) Close() error { return nil }
  37. func (*testConn) LocalAddr() net.Addr { return nil }
  38. func (*testConn) RemoteAddr() net.Addr { return nil }
  39. func (c *testConn) SetDeadline(t time.Time) error { c.readDeadline = t; c.writeDeadline = t; return nil }
  40. func (c *testConn) SetReadDeadline(t time.Time) error { c.readDeadline = t; return nil }
  41. func (c *testConn) SetWriteDeadline(t time.Time) error { c.writeDeadline = t; return nil }
  42. func dialTestConn(r string, w io.Writer) redis.DialOption {
  43. return redis.DialNetDial(func(network, addr string) (net.Conn, error) {
  44. return &testConn{Reader: strings.NewReader(r), Writer: w}, nil
  45. })
  46. }
  47. type tlsTestConn struct {
  48. net.Conn
  49. done chan struct{}
  50. }
  51. func (c *tlsTestConn) Close() error {
  52. c.Conn.Close()
  53. <-c.done
  54. return nil
  55. }
  56. func dialTestConnTLS(r string, w io.Writer) redis.DialOption {
  57. return redis.DialNetDial(func(network, addr string) (net.Conn, error) {
  58. client, server := net.Pipe()
  59. tlsServer := tls.Server(server, &serverTLSConfig)
  60. go io.Copy(tlsServer, strings.NewReader(r))
  61. done := make(chan struct{})
  62. go func() {
  63. io.Copy(w, tlsServer)
  64. close(done)
  65. }()
  66. return &tlsTestConn{Conn: client, done: done}, nil
  67. })
  68. }
  69. type durationArg struct {
  70. time.Duration
  71. }
  72. func (t durationArg) RedisArg() interface{} {
  73. return t.Seconds()
  74. }
  75. type recursiveArg int
  76. func (v recursiveArg) RedisArg() interface{} { return v }
  77. var writeTests = []struct {
  78. args []interface{}
  79. expected string
  80. }{
  81. {
  82. []interface{}{"SET", "key", "value"},
  83. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n",
  84. },
  85. {
  86. []interface{}{"SET", "key", "value"},
  87. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n",
  88. },
  89. {
  90. []interface{}{"SET", "key", byte(100)},
  91. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n100\r\n",
  92. },
  93. {
  94. []interface{}{"SET", "key", 100},
  95. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n100\r\n",
  96. },
  97. {
  98. []interface{}{"SET", "key", int64(math.MinInt64)},
  99. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$20\r\n-9223372036854775808\r\n",
  100. },
  101. {
  102. []interface{}{"SET", "key", float64(1349673917.939762)},
  103. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$21\r\n1.349673917939762e+09\r\n",
  104. },
  105. {
  106. []interface{}{"SET", "key", ""},
  107. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$0\r\n\r\n",
  108. },
  109. {
  110. []interface{}{"SET", "key", nil},
  111. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$0\r\n\r\n",
  112. },
  113. {
  114. []interface{}{"SET", "key", durationArg{time.Minute}},
  115. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$2\r\n60\r\n",
  116. },
  117. {
  118. []interface{}{"SET", "key", recursiveArg(123)},
  119. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n123\r\n",
  120. },
  121. {
  122. []interface{}{"ECHO", true, false},
  123. "*3\r\n$4\r\nECHO\r\n$1\r\n1\r\n$1\r\n0\r\n",
  124. },
  125. }
  126. func TestWrite(t *testing.T) {
  127. for _, tt := range writeTests {
  128. var buf bytes.Buffer
  129. c, _ := redis.Dial("", "", dialTestConn("", &buf))
  130. err := c.Send(tt.args[0].(string), tt.args[1:]...)
  131. if err != nil {
  132. t.Errorf("Send(%v) returned error %v", tt.args, err)
  133. continue
  134. }
  135. c.Flush()
  136. actual := buf.String()
  137. if actual != tt.expected {
  138. t.Errorf("Send(%v) = %q, want %q", tt.args, actual, tt.expected)
  139. }
  140. }
  141. }
  142. var errorSentinel = &struct{}{}
  143. var readTests = []struct {
  144. reply string
  145. expected interface{}
  146. }{
  147. {
  148. "+OK\r\n",
  149. "OK",
  150. },
  151. {
  152. "+PONG\r\n",
  153. "PONG",
  154. },
  155. {
  156. "@OK\r\n",
  157. errorSentinel,
  158. },
  159. {
  160. "$6\r\nfoobar\r\n",
  161. []byte("foobar"),
  162. },
  163. {
  164. "$-1\r\n",
  165. nil,
  166. },
  167. {
  168. ":1\r\n",
  169. int64(1),
  170. },
  171. {
  172. ":-2\r\n",
  173. int64(-2),
  174. },
  175. {
  176. "*0\r\n",
  177. []interface{}{},
  178. },
  179. {
  180. "*-1\r\n",
  181. nil,
  182. },
  183. {
  184. "*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n",
  185. []interface{}{[]byte("foo"), []byte("bar"), []byte("Hello"), []byte("World")},
  186. },
  187. {
  188. "*3\r\n$3\r\nfoo\r\n$-1\r\n$3\r\nbar\r\n",
  189. []interface{}{[]byte("foo"), nil, []byte("bar")},
  190. },
  191. {
  192. // "x" is not a valid length
  193. "$x\r\nfoobar\r\n",
  194. errorSentinel,
  195. },
  196. {
  197. // -2 is not a valid length
  198. "$-2\r\n",
  199. errorSentinel,
  200. },
  201. {
  202. // "x" is not a valid integer
  203. ":x\r\n",
  204. errorSentinel,
  205. },
  206. {
  207. // missing \r\n following value
  208. "$6\r\nfoobar",
  209. errorSentinel,
  210. },
  211. {
  212. // short value
  213. "$6\r\nxx",
  214. errorSentinel,
  215. },
  216. {
  217. // long value
  218. "$6\r\nfoobarx\r\n",
  219. errorSentinel,
  220. },
  221. }
  222. func TestRead(t *testing.T) {
  223. for _, tt := range readTests {
  224. c, _ := redis.Dial("", "", dialTestConn(tt.reply, nil))
  225. actual, err := c.Receive()
  226. if tt.expected == errorSentinel {
  227. if err == nil {
  228. t.Errorf("Receive(%q) did not return expected error", tt.reply)
  229. }
  230. } else {
  231. if err != nil {
  232. t.Errorf("Receive(%q) returned error %v", tt.reply, err)
  233. continue
  234. }
  235. if !reflect.DeepEqual(actual, tt.expected) {
  236. t.Errorf("Receive(%q) = %v, want %v", tt.reply, actual, tt.expected)
  237. }
  238. }
  239. }
  240. }
  241. var testCommands = []struct {
  242. args []interface{}
  243. expected interface{}
  244. }{
  245. {
  246. []interface{}{"PING"},
  247. "PONG",
  248. },
  249. {
  250. []interface{}{"SET", "foo", "bar"},
  251. "OK",
  252. },
  253. {
  254. []interface{}{"GET", "foo"},
  255. []byte("bar"),
  256. },
  257. {
  258. []interface{}{"GET", "nokey"},
  259. nil,
  260. },
  261. {
  262. []interface{}{"MGET", "nokey", "foo"},
  263. []interface{}{nil, []byte("bar")},
  264. },
  265. {
  266. []interface{}{"INCR", "mycounter"},
  267. int64(1),
  268. },
  269. {
  270. []interface{}{"LPUSH", "mylist", "foo"},
  271. int64(1),
  272. },
  273. {
  274. []interface{}{"LPUSH", "mylist", "bar"},
  275. int64(2),
  276. },
  277. {
  278. []interface{}{"LRANGE", "mylist", 0, -1},
  279. []interface{}{[]byte("bar"), []byte("foo")},
  280. },
  281. {
  282. []interface{}{"MULTI"},
  283. "OK",
  284. },
  285. {
  286. []interface{}{"LRANGE", "mylist", 0, -1},
  287. "QUEUED",
  288. },
  289. {
  290. []interface{}{"PING"},
  291. "QUEUED",
  292. },
  293. {
  294. []interface{}{"EXEC"},
  295. []interface{}{
  296. []interface{}{[]byte("bar"), []byte("foo")},
  297. "PONG",
  298. },
  299. },
  300. }
  301. func TestDoCommands(t *testing.T) {
  302. c, err := redis.DialDefaultServer()
  303. if err != nil {
  304. t.Fatalf("error connection to database, %v", err)
  305. }
  306. defer c.Close()
  307. for _, cmd := range testCommands {
  308. actual, err := c.Do(cmd.args[0].(string), cmd.args[1:]...)
  309. if err != nil {
  310. t.Errorf("Do(%v) returned error %v", cmd.args, err)
  311. continue
  312. }
  313. if !reflect.DeepEqual(actual, cmd.expected) {
  314. t.Errorf("Do(%v) = %v, want %v", cmd.args, actual, cmd.expected)
  315. }
  316. }
  317. }
  318. func TestPipelineCommands(t *testing.T) {
  319. c, err := redis.DialDefaultServer()
  320. if err != nil {
  321. t.Fatalf("error connection to database, %v", err)
  322. }
  323. defer c.Close()
  324. for _, cmd := range testCommands {
  325. if err := c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil {
  326. t.Fatalf("Send(%v) returned error %v", cmd.args, err)
  327. }
  328. }
  329. if err := c.Flush(); err != nil {
  330. t.Errorf("Flush() returned error %v", err)
  331. }
  332. for _, cmd := range testCommands {
  333. actual, err := c.Receive()
  334. if err != nil {
  335. t.Fatalf("Receive(%v) returned error %v", cmd.args, err)
  336. }
  337. if !reflect.DeepEqual(actual, cmd.expected) {
  338. t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected)
  339. }
  340. }
  341. }
  342. func TestBlankCommmand(t *testing.T) {
  343. c, err := redis.DialDefaultServer()
  344. if err != nil {
  345. t.Fatalf("error connection to database, %v", err)
  346. }
  347. defer c.Close()
  348. for _, cmd := range testCommands {
  349. if err := c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil {
  350. t.Fatalf("Send(%v) returned error %v", cmd.args, err)
  351. }
  352. }
  353. reply, err := redis.Values(c.Do(""))
  354. if err != nil {
  355. t.Fatalf("Do() returned error %v", err)
  356. }
  357. if len(reply) != len(testCommands) {
  358. t.Fatalf("len(reply)=%d, want %d", len(reply), len(testCommands))
  359. }
  360. for i, cmd := range testCommands {
  361. actual := reply[i]
  362. if !reflect.DeepEqual(actual, cmd.expected) {
  363. t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected)
  364. }
  365. }
  366. }
  367. func TestRecvBeforeSend(t *testing.T) {
  368. c, err := redis.DialDefaultServer()
  369. if err != nil {
  370. t.Fatalf("error connection to database, %v", err)
  371. }
  372. defer c.Close()
  373. done := make(chan struct{})
  374. go func() {
  375. c.Receive()
  376. close(done)
  377. }()
  378. time.Sleep(time.Millisecond)
  379. c.Send("PING")
  380. c.Flush()
  381. <-done
  382. _, err = c.Do("")
  383. if err != nil {
  384. t.Fatalf("error=%v", err)
  385. }
  386. }
  387. func TestError(t *testing.T) {
  388. c, err := redis.DialDefaultServer()
  389. if err != nil {
  390. t.Fatalf("error connection to database, %v", err)
  391. }
  392. defer c.Close()
  393. c.Do("SET", "key", "val")
  394. _, err = c.Do("HSET", "key", "fld", "val")
  395. if err == nil {
  396. t.Errorf("Expected err for HSET on string key.")
  397. }
  398. if c.Err() != nil {
  399. t.Errorf("Conn has Err()=%v, expect nil", c.Err())
  400. }
  401. _, err = c.Do("SET", "key", "val")
  402. if err != nil {
  403. t.Errorf("Do(SET, key, val) returned error %v, expected nil.", err)
  404. }
  405. }
  406. func TestReadTimeout(t *testing.T) {
  407. l, err := net.Listen("tcp", "127.0.0.1:0")
  408. if err != nil {
  409. t.Fatalf("net.Listen returned %v", err)
  410. }
  411. defer l.Close()
  412. go func() {
  413. for {
  414. c, err := l.Accept()
  415. if err != nil {
  416. return
  417. }
  418. go func() {
  419. time.Sleep(time.Second)
  420. c.Write([]byte("+OK\r\n"))
  421. c.Close()
  422. }()
  423. }
  424. }()
  425. // Do
  426. c1, err := redis.Dial(l.Addr().Network(), l.Addr().String(), redis.DialReadTimeout(time.Millisecond))
  427. if err != nil {
  428. t.Fatalf("redis.Dial returned %v", err)
  429. }
  430. defer c1.Close()
  431. _, err = c1.Do("PING")
  432. if err == nil {
  433. t.Fatalf("c1.Do() returned nil, expect error")
  434. }
  435. if c1.Err() == nil {
  436. t.Fatalf("c1.Err() = nil, expect error")
  437. }
  438. // Send/Flush/Receive
  439. c2, err := redis.Dial(l.Addr().Network(), l.Addr().String(), redis.DialReadTimeout(time.Millisecond))
  440. if err != nil {
  441. t.Fatalf("redis.Dial returned %v", err)
  442. }
  443. defer c2.Close()
  444. c2.Send("PING")
  445. c2.Flush()
  446. _, err = c2.Receive()
  447. if err == nil {
  448. t.Fatalf("c2.Receive() returned nil, expect error")
  449. }
  450. if c2.Err() == nil {
  451. t.Fatalf("c2.Err() = nil, expect error")
  452. }
  453. }
  454. var dialErrors = []struct {
  455. rawurl string
  456. expectedError string
  457. }{
  458. {
  459. "localhost",
  460. "invalid redis URL scheme",
  461. },
  462. // The error message for invalid hosts is different in different
  463. // versions of Go, so just check that there is an error message.
  464. {
  465. "redis://weird url",
  466. "",
  467. },
  468. {
  469. "redis://foo:bar:baz",
  470. "",
  471. },
  472. {
  473. "http://www.google.com",
  474. "invalid redis URL scheme: http",
  475. },
  476. {
  477. "redis://localhost:6379/abc123",
  478. "invalid database: abc123",
  479. },
  480. }
  481. func TestDialURLErrors(t *testing.T) {
  482. for _, d := range dialErrors {
  483. _, err := redis.DialURL(d.rawurl)
  484. if err == nil || !strings.Contains(err.Error(), d.expectedError) {
  485. t.Errorf("DialURL did not return expected error (expected %v to contain %s)", err, d.expectedError)
  486. }
  487. }
  488. }
  489. func TestDialURLPort(t *testing.T) {
  490. checkPort := func(network, address string) (net.Conn, error) {
  491. if address != "localhost:6379" {
  492. t.Errorf("DialURL did not set port to 6379 by default (got %v)", address)
  493. }
  494. return nil, nil
  495. }
  496. _, err := redis.DialURL("redis://localhost", redis.DialNetDial(checkPort))
  497. if err != nil {
  498. t.Error("dial error:", err)
  499. }
  500. }
  501. func TestDialURLHost(t *testing.T) {
  502. checkHost := func(network, address string) (net.Conn, error) {
  503. if address != "localhost:6379" {
  504. t.Errorf("DialURL did not set host to localhost by default (got %v)", address)
  505. }
  506. return nil, nil
  507. }
  508. _, err := redis.DialURL("redis://:6379", redis.DialNetDial(checkHost))
  509. if err != nil {
  510. t.Error("dial error:", err)
  511. }
  512. }
  513. var dialURLTests = []struct {
  514. description string
  515. url string
  516. r string
  517. w string
  518. }{
  519. {"password", "redis://x:abc123@localhost", "+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
  520. {"database 3", "redis://localhost/3", "+OK\r\n", "*2\r\n$6\r\nSELECT\r\n$1\r\n3\r\n"},
  521. {"database 99", "redis://localhost/99", "+OK\r\n", "*2\r\n$6\r\nSELECT\r\n$2\r\n99\r\n"},
  522. {"no database", "redis://localhost/", "+OK\r\n", ""},
  523. }
  524. func TestDialURL(t *testing.T) {
  525. for _, tt := range dialURLTests {
  526. var buf bytes.Buffer
  527. // UseTLS should be ignored in all of these tests.
  528. _, err := redis.DialURL(tt.url, dialTestConn(tt.r, &buf), redis.DialUseTLS(true))
  529. if err != nil {
  530. t.Errorf("%s dial error: %v", tt.description, err)
  531. continue
  532. }
  533. if w := buf.String(); w != tt.w {
  534. t.Errorf("%s commands = %q, want %q", tt.description, w, tt.w)
  535. }
  536. }
  537. }
  538. func checkPingPong(t *testing.T, buf *bytes.Buffer, c redis.Conn) {
  539. resp, err := c.Do("PING")
  540. if err != nil {
  541. t.Fatal("ping error:", err)
  542. }
  543. // Close connection to ensure that writes to buf are complete.
  544. c.Close()
  545. expected := "*1\r\n$4\r\nPING\r\n"
  546. actual := buf.String()
  547. if actual != expected {
  548. t.Errorf("commands = %q, want %q", actual, expected)
  549. }
  550. if resp != "PONG" {
  551. t.Errorf("resp = %v, want %v", resp, "PONG")
  552. }
  553. }
  554. const pingResponse = "+PONG\r\n"
  555. func TestDialURLTLS(t *testing.T) {
  556. var buf bytes.Buffer
  557. c, err := redis.DialURL("rediss://example.com/",
  558. redis.DialTLSConfig(&clientTLSConfig),
  559. dialTestConnTLS(pingResponse, &buf))
  560. if err != nil {
  561. t.Fatal("dial error:", err)
  562. }
  563. checkPingPong(t, &buf, c)
  564. }
  565. func TestDialUseTLS(t *testing.T) {
  566. var buf bytes.Buffer
  567. c, err := redis.Dial("tcp", "example.com:6379",
  568. redis.DialTLSConfig(&clientTLSConfig),
  569. dialTestConnTLS(pingResponse, &buf),
  570. redis.DialUseTLS(true))
  571. if err != nil {
  572. t.Fatal("dial error:", err)
  573. }
  574. checkPingPong(t, &buf, c)
  575. }
  576. func TestDialTLSSKipVerify(t *testing.T) {
  577. var buf bytes.Buffer
  578. c, err := redis.Dial("tcp", "example.com:6379",
  579. dialTestConnTLS(pingResponse, &buf),
  580. redis.DialTLSSkipVerify(true),
  581. redis.DialUseTLS(true))
  582. if err != nil {
  583. t.Fatal("dial error:", err)
  584. }
  585. checkPingPong(t, &buf, c)
  586. }
  587. // Connect to local instance of Redis running on the default port.
  588. func ExampleDial() {
  589. c, err := redis.Dial("tcp", ":6379")
  590. if err != nil {
  591. // handle error
  592. }
  593. defer c.Close()
  594. }
  595. // Connect to remote instance of Redis using a URL.
  596. func ExampleDialURL() {
  597. c, err := redis.DialURL(os.Getenv("REDIS_URL"))
  598. if err != nil {
  599. // handle connection error
  600. }
  601. defer c.Close()
  602. }
  603. // TextExecError tests handling of errors in a transaction. See
  604. // http://redis.io/topics/transactions for information on how Redis handles
  605. // errors in a transaction.
  606. func TestExecError(t *testing.T) {
  607. c, err := redis.DialDefaultServer()
  608. if err != nil {
  609. t.Fatalf("error connection to database, %v", err)
  610. }
  611. defer c.Close()
  612. // Execute commands that fail before EXEC is called.
  613. c.Do("DEL", "k0")
  614. c.Do("ZADD", "k0", 0, 0)
  615. c.Send("MULTI")
  616. c.Send("NOTACOMMAND", "k0", 0, 0)
  617. c.Send("ZINCRBY", "k0", 0, 0)
  618. v, err := c.Do("EXEC")
  619. if err == nil {
  620. t.Fatalf("EXEC returned values %v, expected error", v)
  621. }
  622. // Execute commands that fail after EXEC is called. The first command
  623. // returns an error.
  624. c.Do("DEL", "k1")
  625. c.Do("ZADD", "k1", 0, 0)
  626. c.Send("MULTI")
  627. c.Send("HSET", "k1", 0, 0)
  628. c.Send("ZINCRBY", "k1", 0, 0)
  629. v, err = c.Do("EXEC")
  630. if err != nil {
  631. t.Fatalf("EXEC returned error %v", err)
  632. }
  633. vs, err := redis.Values(v, nil)
  634. if err != nil {
  635. t.Fatalf("Values(v) returned error %v", err)
  636. }
  637. if len(vs) != 2 {
  638. t.Fatalf("len(vs) == %d, want 2", len(vs))
  639. }
  640. if _, ok := vs[0].(error); !ok {
  641. t.Fatalf("first result is type %T, expected error", vs[0])
  642. }
  643. if _, ok := vs[1].([]byte); !ok {
  644. t.Fatalf("second result is type %T, expected []byte", vs[1])
  645. }
  646. // Execute commands that fail after EXEC is called. The second command
  647. // returns an error.
  648. c.Do("ZADD", "k2", 0, 0)
  649. c.Send("MULTI")
  650. c.Send("ZINCRBY", "k2", 0, 0)
  651. c.Send("HSET", "k2", 0, 0)
  652. v, err = c.Do("EXEC")
  653. if err != nil {
  654. t.Fatalf("EXEC returned error %v", err)
  655. }
  656. vs, err = redis.Values(v, nil)
  657. if err != nil {
  658. t.Fatalf("Values(v) returned error %v", err)
  659. }
  660. if len(vs) != 2 {
  661. t.Fatalf("len(vs) == %d, want 2", len(vs))
  662. }
  663. if _, ok := vs[0].([]byte); !ok {
  664. t.Fatalf("first result is type %T, expected []byte", vs[0])
  665. }
  666. if _, ok := vs[1].(error); !ok {
  667. t.Fatalf("second result is type %T, expected error", vs[2])
  668. }
  669. }
  670. func BenchmarkDoEmpty(b *testing.B) {
  671. b.StopTimer()
  672. c, err := redis.DialDefaultServer()
  673. if err != nil {
  674. b.Fatal(err)
  675. }
  676. defer c.Close()
  677. b.StartTimer()
  678. for i := 0; i < b.N; i++ {
  679. if _, err := c.Do(""); err != nil {
  680. b.Fatal(err)
  681. }
  682. }
  683. }
  684. func BenchmarkDoPing(b *testing.B) {
  685. b.StopTimer()
  686. c, err := redis.DialDefaultServer()
  687. if err != nil {
  688. b.Fatal(err)
  689. }
  690. defer c.Close()
  691. b.StartTimer()
  692. for i := 0; i < b.N; i++ {
  693. if _, err := c.Do("PING"); err != nil {
  694. b.Fatal(err)
  695. }
  696. }
  697. }
  698. var clientTLSConfig, serverTLSConfig tls.Config
  699. func init() {
  700. // The certificate and key for testing TLS dial options was created
  701. // using the command
  702. //
  703. // go run GOROOT/src/crypto/tls/generate_cert.go \
  704. // --rsa-bits 1024 \
  705. // --host 127.0.0.1,::1,example.com --ca \
  706. // --start-date "Jan 1 00:00:00 1970" \
  707. // --duration=1000000h
  708. //
  709. // where GOROOT is the value of GOROOT reported by go env.
  710. localhostCert := []byte(`
  711. -----BEGIN CERTIFICATE-----
  712. MIICFDCCAX2gAwIBAgIRAJfBL4CUxkXcdlFurb3K+iowDQYJKoZIhvcNAQELBQAw
  713. EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
  714. MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
  715. gYkCgYEArizw8WxMUQ3bGHLeuJ4fDrEpy+L2pqrbYRlKk1DasJ/VkB8bImzIpe6+
  716. LGjiYIxvnDCOJ3f3QplcQuiuMyl6f2irJlJsbFT8Lo/3obnuTKAIaqUdJUqBg6y+
  717. JaL8Auk97FvunfKFv8U1AIhgiLzAfQ/3Eaq1yi87Ra6pMjGbTtcCAwEAAaNoMGYw
  718. DgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQF
  719. MAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAAAAAAAAAA
  720. AAAAAAEwDQYJKoZIhvcNAQELBQADgYEAdZ8daIVkyhVwflt5I19m0oq1TycbGO1+
  721. ach7T6cZiBQeNR/SJtxr/wKPEpmvUgbv2BfFrKJ8QoIHYsbNSURTWSEa02pfw4k9
  722. 6RQhij3ZkG79Ituj5OYRORV6Z0HUW32r670BtcuHuAhq7YA6Nxy4FtSt7bAlVdRt
  723. rrKgNsltzMk=
  724. -----END CERTIFICATE-----`)
  725. localhostKey := []byte(`
  726. -----BEGIN RSA PRIVATE KEY-----
  727. MIICXAIBAAKBgQCuLPDxbExRDdsYct64nh8OsSnL4vamqtthGUqTUNqwn9WQHxsi
  728. bMil7r4saOJgjG+cMI4nd/dCmVxC6K4zKXp/aKsmUmxsVPwuj/ehue5MoAhqpR0l
  729. SoGDrL4lovwC6T3sW+6d8oW/xTUAiGCIvMB9D/cRqrXKLztFrqkyMZtO1wIDAQAB
  730. AoGACrc5G6FOEK6JjDeE/Fa+EmlT6PdNtXNNi+vCas3Opo8u1G8VfEi1D4BgstrB
  731. Eq+RLkrOdB8tVyuYQYWPMhabMqF+hhKJN72j0OwfuPlVvTInwb/cKjo/zbH1IA+Y
  732. HenHNK4ywv7/p/9/MvQPJ3I32cQBCgGUW5chVSH5M1sj5gECQQDabQAI1X0uDqCm
  733. KbX9gXVkAgxkFddrt6LBHt57xujFcqEKFE7nwKhDh7DweVs/VEJ+kpid4z+UnLOw
  734. KjtP9JolAkEAzCNBphQ//IsbH5rNs10wIUw3Ks/Oepicvr6kUFbIv+neRzi1iJHa
  735. m6H7EayK3PWgax6BAsR/t0Jc9XV7r2muSwJAVzN09BHnK+ADGtNEKLTqXMbEk6B0
  736. pDhn7ZmZUOkUPN+Kky+QYM11X6Bob1jDqQDGmymDbGUxGO+GfSofC8inUQJAGfci
  737. Eo3g1a6b9JksMPRZeuLG4ZstGErxJRH6tH1Va5PDwitka8qhk8o2tTjNMO3NSdLH
  738. diKoXBcE2/Pll5pJoQJBAIMiiMIzXJhnN4mX8may44J/HvMlMf2xuVH2gNMwmZuc
  739. Bjqn3yoLHaoZVvbWOi0C2TCN4FjXjaLNZGifQPbIcaA=
  740. -----END RSA PRIVATE KEY-----`)
  741. cert, err := tls.X509KeyPair(localhostCert, localhostKey)
  742. if err != nil {
  743. panic(fmt.Sprintf("error creating key pair: %v", err))
  744. }
  745. serverTLSConfig.Certificates = []tls.Certificate{cert}
  746. certificate, err := x509.ParseCertificate(serverTLSConfig.Certificates[0].Certificate[0])
  747. if err != nil {
  748. panic(fmt.Sprintf("error parsing x509 certificate: %v", err))
  749. }
  750. clientTLSConfig.RootCAs = x509.NewCertPool()
  751. clientTLSConfig.RootCAs.AddCert(certificate)
  752. }
  753. func TestWithTimeout(t *testing.T) {
  754. for _, recv := range []bool{true, false} {
  755. for _, defaultTimout := range []time.Duration{0, time.Minute} {
  756. var buf bytes.Buffer
  757. nc := &testConn{Reader: strings.NewReader("+OK\r\n+OK\r\n+OK\r\n+OK\r\n+OK\r\n+OK\r\n+OK\r\n+OK\r\n+OK\r\n+OK\r\n"), Writer: &buf}
  758. c, _ := redis.Dial("", "", redis.DialReadTimeout(defaultTimout), redis.DialNetDial(func(network, addr string) (net.Conn, error) { return nc, nil }))
  759. for i := 0; i < 4; i++ {
  760. var minDeadline, maxDeadline time.Time
  761. // Alternate between default and specified timeout.
  762. if i%2 == 0 {
  763. if defaultTimout != 0 {
  764. minDeadline = time.Now().Add(defaultTimout)
  765. }
  766. if recv {
  767. c.Receive()
  768. } else {
  769. c.Do("PING")
  770. }
  771. if defaultTimout != 0 {
  772. maxDeadline = time.Now().Add(defaultTimout)
  773. }
  774. } else {
  775. timeout := 10 * time.Minute
  776. minDeadline = time.Now().Add(timeout)
  777. if recv {
  778. redis.ReceiveWithTimeout(c, timeout)
  779. } else {
  780. redis.DoWithTimeout(c, timeout, "PING")
  781. }
  782. maxDeadline = time.Now().Add(timeout)
  783. }
  784. // Expect set deadline in expected range.
  785. if nc.readDeadline.Before(minDeadline) || nc.readDeadline.After(maxDeadline) {
  786. t.Errorf("recv %v, %d: do deadline error: %v, %v, %v", recv, i, minDeadline, nc.readDeadline, maxDeadline)
  787. }
  788. }
  789. }
  790. }
  791. }