summaryrefslogtreecommitdiffstats
path: root/third_party/rust/hashlink/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/hashlink/tests
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/hashlink/tests')
-rw-r--r--third_party/rust/hashlink/tests/linked_hash_map.rs563
-rw-r--r--third_party/rust/hashlink/tests/linked_hash_set.rs543
-rw-r--r--third_party/rust/hashlink/tests/lru_cache.rs166
-rw-r--r--third_party/rust/hashlink/tests/serde.rs108
4 files changed, 1380 insertions, 0 deletions
diff --git a/third_party/rust/hashlink/tests/linked_hash_map.rs b/third_party/rust/hashlink/tests/linked_hash_map.rs
new file mode 100644
index 0000000000..e04629275e
--- /dev/null
+++ b/third_party/rust/hashlink/tests/linked_hash_map.rs
@@ -0,0 +1,563 @@
+use hashlink::{linked_hash_map, LinkedHashMap};
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn set<'new>(v: LinkedHashMap<&'static str, ()>) -> LinkedHashMap<&'new str, ()> {
+ v
+ }
+
+ fn iter<'a, 'new>(
+ v: linked_hash_map::Iter<'a, &'static str, &'static str>,
+ ) -> linked_hash_map::Iter<'a, &'new str, &'new str> {
+ v
+ }
+
+ fn iter_mut<'a, 'new>(
+ v: linked_hash_map::Iter<'a, &'static str, ()>,
+ ) -> linked_hash_map::Iter<'a, &'new str, ()> {
+ v
+ }
+
+ fn into_iter<'new>(
+ v: linked_hash_map::IntoIter<&'static str, &'static str>,
+ ) -> linked_hash_map::IntoIter<&'new str, &'new str> {
+ v
+ }
+
+ fn drain<'new>(
+ d: linked_hash_map::Drain<'static, &'static str, &'static str>,
+ ) -> linked_hash_map::Drain<'new, &'new str, &'new str> {
+ d
+ }
+
+ fn raw_entry_builder<'a, 'new>(
+ v: linked_hash_map::RawEntryBuilder<'a, &'static str, &'static str, ()>,
+ ) -> linked_hash_map::RawEntryBuilder<'a, &'new str, &'new str, ()> {
+ v
+ }
+}
+
+#[test]
+fn test_index() {
+ let mut map = LinkedHashMap::new();
+ map.insert(1, 10);
+ map.insert(2, 20);
+ assert_eq!(10, map[&1]);
+ map[&2] = 22;
+ assert_eq!(22, map[&2]);
+}
+
+#[test]
+fn test_insert_and_get() {
+ let mut map = LinkedHashMap::new();
+ map.insert(1, 10);
+ map.insert(2, 20);
+ assert_eq!(map.get(&1), Some(&10));
+ assert_eq!(map.get(&2), Some(&20));
+ assert_eq!(map.len(), 2);
+}
+
+#[test]
+fn test_insert_update() {
+ let mut map = LinkedHashMap::new();
+ map.insert("1".to_string(), vec![10, 10]);
+ map.insert("1".to_string(), vec![10, 19]);
+ assert_eq!(map.get(&"1".to_string()), Some(&vec![10, 19]));
+ assert_eq!(map.len(), 1);
+}
+
+#[test]
+fn test_entry_insert_vacant() {
+ let mut map = LinkedHashMap::new();
+ match map.entry("1".to_string()) {
+ linked_hash_map::Entry::Vacant(e) => {
+ assert_eq!(*e.insert(vec![10, 10]), vec![10, 10]);
+ }
+ _ => panic!("fail"),
+ }
+ assert!(map.contains_key("1"));
+ assert_eq!(map["1"], vec![10, 10]);
+
+ match map.entry("1".to_string()) {
+ linked_hash_map::Entry::Occupied(mut e) => {
+ assert_eq!(*e.get(), vec![10, 10]);
+ assert_eq!(e.insert(vec![10, 16]), vec![10, 10]);
+ }
+ _ => panic!("fail"),
+ }
+
+ assert!(map.contains_key("1"));
+ assert_eq!(map["1"], vec![10, 16]);
+
+ match map.entry("1".to_string()) {
+ linked_hash_map::Entry::Occupied(e) => {
+ assert_eq!(e.remove(), vec![10, 16]);
+ }
+ _ => panic!("fail"),
+ }
+}
+
+#[test]
+fn test_remove() {
+ let mut map = LinkedHashMap::new();
+ map.insert(1, 10);
+ map.insert(2, 20);
+ map.insert(3, 30);
+ map.insert(4, 40);
+ map.insert(5, 50);
+ map.remove(&3);
+ map.remove(&4);
+ assert!(map.get(&3).is_none());
+ assert!(map.get(&4).is_none());
+ map.insert(6, 60);
+ map.insert(7, 70);
+ map.insert(8, 80);
+ assert_eq!(map.get(&6), Some(&60));
+ assert_eq!(map.get(&7), Some(&70));
+ assert_eq!(map.get(&8), Some(&80));
+}
+
+#[test]
+fn test_pop() {
+ let mut map = LinkedHashMap::new();
+ map.insert(1, 10);
+ map.insert(2, 20);
+ map.insert(3, 30);
+ map.insert(4, 40);
+ map.insert(5, 50);
+ assert_eq!(map.pop_front(), Some((1, 10)));
+ assert!(map.get(&1).is_none());
+ assert_eq!(map.pop_back(), Some((5, 50)));
+ assert!(map.get(&5).is_none());
+ map.insert(6, 60);
+ map.insert(7, 70);
+ map.insert(8, 80);
+ assert_eq!(map.pop_front(), Some((2, 20)));
+ assert!(map.get(&2).is_none());
+ assert_eq!(map.pop_back(), Some((8, 80)));
+ assert!(map.get(&8).is_none());
+ map.insert(3, 30);
+ assert_eq!(map.pop_front(), Some((4, 40)));
+ assert!(map.get(&4).is_none());
+ assert_eq!(map.pop_back(), Some((3, 30)));
+ assert!(map.get(&3).is_none());
+}
+
+#[test]
+fn test_move() {
+ let to_back = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) {
+ linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_back(),
+ linked_hash_map::Entry::Vacant(_) => panic!(),
+ };
+
+ let to_front = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) {
+ linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_front(),
+ linked_hash_map::Entry::Vacant(_) => panic!(),
+ };
+
+ let mut map = LinkedHashMap::new();
+ map.insert(1, 10);
+ map.insert(2, 20);
+ map.insert(3, 30);
+ map.insert(4, 40);
+ map.insert(5, 50);
+
+ to_back(&mut map, 1);
+ assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 3, 4, 5, 1]);
+
+ to_front(&mut map, 4);
+ assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![4, 2, 3, 5, 1]);
+
+ to_back(&mut map, 3);
+ assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![4, 2, 5, 1, 3]);
+
+ to_front(&mut map, 2);
+ assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 4, 5, 1, 3]);
+
+ to_back(&mut map, 3);
+ assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 4, 5, 1, 3]);
+
+ to_front(&mut map, 2);
+ assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 4, 5, 1, 3]);
+}
+
+#[test]
+fn test_clear() {
+ let mut map = LinkedHashMap::new();
+ map.insert(1, 10);
+ map.insert(2, 20);
+ map.clear();
+ assert!(map.get(&1).is_none());
+ assert!(map.get(&2).is_none());
+ assert!(map.is_empty());
+}
+
+#[test]
+fn test_iter() {
+ let mut map = LinkedHashMap::new();
+
+ // empty iter
+ assert_eq!(None, map.iter().next());
+
+ map.insert("a", 10);
+ map.insert("b", 20);
+ map.insert("c", 30);
+
+ // regular iter
+ let mut iter = map.iter();
+ assert_eq!((&"a", &10), iter.next().unwrap());
+ assert_eq!((&"b", &20), iter.next().unwrap());
+ assert_eq!((&"c", &30), iter.next().unwrap());
+ assert_eq!(None, iter.next());
+ assert_eq!(None, iter.next());
+
+ let mut iter = map.iter();
+ assert_eq!((&"a", &10), iter.next().unwrap());
+ let mut iclone = iter.clone();
+ assert_eq!((&"b", &20), iter.next().unwrap());
+ assert_eq!((&"b", &20), iclone.next().unwrap());
+ assert_eq!((&"c", &30), iter.next().unwrap());
+ assert_eq!((&"c", &30), iclone.next().unwrap());
+
+ // reversed iter
+ let mut rev_iter = map.iter().rev();
+ assert_eq!((&"c", &30), rev_iter.next().unwrap());
+ assert_eq!((&"b", &20), rev_iter.next().unwrap());
+ assert_eq!((&"a", &10), rev_iter.next().unwrap());
+ assert_eq!(None, rev_iter.next());
+ assert_eq!(None, rev_iter.next());
+
+ // mixed
+ let mut mixed_iter = map.iter();
+ assert_eq!((&"a", &10), mixed_iter.next().unwrap());
+ assert_eq!((&"c", &30), mixed_iter.next_back().unwrap());
+ assert_eq!((&"b", &20), mixed_iter.next().unwrap());
+ assert_eq!(None, mixed_iter.next());
+ assert_eq!(None, mixed_iter.next_back());
+}
+
+#[test]
+fn test_borrow() {
+ #[derive(PartialEq, Eq, Hash)]
+ struct Foo(Bar);
+ #[derive(PartialEq, Eq, Hash)]
+ struct Bar(i32);
+
+ impl ::std::borrow::Borrow<Bar> for Foo {
+ fn borrow(&self) -> &Bar {
+ &self.0
+ }
+ }
+
+ let mut map = LinkedHashMap::new();
+ map.insert(Foo(Bar(1)), "a");
+ map.insert(Foo(Bar(2)), "b");
+
+ assert!(map.contains_key(&Bar(1)));
+ assert!(map.contains_key(&Bar(2)));
+ assert!(map.contains_key(&Foo(Bar(1))));
+ assert!(map.contains_key(&Foo(Bar(2))));
+
+ assert_eq!(map.get(&Bar(1)), Some(&"a"));
+ assert_eq!(map.get(&Bar(2)), Some(&"b"));
+ assert_eq!(map.get(&Foo(Bar(1))), Some(&"a"));
+ assert_eq!(map.get(&Foo(Bar(2))), Some(&"b"));
+
+ assert_eq!(map.get_mut(&Bar(1)), Some(&mut "a"));
+ assert_eq!(map.get_mut(&Bar(2)), Some(&mut "b"));
+ assert_eq!(map.get_mut(&Foo(Bar(1))), Some(&mut "a"));
+ assert_eq!(map.get_mut(&Foo(Bar(2))), Some(&mut "b"));
+
+ assert_eq!(map[&Bar(1)], "a");
+ assert_eq!(map[&Bar(2)], "b");
+ assert_eq!(map[&Foo(Bar(1))], "a");
+ assert_eq!(map[&Foo(Bar(2))], "b");
+
+ assert_eq!(map.remove(&Bar(1)), Some("a"));
+ assert_eq!(map.remove(&Bar(2)), Some("b"));
+ assert_eq!(map.remove(&Foo(Bar(1))), None);
+ assert_eq!(map.remove(&Foo(Bar(2))), None);
+}
+
+#[test]
+fn test_iter_mut() {
+ let mut map = LinkedHashMap::new();
+ map.insert("a", 10);
+ map.insert("c", 30);
+ map.insert("b", 20);
+
+ {
+ let mut iter = map.iter_mut();
+ let entry = iter.next().unwrap();
+ assert_eq!("a", *entry.0);
+ *entry.1 = 17;
+
+ assert_eq!(format!("{:?}", iter), "[(\"c\", 30), (\"b\", 20)]");
+
+ // reverse iterator
+ let mut iter = iter.rev();
+ let entry = iter.next().unwrap();
+ assert_eq!("b", *entry.0);
+ *entry.1 = 23;
+
+ let entry = iter.next().unwrap();
+ assert_eq!("c", *entry.0);
+ assert_eq!(None, iter.next());
+ assert_eq!(None, iter.next());
+ }
+
+ assert_eq!(17, map[&"a"]);
+ assert_eq!(23, map[&"b"]);
+}
+
+#[test]
+fn test_consuming_iter() {
+ let map = {
+ let mut map = LinkedHashMap::new();
+ map.insert("a", 10);
+ map.insert("c", 30);
+ map.insert("b", 20);
+ map
+ };
+
+ let mut iter = map.into_iter();
+ assert_eq!(Some(("a", 10)), iter.next());
+ assert_eq!(Some(("b", 20)), iter.next_back());
+ assert_eq!(iter.len(), 1);
+ assert_eq!(format!("{:?}", iter), "[(\"c\", 30)]");
+ assert_eq!(Some(("c", 30)), iter.next());
+ assert_eq!(None, iter.next());
+}
+
+#[test]
+fn test_consuming_iter_empty() {
+ let map = LinkedHashMap::<&str, i32>::new();
+ let mut iter = map.into_iter();
+ assert_eq!(None, iter.next());
+}
+
+#[test]
+fn test_consuming_iter_with_free_list() {
+ let mut map = LinkedHashMap::new();
+ map.insert("a", 10);
+ map.insert("c", 30);
+ map.insert("b", 20);
+ map.remove("a");
+ map.remove("b");
+
+ let mut iter = map.into_iter();
+ assert_eq!(Some(("c", 30)), iter.next());
+ assert_eq!(None, iter.next());
+}
+
+#[test]
+fn test_into_iter_drop() {
+ struct Counter<'a>(&'a mut usize);
+
+ impl<'a> Drop for Counter<'a> {
+ fn drop(&mut self) {
+ *self.0 += 1;
+ }
+ }
+
+ let mut a = 0;
+ let mut b = 0;
+ let mut c = 0;
+
+ {
+ let mut map = LinkedHashMap::new();
+ map.insert("a", Counter(&mut a));
+ map.insert("b", Counter(&mut b));
+ map.insert("c", Counter(&mut c));
+
+ let mut iter = map.into_iter();
+ assert_eq!(iter.next().map(|p| p.0), Some("a"));
+ assert_eq!(iter.next_back().map(|p| p.0), Some("c"));
+ }
+
+ assert_eq!(a, 1);
+ assert_eq!(b, 1);
+ assert_eq!(c, 1);
+}
+
+#[test]
+fn test_drain() {
+ use std::{cell::Cell, rc::Rc};
+
+ struct Counter(Rc<Cell<u32>>);
+
+ impl<'a> Drop for Counter {
+ fn drop(&mut self) {
+ self.0.set(self.0.get() + 1);
+ }
+ }
+
+ let mut map = LinkedHashMap::new();
+
+ let a = Rc::new(Cell::new(0));
+ let b = Rc::new(Cell::new(0));
+ let c = Rc::new(Cell::new(0));
+
+ map.insert("a", Counter(a.clone()));
+ map.insert("b", Counter(b.clone()));
+ map.insert("c", Counter(c.clone()));
+
+ let mut iter = map.drain();
+ assert_eq!(iter.next().map(|p| p.0), Some("a"));
+ assert_eq!(iter.next_back().map(|p| p.0), Some("c"));
+ assert_eq!(iter.next_back().map(|p| p.0), Some("b"));
+ assert!(iter.next().is_none());
+ assert!(iter.next_back().is_none());
+
+ drop(iter);
+ assert_eq!(map.len(), 0);
+
+ assert_eq!(a.get(), 1);
+ assert_eq!(b.get(), 1);
+ assert_eq!(c.get(), 1);
+
+ map.insert("a", Counter(a.clone()));
+ map.insert("b", Counter(b.clone()));
+ map.insert("c", Counter(c.clone()));
+
+ let mut iter = map.drain();
+ assert_eq!(iter.next().map(|p| p.0), Some("a"));
+ assert_eq!(iter.next().map(|p| p.0), Some("b"));
+ assert_eq!(iter.next_back().map(|p| p.0), Some("c"));
+ assert!(iter.next().is_none());
+ assert!(iter.next_back().is_none());
+
+ drop(iter);
+ assert_eq!(map.len(), 0);
+
+ assert_eq!(a.get(), 2);
+ assert_eq!(b.get(), 2);
+ assert_eq!(c.get(), 2);
+
+ map.insert("a", Counter(a.clone()));
+ map.insert("b", Counter(b.clone()));
+ map.insert("c", Counter(c.clone()));
+
+ map.drain();
+ assert_eq!(map.len(), 0);
+
+ assert_eq!(a.get(), 3);
+ assert_eq!(b.get(), 3);
+ assert_eq!(c.get(), 3);
+}
+
+#[test]
+fn test_send_sync() {
+ fn is_send_sync<T: Send + Sync>() {}
+
+ is_send_sync::<LinkedHashMap<u32, i32>>();
+ is_send_sync::<linked_hash_map::Entry<u32, i32, ()>>();
+ is_send_sync::<linked_hash_map::RawEntryBuilder<u32, i32, ()>>();
+ is_send_sync::<linked_hash_map::RawEntryBuilderMut<u32, i32, ()>>();
+ is_send_sync::<linked_hash_map::RawEntryMut<u32, i32, ()>>();
+ is_send_sync::<linked_hash_map::Iter<u32, i32>>();
+ is_send_sync::<linked_hash_map::IterMut<u32, i32>>();
+ is_send_sync::<linked_hash_map::Drain<u32, i32>>();
+ is_send_sync::<linked_hash_map::Keys<u32, i32>>();
+ is_send_sync::<linked_hash_map::Values<u32, i32>>();
+}
+
+#[test]
+fn test_retain() {
+ use std::{cell::Cell, rc::Rc};
+
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut map: LinkedHashMap<String, i32> = xs.iter().map(|i| (i.to_string(), *i)).collect();
+ map.retain(|_, v| *v % 2 == 0);
+ assert_eq!(map.len(), 3);
+ assert!(map.contains_key("2"));
+ assert!(map.contains_key("4"));
+ assert!(map.contains_key("6"));
+
+ struct Counter(Rc<Cell<u32>>);
+
+ impl<'a> Drop for Counter {
+ fn drop(&mut self) {
+ self.0.set(self.0.get() + 1);
+ }
+ }
+
+ let c = Rc::new(Cell::new(0));
+
+ let mut map = LinkedHashMap::new();
+ map.insert(1, Counter(Rc::clone(&c)));
+ map.insert(2, Counter(Rc::clone(&c)));
+ map.insert(3, Counter(Rc::clone(&c)));
+ map.insert(4, Counter(Rc::clone(&c)));
+
+ map.retain(|k, _| *k % 2 == 0);
+
+ assert!(c.get() == 2);
+ drop(map);
+ assert!(c.get() == 4);
+}
+
+#[test]
+fn test_order_equality() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut map1: LinkedHashMap<String, i32> = xs.iter().map(|i| (i.to_string(), *i)).collect();
+ let mut map2: LinkedHashMap<String, i32> = xs.iter().map(|i| (i.to_string(), *i)).collect();
+
+ assert_eq!(map1, map2);
+
+ map1.to_front("4");
+ assert_ne!(map1, map2);
+
+ map2.to_front("4");
+ assert_eq!(map1, map2);
+}
+
+#[test]
+fn test_replace() {
+ let mut map = LinkedHashMap::new();
+
+ map.insert(1, 1);
+ map.insert(2, 2);
+ map.insert(3, 3);
+ map.insert(4, 4);
+
+ assert!(map
+ .iter()
+ .map(|(k, v)| (*k, *v))
+ .eq([(1, 1), (2, 2), (3, 3), (4, 4)].iter().copied()));
+
+ map.insert(3, 5);
+
+ assert!(map
+ .iter()
+ .map(|(k, v)| (*k, *v))
+ .eq([(1, 1), (2, 2), (4, 4), (3, 5)].iter().copied()));
+
+ map.replace(2, 6);
+
+ assert!(map
+ .iter()
+ .map(|(k, v)| (*k, *v))
+ .eq([(1, 1), (2, 6), (4, 4), (3, 5)].iter().copied()));
+}
+
+#[test]
+fn test_shrink_to_fit_resize() {
+ let mut map = LinkedHashMap::new();
+ map.shrink_to_fit();
+
+ for i in 0..100 {
+ map.insert(i, i);
+ }
+ map.shrink_to_fit();
+
+ for _ in 0..50 {
+ map.pop_front();
+ map.shrink_to_fit();
+ }
+
+ assert_eq!(map.len(), 50);
+ for i in 50..100 {
+ assert_eq!(map.get(&i).unwrap(), &i);
+ }
+}
diff --git a/third_party/rust/hashlink/tests/linked_hash_set.rs b/third_party/rust/hashlink/tests/linked_hash_set.rs
new file mode 100644
index 0000000000..7a9e33f90d
--- /dev/null
+++ b/third_party/rust/hashlink/tests/linked_hash_set.rs
@@ -0,0 +1,543 @@
+use hashbrown::hash_map::DefaultHashBuilder;
+use hashlink::linked_hash_set::{self, LinkedHashSet};
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn set<'new>(v: LinkedHashSet<&'static str>) -> LinkedHashSet<&'new str> {
+ v
+ }
+
+ fn iter<'a, 'new>(
+ v: linked_hash_set::Iter<'a, &'static str>,
+ ) -> linked_hash_set::Iter<'a, &'new str> {
+ v
+ }
+
+ fn into_iter<'new>(
+ v: linked_hash_set::IntoIter<&'static str>,
+ ) -> linked_hash_set::IntoIter<&'new str> {
+ v
+ }
+
+ fn difference<'a, 'new>(
+ v: linked_hash_set::Difference<'a, &'static str, DefaultHashBuilder>,
+ ) -> linked_hash_set::Difference<'a, &'new str, DefaultHashBuilder> {
+ v
+ }
+
+ fn symmetric_difference<'a, 'new>(
+ v: linked_hash_set::SymmetricDifference<'a, &'static str, DefaultHashBuilder>,
+ ) -> linked_hash_set::SymmetricDifference<'a, &'new str, DefaultHashBuilder> {
+ v
+ }
+
+ fn intersection<'a, 'new>(
+ v: linked_hash_set::Intersection<'a, &'static str, DefaultHashBuilder>,
+ ) -> linked_hash_set::Intersection<'a, &'new str, DefaultHashBuilder> {
+ v
+ }
+
+ fn union<'a, 'new>(
+ v: linked_hash_set::Union<'a, &'static str, DefaultHashBuilder>,
+ ) -> linked_hash_set::Union<'a, &'new str, DefaultHashBuilder> {
+ v
+ }
+
+ fn drain<'new>(
+ d: linked_hash_set::Drain<'static, &'static str>,
+ ) -> linked_hash_set::Drain<'new, &'new str> {
+ d
+ }
+}
+
+#[test]
+fn test_zero_capacities() {
+ type HS = LinkedHashSet<i32>;
+
+ let s = HS::new();
+ assert_eq!(s.capacity(), 0);
+
+ let s = HS::default();
+ assert_eq!(s.capacity(), 0);
+
+ let s = HS::with_hasher(DefaultHashBuilder::default());
+ assert_eq!(s.capacity(), 0);
+
+ let s = HS::with_capacity(0);
+ assert_eq!(s.capacity(), 0);
+
+ let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default());
+ assert_eq!(s.capacity(), 0);
+
+ let mut s = HS::new();
+ s.insert(1);
+ s.insert(2);
+ s.remove(&1);
+ s.remove(&2);
+ s.shrink_to_fit();
+ assert_eq!(s.capacity(), 0);
+
+ let mut s = HS::new();
+ s.reserve(0);
+ assert_eq!(s.capacity(), 0);
+}
+
+#[test]
+fn test_disjoint() {
+ let mut xs = LinkedHashSet::new();
+ let mut ys = LinkedHashSet::new();
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(xs.insert(5));
+ assert!(ys.insert(11));
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(xs.insert(7));
+ assert!(xs.insert(19));
+ assert!(xs.insert(4));
+ assert!(ys.insert(2));
+ assert!(ys.insert(-11));
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(ys.insert(7));
+ assert!(!xs.is_disjoint(&ys));
+ assert!(!ys.is_disjoint(&xs));
+}
+
+#[test]
+fn test_subset_and_superset() {
+ let mut a = LinkedHashSet::new();
+ assert!(a.insert(0));
+ assert!(a.insert(5));
+ assert!(a.insert(11));
+ assert!(a.insert(7));
+
+ let mut b = LinkedHashSet::new();
+ assert!(b.insert(0));
+ assert!(b.insert(7));
+ assert!(b.insert(19));
+ assert!(b.insert(250));
+ assert!(b.insert(11));
+ assert!(b.insert(200));
+
+ assert!(!a.is_subset(&b));
+ assert!(!a.is_superset(&b));
+ assert!(!b.is_subset(&a));
+ assert!(!b.is_superset(&a));
+
+ assert!(b.insert(5));
+
+ assert!(a.is_subset(&b));
+ assert!(!a.is_superset(&b));
+ assert!(!b.is_subset(&a));
+ assert!(b.is_superset(&a));
+}
+
+#[test]
+fn test_iterate() {
+ let mut a = LinkedHashSet::new();
+ for i in 0..32 {
+ assert!(a.insert(i));
+ }
+ let mut observed: u32 = 0;
+ for k in &a {
+ observed |= 1 << *k;
+ }
+ assert_eq!(observed, 0xFFFF_FFFF);
+}
+
+#[test]
+fn test_intersection() {
+ let mut a = LinkedHashSet::new();
+ let mut b = LinkedHashSet::new();
+
+ assert!(a.insert(11));
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(77));
+ assert!(a.insert(103));
+ assert!(a.insert(5));
+ assert!(a.insert(-5));
+
+ assert!(b.insert(2));
+ assert!(b.insert(11));
+ assert!(b.insert(77));
+ assert!(b.insert(-9));
+ assert!(b.insert(-42));
+ assert!(b.insert(5));
+ assert!(b.insert(3));
+
+ let mut i = 0;
+ let expected = [3, 5, 11, 77];
+ for x in a.intersection(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_difference() {
+ let mut a = LinkedHashSet::new();
+ let mut b = LinkedHashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+
+ assert!(b.insert(3));
+ assert!(b.insert(9));
+
+ let mut i = 0;
+ let expected = [1, 5, 11];
+ for x in a.difference(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_symmetric_difference() {
+ let mut a = LinkedHashSet::new();
+ let mut b = LinkedHashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+
+ assert!(b.insert(-2));
+ assert!(b.insert(3));
+ assert!(b.insert(9));
+ assert!(b.insert(14));
+ assert!(b.insert(22));
+
+ let mut i = 0;
+ let expected = [-2, 1, 5, 11, 14, 22];
+ for x in a.symmetric_difference(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_union() {
+ let mut a = LinkedHashSet::new();
+ let mut b = LinkedHashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+ assert!(a.insert(16));
+ assert!(a.insert(19));
+ assert!(a.insert(24));
+
+ assert!(b.insert(-2));
+ assert!(b.insert(1));
+ assert!(b.insert(5));
+ assert!(b.insert(9));
+ assert!(b.insert(13));
+ assert!(b.insert(19));
+
+ let mut i = 0;
+ let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
+ for x in a.union(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_from_iter() {
+ let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+ let set: LinkedHashSet<_> = xs.iter().cloned().collect();
+
+ for x in &xs {
+ assert!(set.contains(x));
+ }
+}
+
+#[test]
+fn test_move_iter() {
+ let hs = {
+ let mut hs = LinkedHashSet::new();
+
+ hs.insert('a');
+ hs.insert('b');
+
+ hs
+ };
+
+ let v = hs.into_iter().collect::<Vec<char>>();
+ assert!(v == ['a', 'b'] || v == ['b', 'a']);
+}
+
+#[test]
+fn test_eq() {
+ let mut s1 = LinkedHashSet::new();
+
+ s1.insert(1);
+ s1.insert(2);
+ s1.insert(3);
+
+ let mut s2 = LinkedHashSet::new();
+
+ s2.insert(1);
+ s2.insert(2);
+
+ assert!(s1 != s2);
+
+ s2.insert(3);
+
+ assert_eq!(s1, s2);
+}
+
+#[test]
+fn test_show() {
+ let mut set = LinkedHashSet::new();
+ let empty = LinkedHashSet::<i32>::new();
+
+ set.insert(1);
+ set.insert(2);
+
+ let set_str = format!("{:?}", set);
+
+ assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
+ assert_eq!(format!("{:?}", empty), "{}");
+}
+
+#[test]
+fn test_trivial_drain() {
+ let mut s = LinkedHashSet::<i32>::new();
+ for _ in s.drain() {}
+ assert!(s.is_empty());
+ drop(s);
+
+ let mut s = LinkedHashSet::<i32>::new();
+ drop(s.drain());
+ assert!(s.is_empty());
+}
+
+#[test]
+fn test_drain() {
+ let mut s: LinkedHashSet<_> = (1..100).collect();
+
+ for _ in 0..20 {
+ assert_eq!(s.len(), 99);
+
+ {
+ let mut last_i = 0;
+ let mut d = s.drain();
+ for (i, x) in d.by_ref().take(50).enumerate() {
+ last_i = i;
+ assert!(x != 0);
+ }
+ assert_eq!(last_i, 49);
+ }
+
+ for _ in &s {
+ panic!("s should be empty!");
+ }
+
+ s.extend(1..100);
+ }
+}
+
+#[test]
+fn test_replace() {
+ use core::hash;
+
+ #[derive(Debug)]
+ struct Foo(&'static str, i32);
+
+ impl PartialEq for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+ }
+
+ impl Eq for Foo {}
+
+ impl hash::Hash for Foo {
+ fn hash<H: hash::Hasher>(&self, h: &mut H) {
+ self.0.hash(h);
+ }
+ }
+
+ let mut s = LinkedHashSet::new();
+ assert_eq!(s.replace(Foo("a", 1)), None);
+ assert_eq!(s.len(), 1);
+ assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
+ assert_eq!(s.len(), 1);
+
+ let mut it = s.iter();
+ assert_eq!(it.next(), Some(&Foo("a", 2)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = LinkedHashSet::new();
+ a.insert(1);
+
+ a.extend(&[2, 3, 4]);
+
+ assert_eq!(a.len(), 4);
+ assert!(a.contains(&1));
+ assert!(a.contains(&2));
+ assert!(a.contains(&3));
+ assert!(a.contains(&4));
+
+ let mut b = LinkedHashSet::new();
+ b.insert(5);
+ b.insert(6);
+
+ a.extend(&b);
+
+ assert_eq!(a.len(), 6);
+ assert!(a.contains(&1));
+ assert!(a.contains(&2));
+ assert!(a.contains(&3));
+ assert!(a.contains(&4));
+ assert!(a.contains(&5));
+ assert!(a.contains(&6));
+}
+
+#[test]
+fn test_retain() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut set: LinkedHashSet<i32> = xs.iter().cloned().collect();
+ set.retain(|&k| k % 2 == 0);
+ assert_eq!(set.len(), 3);
+ assert!(set.contains(&2));
+ assert!(set.contains(&4));
+ assert!(set.contains(&6));
+}
+
+#[test]
+fn test_retain_with_order() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut set: LinkedHashSet<i32> = xs.iter().cloned().collect();
+ let mut vec = Vec::new();
+ set.retain_with_order(|&k| {
+ if k % 2 == 0 {
+ true
+ } else {
+ vec.push(k);
+ false
+ }
+ });
+ assert_eq!(vec![1, 3, 5], vec);
+}
+
+#[test]
+fn insert_order() {
+ let mut set = LinkedHashSet::new();
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+ set.insert(4);
+ assert_eq!(
+ set.clone().into_iter().collect::<Vec<_>>(),
+ vec![1, 2, 3, 4]
+ );
+ assert_eq!(set.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4]);
+}
+
+#[test]
+fn front_back() {
+ let mut set = LinkedHashSet::new();
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+ set.insert(4);
+ assert_eq!(set.front(), Some(&1));
+ assert_eq!(set.back(), Some(&4));
+ assert_eq!(set.pop_back(), Some(4));
+ assert_eq!(set.back(), Some(&3));
+ assert_eq!(set.pop_front(), Some(1));
+ assert_eq!(set.front(), Some(&2));
+}
+
+#[test]
+fn double_ended_iter() {
+ let mut set = LinkedHashSet::new();
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+ set.insert(4);
+
+ let mut iter = set.iter();
+ assert_eq!(iter.next(), Some(&1));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.next_back(), Some(&4));
+ assert_eq!(iter.next_back(), Some(&3));
+ assert_eq!(iter.next_back(), None);
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.next_back(), None);
+ drop(iter);
+
+ let mut iter = set.drain();
+ assert_eq!(iter.next(), Some(1));
+ assert_eq!(iter.next(), Some(2));
+ assert_eq!(iter.next_back(), Some(4));
+ assert_eq!(iter.next_back(), Some(3));
+ assert_eq!(iter.next_back(), None);
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.next_back(), None);
+ drop(iter);
+
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+ set.insert(4);
+
+ let mut iter = set.into_iter();
+ assert_eq!(iter.next(), Some(1));
+ assert_eq!(iter.next(), Some(2));
+ assert_eq!(iter.next_back(), Some(4));
+ assert_eq!(iter.next_back(), Some(3));
+ assert_eq!(iter.next_back(), None);
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.next_back(), None);
+}
+
+#[test]
+fn to_back_front_order() {
+ let mut set = LinkedHashSet::new();
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+ set.insert(4);
+
+ assert_eq!(set.back().copied(), Some(4));
+ assert_eq!(set.front().copied(), Some(1));
+ set.to_back(&2);
+ assert_eq!(set.back().copied(), Some(2));
+ set.to_front(&3);
+ assert_eq!(set.front().copied(), Some(3));
+}
+
+#[test]
+fn test_order_equality() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut set1: LinkedHashSet<i32> = xs.iter().copied().collect();
+ let mut set2: LinkedHashSet<i32> = xs.iter().copied().collect();
+
+ assert_eq!(set1, set2);
+
+ set1.to_front(&4);
+ assert_ne!(set1, set2);
+
+ set2.to_front(&4);
+ assert_eq!(set1, set2);
+}
diff --git a/third_party/rust/hashlink/tests/lru_cache.rs b/third_party/rust/hashlink/tests/lru_cache.rs
new file mode 100644
index 0000000000..f863c70e9c
--- /dev/null
+++ b/third_party/rust/hashlink/tests/lru_cache.rs
@@ -0,0 +1,166 @@
+use hashlink::LruCache;
+
+#[test]
+fn test_put_and_get() {
+ let mut cache = LruCache::new(2);
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ assert_eq!(cache.get_mut(&1), Some(&mut 10));
+ assert_eq!(cache.get_mut(&2), Some(&mut 20));
+ assert_eq!(cache.len(), 2);
+}
+
+#[test]
+fn test_put_update() {
+ let mut cache = LruCache::new(1);
+ cache.insert("1", 10);
+ cache.insert("1", 19);
+ assert_eq!(cache.get_mut("1"), Some(&mut 19));
+ assert_eq!(cache.len(), 1);
+}
+
+#[test]
+fn test_contains_key() {
+ let mut cache = LruCache::new(1);
+ cache.insert("1", 10);
+ assert_eq!(cache.contains_key("1"), true);
+}
+
+#[test]
+fn test_expire_lru() {
+ let mut cache = LruCache::new(2);
+ cache.insert("foo1", "bar1");
+ cache.insert("foo2", "bar2");
+ cache.insert("foo3", "bar3");
+ assert!(cache.get_mut("foo1").is_none());
+ cache.insert("foo2", "bar2update");
+ cache.insert("foo4", "bar4");
+ assert!(cache.get_mut("foo3").is_none());
+}
+
+#[test]
+fn test_pop() {
+ let mut cache = LruCache::new(2);
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ assert_eq!(cache.len(), 2);
+ let opt1 = cache.remove(&1);
+ assert!(opt1.is_some());
+ assert_eq!(opt1.unwrap(), 10);
+ assert!(cache.get_mut(&1).is_none());
+ assert_eq!(cache.len(), 1);
+}
+
+#[test]
+fn test_change_capacity() {
+ let mut cache = LruCache::new(2);
+ assert_eq!(cache.capacity(), 2);
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ cache.set_capacity(1);
+ assert!(cache.get_mut(&1).is_none());
+ assert_eq!(cache.capacity(), 1);
+}
+
+#[test]
+fn test_remove() {
+ let mut cache = LruCache::new(3);
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ cache.insert(3, 30);
+ cache.insert(4, 40);
+ cache.insert(5, 50);
+ cache.remove(&3);
+ cache.remove(&4);
+ assert!(cache.get_mut(&3).is_none());
+ assert!(cache.get_mut(&4).is_none());
+ cache.insert(6, 60);
+ cache.insert(7, 70);
+ cache.insert(8, 80);
+ assert!(cache.get_mut(&5).is_none());
+ assert_eq!(cache.get_mut(&6), Some(&mut 60));
+ assert_eq!(cache.get_mut(&7), Some(&mut 70));
+ assert_eq!(cache.get_mut(&8), Some(&mut 80));
+}
+
+#[test]
+fn test_clear() {
+ let mut cache = LruCache::new(2);
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ cache.clear();
+ assert!(cache.get_mut(&1).is_none());
+ assert!(cache.get_mut(&2).is_none());
+ assert!(cache.is_empty())
+}
+
+#[test]
+fn test_iter() {
+ let mut cache = LruCache::new(3);
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ cache.insert(3, 30);
+ cache.insert(4, 40);
+ cache.insert(5, 50);
+ assert_eq!(
+ cache.iter().collect::<Vec<_>>(),
+ [(&3, &30), (&4, &40), (&5, &50)]
+ );
+ assert_eq!(
+ cache.iter_mut().collect::<Vec<_>>(),
+ [(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)]
+ );
+ assert_eq!(
+ cache.iter().rev().collect::<Vec<_>>(),
+ [(&5, &50), (&4, &40), (&3, &30)]
+ );
+ assert_eq!(
+ cache.iter_mut().rev().collect::<Vec<_>>(),
+ [(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)]
+ );
+}
+
+#[test]
+fn test_peek() {
+ let mut cache = LruCache::new_unbounded();
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ cache.insert(3, 30);
+ cache.insert(4, 40);
+ cache.insert(5, 50);
+ cache.insert(6, 60);
+
+ assert_eq!(cache.remove_lru(), Some((1, 10)));
+ assert_eq!(cache.peek(&2), Some(&20));
+ assert_eq!(cache.remove_lru(), Some((2, 20)));
+ assert_eq!(cache.peek_mut(&3), Some(&mut 30));
+ assert_eq!(cache.remove_lru(), Some((3, 30)));
+ assert_eq!(cache.get(&4), Some(&40));
+ assert_eq!(cache.remove_lru(), Some((5, 50)));
+}
+
+#[test]
+fn test_entry() {
+ let mut cache = LruCache::new(4);
+
+ cache.insert(1, 10);
+ cache.insert(2, 20);
+ cache.insert(3, 30);
+ cache.insert(4, 40);
+ cache.insert(5, 50);
+ cache.insert(6, 60);
+
+ assert_eq!(cache.len(), 4);
+
+ cache.entry(7).or_insert(70);
+ cache.entry(8).or_insert(80);
+ cache.entry(9).or_insert(90);
+
+ assert!(cache.len() <= 5);
+
+ cache.raw_entry_mut().from_key(&10).or_insert(10, 100);
+ cache.raw_entry_mut().from_key(&11).or_insert(11, 110);
+ cache.raw_entry_mut().from_key(&12).or_insert(12, 120);
+
+ assert!(cache.len() <= 5);
+}
diff --git a/third_party/rust/hashlink/tests/serde.rs b/third_party/rust/hashlink/tests/serde.rs
new file mode 100644
index 0000000000..d397a245fa
--- /dev/null
+++ b/third_party/rust/hashlink/tests/serde.rs
@@ -0,0 +1,108 @@
+#![cfg(feature = "serde_impl")]
+
+use fxhash::FxBuildHasher;
+use hashlink::{LinkedHashMap, LinkedHashSet};
+use serde_test::{assert_tokens, Token};
+
+#[test]
+fn map_serde_tokens_empty() {
+ let map = LinkedHashMap::<char, u32>::new();
+
+ assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
+}
+
+#[test]
+fn map_serde_tokens() {
+ let mut map = LinkedHashMap::new();
+ map.insert('a', 10);
+ map.insert('b', 20);
+ map.insert('c', 30);
+
+ assert_tokens(
+ &map,
+ &[
+ Token::Map { len: Some(3) },
+ Token::Char('a'),
+ Token::I32(10),
+ Token::Char('b'),
+ Token::I32(20),
+ Token::Char('c'),
+ Token::I32(30),
+ Token::MapEnd,
+ ],
+ );
+}
+
+#[test]
+fn map_serde_tokens_empty_generic() {
+ let map = LinkedHashMap::<char, u32, FxBuildHasher>::with_hasher(FxBuildHasher::default());
+
+ assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
+}
+
+#[test]
+fn map_serde_tokens_generic() {
+ let mut map = LinkedHashMap::with_hasher(FxBuildHasher::default());
+ map.insert('a', 10);
+ map.insert('b', 20);
+ map.insert('c', 30);
+
+ assert_tokens(
+ &map,
+ &[
+ Token::Map { len: Some(3) },
+ Token::Char('a'),
+ Token::I32(10),
+ Token::Char('b'),
+ Token::I32(20),
+ Token::Char('c'),
+ Token::I32(30),
+ Token::MapEnd,
+ ],
+ );
+}
+
+#[test]
+fn set_serde_tokens_empty() {
+ let set = LinkedHashSet::<u32>::new();
+
+ assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
+}
+
+#[test]
+fn set_serde_tokens() {
+ let mut set = LinkedHashSet::new();
+ set.insert(10);
+ set.insert(20);
+ set.insert(30);
+
+ assert_tokens(
+ &set,
+ &[
+ Token::Seq { len: Some(3) },
+ Token::I32(10),
+ Token::I32(20),
+ Token::I32(30),
+ Token::SeqEnd,
+ ],
+ );
+}
+
+#[test]
+fn set_serde_tokens_generic() {
+ let mut set = LinkedHashSet::with_hasher(FxBuildHasher::default());
+ set.insert('a');
+ set.insert('b');
+ set.insert('c');
+
+ assert_tokens(
+ &set,
+ &[
+ Token::Seq { len: Some(3) },
+ Token::Char('a'),
+ Token::Char('b'),
+ Token::Char('c'),
+ Token::SeqEnd,
+ ],
+ );
+}