You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

671 lines
14 KiB

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