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