diff --git a/crates/radicle-oid/src/lib.rs b/crates/radicle-oid/src/lib.rs index e01fc7dd..9ac9d9a0 100644 --- a/crates/radicle-oid/src/lib.rs +++ b/crates/radicle-oid/src/lib.rs @@ -350,7 +350,8 @@ mod std { #[allow(clippy::derived_hash_with_manual_eq)] impl hash::Hash for Oid { fn hash(&self, state: &mut H) { - state.write(self.as_ref()); + let bytes: &[u8] = self.as_ref(); + std::hash::Hash::hash(bytes, state) } } } diff --git a/crates/radicle-protocol/src/service/filter.rs b/crates/radicle-protocol/src/service/filter.rs index 3b934dfa..500bb26a 100644 --- a/crates/radicle-protocol/src/service/filter.rs +++ b/crates/radicle-protocol/src/service/filter.rs @@ -130,6 +130,7 @@ impl qcheck::Arbitrary for Filter { } } +#[allow(clippy::unwrap_used)] #[cfg(test)] mod test { use super::*; @@ -190,4 +191,49 @@ mod test { let hs = arbitrary::set::(42..=42); assert_eq!(hs.iter().size_hint(), (42, Some(42))); } + + /// Checks that a particular filter extracted from a live deployment of + /// `radicle-node` at `release/1.5.0`, which is known to contain + /// "heartwood", actually also evaluates to contain "heartwood". + /// + /// This is to catch regressions in the [`std::hash::Hash`] implementation + /// [`RepoId`] and other breaking changes to [`Filter`]. + #[test] + fn compatible() { + let filter = { + let mut filter = [0u8; FILTER_SIZE_S]; + + #[rustfmt::skip] + const COMPRESSED_FIXTURE: [(usize, u8); 100] = [ + (0x002, 0xa8), (0x010, 0x08), (0x016, 0x40), (0x01b, 0x20), (0x04d, 0x04), + (0x050, 0x04), (0x05a, 0x02), (0x05e, 0x80), (0x06d, 0x40), (0x075, 0x08), + (0x082, 0x80), (0x084, 0x80), (0x089, 0x01), (0x08b, 0x08), (0x099, 0x04), + (0x0a1, 0x40), (0x0a7, 0x40), (0x0be, 0x40), (0x0d3, 0x01), (0x0e2, 0x01), + (0x0ee, 0x08), (0x0f2, 0x04), (0x109, 0x08), (0x119, 0x10), (0x15b, 0x40), + (0x160, 0x44), (0x163, 0x01), (0x168, 0x08), (0x16b, 0x01), (0x16d, 0x04), + (0x176, 0x80), (0x17e, 0x40), (0x189, 0x20), (0x18f, 0x04), (0x19f, 0x20), + (0x1b2, 0x08), (0x1b5, 0x04), (0x1b8, 0x20), (0x1ed, 0x10), (0x1f1, 0x40), + (0x1f3, 0x04), (0x1fa, 0x40), (0x20b, 0x08), (0x20e, 0x04), (0x218, 0x01), + (0x231, 0x02), (0x23d, 0x80), (0x248, 0x10), (0x24e, 0x04), (0x250, 0x01), + (0x251, 0x01), (0x255, 0x04), (0x25a, 0x10), (0x265, 0x20), (0x27c, 0x01), + (0x284, 0x04), (0x285, 0x20), (0x28d, 0x81), (0x29f, 0x01), (0x2a6, 0x10), + (0x2ac, 0x40), (0x2ad, 0x10), (0x2b4, 0x04), (0x2b8, 0x02), (0x2cb, 0x01), + (0x2d1, 0x80), (0x2d4, 0x01), (0x2d7, 0x40), (0x2ed, 0x80), (0x2f7, 0x01), + (0x302, 0x80), (0x303, 0x40), (0x307, 0x40), (0x309, 0x04), (0x318, 0x04), + (0x31e, 0x10), (0x335, 0x01), (0x336, 0x40), (0x338, 0x40), (0x351, 0x80), + (0x353, 0x10), (0x359, 0x0c), (0x360, 0x40), (0x367, 0x01), (0x36b, 0x08), + (0x36c, 0x40), (0x37b, 0x10), (0x37d, 0x40), (0x399, 0x02), (0x39f, 0x02), + (0x3a6, 0x02), (0x3a9, 0x04), (0x3ab, 0x01), (0x3cb, 0x04), (0x3e2, 0x01), + (0x3e5, 0x10), (0x3ea, 0x40), (0x3ed, 0x40), (0x3f2, 0x02), (0x3f5, 0x80), + ]; + + for (i, v) in COMPRESSED_FIXTURE.into_iter() { + filter[i] = v; + } + + Filter(BloomFilter::from(filter.to_vec())) + }; + + assert!(filter.contains(&"rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5".parse().unwrap()),); + } }