|
| 1 | +//! Regression tests which fail if some collections' `PartialEq::eq` impls compare |
| 2 | +//! elements when the collections have different sizes. |
| 3 | +//! This behavior is not guaranteed either way, so regressing these tests is fine |
| 4 | +//! if it is done on purpose. |
| 5 | +use std::cmp::Ordering; |
| 6 | +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList}; |
| 7 | + |
| 8 | +/// This intentionally has a panicking `PartialEq` impl, to test that various |
| 9 | +/// collections' `PartialEq` impls don't actually compare elements if their sizes |
| 10 | +/// are unequal. |
| 11 | +/// |
| 12 | +/// This is not advisable in normal code. |
| 13 | +#[derive(Debug, Clone, Copy, Hash)] |
| 14 | +struct Evil; |
| 15 | + |
| 16 | +impl PartialEq for Evil { |
| 17 | + fn eq(&self, _: &Self) -> bool { |
| 18 | + panic!("Evil::eq is evil"); |
| 19 | + } |
| 20 | +} |
| 21 | +impl Eq for Evil {} |
| 22 | + |
| 23 | +impl PartialOrd for Evil { |
| 24 | + fn partial_cmp(&self, _: &Self) -> Option<Ordering> { |
| 25 | + Some(Ordering::Equal) |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +impl Ord for Evil { |
| 30 | + fn cmp(&self, _: &Self) -> Ordering { |
| 31 | + // Constructing a `BTreeSet`/`BTreeMap` uses `cmp` on the elements, |
| 32 | + // but comparing it with with `==` uses `eq` on the elements, |
| 33 | + // so Evil::cmp doesn't need to be evil. |
| 34 | + Ordering::Equal |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +// check Evil works |
| 39 | +#[test] |
| 40 | +#[should_panic = "Evil::eq is evil"] |
| 41 | +fn evil_eq_works() { |
| 42 | + let v1 = vec![Evil]; |
| 43 | + let v2 = vec![Evil]; |
| 44 | + |
| 45 | + _ = v1 == v2; |
| 46 | +} |
| 47 | + |
| 48 | +// check various containers don't compare if their sizes are different |
| 49 | + |
| 50 | +#[test] |
| 51 | +fn vec_evil_eq() { |
| 52 | + let v1 = vec![Evil]; |
| 53 | + let v2 = vec![Evil; 2]; |
| 54 | + |
| 55 | + assert_eq!(false, v1 == v2); |
| 56 | +} |
| 57 | + |
| 58 | +#[test] |
| 59 | +fn hashset_evil_eq() { |
| 60 | + let s1 = HashSet::from([(0, Evil)]); |
| 61 | + let s2 = HashSet::from([(0, Evil), (1, Evil)]); |
| 62 | + |
| 63 | + assert_eq!(false, s1 == s2); |
| 64 | +} |
| 65 | + |
| 66 | +#[test] |
| 67 | +fn hashmap_evil_eq() { |
| 68 | + let m1 = HashMap::from([(0, Evil)]); |
| 69 | + let m2 = HashMap::from([(0, Evil), (1, Evil)]); |
| 70 | + |
| 71 | + assert_eq!(false, m1 == m2); |
| 72 | +} |
| 73 | + |
| 74 | +#[test] |
| 75 | +fn btreeset_evil_eq() { |
| 76 | + let s1 = BTreeSet::from([(0, Evil)]); |
| 77 | + let s2 = BTreeSet::from([(0, Evil), (1, Evil)]); |
| 78 | + |
| 79 | + assert_eq!(false, s1 == s2); |
| 80 | +} |
| 81 | + |
| 82 | +#[test] |
| 83 | +fn btreemap_evil_eq() { |
| 84 | + let m1 = BTreeMap::from([(0, Evil)]); |
| 85 | + let m2 = BTreeMap::from([(0, Evil), (1, Evil)]); |
| 86 | + |
| 87 | + assert_eq!(false, m1 == m2); |
| 88 | +} |
| 89 | + |
| 90 | +#[test] |
| 91 | +fn linkedlist_evil_eq() { |
| 92 | + let m1 = LinkedList::from([Evil]); |
| 93 | + let m2 = LinkedList::from([Evil; 2]); |
| 94 | + |
| 95 | + assert_eq!(false, m1 == m2); |
| 96 | +} |
0 commit comments