// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). //! Test utilities, primarily targeted to custom LiteMap stores. use crate::store::*; use crate::LiteMap; use alloc::vec::Vec; use core::fmt::Debug; // Test code #[allow(clippy::expect_used)] fn check_equivalence<'a, K, V, S0, S1>(mut a: S0, mut b: S1) where K: Ord + Debug + PartialEq + 'a, V: Debug + PartialEq + 'a, S0: StoreMut + StoreIterable<'a, K, V>, S1: StoreMut + StoreIterable<'a, K, V>, { let len = a.lm_len(); assert_eq!(len, b.lm_len()); if len == 0 { assert!(a.lm_is_empty()); assert!(b.lm_is_empty()); } for i in 0..len { let a_kv = a.lm_get(i); let b_kv = b.lm_get(i); assert!(a_kv.is_some()); assert_eq!(a_kv, b_kv); let a_kv_mut = a.lm_get_mut(i); let b_kv_mut = b.lm_get_mut(i); assert!(a_kv_mut.is_some()); assert_eq!(a_kv_mut, b_kv_mut); } for j in 0..len { let needle = a.lm_get(j).expect("j is in range").0; let a_binary = a.lm_binary_search_by(|k| k.cmp(needle)); let b_binary = a.lm_binary_search_by(|k| k.cmp(needle)); assert_eq!(Ok(j), a_binary); assert_eq!(Ok(j), b_binary); } assert!(a.lm_get(len).is_none()); assert!(b.lm_get(len).is_none()); assert_eq!(a.lm_last(), b.lm_last()); } // Test code #[allow(clippy::expect_used)] fn check_into_iter_equivalence<'a, K, V, S0, S1>(a: S0, b: S1) where K: Ord + Debug + PartialEq + 'a, V: Debug + PartialEq + 'a, S0: StoreIterableMut<'a, K, V>, S1: StoreIterableMut<'a, K, V>, { let a_vec = a.lm_into_iter().collect::>(); let b_vec = b.lm_into_iter().collect::>(); assert_eq!(a_vec, b_vec); } const SORTED_DATA: &[(u32, u64)] = &[ (106, 4816), (147, 9864), (188, 8588), (252, 6031), (434, 2518), (574, 8500), (607, 3756), (619, 4965), (663, 2669), (724, 9211), ]; const RANDOM_DATA: &[(u32, u64)] = &[ (546, 7490), (273, 4999), (167, 8078), (176, 2101), (373, 1304), (339, 9613), (561, 3620), (301, 1214), (483, 4453), (704, 5359), ]; // Test code #[allow(clippy::expect_used)] #[allow(clippy::panic)] fn populate_litemap(map: &mut LiteMap) where S: StoreMut + Debug, { assert_eq!(0, map.len()); assert!(map.is_empty()); for (k, v) in SORTED_DATA.iter() { #[allow(clippy::single_match)] // for clarity match map.try_append(*k, *v) { Some(_) => panic!("appending sorted data: {k:?} to {map:?}"), None => (), // OK }; } assert_eq!(10, map.len()); for (k, v) in RANDOM_DATA.iter() { #[allow(clippy::single_match)] // for clarity match map.try_append(*k, *v) { Some(_) => (), // OK None => panic!("cannot append random data: {k:?} to{map:?}"), }; } assert_eq!(10, map.len()); for (k, v) in RANDOM_DATA.iter() { map.insert(*k, *v); } assert_eq!(20, map.len()); } /// Tests that a litemap that uses the given store as backend has behavior consistent with the /// reference impl. /// /// Call this function in a test with the store impl to test as a valid backend for LiteMap. // Test code #[allow(clippy::expect_used)] pub fn check_store<'a, S>() where S: StoreConstEmpty + StoreMut + StoreIterable<'a, u32, u64> + StoreFromIterator + Clone + Debug + PartialEq + 'a, { let mut litemap_test: LiteMap = LiteMap::new(); assert!(litemap_test.is_empty()); let mut litemap_std = LiteMap::::new(); populate_litemap(&mut litemap_test); populate_litemap(&mut litemap_std); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); litemap_test.retain(|_, v| v % 2 == 0); litemap_std.retain(|_, v| v % 2 == 0); assert_eq!(11, litemap_test.len()); assert_eq!(11, litemap_std.len()); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); litemap_test .remove(&175) .ok_or(()) .expect_err("does not exist"); litemap_test.remove(&147).ok_or(()).expect("exists"); litemap_std .remove(&175) .ok_or(()) .expect_err("does not exist"); litemap_std.remove(&147).ok_or(()).expect("exists"); assert_eq!(10, litemap_test.len()); assert_eq!(10, litemap_std.len()); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); litemap_test.clear(); litemap_std.clear(); check_equivalence(litemap_test.values, litemap_std.values); } /// Similar to [`check_store`] function, but also checks the validitiy of [`StoreIterableMut`] /// trait. // Test code #[allow(clippy::expect_used)] pub fn check_store_full<'a, S>() where S: StoreConstEmpty + StoreIterableMut<'a, u32, u64> + StoreFromIterator + Clone + Debug + PartialEq + 'a, { let mut litemap_test: LiteMap = LiteMap::new(); assert!(litemap_test.is_empty()); let mut litemap_std = LiteMap::::new(); populate_litemap(&mut litemap_test); populate_litemap(&mut litemap_std); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values); let extras_test = litemap_test.clone(); let extras_test = litemap_test .extend_from_litemap(extras_test) .expect("duplicates"); assert_eq!(extras_test, litemap_test); let extras_std = litemap_std.clone(); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values); litemap_test.retain(|_, v| v % 2 == 0); litemap_std.retain(|_, v| v % 2 == 0); assert_eq!(11, litemap_test.len()); assert_eq!(11, litemap_std.len()); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values); let extras_test = litemap_test .extend_from_litemap(extras_test) .expect("duplicates"); let extras_std = litemap_std .extend_from_litemap(extras_std) .expect("duplicates"); assert_eq!(11, extras_test.len()); assert_eq!(11, extras_std.len()); assert_eq!(20, litemap_test.len()); assert_eq!(20, litemap_std.len()); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values); litemap_test .remove(&175) .ok_or(()) .expect_err("does not exist"); litemap_test.remove(&176).ok_or(()).expect("exists"); litemap_std .remove(&175) .ok_or(()) .expect_err("does not exist"); litemap_std.remove(&176).ok_or(()).expect("exists"); assert_eq!(19, litemap_test.len()); assert_eq!(19, litemap_std.len()); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values); litemap_test.clear(); litemap_std.clear(); check_equivalence(litemap_test.clone().values, litemap_std.clone().values); check_into_iter_equivalence(litemap_test.values, litemap_std.values); }