conn_test.go 19 KB

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