conn_test.go 19 KB

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