use flurry::*; use std::sync::Arc; // These tests all use `K = String` and `Q = str` for `Borrow`-based lookups #[test] fn get_empty() { let map = HashMap::::new(); { let guard = map.guard(); let e = map.get("foo", &guard); assert!(e.is_none()); } } #[test] fn remove_empty() { let map = HashMap::::new(); { let guard = map.guard(); let old = map.remove("foo", &guard); assert!(old.is_none()); } } #[test] fn insert_and_remove() { let map = HashMap::::new(); { let guard = map.guard(); map.insert("foo".to_string(), 0, &guard); let old = map.remove("foo", &guard).unwrap(); assert_eq!(old, &0); assert!(map.get("foo", &guard).is_none()); } } #[test] fn insert_and_get() { let map = HashMap::::new(); map.insert("foo".to_string(), 0, &map.guard()); { let guard = map.guard(); let e = map.get("foo", &guard).unwrap(); assert_eq!(e, &0); } } #[test] fn update() { let map = HashMap::::new(); let guard = map.guard(); map.insert("foo".to_string(), 0, &guard); let old = map.insert("foo".to_string(), 1, &guard); assert_eq!(old, Some(&0)); { let guard = map.guard(); let e = map.get("foo", &guard).unwrap(); assert_eq!(e, &1); } } #[test] #[cfg_attr(miri, ignore)] fn concurrent_insert() { let map = Arc::new(HashMap::::new()); let keys = Arc::new((0..64).map(|i| i.to_string()).collect::>()); let map1 = map.clone(); let keys1 = keys.clone(); let t1 = std::thread::spawn(move || { for key in keys1.iter() { map1.insert(key.clone(), 0, &map1.guard()); } }); let map2 = map.clone(); let keys2 = keys.clone(); let t2 = std::thread::spawn(move || { for key in keys2.iter() { map2.insert(key.clone(), 1, &map2.guard()); } }); t1.join().unwrap(); t2.join().unwrap(); let guard = map.guard(); for key in keys.iter() { let v = map.get(key.as_str(), &guard).unwrap(); assert!(v == &0 || v == &1); } } #[test] #[cfg_attr(miri, ignore)] fn concurrent_remove() { let map = Arc::new(HashMap::::new()); let keys = Arc::new((0..64).map(|i| i.to_string()).collect::>()); { let guard = map.guard(); for (i, key) in keys.iter().enumerate() { map.insert(key.clone(), i, &guard); } } let map1 = map.clone(); let keys1 = keys.clone(); let t1 = std::thread::spawn(move || { let guard = map1.guard(); for (i, key) in keys1.iter().enumerate() { if let Some(v) = map1.remove(key.as_str(), &guard) { assert_eq!(v, &i); } } }); let map2 = map.clone(); let keys2 = keys.clone(); let t2 = std::thread::spawn(move || { let guard = map2.guard(); for (i, key) in keys2.iter().enumerate() { if let Some(v) = map2.remove(key.as_str(), &guard) { assert_eq!(v, &i); } } }); t1.join().unwrap(); t2.join().unwrap(); // after joining the threads, the map should be empty let guard = map.guard(); for key in keys.iter() { assert!(map.get(key.as_str(), &guard).is_none()); } }