• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4 
5 //! Test utilities, primarily targeted to custom LiteMap stores.
6 
7 use crate::store::*;
8 use crate::LiteMap;
9 use alloc::vec::Vec;
10 use core::fmt::Debug;
11 
12 // Test code
13 #[allow(clippy::expect_used)]
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<K, V> + StoreIterable<'a, K, V>, S1: StoreMut<K, V> + StoreIterable<'a, K, V>,14 fn check_equivalence<'a, K, V, S0, S1>(mut a: S0, mut b: S1)
15 where
16     K: Ord + Debug + PartialEq + 'a,
17     V: Debug + PartialEq + 'a,
18     S0: StoreMut<K, V> + StoreIterable<'a, K, V>,
19     S1: StoreMut<K, V> + StoreIterable<'a, K, V>,
20 {
21     let len = a.lm_len();
22     assert_eq!(len, b.lm_len());
23     if len == 0 {
24         assert!(a.lm_is_empty());
25         assert!(b.lm_is_empty());
26     }
27     for i in 0..len {
28         let a_kv = a.lm_get(i);
29         let b_kv = b.lm_get(i);
30         assert!(a_kv.is_some());
31         assert_eq!(a_kv, b_kv);
32         let a_kv_mut = a.lm_get_mut(i);
33         let b_kv_mut = b.lm_get_mut(i);
34         assert!(a_kv_mut.is_some());
35         assert_eq!(a_kv_mut, b_kv_mut);
36     }
37     for j in 0..len {
38         let needle = a.lm_get(j).expect("j is in range").0;
39         let a_binary = a.lm_binary_search_by(|k| k.cmp(needle));
40         let b_binary = a.lm_binary_search_by(|k| k.cmp(needle));
41         assert_eq!(Ok(j), a_binary);
42         assert_eq!(Ok(j), b_binary);
43     }
44     assert!(a.lm_get(len).is_none());
45     assert!(b.lm_get(len).is_none());
46     assert_eq!(a.lm_last(), b.lm_last());
47 }
48 
49 // Test code
50 #[allow(clippy::expect_used)]
check_into_iter_equivalence<K, V, S0, S1>(a: S0, b: S1) where K: Ord + Debug + PartialEq, V: Debug + PartialEq, S0: StoreIntoIterator<K, V>, S1: StoreIntoIterator<K, V>,51 fn check_into_iter_equivalence<K, V, S0, S1>(a: S0, b: S1)
52 where
53     K: Ord + Debug + PartialEq,
54     V: Debug + PartialEq,
55     S0: StoreIntoIterator<K, V>,
56     S1: StoreIntoIterator<K, V>,
57 {
58     let a_vec = a.lm_into_iter().collect::<Vec<_>>();
59     let b_vec = b.lm_into_iter().collect::<Vec<_>>();
60     assert_eq!(a_vec, b_vec);
61 }
62 
63 const SORTED_DATA: &[(u32, u64)] = &[
64     (106, 4816),
65     (147, 9864),
66     (188, 8588),
67     (252, 6031),
68     (434, 2518),
69     (574, 8500),
70     (607, 3756),
71     (619, 4965),
72     (663, 2669),
73     (724, 9211),
74 ];
75 
76 const RANDOM_DATA: &[(u32, u64)] = &[
77     (546, 7490),
78     (273, 4999),
79     (167, 8078),
80     (176, 2101),
81     (373, 1304),
82     (339, 9613),
83     (561, 3620),
84     (301, 1214),
85     (483, 4453),
86     (704, 5359),
87 ];
88 
89 // Test code
90 #[allow(clippy::expect_used)]
91 #[allow(clippy::panic)]
populate_litemap<S>(map: &mut LiteMap<u32, u64, S>) where S: StoreMut<u32, u64> + Debug,92 fn populate_litemap<S>(map: &mut LiteMap<u32, u64, S>)
93 where
94     S: StoreMut<u32, u64> + Debug,
95 {
96     assert_eq!(0, map.len());
97     assert!(map.is_empty());
98     for (k, v) in SORTED_DATA.iter() {
99         #[allow(clippy::single_match)] // for clarity
100         match map.try_append(*k, *v) {
101             Some(_) => panic!("appending sorted data: {k:?} to {map:?}"),
102             None => (), // OK
103         };
104     }
105     assert_eq!(10, map.len());
106     for (k, v) in RANDOM_DATA.iter() {
107         #[allow(clippy::single_match)] // for clarity
108         match map.try_append(*k, *v) {
109             Some(_) => (), // OK
110             None => panic!("cannot append random data: {k:?} to{map:?}"),
111         };
112     }
113     assert_eq!(10, map.len());
114     for (k, v) in RANDOM_DATA.iter() {
115         map.insert(*k, *v);
116     }
117     assert_eq!(20, map.len());
118 }
119 
120 /// Tests that a litemap that uses the given store as backend has behavior consistent with the
121 /// reference impl.
122 ///
123 /// Call this function in a test with the store impl to test as a valid backend for LiteMap.
124 // Test code
125 #[allow(clippy::expect_used)]
check_store<'a, S>() where S: StoreConstEmpty<u32, u64> + StoreMut<u32, u64> + StoreIterable<'a, u32, u64> + StoreFromIterator<u32, u64> + Clone + Debug + PartialEq + 'a,126 pub fn check_store<'a, S>()
127 where
128     S: StoreConstEmpty<u32, u64>
129         + StoreMut<u32, u64>
130         + StoreIterable<'a, u32, u64>
131         + StoreFromIterator<u32, u64>
132         + Clone
133         + Debug
134         + PartialEq
135         + 'a,
136 {
137     let mut litemap_test: LiteMap<u32, u64, S> = LiteMap::new();
138     assert!(litemap_test.is_empty());
139     let mut litemap_std = LiteMap::<u32, u64>::new();
140     populate_litemap(&mut litemap_test);
141     populate_litemap(&mut litemap_std);
142     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
143 
144     litemap_test.retain(|_, v| v % 2 == 0);
145     litemap_std.retain(|_, v| v % 2 == 0);
146     assert_eq!(11, litemap_test.len());
147     assert_eq!(11, litemap_std.len());
148     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
149 
150     litemap_test
151         .remove(&175)
152         .ok_or(())
153         .expect_err("does not exist");
154     litemap_test.remove(&147).ok_or(()).expect("exists");
155     litemap_std
156         .remove(&175)
157         .ok_or(())
158         .expect_err("does not exist");
159     litemap_std.remove(&147).ok_or(()).expect("exists");
160 
161     assert_eq!(10, litemap_test.len());
162     assert_eq!(10, litemap_std.len());
163     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
164 
165     litemap_test.clear();
166     litemap_std.clear();
167     check_equivalence(litemap_test.values, litemap_std.values);
168 }
169 
170 /// Similar to [`check_store`] function, but also checks the validitiy of [`StoreIterableMut`]
171 /// trait.
172 // Test code
173 #[allow(clippy::expect_used)]
check_store_full<'a, S>() where S: StoreConstEmpty<u32, u64> + StoreIterableMut<'a, u32, u64> + StoreIntoIterator<u32, u64> + StoreFromIterator<u32, u64> + Clone + Debug + PartialEq + 'a,174 pub fn check_store_full<'a, S>()
175 where
176     S: StoreConstEmpty<u32, u64>
177         + StoreIterableMut<'a, u32, u64>
178         + StoreIntoIterator<u32, u64>
179         + StoreFromIterator<u32, u64>
180         + Clone
181         + Debug
182         + PartialEq
183         + 'a,
184 {
185     let mut litemap_test: LiteMap<u32, u64, S> = LiteMap::new();
186     assert!(litemap_test.is_empty());
187     let mut litemap_std = LiteMap::<u32, u64>::new();
188     populate_litemap(&mut litemap_test);
189     populate_litemap(&mut litemap_std);
190     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
191     check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values);
192 
193     let extras_test = litemap_test.clone();
194     let extras_test = litemap_test
195         .extend_from_litemap(extras_test)
196         .expect("duplicates");
197     assert_eq!(extras_test, litemap_test);
198     let extras_std = litemap_std.clone();
199     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
200     check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values);
201 
202     litemap_test.retain(|_, v| v % 2 == 0);
203     litemap_std.retain(|_, v| v % 2 == 0);
204     assert_eq!(11, litemap_test.len());
205     assert_eq!(11, litemap_std.len());
206     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
207     check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values);
208 
209     let extras_test = litemap_test
210         .extend_from_litemap(extras_test)
211         .expect("duplicates");
212     let extras_std = litemap_std
213         .extend_from_litemap(extras_std)
214         .expect("duplicates");
215     assert_eq!(11, extras_test.len());
216     assert_eq!(11, extras_std.len());
217     assert_eq!(20, litemap_test.len());
218     assert_eq!(20, litemap_std.len());
219     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
220     check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values);
221 
222     litemap_test
223         .remove(&175)
224         .ok_or(())
225         .expect_err("does not exist");
226     litemap_test.remove(&176).ok_or(()).expect("exists");
227     litemap_std
228         .remove(&175)
229         .ok_or(())
230         .expect_err("does not exist");
231     litemap_std.remove(&176).ok_or(()).expect("exists");
232     assert_eq!(19, litemap_test.len());
233     assert_eq!(19, litemap_std.len());
234     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
235     check_into_iter_equivalence(litemap_test.clone().values, litemap_std.clone().values);
236 
237     litemap_test.clear();
238     litemap_std.clear();
239     check_equivalence(litemap_test.clone().values, litemap_std.clone().values);
240     check_into_iter_equivalence(litemap_test.values, litemap_std.values);
241 }
242