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