1 extern crate net2;
2 extern crate rand;
3 extern crate redis;
4 
5 use redis::{Commands, ControlFlow, PipelineCommands, PubSubCommands};
6 
7 use std::collections::{BTreeMap, BTreeSet};
8 use std::collections::{HashMap, HashSet};
9 use std::io::BufReader;
10 use std::thread::{sleep, spawn};
11 use std::time::Duration;
12 
13 use support::*;
14 
15 mod support;
16 
17 #[test]
test_parse_redis_url()18 fn test_parse_redis_url() {
19     let redis_url = format!("redis://127.0.0.1:1234/0");
20     match redis::parse_redis_url(&redis_url) {
21         Ok(_) => assert!(true),
22         Err(_) => assert!(false),
23     }
24     match redis::parse_redis_url("unix:/var/run/redis/redis.sock") {
25         Ok(_) => assert!(true),
26         Err(_) => assert!(false),
27     }
28     match redis::parse_redis_url("127.0.0.1") {
29         Ok(_) => assert!(false),
30         Err(_) => assert!(true),
31     }
32 }
33 
34 #[test]
test_args()35 fn test_args() {
36     let ctx = TestContext::new();
37     let con = ctx.connection();
38 
39     redis::cmd("SET").arg("key1").arg(b"foo").execute(&con);
40     redis::cmd("SET").arg(&["key2", "bar"]).execute(&con);
41 
42     assert_eq!(
43         redis::cmd("MGET").arg(&["key1", "key2"]).query(&con),
44         Ok(("foo".to_string(), b"bar".to_vec()))
45     );
46 }
47 
48 #[test]
test_getset()49 fn test_getset() {
50     let ctx = TestContext::new();
51     let con = ctx.connection();
52 
53     redis::cmd("SET").arg("foo").arg(42).execute(&con);
54     assert_eq!(redis::cmd("GET").arg("foo").query(&con), Ok(42));
55 
56     redis::cmd("SET").arg("bar").arg("foo").execute(&con);
57     assert_eq!(
58         redis::cmd("GET").arg("bar").query(&con),
59         Ok(b"foo".to_vec())
60     );
61 }
62 
63 #[test]
test_incr()64 fn test_incr() {
65     let ctx = TestContext::new();
66     let con = ctx.connection();
67 
68     redis::cmd("SET").arg("foo").arg(42).execute(&con);
69     assert_eq!(redis::cmd("INCR").arg("foo").query(&con), Ok(43usize));
70 }
71 
72 #[test]
test_info()73 fn test_info() {
74     let ctx = TestContext::new();
75     let con = ctx.connection();
76 
77     let info: redis::InfoDict = redis::cmd("INFO").query(&con).unwrap();
78     assert_eq!(
79         info.find(&"role"),
80         Some(&redis::Value::Status("master".to_string()))
81     );
82     assert_eq!(info.get("role"), Some("master".to_string()));
83     assert_eq!(info.get("loading"), Some(false));
84     assert!(info.len() > 0);
85     assert!(info.contains_key(&"role"));
86 }
87 
88 #[test]
test_hash_ops()89 fn test_hash_ops() {
90     let ctx = TestContext::new();
91     let con = ctx.connection();
92 
93     redis::cmd("HSET")
94         .arg("foo")
95         .arg("key_1")
96         .arg(1)
97         .execute(&con);
98     redis::cmd("HSET")
99         .arg("foo")
100         .arg("key_2")
101         .arg(2)
102         .execute(&con);
103 
104     let h: HashMap<String, i32> = redis::cmd("HGETALL").arg("foo").query(&con).unwrap();
105     assert_eq!(h.len(), 2);
106     assert_eq!(h.get("key_1"), Some(&1i32));
107     assert_eq!(h.get("key_2"), Some(&2i32));
108 
109     let h: BTreeMap<String, i32> = redis::cmd("HGETALL").arg("foo").query(&con).unwrap();
110     assert_eq!(h.len(), 2);
111     assert_eq!(h.get("key_1"), Some(&1i32));
112     assert_eq!(h.get("key_2"), Some(&2i32));
113 }
114 
115 #[test]
test_set_ops()116 fn test_set_ops() {
117     let ctx = TestContext::new();
118     let con = ctx.connection();
119 
120     redis::cmd("SADD").arg("foo").arg(1).execute(&con);
121     redis::cmd("SADD").arg("foo").arg(2).execute(&con);
122     redis::cmd("SADD").arg("foo").arg(3).execute(&con);
123 
124     let mut s: Vec<i32> = redis::cmd("SMEMBERS").arg("foo").query(&con).unwrap();
125     s.sort();
126     assert_eq!(s.len(), 3);
127     assert_eq!(&s, &[1, 2, 3]);
128 
129     let set: HashSet<i32> = redis::cmd("SMEMBERS").arg("foo").query(&con).unwrap();
130     assert_eq!(set.len(), 3);
131     assert!(set.contains(&1i32));
132     assert!(set.contains(&2i32));
133     assert!(set.contains(&3i32));
134 
135     let set: BTreeSet<i32> = redis::cmd("SMEMBERS").arg("foo").query(&con).unwrap();
136     assert_eq!(set.len(), 3);
137     assert!(set.contains(&1i32));
138     assert!(set.contains(&2i32));
139     assert!(set.contains(&3i32));
140 }
141 
142 #[test]
test_scan()143 fn test_scan() {
144     let ctx = TestContext::new();
145     let con = ctx.connection();
146 
147     redis::cmd("SADD").arg("foo").arg(1).execute(&con);
148     redis::cmd("SADD").arg("foo").arg(2).execute(&con);
149     redis::cmd("SADD").arg("foo").arg(3).execute(&con);
150 
151     let (cur, mut s): (i32, Vec<i32>) = redis::cmd("SSCAN").arg("foo").arg(0).query(&con).unwrap();
152     s.sort();
153     assert_eq!(cur, 0i32);
154     assert_eq!(s.len(), 3);
155     assert_eq!(&s, &[1, 2, 3]);
156 }
157 
158 #[test]
test_optionals()159 fn test_optionals() {
160     let ctx = TestContext::new();
161     let con = ctx.connection();
162 
163     redis::cmd("SET").arg("foo").arg(1).execute(&con);
164 
165     let (a, b): (Option<i32>, Option<i32>) = redis::cmd("MGET")
166         .arg("foo")
167         .arg("missing")
168         .query(&con)
169         .unwrap();
170     assert_eq!(a, Some(1i32));
171     assert_eq!(b, None);
172 
173     let a = redis::cmd("GET").arg("missing").query(&con).unwrap_or(0i32);
174     assert_eq!(a, 0i32);
175 }
176 
177 #[cfg(feature = "with-rustc-json")]
178 #[test]
test_json()179 fn test_json() {
180     use redis::Json;
181 
182     let ctx = TestContext::new();
183     let con = ctx.connection();
184 
185     redis::cmd("SET").arg("foo").arg("[1, 2, 3]").execute(&con);
186 
187     let json: Json = redis::cmd("GET").arg("foo").query(&con).unwrap();
188     assert_eq!(
189         json,
190         Json::Array(vec![Json::U64(1), Json::U64(2), Json::U64(3)])
191     );
192 }
193 
194 #[test]
test_scanning()195 fn test_scanning() {
196     let ctx = TestContext::new();
197     let con = ctx.connection();
198     let mut unseen = HashSet::new();
199 
200     for x in 0..1000 {
201         redis::cmd("SADD").arg("foo").arg(x).execute(&con);
202         unseen.insert(x);
203     }
204 
205     let iter = redis::cmd("SSCAN")
206         .arg("foo")
207         .cursor_arg(0)
208         .iter(&con)
209         .unwrap();
210 
211     for x in iter {
212         // type inference limitations
213         let x: usize = x;
214         unseen.remove(&x);
215     }
216 
217     assert_eq!(unseen.len(), 0);
218 }
219 
220 #[test]
test_filtered_scanning()221 fn test_filtered_scanning() {
222     let ctx = TestContext::new();
223     let con = ctx.connection();
224     let mut unseen = HashSet::new();
225 
226     for x in 0..3000 {
227         let _: () = con
228             .hset("foo", format!("key_{}_{}", x % 100, x), x)
229             .unwrap();
230         if x % 100 == 0 {
231             unseen.insert(x);
232         }
233     }
234 
235     let iter = con.hscan_match("foo", "key_0_*").unwrap();
236 
237     for x in iter {
238         // type inference limitations
239         let x: usize = x;
240         unseen.remove(&x);
241     }
242 
243     assert_eq!(unseen.len(), 0);
244 }
245 
246 #[test]
test_pipeline()247 fn test_pipeline() {
248     let ctx = TestContext::new();
249     let con = ctx.connection();
250 
251     let ((k1, k2),): ((i32, i32),) = redis::pipe()
252         .cmd("SET")
253         .arg("key_1")
254         .arg(42)
255         .ignore()
256         .cmd("SET")
257         .arg("key_2")
258         .arg(43)
259         .ignore()
260         .cmd("MGET")
261         .arg(&["key_1", "key_2"])
262         .query(&con)
263         .unwrap();
264 
265     assert_eq!(k1, 42);
266     assert_eq!(k2, 43);
267 }
268 
269 #[test]
test_empty_pipeline()270 fn test_empty_pipeline() {
271     let ctx = TestContext::new();
272     let con = ctx.connection();
273 
274     let _: () = redis::pipe().cmd("PING").ignore().query(&con).unwrap();
275 
276     let _: () = redis::pipe().query(&con).unwrap();
277 }
278 
279 #[test]
test_pipeline_transaction()280 fn test_pipeline_transaction() {
281     let ctx = TestContext::new();
282     let con = ctx.connection();
283 
284     let ((k1, k2),): ((i32, i32),) = redis::pipe()
285         .atomic()
286         .cmd("SET")
287         .arg("key_1")
288         .arg(42)
289         .ignore()
290         .cmd("SET")
291         .arg("key_2")
292         .arg(43)
293         .ignore()
294         .cmd("MGET")
295         .arg(&["key_1", "key_2"])
296         .query(&con)
297         .unwrap();
298 
299     assert_eq!(k1, 42);
300     assert_eq!(k2, 43);
301 }
302 
303 #[test]
test_pipeline_reuse_query()304 fn test_pipeline_reuse_query() {
305     let ctx = TestContext::new();
306     let con = ctx.connection();
307 
308     let mut pl = redis::pipe();
309 
310     let ((k1,),): ((i32,),) = pl
311         .cmd("SET")
312         .arg("pkey_1")
313         .arg(42)
314         .ignore()
315         .cmd("MGET")
316         .arg(&["pkey_1"])
317         .query(&con)
318         .unwrap();
319 
320     assert_eq!(k1, 42);
321 
322     redis::cmd("DEL").arg("pkey_1").execute(&con);
323 
324     // The internal commands vector of the pipeline still contains the previous commands.
325     let ((k1,), (k2, k3)): ((i32,), (i32, i32)) = pl
326         .cmd("SET")
327         .arg("pkey_2")
328         .arg(43)
329         .ignore()
330         .cmd("MGET")
331         .arg(&["pkey_1"])
332         .arg(&["pkey_2"])
333         .query(&con)
334         .unwrap();
335 
336     assert_eq!(k1, 42);
337     assert_eq!(k2, 42);
338     assert_eq!(k3, 43);
339 }
340 
341 #[test]
test_pipeline_reuse_query_clear()342 fn test_pipeline_reuse_query_clear() {
343     let ctx = TestContext::new();
344     let con = ctx.connection();
345 
346     let mut pl = redis::pipe();
347 
348     let ((k1,),): ((i32,),) = pl
349         .cmd("SET")
350         .arg("pkey_1")
351         .arg(44)
352         .ignore()
353         .cmd("MGET")
354         .arg(&["pkey_1"])
355         .query(&con)
356         .unwrap();
357     pl.clear();
358 
359     assert_eq!(k1, 44);
360 
361     redis::cmd("DEL").arg("pkey_1").execute(&con);
362 
363     let ((k1, k2),): ((bool, i32),) = pl
364         .cmd("SET")
365         .arg("pkey_2")
366         .arg(45)
367         .ignore()
368         .cmd("MGET")
369         .arg(&["pkey_1"])
370         .arg(&["pkey_2"])
371         .query(&con)
372         .unwrap();
373     pl.clear();
374 
375     assert_eq!(k1, false);
376     assert_eq!(k2, 45);
377 }
378 
379 #[test]
test_real_transaction()380 fn test_real_transaction() {
381     let ctx = TestContext::new();
382     let con = ctx.connection();
383 
384     let key = "the_key";
385     let _: () = redis::cmd("SET").arg(key).arg(42).query(&con).unwrap();
386 
387     loop {
388         let _: () = redis::cmd("WATCH").arg(key).query(&con).unwrap();
389         let val: isize = redis::cmd("GET").arg(key).query(&con).unwrap();
390         let response: Option<(isize,)> = redis::pipe()
391             .atomic()
392             .cmd("SET")
393             .arg(key)
394             .arg(val + 1)
395             .ignore()
396             .cmd("GET")
397             .arg(key)
398             .query(&con)
399             .unwrap();
400 
401         match response {
402             None => {
403                 continue;
404             }
405             Some(response) => {
406                 assert_eq!(response, (43,));
407                 break;
408             }
409         }
410     }
411 }
412 
413 #[test]
test_real_transaction_highlevel()414 fn test_real_transaction_highlevel() {
415     let ctx = TestContext::new();
416     let con = ctx.connection();
417 
418     let key = "the_key";
419     let _: () = redis::cmd("SET").arg(key).arg(42).query(&con).unwrap();
420 
421     let response: (isize,) = redis::transaction(&con, &[key], |pipe| {
422         let val: isize = redis::cmd("GET").arg(key).query(&con)?;
423         pipe.cmd("SET")
424             .arg(key)
425             .arg(val + 1)
426             .ignore()
427             .cmd("GET")
428             .arg(key)
429             .query(&con)
430     })
431     .unwrap();
432 
433     assert_eq!(response, (43,));
434 }
435 
436 #[test]
test_pubsub()437 fn test_pubsub() {
438     use std::sync::{Arc, Barrier};
439     let ctx = TestContext::new();
440     let con = ctx.connection();
441 
442     // Connection for subscriber api
443     let mut pubsub_con = ctx.connection();
444 
445     // Barrier is used to make test thread wait to publish
446     // until after the pubsub thread has subscribed.
447     let barrier = Arc::new(Barrier::new(2));
448     let pubsub_barrier = barrier.clone();
449 
450     let thread = spawn(move || {
451         let mut pubsub = pubsub_con.as_pubsub();
452         pubsub.subscribe("foo").unwrap();
453 
454         let _ = pubsub_barrier.wait();
455 
456         let msg = pubsub.get_message().unwrap();
457         assert_eq!(msg.get_channel(), Ok("foo".to_string()));
458         assert_eq!(msg.get_payload(), Ok(42));
459 
460         let msg = pubsub.get_message().unwrap();
461         assert_eq!(msg.get_channel(), Ok("foo".to_string()));
462         assert_eq!(msg.get_payload(), Ok(23));
463     });
464 
465     let _ = barrier.wait();
466     redis::cmd("PUBLISH").arg("foo").arg(42).execute(&con);
467     // We can also call the command directly
468     assert_eq!(con.publish("foo", 23), Ok(1));
469 
470     thread.join().ok().expect("Something went wrong");
471 }
472 
473 #[test]
test_pubsub_unsubscribe()474 fn test_pubsub_unsubscribe() {
475     let ctx = TestContext::new();
476     let mut con = ctx.connection();
477 
478     {
479         let mut pubsub = con.as_pubsub();
480         pubsub.subscribe("foo").unwrap();
481         pubsub.subscribe("bar").unwrap();
482         pubsub.subscribe("baz").unwrap();
483         pubsub.psubscribe("foo*").unwrap();
484         pubsub.psubscribe("bar*").unwrap();
485         pubsub.psubscribe("baz*").unwrap();
486     }
487 
488     // Connection should be usable again for non-pubsub commands
489     let _: redis::Value = con.set("foo", "bar").unwrap();
490     let foo: String = con.get("foo").unwrap();
491     assert_eq!(&foo[..], "bar");
492 }
493 
494 #[test]
test_pubsub_unsubscribe_no_subs()495 fn test_pubsub_unsubscribe_no_subs() {
496     let ctx = TestContext::new();
497     let mut con = ctx.connection();
498 
499     {
500         let _pubsub = con.as_pubsub();
501     }
502 
503     // Connection should be usable again for non-pubsub commands
504     let _: redis::Value = con.set("foo", "bar").unwrap();
505     let foo: String = con.get("foo").unwrap();
506     assert_eq!(&foo[..], "bar");
507 }
508 
509 #[test]
test_pubsub_unsubscribe_one_sub()510 fn test_pubsub_unsubscribe_one_sub() {
511     let ctx = TestContext::new();
512     let mut con = ctx.connection();
513 
514     {
515         let mut pubsub = con.as_pubsub();
516         pubsub.subscribe("foo").unwrap();
517     }
518 
519     // Connection should be usable again for non-pubsub commands
520     let _: redis::Value = con.set("foo", "bar").unwrap();
521     let foo: String = con.get("foo").unwrap();
522     assert_eq!(&foo[..], "bar");
523 }
524 
525 #[test]
test_pubsub_unsubscribe_one_sub_one_psub()526 fn test_pubsub_unsubscribe_one_sub_one_psub() {
527     let ctx = TestContext::new();
528     let mut con = ctx.connection();
529 
530     {
531         let mut pubsub = con.as_pubsub();
532         pubsub.subscribe("foo").unwrap();
533         pubsub.psubscribe("foo*").unwrap();
534     }
535 
536     // Connection should be usable again for non-pubsub commands
537     let _: redis::Value = con.set("foo", "bar").unwrap();
538     let foo: String = con.get("foo").unwrap();
539     assert_eq!(&foo[..], "bar");
540 }
541 
542 #[test]
scoped_pubsub()543 fn scoped_pubsub() {
544     let ctx = TestContext::new();
545     let con = ctx.connection();
546 
547     // Connection for subscriber api
548     let mut pubsub_con = ctx.connection();
549 
550     let thread = spawn(move || {
551         let mut count = 0;
552         pubsub_con
553             .subscribe(&["foo", "bar"], |msg| {
554                 count += 1;
555                 match count {
556                     1 => {
557                         assert_eq!(msg.get_channel(), Ok("foo".to_string()));
558                         assert_eq!(msg.get_payload(), Ok(42));
559                         ControlFlow::Continue
560                     }
561                     2 => {
562                         assert_eq!(msg.get_channel(), Ok("bar".to_string()));
563                         assert_eq!(msg.get_payload(), Ok(23));
564                         ControlFlow::Break(())
565                     }
566                     _ => ControlFlow::Break(()),
567                 }
568             })
569             .unwrap();
570 
571         pubsub_con
572     });
573 
574     // Can't use a barrier in this case since there's no opportunity to run code
575     // between channel subscription and blocking for messages.
576     sleep(Duration::from_millis(100));
577 
578     redis::cmd("PUBLISH").arg("foo").arg(42).execute(&con);
579     assert_eq!(con.publish("bar", 23), Ok(1));
580 
581     // Wait for thread
582     let pubsub_con = thread.join().ok().expect("pubsub thread terminates ok");
583 
584     // Connection should be usable again for non-pubsub commands
585     let _: redis::Value = pubsub_con.set("foo", "bar").unwrap();
586     let foo: String = pubsub_con.get("foo").unwrap();
587     assert_eq!(&foo[..], "bar");
588 }
589 
590 #[test]
test_script()591 fn test_script() {
592     let ctx = TestContext::new();
593     let con = ctx.connection();
594 
595     let script = redis::Script::new(
596         r"
597        return {redis.call('GET', KEYS[1]), ARGV[1]}
598     ",
599     );
600 
601     let _: () = redis::cmd("SET")
602         .arg("my_key")
603         .arg("foo")
604         .query(&con)
605         .unwrap();
606     let response = script.key("my_key").arg(42).invoke(&con);
607 
608     assert_eq!(response, Ok(("foo".to_string(), 42)));
609 }
610 
611 #[test]
test_tuple_args()612 fn test_tuple_args() {
613     let ctx = TestContext::new();
614     let con = ctx.connection();
615 
616     redis::cmd("HMSET")
617         .arg("my_key")
618         .arg(&[("field_1", 42), ("field_2", 23)])
619         .execute(&con);
620 
621     assert_eq!(
622         redis::cmd("HGET").arg("my_key").arg("field_1").query(&con),
623         Ok(42)
624     );
625     assert_eq!(
626         redis::cmd("HGET").arg("my_key").arg("field_2").query(&con),
627         Ok(23)
628     );
629 }
630 
631 #[test]
test_nice_api()632 fn test_nice_api() {
633     let ctx = TestContext::new();
634     let con = ctx.connection();
635 
636     assert_eq!(con.set("my_key", 42), Ok(()));
637     assert_eq!(con.get("my_key"), Ok(42));
638 
639     let (k1, k2): (i32, i32) = redis::pipe()
640         .atomic()
641         .set("key_1", 42)
642         .ignore()
643         .set("key_2", 43)
644         .ignore()
645         .get("key_1")
646         .get("key_2")
647         .query(&con)
648         .unwrap();
649 
650     assert_eq!(k1, 42);
651     assert_eq!(k2, 43);
652 }
653 
654 #[test]
test_auto_m_versions()655 fn test_auto_m_versions() {
656     let ctx = TestContext::new();
657     let con = ctx.connection();
658 
659     assert_eq!(con.set_multiple(&[("key1", 1), ("key2", 2)]), Ok(()));
660     assert_eq!(con.get(&["key1", "key2"]), Ok((1, 2)));
661 }
662 
663 #[test]
test_nice_hash_api()664 fn test_nice_hash_api() {
665     let ctx = TestContext::new();
666     let con = ctx.connection();
667 
668     assert_eq!(
669         con.hset_multiple("my_hash", &[("f1", 1), ("f2", 2), ("f3", 4), ("f4", 8)]),
670         Ok(())
671     );
672 
673     let hm: HashMap<String, isize> = con.hgetall("my_hash").unwrap();
674     assert_eq!(hm.get("f1"), Some(&1));
675     assert_eq!(hm.get("f2"), Some(&2));
676     assert_eq!(hm.get("f3"), Some(&4));
677     assert_eq!(hm.get("f4"), Some(&8));
678     assert_eq!(hm.len(), 4);
679 
680     let hm: BTreeMap<String, isize> = con.hgetall("my_hash").unwrap();
681     assert_eq!(hm.get("f1"), Some(&1));
682     assert_eq!(hm.get("f2"), Some(&2));
683     assert_eq!(hm.get("f3"), Some(&4));
684     assert_eq!(hm.get("f4"), Some(&8));
685     assert_eq!(hm.len(), 4);
686 
687     let v: Vec<(String, isize)> = con.hgetall("my_hash").unwrap();
688     assert_eq!(
689         v,
690         vec![
691             ("f1".to_string(), 1),
692             ("f2".to_string(), 2),
693             ("f3".to_string(), 4),
694             ("f4".to_string(), 8),
695         ]
696     );
697 
698     assert_eq!(con.hget("my_hash", &["f2", "f4"]), Ok((2, 8)));
699     assert_eq!(con.hincr("my_hash", "f1", 1), Ok(2));
700     assert_eq!(con.hincr("my_hash", "f2", 1.5f32), Ok(3.5f32));
701     assert_eq!(con.hexists("my_hash", "f2"), Ok(true));
702     assert_eq!(con.hdel("my_hash", &["f1", "f2"]), Ok(()));
703     assert_eq!(con.hexists("my_hash", "f2"), Ok(false));
704 
705     let iter: redis::Iter<(String, isize)> = con.hscan("my_hash").unwrap();
706     let mut found = HashSet::new();
707     for item in iter {
708         found.insert(item);
709     }
710 
711     assert_eq!(found.len(), 2);
712     assert_eq!(found.contains(&("f3".to_string(), 4)), true);
713     assert_eq!(found.contains(&("f4".to_string(), 8)), true);
714 }
715 
716 #[test]
test_nice_list_api()717 fn test_nice_list_api() {
718     let ctx = TestContext::new();
719     let con = ctx.connection();
720 
721     assert_eq!(con.rpush("my_list", &[1, 2, 3, 4]), Ok(4));
722     assert_eq!(con.rpush("my_list", &[5, 6, 7, 8]), Ok(8));
723     assert_eq!(con.llen("my_list"), Ok(8));
724 
725     assert_eq!(con.lpop("my_list"), Ok(1));
726     assert_eq!(con.llen("my_list"), Ok(7));
727 
728     assert_eq!(con.lrange("my_list", 0, 2), Ok((2, 3, 4)));
729 
730     assert_eq!(con.lset("my_list", 0, 4), Ok(true));
731     assert_eq!(con.lrange("my_list", 0, 2), Ok((4, 3, 4)));
732 }
733 
734 #[test]
test_tuple_decoding_regression()735 fn test_tuple_decoding_regression() {
736     let ctx = TestContext::new();
737     let con = ctx.connection();
738 
739     assert_eq!(con.del("my_zset"), Ok(()));
740     assert_eq!(con.zadd("my_zset", "one", 1), Ok(1));
741     assert_eq!(con.zadd("my_zset", "two", 2), Ok(1));
742 
743     let vec: Vec<(String, u32)> = con.zrangebyscore_withscores("my_zset", 0, 10).unwrap();
744     assert_eq!(vec.len(), 2);
745 
746     assert_eq!(con.del("my_zset"), Ok(1));
747 
748     let vec: Vec<(String, u32)> = con.zrangebyscore_withscores("my_zset", 0, 10).unwrap();
749     assert_eq!(vec.len(), 0);
750 }
751 
752 #[test]
test_bit_operations()753 fn test_bit_operations() {
754     let ctx = TestContext::new();
755     let con = ctx.connection();
756 
757     assert_eq!(con.setbit("bitvec", 10, true), Ok(false));
758     assert_eq!(con.getbit("bitvec", 10), Ok(true));
759 }
760 
761 #[test]
test_invalid_protocol()762 fn test_invalid_protocol() {
763     use redis::{Parser, RedisResult};
764     use std::error::Error;
765     use std::io::Write;
766     use std::net::TcpListener;
767     use std::thread;
768 
769     let listener = TcpListener::bind("127.0.0.1:0").unwrap();
770     let port = listener.local_addr().unwrap().port();
771 
772     let child = thread::spawn(move || -> Result<(), Box<Error + Send + Sync>> {
773         let mut stream = BufReader::new(listener.incoming().next().unwrap()?);
774         // read the request and respond with garbage
775         let _: redis::Value = Parser::new(&mut stream).parse_value()?;
776         stream.get_mut().write_all(b"garbage ---!#!#\r\n\r\n\n\r")?;
777         // block until the stream is shutdown by the client
778         let _: RedisResult<redis::Value> = Parser::new(&mut stream).parse_value();
779         Ok(())
780     });
781     sleep(Duration::from_millis(100));
782     // some work here
783     let cli = redis::Client::open(&format!("redis://127.0.0.1:{}", port)[..]).unwrap();
784     let con = cli.get_connection().unwrap();
785 
786     let mut result: redis::RedisResult<u8>;
787     // first requests returns ResponseError
788     result = con.del("my_zset");
789     assert_eq!(result.unwrap_err().kind(), redis::ErrorKind::ResponseError);
790     // from now on it's IoError due to the closed connection
791     result = con.del("my_zset");
792     assert_eq!(result.unwrap_err().kind(), redis::ErrorKind::IoError);
793 
794     child.join().unwrap().unwrap();
795 }
796 
797 #[test]
test_redis_server_down()798 fn test_redis_server_down() {
799     let mut ctx = TestContext::new();
800     let con = ctx.connection();
801 
802     let ping = redis::cmd("PING").query::<String>(&con);
803     assert_eq!(ping, Ok("PONG".into()));
804 
805     ctx.stop_server();
806 
807     let ping = redis::cmd("PING").query::<String>(&con);
808 
809     assert_eq!(ping.is_err(), true);
810     assert_eq!(con.is_open(), false);
811 }
812