conn_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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
  15. import (
  16. "bytes"
  17. "io"
  18. "math"
  19. "net"
  20. "os"
  21. "reflect"
  22. "strings"
  23. "testing"
  24. "time"
  25. )
  26. type testConn struct {
  27. io.Reader
  28. io.Writer
  29. }
  30. func (*testConn) Close() error { return nil }
  31. func (*testConn) LocalAddr() net.Addr { return nil }
  32. func (*testConn) RemoteAddr() net.Addr { return nil }
  33. func (*testConn) SetDeadline(t time.Time) error { return nil }
  34. func (*testConn) SetReadDeadline(t time.Time) error { return nil }
  35. func (*testConn) SetWriteDeadline(t time.Time) error { return nil }
  36. func dialTestConn(r io.Reader, w io.Writer) DialOption {
  37. return DialNetDial(func(net, addr string) (net.Conn, error) {
  38. return &testConn{Reader: r, Writer: w}, nil
  39. })
  40. }
  41. var writeTests = []struct {
  42. args []interface{}
  43. expected string
  44. }{
  45. {
  46. []interface{}{"SET", "key", "value"},
  47. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n",
  48. },
  49. {
  50. []interface{}{"SET", "key", "value"},
  51. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n",
  52. },
  53. {
  54. []interface{}{"SET", "key", byte(100)},
  55. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n100\r\n",
  56. },
  57. {
  58. []interface{}{"SET", "key", 100},
  59. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n100\r\n",
  60. },
  61. {
  62. []interface{}{"SET", "key", int64(math.MinInt64)},
  63. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$20\r\n-9223372036854775808\r\n",
  64. },
  65. {
  66. []interface{}{"SET", "key", float64(1349673917.939762)},
  67. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$21\r\n1.349673917939762e+09\r\n",
  68. },
  69. {
  70. []interface{}{"SET", "key", ""},
  71. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$0\r\n\r\n",
  72. },
  73. {
  74. []interface{}{"SET", "key", nil},
  75. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$0\r\n\r\n",
  76. },
  77. {
  78. []interface{}{"ECHO", true, false},
  79. "*3\r\n$4\r\nECHO\r\n$1\r\n1\r\n$1\r\n0\r\n",
  80. },
  81. }
  82. func TestWrite(t *testing.T) {
  83. for _, tt := range writeTests {
  84. var buf bytes.Buffer
  85. c, _ := Dial("", "", dialTestConn(nil, &buf))
  86. err := c.Send(tt.args[0].(string), tt.args[1:]...)
  87. if err != nil {
  88. t.Errorf("Send(%v) returned error %v", tt.args, err)
  89. continue
  90. }
  91. c.Flush()
  92. actual := buf.String()
  93. if actual != tt.expected {
  94. t.Errorf("Send(%v) = %q, want %q", tt.args, actual, tt.expected)
  95. }
  96. }
  97. }
  98. var errorSentinel = &struct{}{}
  99. var readTests = []struct {
  100. reply string
  101. expected interface{}
  102. }{
  103. {
  104. "+OK\r\n",
  105. "OK",
  106. },
  107. {
  108. "+PONG\r\n",
  109. "PONG",
  110. },
  111. {
  112. "@OK\r\n",
  113. errorSentinel,
  114. },
  115. {
  116. "$6\r\nfoobar\r\n",
  117. []byte("foobar"),
  118. },
  119. {
  120. "$-1\r\n",
  121. nil,
  122. },
  123. {
  124. ":1\r\n",
  125. int64(1),
  126. },
  127. {
  128. ":-2\r\n",
  129. int64(-2),
  130. },
  131. {
  132. "*0\r\n",
  133. []interface{}{},
  134. },
  135. {
  136. "*-1\r\n",
  137. nil,
  138. },
  139. {
  140. "*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n",
  141. []interface{}{[]byte("foo"), []byte("bar"), []byte("Hello"), []byte("World")},
  142. },
  143. {
  144. "*3\r\n$3\r\nfoo\r\n$-1\r\n$3\r\nbar\r\n",
  145. []interface{}{[]byte("foo"), nil, []byte("bar")},
  146. },
  147. {
  148. // "x" is not a valid length
  149. "$x\r\nfoobar\r\n",
  150. errorSentinel,
  151. },
  152. {
  153. // -2 is not a valid length
  154. "$-2\r\n",
  155. errorSentinel,
  156. },
  157. {
  158. // "x" is not a valid integer
  159. ":x\r\n",
  160. errorSentinel,
  161. },
  162. {
  163. // missing \r\n following value
  164. "$6\r\nfoobar",
  165. errorSentinel,
  166. },
  167. {
  168. // short value
  169. "$6\r\nxx",
  170. errorSentinel,
  171. },
  172. {
  173. // long value
  174. "$6\r\nfoobarx\r\n",
  175. errorSentinel,
  176. },
  177. }
  178. func TestRead(t *testing.T) {
  179. for _, tt := range readTests {
  180. c, _ := Dial("", "", dialTestConn(strings.NewReader(tt.reply), nil))
  181. actual, err := c.Receive()
  182. if tt.expected == errorSentinel {
  183. if err == nil {
  184. t.Errorf("Receive(%q) did not return expected error", tt.reply)
  185. }
  186. } else {
  187. if err != nil {
  188. t.Errorf("Receive(%q) returned error %v", tt.reply, err)
  189. continue
  190. }
  191. if !reflect.DeepEqual(actual, tt.expected) {
  192. t.Errorf("Receive(%q) = %v, want %v", tt.reply, actual, tt.expected)
  193. }
  194. }
  195. }
  196. }
  197. var testCommands = []struct {
  198. args []interface{}
  199. expected interface{}
  200. }{
  201. {
  202. []interface{}{"PING"},
  203. "PONG",
  204. },
  205. {
  206. []interface{}{"SET", "foo", "bar"},
  207. "OK",
  208. },
  209. {
  210. []interface{}{"GET", "foo"},
  211. []byte("bar"),
  212. },
  213. {
  214. []interface{}{"GET", "nokey"},
  215. nil,
  216. },
  217. {
  218. []interface{}{"MGET", "nokey", "foo"},
  219. []interface{}{nil, []byte("bar")},
  220. },
  221. {
  222. []interface{}{"INCR", "mycounter"},
  223. int64(1),
  224. },
  225. {
  226. []interface{}{"LPUSH", "mylist", "foo"},
  227. int64(1),
  228. },
  229. {
  230. []interface{}{"LPUSH", "mylist", "bar"},
  231. int64(2),
  232. },
  233. {
  234. []interface{}{"LRANGE", "mylist", 0, -1},
  235. []interface{}{[]byte("bar"), []byte("foo")},
  236. },
  237. {
  238. []interface{}{"MULTI"},
  239. "OK",
  240. },
  241. {
  242. []interface{}{"LRANGE", "mylist", 0, -1},
  243. "QUEUED",
  244. },
  245. {
  246. []interface{}{"PING"},
  247. "QUEUED",
  248. },
  249. {
  250. []interface{}{"EXEC"},
  251. []interface{}{
  252. []interface{}{[]byte("bar"), []byte("foo")},
  253. "PONG",
  254. },
  255. },
  256. }
  257. func TestDoCommands(t *testing.T) {
  258. c, err := DialDefaultServer()
  259. if err != nil {
  260. t.Fatalf("error connection to database, %v", err)
  261. }
  262. defer c.Close()
  263. for _, cmd := range testCommands {
  264. actual, err := c.Do(cmd.args[0].(string), cmd.args[1:]...)
  265. if err != nil {
  266. t.Errorf("Do(%v) returned error %v", cmd.args, err)
  267. continue
  268. }
  269. if !reflect.DeepEqual(actual, cmd.expected) {
  270. t.Errorf("Do(%v) = %v, want %v", cmd.args, actual, cmd.expected)
  271. }
  272. }
  273. }
  274. func TestPipelineCommands(t *testing.T) {
  275. c, err := DialDefaultServer()
  276. if err != nil {
  277. t.Fatalf("error connection to database, %v", err)
  278. }
  279. defer c.Close()
  280. for _, cmd := range testCommands {
  281. if err := c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil {
  282. t.Fatalf("Send(%v) returned error %v", cmd.args, err)
  283. }
  284. }
  285. if err := c.Flush(); err != nil {
  286. t.Errorf("Flush() returned error %v", err)
  287. }
  288. for _, cmd := range testCommands {
  289. actual, err := c.Receive()
  290. if err != nil {
  291. t.Fatalf("Receive(%v) returned error %v", cmd.args, err)
  292. }
  293. if !reflect.DeepEqual(actual, cmd.expected) {
  294. t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected)
  295. }
  296. }
  297. }
  298. func TestBlankCommmand(t *testing.T) {
  299. c, err := DialDefaultServer()
  300. if err != nil {
  301. t.Fatalf("error connection to database, %v", err)
  302. }
  303. defer c.Close()
  304. for _, cmd := range testCommands {
  305. if err = c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil {
  306. t.Fatalf("Send(%v) returned error %v", cmd.args, err)
  307. }
  308. }
  309. reply, err := Values(c.Do(""))
  310. if err != nil {
  311. t.Fatalf("Do() returned error %v", err)
  312. }
  313. if len(reply) != len(testCommands) {
  314. t.Fatalf("len(reply)=%d, want %d", len(reply), len(testCommands))
  315. }
  316. for i, cmd := range testCommands {
  317. actual := reply[i]
  318. if !reflect.DeepEqual(actual, cmd.expected) {
  319. t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected)
  320. }
  321. }
  322. }
  323. func TestRecvBeforeSend(t *testing.T) {
  324. c, err := DialDefaultServer()
  325. if err != nil {
  326. t.Fatalf("error connection to database, %v", err)
  327. }
  328. defer c.Close()
  329. done := make(chan struct{})
  330. go func() {
  331. c.Receive()
  332. close(done)
  333. }()
  334. time.Sleep(time.Millisecond)
  335. c.Send("PING")
  336. c.Flush()
  337. <-done
  338. _, err = c.Do("")
  339. if err != nil {
  340. t.Fatalf("error=%v", err)
  341. }
  342. }
  343. func TestError(t *testing.T) {
  344. c, err := DialDefaultServer()
  345. if err != nil {
  346. t.Fatalf("error connection to database, %v", err)
  347. }
  348. defer c.Close()
  349. c.Do("SET", "key", "val")
  350. _, err = c.Do("HSET", "key", "fld", "val")
  351. if err == nil {
  352. t.Errorf("Expected err for HSET on string key.")
  353. }
  354. if c.Err() != nil {
  355. t.Errorf("Conn has Err()=%v, expect nil", c.Err())
  356. }
  357. _, err = c.Do("SET", "key", "val")
  358. if err != nil {
  359. t.Errorf("Do(SET, key, val) returned error %v, expected nil.", err)
  360. }
  361. }
  362. func TestReadTimeout(t *testing.T) {
  363. l, err := net.Listen("tcp", "127.0.0.1:0")
  364. if err != nil {
  365. t.Fatalf("net.Listen returned %v", err)
  366. }
  367. defer l.Close()
  368. go func() {
  369. for {
  370. c, err1 := l.Accept()
  371. if err1 != nil {
  372. return
  373. }
  374. go func() {
  375. time.Sleep(time.Second)
  376. c.Write([]byte("+OK\r\n"))
  377. c.Close()
  378. }()
  379. }
  380. }()
  381. // Do
  382. c1, err := Dial(l.Addr().Network(), l.Addr().String(), DialReadTimeout(time.Millisecond))
  383. if err != nil {
  384. t.Fatalf("Dial returned %v", err)
  385. }
  386. defer c1.Close()
  387. _, err = c1.Do("PING")
  388. if err == nil {
  389. t.Fatalf("c1.Do() returned nil, expect error")
  390. }
  391. if c1.Err() == nil {
  392. t.Fatalf("c1.Err() = nil, expect error")
  393. }
  394. // Send/Flush/Receive
  395. c2, err := Dial(l.Addr().Network(), l.Addr().String(), DialReadTimeout(time.Millisecond))
  396. if err != nil {
  397. t.Fatalf("Dial returned %v", err)
  398. }
  399. defer c2.Close()
  400. c2.Send("PING")
  401. c2.Flush()
  402. _, err = c2.Receive()
  403. if err == nil {
  404. t.Fatalf("c2.Receive() returned nil, expect error")
  405. }
  406. if c2.Err() == nil {
  407. t.Fatalf("c2.Err() = nil, expect error")
  408. }
  409. }
  410. var dialErrors = []struct {
  411. rawurl string
  412. expectedError string
  413. }{
  414. {
  415. "localhost",
  416. "invalid redis URL scheme",
  417. },
  418. // The error message for invalid hosts is diffferent in different
  419. // versions of Go, so just check that there is an error message.
  420. {
  421. "redis://weird url",
  422. "",
  423. },
  424. {
  425. "redis://foo:bar:baz",
  426. "",
  427. },
  428. {
  429. "http://www.google.com",
  430. "invalid redis URL scheme: http",
  431. },
  432. {
  433. "redis://localhost:6379/abc123",
  434. "invalid database: abc123",
  435. },
  436. }
  437. func TestDialURLErrors(t *testing.T) {
  438. for _, d := range dialErrors {
  439. _, err := DialURL(d.rawurl)
  440. if err == nil || !strings.Contains(err.Error(), d.expectedError) {
  441. t.Errorf("DialURL did not return expected error (expected %v to contain %s)", err, d.expectedError)
  442. }
  443. }
  444. }
  445. func TestDialURLPort(t *testing.T) {
  446. checkPort := func(network, address string) (net.Conn, error) {
  447. if address != "localhost:6379" {
  448. t.Errorf("DialURL did not set port to 6379 by default (got %v)", address)
  449. }
  450. return nil, nil
  451. }
  452. _, err := DialURL("redis://localhost", DialNetDial(checkPort))
  453. if err != nil {
  454. t.Error("dial error:", err)
  455. }
  456. }
  457. func TestDialURLHost(t *testing.T) {
  458. checkHost := func(network, address string) (net.Conn, error) {
  459. if address != "localhost:6379" {
  460. t.Errorf("DialURL did not set host to localhost by default (got %v)", address)
  461. }
  462. return nil, nil
  463. }
  464. _, err := DialURL("redis://:6379", DialNetDial(checkHost))
  465. if err != nil {
  466. t.Error("dial error:", err)
  467. }
  468. }
  469. func TestDialURLPassword(t *testing.T) {
  470. var buf bytes.Buffer
  471. _, err := DialURL("redis://x:abc123@localhost", dialTestConn(strings.NewReader("+OK\r\n"), &buf))
  472. if err != nil {
  473. t.Error("dial error:", err)
  474. }
  475. expected := "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"
  476. actual := buf.String()
  477. if actual != expected {
  478. t.Errorf("commands = %q, want %q", actual, expected)
  479. }
  480. }
  481. func TestDialURLDatabase(t *testing.T) {
  482. var buf bytes.Buffer
  483. _, err := DialURL("redis://localhost/3", dialTestConn(strings.NewReader("+OK\r\n"), &buf))
  484. if err != nil {
  485. t.Error("dial error:", err)
  486. }
  487. expected := "*2\r\n$6\r\nSELECT\r\n$1\r\n3\r\n"
  488. actual := buf.String()
  489. if actual != expected {
  490. t.Errorf("commands = %q, want %q", actual, expected)
  491. }
  492. }
  493. // Connect to local instance of Redis running on the default port.
  494. func ExampleDial() {
  495. c, err := Dial("tcp", ":6379")
  496. if err != nil {
  497. // handle error
  498. }
  499. defer c.Close()
  500. }
  501. // Connect to remote instance of Redis using a URL.
  502. func ExampleDialURL() {
  503. c, err := DialURL(os.Getenv("REDIS_URL"))
  504. if err != nil {
  505. // handle connection error
  506. }
  507. defer c.Close()
  508. }
  509. // TextExecError tests handling of errors in a transaction. See
  510. // http://io/topics/transactions for information on how Redis handles
  511. // errors in a transaction.
  512. func TestExecError(t *testing.T) {
  513. c, err := DialDefaultServer()
  514. if err != nil {
  515. t.Fatalf("error connection to database, %v", err)
  516. }
  517. defer c.Close()
  518. // Execute commands that fail before EXEC is called.
  519. c.Do("DEL", "k0")
  520. c.Do("ZADD", "k0", 0, 0)
  521. c.Send("MULTI")
  522. c.Send("NOTACOMMAND", "k0", 0, 0)
  523. c.Send("ZINCRBY", "k0", 0, 0)
  524. v, err := c.Do("EXEC")
  525. if err == nil {
  526. t.Fatalf("EXEC returned values %v, expected error", v)
  527. }
  528. // Execute commands that fail after EXEC is called. The first command
  529. // returns an error.
  530. c.Do("DEL", "k1")
  531. c.Do("ZADD", "k1", 0, 0)
  532. c.Send("MULTI")
  533. c.Send("HSET", "k1", 0, 0)
  534. c.Send("ZINCRBY", "k1", 0, 0)
  535. v, err = c.Do("EXEC")
  536. if err != nil {
  537. t.Fatalf("EXEC returned error %v", err)
  538. }
  539. vs, err := Values(v, nil)
  540. if err != nil {
  541. t.Fatalf("Values(v) returned error %v", err)
  542. }
  543. if len(vs) != 2 {
  544. t.Fatalf("len(vs) == %d, want 2", len(vs))
  545. }
  546. if _, ok := vs[0].(error); !ok {
  547. t.Fatalf("first result is type %T, expected error", vs[0])
  548. }
  549. if _, ok := vs[1].([]byte); !ok {
  550. t.Fatalf("second result is type %T, expected []byte", vs[1])
  551. }
  552. // Execute commands that fail after EXEC is called. The second command
  553. // returns an error.
  554. c.Do("ZADD", "k2", 0, 0)
  555. c.Send("MULTI")
  556. c.Send("ZINCRBY", "k2", 0, 0)
  557. c.Send("HSET", "k2", 0, 0)
  558. v, err = c.Do("EXEC")
  559. if err != nil {
  560. t.Fatalf("EXEC returned error %v", err)
  561. }
  562. vs, err = Values(v, nil)
  563. if err != nil {
  564. t.Fatalf("Values(v) returned error %v", err)
  565. }
  566. if len(vs) != 2 {
  567. t.Fatalf("len(vs) == %d, want 2", len(vs))
  568. }
  569. if _, ok := vs[0].([]byte); !ok {
  570. t.Fatalf("first result is type %T, expected []byte", vs[0])
  571. }
  572. if _, ok := vs[1].(error); !ok {
  573. t.Fatalf("second result is type %T, expected error", vs[2])
  574. }
  575. }
  576. func BenchmarkDoEmpty(b *testing.B) {
  577. b.StopTimer()
  578. c, err := DialDefaultServer()
  579. if err != nil {
  580. b.Fatal(err)
  581. }
  582. defer c.Close()
  583. b.StartTimer()
  584. for i := 0; i < b.N; i++ {
  585. if _, err := c.Do(""); err != nil {
  586. b.Fatal(err)
  587. }
  588. }
  589. }
  590. func BenchmarkDoPing(b *testing.B) {
  591. b.StopTimer()
  592. c, err := DialDefaultServer()
  593. if err != nil {
  594. b.Fatal(err)
  595. }
  596. defer c.Close()
  597. b.StartTimer()
  598. for i := 0; i < b.N; i++ {
  599. if _, err := c.Do("PING"); err != nil {
  600. b.Fatal(err)
  601. }
  602. }
  603. }