// #![allow(clippy::let_unit_value)] // use lunatic::{sleep, spawn_link, test}; // use lunatic_redis::{ // Client, Commands, ConnectionInfo, ConnectionLike, ControlFlow, ErrorKind, Expiry, // PubSubCommands, RedisResult, // }; // use std::collections::{BTreeMap, BTreeSet}; // use std::collections::{HashMap, HashSet}; // use std::time::Duration; // use crate::support::*; // mod support; // #[test] // fn test_parse_redis_url() { // let redis_url = "redis://127.0.0.1:1234/0".to_string(); // lunatic_redis::parse_redis_url(&redis_url).unwrap(); // lunatic_redis::parse_redis_url("unix:/var/run/redis/redis.sock").unwrap(); // assert!(lunatic_redis::parse_redis_url("127.0.0.1").is_none()); // } // #[test] // fn test_redis_url_fromstr() { // let _info: ConnectionInfo = "redis://127.0.0.1:1234/0".parse().unwrap(); // } // #[test] // fn test_args() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("key1") // .arg(b"foo") // .execute(&mut con); // lunatic_redis::cmd("SET") // .arg(&["key2", "bar"]) // .execute(&mut con); // assert_eq!( // lunatic_redis::cmd("MGET") // .arg(&["key1", "key2"]) // .query(&mut con), // Ok(("foo".to_string(), b"bar".to_vec())) // ); // } // #[test] // fn test_getset() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(42) // .execute(&mut con); // assert_eq!(lunatic_redis::cmd("GET").arg("foo").query(&mut con), Ok(42)); // lunatic_redis::cmd("SET") // .arg("bar") // .arg("foo") // .execute(&mut con); // assert_eq!( // lunatic_redis::cmd("GET").arg("bar").query(&mut con), // Ok(b"foo".to_vec()) // ); // } // #[test] // fn test_incr() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(42) // .execute(&mut con); // assert_eq!( // lunatic_redis::cmd("INCR").arg("foo").query(&mut con), // Ok(43usize) // ); // } // #[test] // fn test_getdel() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(42) // .execute(&mut con); // assert_eq!(con.get_del("foo"), Ok(42usize)); // assert_eq!( // lunatic_redis::cmd("GET").arg("foo").query(&mut con), // Ok(None::) // ); // } // #[test] // fn test_getex() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(42usize) // .execute(&mut con); // // Return of get_ex must match set value // let ret_value = con.get_ex::<_, usize>("foo", Expiry::EX(1)).unwrap(); // assert_eq!(ret_value, 42usize); // // Get before expiry time must also return value // sleep(Duration::from_millis(100)); // let delayed_get = con.get::<_, usize>("foo").unwrap(); // assert_eq!(delayed_get, 42usize); // // Get after expiry time mustn't return value // sleep(Duration::from_secs(1)); // let after_expire_get = con.get::<_, Option>("foo").unwrap(); // assert_eq!(after_expire_get, None); // // Persist option test prep // lunatic_redis::cmd("SET") // .arg("foo") // .arg(420usize) // .execute(&mut con); // // Return of get_ex with persist option must match set value // let ret_value = con.get_ex::<_, usize>("foo", Expiry::PERSIST).unwrap(); // assert_eq!(ret_value, 420usize); // // Get after persist get_ex must return value // sleep(Duration::from_millis(200)); // let delayed_get = con.get::<_, usize>("foo").unwrap(); // assert_eq!(delayed_get, 420usize); // } // #[test] // fn test_info() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let info: lunatic_redis::InfoDict = lunatic_redis::cmd("INFO").query(&mut con).unwrap(); // assert_eq!( // info.find(&"role"), // Some(&lunatic_redis::Value::Status("master".to_string())) // ); // assert_eq!(info.get("role"), Some("master".to_string())); // assert_eq!(info.get("loading"), Some(false)); // assert!(!info.is_empty()); // assert!(info.contains_key(&"role")); // } // #[test] // fn test_hash_ops() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("HSET") // .arg("foo") // .arg("key_1") // .arg(1) // .execute(&mut con); // lunatic_redis::cmd("HSET") // .arg("foo") // .arg("key_2") // .arg(2) // .execute(&mut con); // let h: HashMap = lunatic_redis::cmd("HGETALL") // .arg("foo") // .query(&mut con) // .unwrap(); // assert_eq!(h.len(), 2); // assert_eq!(h.get("key_1"), Some(&1i32)); // assert_eq!(h.get("key_2"), Some(&2i32)); // let h: BTreeMap = lunatic_redis::cmd("HGETALL") // .arg("foo") // .query(&mut con) // .unwrap(); // assert_eq!(h.len(), 2); // assert_eq!(h.get("key_1"), Some(&1i32)); // assert_eq!(h.get("key_2"), Some(&2i32)); // } // // Requires redis-server >= 4.0.0. // // Not supported with the current appveyor/windows binary deployed. // #[cfg(not(target_os = "windows"))] // #[test] // fn test_unlink() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(42) // .execute(&mut con); // assert_eq!(lunatic_redis::cmd("GET").arg("foo").query(&mut con), Ok(42)); // assert_eq!(con.unlink("foo"), Ok(1)); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(42) // .execute(&mut con); // lunatic_redis::cmd("SET") // .arg("bar") // .arg(42) // .execute(&mut con); // assert_eq!(con.unlink(&["foo", "bar"]), Ok(2)); // } // #[test] // fn test_set_ops() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.sadd("foo", &[1, 2, 3]), Ok(3)); // let mut s: Vec = con.smembers("foo").unwrap(); // s.sort_unstable(); // assert_eq!(s.len(), 3); // assert_eq!(&s, &[1, 2, 3]); // let set: HashSet = con.smembers("foo").unwrap(); // assert_eq!(set.len(), 3); // assert!(set.contains(&1i32)); // assert!(set.contains(&2i32)); // assert!(set.contains(&3i32)); // let set: BTreeSet = con.smembers("foo").unwrap(); // assert_eq!(set.len(), 3); // assert!(set.contains(&1i32)); // assert!(set.contains(&2i32)); // assert!(set.contains(&3i32)); // } // #[test] // fn test_scan() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.sadd("foo", &[1, 2, 3]), Ok(3)); // let (cur, mut s): (i32, Vec) = lunatic_redis::cmd("SSCAN") // .arg("foo") // .arg(0) // .query(&mut con) // .unwrap(); // s.sort_unstable(); // assert_eq!(cur, 0i32); // assert_eq!(s.len(), 3); // assert_eq!(&s, &[1, 2, 3]); // } // #[test] // fn test_optionals() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("SET") // .arg("foo") // .arg(1) // .execute(&mut con); // let (a, b): (Option, Option) = lunatic_redis::cmd("MGET") // .arg("foo") // .arg("missing") // .query(&mut con) // .unwrap(); // assert_eq!(a, Some(1i32)); // assert_eq!(b, None); // let a = lunatic_redis::cmd("GET") // .arg("missing") // .query(&mut con) // .unwrap_or(0i32); // assert_eq!(a, 0i32); // } // #[test] // fn test_scanning() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let mut unseen = HashSet::new(); // for x in 0..1000 { // lunatic_redis::cmd("SADD") // .arg("foo") // .arg(x) // .execute(&mut con); // unseen.insert(x); // } // let iter = lunatic_redis::cmd("SSCAN") // .arg("foo") // .cursor_arg(0) // .clone() // .iter(&mut con) // .unwrap(); // for x in iter { // // type inference limitations // let x: usize = x; // unseen.remove(&x); // } // assert_eq!(unseen.len(), 0); // } // #[test] // fn test_filtered_scanning() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let mut unseen = HashSet::new(); // for x in 0..3000 { // let _: () = con // .hset("foo", format!("key_{}_{}", x % 100, x), x) // .unwrap(); // if x % 100 == 0 { // unseen.insert(x); // } // } // let iter = con // .hscan_match::<&str, &str, (String, usize)>("foo", "key_0_*") // .unwrap(); // for (_field, value) in iter { // unseen.remove(&value); // } // assert_eq!(unseen.len(), 0); // } // #[test] // fn test_pipeline() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let ((k1, k2),): ((i32, i32),) = lunatic_redis::pipe() // .cmd("SET") // .arg("key_1") // .arg(42) // .ignore() // .cmd("SET") // .arg("key_2") // .arg(43) // .ignore() // .cmd("MGET") // .arg(&["key_1", "key_2"]) // .query(&mut con) // .unwrap(); // assert_eq!(k1, 42); // assert_eq!(k2, 43); // } // #[test] // fn test_pipeline_with_err() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let _: () = lunatic_redis::cmd("SET") // .arg("x") // .arg("x-value") // .query(&mut con) // .unwrap(); // let _: () = lunatic_redis::cmd("SET") // .arg("y") // .arg("y-value") // .query(&mut con) // .unwrap(); // let _: () = lunatic_redis::cmd("SLAVEOF") // .arg("1.1.1.1") // .arg("99") // .query(&mut con) // .unwrap(); // let res = lunatic_redis::pipe() // .set("x", "another-x-value") // .ignore() // .get("y") // .query::<()>(&mut con); // assert!(res.is_err() && res.unwrap_err().kind() == ErrorKind::ReadOnly); // // Make sure we don't get leftover responses from the pipeline ("y-value"). See #436. // let res = lunatic_redis::cmd("GET") // .arg("x") // .query::(&mut con) // .unwrap(); // assert_eq!(res, "x-value"); // } // #[test] // fn test_empty_pipeline() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let _: () = lunatic_redis::pipe() // .cmd("PING") // .ignore() // .query(&mut con) // .unwrap(); // let _: () = lunatic_redis::pipe().query(&mut con).unwrap(); // } // #[test] // fn test_pipeline_transaction() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let ((k1, k2),): ((i32, i32),) = lunatic_redis::pipe() // .atomic() // .cmd("SET") // .arg("key_1") // .arg(42) // .ignore() // .cmd("SET") // .arg("key_2") // .arg(43) // .ignore() // .cmd("MGET") // .arg(&["key_1", "key_2"]) // .query(&mut con) // .unwrap(); // assert_eq!(k1, 42); // assert_eq!(k2, 43); // } // #[test] // fn test_pipeline_transaction_with_errors() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let _: () = con.set("x", 42).unwrap(); // // Make Redis a replica of a nonexistent master, thereby making it read-only. // let _: () = lunatic_redis::cmd("slaveof") // .arg("1.1.1.1") // .arg("1") // .query(&mut con) // .unwrap(); // // Ensure that a write command fails with a READONLY error // let err: RedisResult<()> = lunatic_redis::pipe() // .atomic() // .set("x", 142) // .ignore() // .get("x") // .query(&mut con); // assert_eq!(err.unwrap_err().kind(), ErrorKind::ReadOnly); // let x: i32 = con.get("x").unwrap(); // assert_eq!(x, 42); // } // #[test] // fn test_pipeline_reuse_query() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let mut pl = lunatic_redis::pipe(); // let ((k1,),): ((i32,),) = pl // .cmd("SET") // .arg("pkey_1") // .arg(42) // .ignore() // .cmd("MGET") // .arg(&["pkey_1"]) // .query(&mut con) // .unwrap(); // assert_eq!(k1, 42); // lunatic_redis::cmd("DEL").arg("pkey_1").execute(&mut con); // // The internal commands vector of the pipeline still contains the previous commands. // let ((k1,), (k2, k3)): ((i32,), (i32, i32)) = pl // .cmd("SET") // .arg("pkey_2") // .arg(43) // .ignore() // .cmd("MGET") // .arg(&["pkey_1"]) // .arg(&["pkey_2"]) // .query(&mut con) // .unwrap(); // assert_eq!(k1, 42); // assert_eq!(k2, 42); // assert_eq!(k3, 43); // } // #[test] // fn test_pipeline_reuse_query_clear() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let mut pl = lunatic_redis::pipe(); // let ((k1,),): ((i32,),) = pl // .cmd("SET") // .arg("pkey_1") // .arg(44) // .ignore() // .cmd("MGET") // .arg(&["pkey_1"]) // .query(&mut con) // .unwrap(); // pl.clear(); // assert_eq!(k1, 44); // lunatic_redis::cmd("DEL").arg("pkey_1").execute(&mut con); // let ((k1, k2),): ((bool, i32),) = pl // .cmd("SET") // .arg("pkey_2") // .arg(45) // .ignore() // .cmd("MGET") // .arg(&["pkey_1"]) // .arg(&["pkey_2"]) // .query(&mut con) // .unwrap(); // pl.clear(); // assert!(!k1); // assert_eq!(k2, 45); // } // #[test] // fn test_real_transaction() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let key = "the_key"; // let _: () = lunatic_redis::cmd("SET") // .arg(key) // .arg(42) // .query(&mut con) // .unwrap(); // loop { // let _: () = lunatic_redis::cmd("WATCH") // .arg(key) // .query(&mut con) // .unwrap(); // let val: isize = lunatic_redis::cmd("GET").arg(key).query(&mut con).unwrap(); // let response: Option<(isize,)> = lunatic_redis::pipe() // .atomic() // .cmd("SET") // .arg(key) // .arg(val + 1) // .ignore() // .cmd("GET") // .arg(key) // .query(&mut con) // .unwrap(); // match response { // None => { // continue; // } // Some(response) => { // assert_eq!(response, (43,)); // break; // } // } // } // } // #[test] // fn test_real_transaction_highlevel() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let key = "the_key"; // let _: () = lunatic_redis::cmd("SET") // .arg(key) // .arg(42) // .query(&mut con) // .unwrap(); // let response: (isize,) = lunatic_redis::transaction(&mut con, &[key], |con, pipe| { // let val: isize = lunatic_redis::cmd("GET").arg(key).query(con)?; // pipe.cmd("SET") // .arg(key) // .arg(val + 1) // .ignore() // .cmd("GET") // .arg(key) // .query(con) // }) // .unwrap(); // assert_eq!(response, (43,)); // } // #[test] // fn test_pubsub() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // // Connection for subscriber api // let mut pubsub_con = ctx.connection(); // // Barrier is used to make test thread wait to publish // // until after the pubsub thread has subscribed. // // let barrier = Arc::new(Barrier::new(2)); // // let pubsub_barrier = barrier.clone(); // let thread = spawn_link!(@task |pubsub_con| { // let mut pubsub = pubsub_con.as_pubsub(); // pubsub.subscribe("foo").unwrap(); // // let _ = pubsub_barrier.wait(); // let msg = pubsub.receive().unwrap(); // assert_eq!(msg.get_channel(), Ok("foo".to_string())); // assert_eq!(msg.get_payload(), Ok(42)); // let msg = pubsub.receive().unwrap(); // assert_eq!(msg.get_channel(), Ok("foo".to_string())); // assert_eq!(msg.get_payload(), Ok(23)); // }); // // let _ = barrier.wait(); // lunatic_redis::cmd("PUBLISH") // .arg("foo") // .arg(42) // .execute(&mut con); // // We can also call the command directly // assert_eq!(con.publish("foo", 23), Ok(1)); // thread.result(); // } // // #[test] // // fn test_pubsub_unsubscribe() { // // let ctx = TestContext::new(); // // let mut con = ctx.connection(); // // { // // let mut pubsub = con.as_pubsub(); // // pubsub.subscribe("foo").unwrap(); // // pubsub.subscribe("bar").unwrap(); // // pubsub.subscribe("baz").unwrap(); // // pubsub.psubscribe("foo*").unwrap(); // // pubsub.psubscribe("bar*").unwrap(); // // pubsub.psubscribe("baz*").unwrap(); // // } // // // Connection should be usable again for non-pubsub commands // // let _: lunatic_redis::Value = con.set("foo", "bar").unwrap(); // // let value: String = con.get("foo").unwrap(); // // assert_eq!(&value[..], "bar"); // // } // // #[test] // // fn test_pubsub_unsubscribe_no_subs() { // // let ctx = TestContext::new(); // // let mut con = ctx.connection(); // // { // // let _pubsub = con.as_pubsub(); // // } // // // Connection should be usable again for non-pubsub commands // // let _: lunatic_redis::Value = con.set("foo", "bar").unwrap(); // // let value: String = con.get("foo").unwrap(); // // assert_eq!(&value[..], "bar"); // // } // // #[test] // // fn test_pubsub_unsubscribe_one_sub() { // // let ctx = TestContext::new(); // // let mut con = ctx.connection(); // // { // // let mut pubsub = con.as_pubsub(); // // pubsub.subscribe("foo").unwrap(); // // } // // // Connection should be usable again for non-pubsub commands // // let _: lunatic_redis::Value = con.set("foo", "bar").unwrap(); // // let value: String = con.get("foo").unwrap(); // // assert_eq!(&value[..], "bar"); // // } // // #[test] // // fn test_pubsub_unsubscribe_one_sub_one_psub() { // // let ctx = TestContext::new(); // // let mut con = ctx.connection(); // // { // // let mut pubsub = con.as_pubsub(); // // pubsub.subscribe("foo").unwrap(); // // pubsub.psubscribe("foo*").unwrap(); // // } // // // Connection should be usable again for non-pubsub commands // // let _: lunatic_redis::Value = con.set("foo", "bar").unwrap(); // // let value: String = con.get("foo").unwrap(); // // assert_eq!(&value[..], "bar"); // // } // // #[test] // // fn scoped_pubsub() { // // let ctx = TestContext::new(); // // let mut con = ctx.connection(); // // // Connection for subscriber api // // let mut pubsub_con = ctx.connection().as_pubsub(); // // let thread = spawn!(|pubsub_con| { // // let mut count = 0; // // pubsub_con // // .subscribe(&["foo", "bar"], |msg| { // // count += 1; // // match count { // // 1 => { // // assert_eq!(msg.get_channel(), Ok("foo".to_string())); // // assert_eq!(msg.get_payload(), Ok(42)); // // ControlFlow::Continue // // } // // 2 => { // // assert_eq!(msg.get_channel(), Ok("bar".to_string())); // // assert_eq!(msg.get_payload(), Ok(23)); // // ControlFlow::Break(()) // // } // // _ => ControlFlow::Break(()), // // } // // }) // // .unwrap(); // // pubsub_con // // }); // // // Can't use a barrier in this case since there's no opportunity to run code // // // between channel subscription and blocking for messages. // // sleep(Duration::from_millis(100)); // // lunatic_redis::cmd("PUBLISH") // // .arg("foo") // // .arg(42) // // .execute(&mut con); // // assert_eq!(con.publish("bar", 23), Ok(1)); // // // Wait for thread // // let mut pubsub_con = thread.join().expect("pubsub thread terminates ok"); // // // Connection should be usable again for non-pubsub commands // // let _: lunatic_redis::Value = pubsub_con.set("foo", "bar").unwrap(); // // let value: String = pubsub_con.get("foo").unwrap(); // // assert_eq!(&value[..], "bar"); // // } // #[test] // #[cfg(feature = "script")] // fn test_script() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let script = lunatic_redis::Script::new( // r" // return {redis.call('GET', KEYS[1]), ARGV[1]} // ", // ); // let _: () = lunatic_redis::cmd("SET") // .arg("my_key") // .arg("foo") // .query(&mut con) // .unwrap(); // let response = script.key("my_key").arg(42).invoke(&mut con); // assert_eq!(response, Ok(("foo".to_string(), 42))); // } // #[test] // #[cfg(feature = "script")] // fn test_script_load() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let script = lunatic_redis::Script::new("return 'Hello World'"); // let hash = script.prepare_invoke().load(&mut con); // assert_eq!(hash, Ok(script.get_hash().to_string())); // } // #[test] // fn test_tuple_args() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // lunatic_redis::cmd("HMSET") // .arg("my_key") // .arg(&[("field_1", 42), ("field_2", 23)]) // .execute(&mut con); // assert_eq!( // lunatic_redis::cmd("HGET") // .arg("my_key") // .arg("field_1") // .query(&mut con), // Ok(42) // ); // assert_eq!( // lunatic_redis::cmd("HGET") // .arg("my_key") // .arg("field_2") // .query(&mut con), // Ok(23) // ); // } // #[test] // fn test_nice_api() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.set("my_key", 42), Ok(())); // assert_eq!(con.get("my_key"), Ok(42)); // let (k1, k2): (i32, i32) = lunatic_redis::pipe() // .atomic() // .set("key_1", 42) // .ignore() // .set("key_2", 43) // .ignore() // .get("key_1") // .get("key_2") // .query(&mut con) // .unwrap(); // assert_eq!(k1, 42); // assert_eq!(k2, 43); // } // #[test] // fn test_auto_m_versions() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.set_multiple(&[("key1", 1), ("key2", 2)]), Ok(())); // assert_eq!(con.get(&["key1", "key2"]), Ok((1, 2))); // assert_eq!(con.get(vec!["key1", "key2"]), Ok((1, 2))); // assert_eq!(con.get(&vec!["key1", "key2"]), Ok((1, 2))); // } // #[test] // fn test_nice_hash_api() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!( // con.hset_multiple("my_hash", &[("f1", 1), ("f2", 2), ("f3", 4), ("f4", 8)]), // Ok(()) // ); // let hm: HashMap = con.hgetall("my_hash").unwrap(); // assert_eq!(hm.get("f1"), Some(&1)); // assert_eq!(hm.get("f2"), Some(&2)); // assert_eq!(hm.get("f3"), Some(&4)); // assert_eq!(hm.get("f4"), Some(&8)); // assert_eq!(hm.len(), 4); // let hm: BTreeMap = con.hgetall("my_hash").unwrap(); // assert_eq!(hm.get("f1"), Some(&1)); // assert_eq!(hm.get("f2"), Some(&2)); // assert_eq!(hm.get("f3"), Some(&4)); // assert_eq!(hm.get("f4"), Some(&8)); // assert_eq!(hm.len(), 4); // let v: Vec<(String, isize)> = con.hgetall("my_hash").unwrap(); // assert_eq!( // v, // vec![ // ("f1".to_string(), 1), // ("f2".to_string(), 2), // ("f3".to_string(), 4), // ("f4".to_string(), 8), // ] // ); // assert_eq!(con.hget("my_hash", &["f2", "f4"]), Ok((2, 8))); // assert_eq!(con.hincr("my_hash", "f1", 1), Ok(2)); // assert_eq!(con.hincr("my_hash", "f2", 1.5f32), Ok(3.5f32)); // assert_eq!(con.hexists("my_hash", "f2"), Ok(true)); // assert_eq!(con.hdel("my_hash", &["f1", "f2"]), Ok(())); // assert_eq!(con.hexists("my_hash", "f2"), Ok(false)); // let iter: lunatic_redis::Iter<'_, (String, isize)> = con.hscan("my_hash").unwrap(); // let mut found = HashSet::new(); // for item in iter { // found.insert(item); // } // assert_eq!(found.len(), 2); // assert!(found.contains(&("f3".to_string(), 4))); // assert!(found.contains(&("f4".to_string(), 8))); // } // #[test] // fn test_nice_list_api() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.rpush("my_list", &[1, 2, 3, 4]), Ok(4)); // assert_eq!(con.rpush("my_list", &[5, 6, 7, 8]), Ok(8)); // assert_eq!(con.llen("my_list"), Ok(8)); // assert_eq!(con.lpop("my_list", Default::default()), Ok(1)); // assert_eq!(con.llen("my_list"), Ok(7)); // assert_eq!(con.lrange("my_list", 0, 2), Ok((2, 3, 4))); // assert_eq!(con.lset("my_list", 0, 4), Ok(true)); // assert_eq!(con.lrange("my_list", 0, 2), Ok((4, 3, 4))); // #[cfg(not(windows))] // //Windows version of redis is limited to v3.x // { // let my_list: Vec = con.lrange("my_list", 0, 10).expect("To get range"); // assert_eq!( // con.lpop("my_list", core::num::NonZeroUsize::new(10)), // Ok(my_list) // ); // } // } // #[test] // fn test_tuple_decoding_regression() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.del("my_zset"), Ok(())); // assert_eq!(con.zadd("my_zset", "one", 1), Ok(1)); // assert_eq!(con.zadd("my_zset", "two", 2), Ok(1)); // let vec: Vec<(String, u32)> = con.zrangebyscore_withscores("my_zset", 0, 10).unwrap(); // assert_eq!(vec.len(), 2); // assert_eq!(con.del("my_zset"), Ok(1)); // let vec: Vec<(String, u32)> = con.zrangebyscore_withscores("my_zset", 0, 10).unwrap(); // assert_eq!(vec.len(), 0); // } // #[test] // fn test_bit_operations() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // assert_eq!(con.setbit("bitvec", 10, true), Ok(false)); // assert_eq!(con.getbit("bitvec", 10), Ok(true)); // } // #[test] // fn test_redis_server_down() { // let mut ctx = TestContext::new(); // let mut con = ctx.connection(); // let ping = lunatic_redis::cmd("PING").query::(&mut con); // assert_eq!(ping, Ok("PONG".into())); // ctx.stop_server(); // let ping = lunatic_redis::cmd("PING").query::(&mut con); // assert!(ping.is_err()); // eprintln!("{}", ping.unwrap_err()); // assert!(!con.is_open()); // } // #[test] // fn test_zinterstore_weights() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let _: () = con // .zadd_multiple("zset1", &[(1, "one"), (2, "two"), (4, "four")]) // .unwrap(); // let _: () = con // .zadd_multiple("zset2", &[(1, "one"), (2, "two"), (3, "three")]) // .unwrap(); // // zinterstore_weights // assert_eq!( // con.zinterstore_weights("out", &[("zset1", 2), ("zset2", 3)]), // Ok(2) // ); // assert_eq!( // con.zrange_withscores("out", 0, -1), // Ok(vec![ // ("one".to_string(), "5".to_string()), // ("two".to_string(), "10".to_string()) // ]) // ); // // zinterstore_min_weights // assert_eq!( // con.zinterstore_min_weights("out", &[("zset1", 2), ("zset2", 3)]), // Ok(2) // ); // assert_eq!( // con.zrange_withscores("out", 0, -1), // Ok(vec![ // ("one".to_string(), "2".to_string()), // ("two".to_string(), "4".to_string()), // ]) // ); // // zinterstore_max_weights // assert_eq!( // con.zinterstore_max_weights("out", &[("zset1", 2), ("zset2", 3)]), // Ok(2) // ); // assert_eq!( // con.zrange_withscores("out", 0, -1), // Ok(vec![ // ("one".to_string(), "3".to_string()), // ("two".to_string(), "6".to_string()), // ]) // ); // } // #[test] // fn test_zunionstore_weights() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let _: () = con // .zadd_multiple("zset1", &[(1, "one"), (2, "two")]) // .unwrap(); // let _: () = con // .zadd_multiple("zset2", &[(1, "one"), (2, "two"), (3, "three")]) // .unwrap(); // // zunionstore_weights // assert_eq!( // con.zunionstore_weights("out", &[("zset1", 2), ("zset2", 3)]), // Ok(3) // ); // assert_eq!( // con.zrange_withscores("out", 0, -1), // Ok(vec![ // ("one".to_string(), "5".to_string()), // ("three".to_string(), "9".to_string()), // ("two".to_string(), "10".to_string()) // ]) // ); // // zunionstore_min_weights // assert_eq!( // con.zunionstore_min_weights("out", &[("zset1", 2), ("zset2", 3)]), // Ok(3) // ); // assert_eq!( // con.zrange_withscores("out", 0, -1), // Ok(vec![ // ("one".to_string(), "2".to_string()), // ("two".to_string(), "4".to_string()), // ("three".to_string(), "9".to_string()) // ]) // ); // // zunionstore_max_weights // assert_eq!( // con.zunionstore_max_weights("out", &[("zset1", 2), ("zset2", 3)]), // Ok(3) // ); // assert_eq!( // con.zrange_withscores("out", 0, -1), // Ok(vec![ // ("one".to_string(), "3".to_string()), // ("two".to_string(), "6".to_string()), // ("three".to_string(), "9".to_string()) // ]) // ); // } // #[test] // fn test_zrembylex() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let setname = "myzset"; // assert_eq!( // con.zadd_multiple( // setname, // &[ // (0, "apple"), // (0, "banana"), // (0, "carrot"), // (0, "durian"), // (0, "eggplant"), // (0, "grapes"), // ], // ), // Ok(6) // ); // // Will remove "banana", "carrot", "durian" and "eggplant" // let num_removed: u32 = con.zrembylex(setname, "[banana", "[eggplant").unwrap(); // assert_eq!(4, num_removed); // let remaining: Vec = con.zrange(setname, 0, -1).unwrap(); // assert_eq!(remaining, vec!["apple".to_string(), "grapes".to_string()]); // } // // Requires redis-server >= 6.2.0. // // Not supported with the current appveyor/windows binary deployed. // #[cfg(not(target_os = "windows"))] // #[test] // fn test_zrandmember() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let setname = "myzrandset"; // let () = con.zadd(setname, "one", 1).unwrap(); // let result: String = con.zrandmember(setname, None).unwrap(); // assert_eq!(result, "one".to_string()); // let result: Vec = con.zrandmember(setname, Some(1)).unwrap(); // assert_eq!(result.len(), 1); // assert_eq!(result[0], "one".to_string()); // let result: Vec = con.zrandmember(setname, Some(2)).unwrap(); // assert_eq!(result.len(), 1); // assert_eq!(result[0], "one".to_string()); // assert_eq!( // con.zadd_multiple( // setname, // &[(2, "two"), (3, "three"), (4, "four"), (5, "five")] // ), // Ok(4) // ); // let results: Vec = con.zrandmember(setname, Some(5)).unwrap(); // assert_eq!(results.len(), 5); // let results: Vec = con.zrandmember(setname, Some(-5)).unwrap(); // assert_eq!(results.len(), 5); // let results: Vec = con.zrandmember_withscores(setname, 5).unwrap(); // assert_eq!(results.len(), 10); // let results: Vec = con.zrandmember_withscores(setname, -5).unwrap(); // assert_eq!(results.len(), 10); // } // #[test] // fn test_object_commands() { // let ctx = TestContext::new(); // let mut con = ctx.connection(); // let _: () = con.set("object_key_str", "object_value_str").unwrap(); // let _: () = con.set("object_key_int", 42).unwrap(); // assert_eq!( // con.object_encoding::<_, String>("object_key_str").unwrap(), // "embstr" // ); // assert_eq!( // con.object_encoding::<_, String>("object_key_int").unwrap(), // "int" // ); // assert_eq!(con.object_idletime::<_, i32>("object_key_str").unwrap(), 0); // assert_eq!(con.object_refcount::<_, i32>("object_key_str").unwrap(), 1); // // Needed for OBJECT FREQ and can't be set before object_idletime // // since that will break getting the idletime before idletime adjuts // lunatic_redis::cmd("CONFIG") // .arg("SET") // .arg(b"maxmemory-policy") // .arg("allkeys-lfu") // .execute(&mut con); // let _: () = con.get("object_key_str").unwrap(); // // since maxmemory-policy changed, freq should reset to 1 since we only called // // get after that // assert_eq!(con.object_freq::<_, i32>("object_key_str").unwrap(), 1); // }