conn_test.go 19 KB

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