1 use indexmap
::{IndexMap, IndexSet}
;
2 use itertools
::Itertools
;
4 use quickcheck
::Arbitrary
;
6 use quickcheck
::QuickCheck
;
7 use quickcheck
::TestResult
;
10 use std
::hash
::{BuildHasher, BuildHasherDefault}
;
11 type FnvBuilder
= BuildHasherDefault
<FnvHasher
>;
12 type IndexMapFnv
<K
, V
> = IndexMap
<K
, V
, FnvBuilder
>;
15 use std
::collections
::HashMap
;
16 use std
::collections
::HashSet
;
19 use std
::iter
::FromIterator
;
23 use indexmap
::map
::Entry
as OEntry
;
24 use std
::collections
::hash_map
::Entry
as HEntry
;
26 fn set
<'a
, T
: 'a
, I
>(iter
: I
) -> HashSet
<T
>
28 I
: IntoIterator
<Item
= &'a T
>,
31 iter
.into_iter().copied().collect()
34 fn indexmap
<'a
, T
: 'a
, I
>(iter
: I
) -> IndexMap
<T
, ()>
36 I
: IntoIterator
<Item
= &'a T
>,
39 IndexMap
::from_iter(iter
.into_iter().copied().map(|k
| (k
, ())))
42 // Helper macro to allow us to use smaller quickcheck limits under miri.
43 macro_rules
! quickcheck_limit
{
44 (@as_items $
($i
:item
)*) => ($
($i
)*);
48 fn $fn_name
:ident($
($arg_name
:ident
: $arg_ty
:ty
),*) -> $ret
:ty
{
53 quickcheck
::quickcheck
! {
59 fn prop($
($arg_name
: $arg_ty
),*) -> $ret
{
62 let mut quickcheck
= QuickCheck
::new();
64 quickcheck
= quickcheck
70 quickcheck
.quickcheck(prop
as fn($
($arg_ty
),*) -> $ret
);
78 fn contains(insert
: Vec
<u32>) -> bool
{
79 let mut map
= IndexMap
::new();
83 insert
.iter().all(|&key
| map
.get(&key
).is_some())
86 fn contains_not(insert
: Vec
<u8>, not
: Vec
<u8>) -> bool
{
87 let mut map
= IndexMap
::new();
91 let nots
= &set(¬
) - &set(&insert
);
92 nots
.iter().all(|&key
| map
.get(&key
).is_none())
95 fn insert_remove(insert
: Vec
<u8>, remove
: Vec
<u8>) -> bool
{
96 let mut map
= IndexMap
::new();
100 for &key
in &remove
{
101 map
.swap_remove(&key
);
103 let elements
= &set(&insert
) - &set(&remove
);
104 map
.len() == elements
.len() && map
.iter().count() == elements
.len() &&
105 elements
.iter().all(|k
| map
.get(k
).is_some())
108 fn insertion_order(insert
: Vec
<u32>) -> bool
{
109 let mut map
= IndexMap
::new();
110 for &key
in &insert
{
113 itertools
::assert_equal(insert
.iter().unique(), map
.keys());
117 fn pop(insert
: Vec
<u8>) -> bool
{
118 let mut map
= IndexMap
::new();
119 for &key
in &insert
{
122 let mut pops
= Vec
::new();
123 while let Some((key
, _v
)) = map
.pop() {
128 itertools
::assert_equal(insert
.iter().unique(), &pops
);
132 fn with_cap(template
: Vec
<()>) -> bool
{
133 let cap
= template
.len();
134 let map
: IndexMap
<u8, u8> = IndexMap
::with_capacity(cap
);
135 println
!("wish: {}, got: {} (diff: {})", cap
, map
.capacity(), map
.capacity() as isize - cap
as isize);
136 map
.capacity() >= cap
139 fn drain_full(insert
: Vec
<u8>) -> bool
{
140 let mut map
= IndexMap
::new();
141 for &key
in &insert
{
144 let mut clone
= map
.clone();
145 let drained
= clone
.drain(..);
146 for (key
, _
) in drained
{
147 map
.swap_remove(&key
);
152 fn drain_bounds(insert
: Vec
<u8>, range
: (Bound
<usize>, Bound
<usize>)) -> TestResult
{
153 let mut map
= IndexMap
::new();
154 for &key
in &insert
{
158 // First see if `Vec::drain` is happy with this range.
159 let result
= std
::panic
::catch_unwind(|| {
160 let mut keys
: Vec
<u8> = map
.keys().copied().collect();
165 if let Ok(keys
) = result
{
167 // Check that our `drain` matches the same key order.
168 assert
!(map
.keys().eq(&keys
));
169 // Check that hash lookups all work too.
170 assert
!(keys
.iter().all(|key
| map
.contains_key(key
)));
173 // If `Vec::drain` panicked, so should we.
174 TestResult
::must_fail(move || { map.drain(range); }
)
178 fn shift_remove(insert
: Vec
<u8>, remove
: Vec
<u8>) -> bool
{
179 let mut map
= IndexMap
::new();
180 for &key
in &insert
{
183 for &key
in &remove
{
184 map
.shift_remove(&key
);
186 let elements
= &set(&insert
) - &set(&remove
);
188 // Check that order is preserved after removals
189 let mut iter
= map
.keys();
190 for &key
in insert
.iter().unique() {
191 if elements
.contains(&key
) {
192 assert_eq
!(Some(&key
), iter
.next());
196 map
.len() == elements
.len() && map
.iter().count() == elements
.len() &&
197 elements
.iter().all(|k
| map
.get(k
).is_some())
200 fn indexing(insert
: Vec
<u8>) -> bool
{
201 let mut map
: IndexMap
<_
, _
> = insert
.into_iter().map(|x
| (x
, x
)).collect();
202 let set
: IndexSet
<_
> = map
.keys().copied().collect();
203 assert_eq
!(map
.len(), set
.len());
205 for (i
, &key
) in set
.iter().enumerate() {
206 assert_eq
!(map
.get_index(i
), Some((&key
, &key
)));
207 assert_eq
!(set
.get_index(i
), Some(&key
));
208 assert_eq
!(map
[i
], key
);
209 assert_eq
!(set
[i
], key
);
211 *map
.get_index_mut(i
).unwrap().1 >>= 1;
215 set
.iter().enumerate().all(|(i
, &key
)| {
216 let value
= key
& !1;
217 map
[&key
] == value
&& map
[i
] == value
223 #[derive(Copy, Clone, Debug)]
231 impl<K
, V
> Arbitrary
for Op
<K
, V
>
236 fn arbitrary(g
: &mut Gen
) -> Self {
237 match u32::arbitrary(g
) % 4 {
238 0 => Add(K
::arbitrary(g
), V
::arbitrary(g
)),
239 1 => AddEntry(K
::arbitrary(g
), V
::arbitrary(g
)),
240 2 => Remove(K
::arbitrary(g
)),
241 _
=> RemoveEntry(K
::arbitrary(g
)),
246 fn do_ops
<K
, V
, S
>(ops
: &[Op
<K
, V
>], a
: &mut IndexMap
<K
, V
, S
>, b
: &mut HashMap
<K
, V
>)
248 K
: Hash
+ Eq
+ Clone
,
254 Add(ref k
, ref v
) => {
255 a
.insert(k
.clone(), v
.clone());
256 b
.insert(k
.clone(), v
.clone());
258 AddEntry(ref k
, ref v
) => {
259 a
.entry(k
.clone()).or_insert_with(|| v
.clone());
260 b
.entry(k
.clone()).or_insert_with(|| v
.clone());
266 RemoveEntry(ref k
) => {
267 if let OEntry
::Occupied(ent
) = a
.entry(k
.clone()) {
268 ent
.swap_remove_entry();
270 if let HEntry
::Occupied(ent
) = b
.entry(k
.clone()) {
275 //println!("{:?}", a);
279 fn assert_maps_equivalent
<K
, V
>(a
: &IndexMap
<K
, V
>, b
: &HashMap
<K
, V
>) -> bool
281 K
: Hash
+ Eq
+ Debug
,
284 assert_eq
!(a
.len(), b
.len());
285 assert_eq
!(a
.iter().next().is_some(), b
.iter().next().is_some());
286 for key
in a
.keys() {
287 assert
!(b
.contains_key(key
), "b does not contain {:?}", key
);
289 for key
in b
.keys() {
290 assert
!(a
.get(key
).is_some(), "a does not contain {:?}", key
);
292 for key
in a
.keys() {
293 assert_eq
!(a
[key
], b
[key
]);
299 fn operations_i8(ops
: Large
<Vec
<Op
<i8, i8>>>) -> bool
{
300 let mut map
= IndexMap
::new();
301 let mut reference
= HashMap
::new();
302 do_ops(&ops
, &mut map
, &mut reference
);
303 assert_maps_equivalent(&map
, &reference
)
306 fn operations_string(ops
: Vec
<Op
<Alpha
, i8>>) -> bool
{
307 let mut map
= IndexMap
::new();
308 let mut reference
= HashMap
::new();
309 do_ops(&ops
, &mut map
, &mut reference
);
310 assert_maps_equivalent(&map
, &reference
)
313 fn keys_values(ops
: Large
<Vec
<Op
<i8, i8>>>) -> bool
{
314 let mut map
= IndexMap
::new();
315 let mut reference
= HashMap
::new();
316 do_ops(&ops
, &mut map
, &mut reference
);
317 let mut visit
= IndexMap
::new();
318 for (k
, v
) in map
.keys().zip(map
.values()) {
319 assert_eq
!(&map
[k
], v
);
320 assert
!(!visit
.contains_key(k
));
321 visit
.insert(*k
, *v
);
323 assert_eq
!(visit
.len(), reference
.len());
327 fn keys_values_mut(ops
: Large
<Vec
<Op
<i8, i8>>>) -> bool
{
328 let mut map
= IndexMap
::new();
329 let mut reference
= HashMap
::new();
330 do_ops(&ops
, &mut map
, &mut reference
);
331 let mut visit
= IndexMap
::new();
332 let keys
= Vec
::from_iter(map
.keys().copied());
333 for (k
, v
) in keys
.iter().zip(map
.values_mut()) {
334 assert_eq
!(&reference
[k
], v
);
335 assert
!(!visit
.contains_key(k
));
336 visit
.insert(*k
, *v
);
338 assert_eq
!(visit
.len(), reference
.len());
342 fn equality(ops1
: Vec
<Op
<i8, i8>>, removes
: Vec
<usize>) -> bool
{
343 let mut map
= IndexMap
::new();
344 let mut reference
= HashMap
::new();
345 do_ops(&ops1
, &mut map
, &mut reference
);
346 let mut ops2
= ops1
.clone();
348 if !ops2
.is_empty() {
349 let i
= r
% ops2
.len();
353 let mut map2
= IndexMapFnv
::default();
354 let mut reference2
= HashMap
::new();
355 do_ops(&ops2
, &mut map2
, &mut reference2
);
356 assert_eq
!(map
== map2
, reference
== reference2
);
360 fn retain_ordered(keys
: Large
<Vec
<i8>>, remove
: Large
<Vec
<i8>>) -> () {
361 let mut map
= indexmap(keys
.iter());
362 let initial_map
= map
.clone(); // deduplicated in-order input
363 let remove_map
= indexmap(remove
.iter());
364 let keys_s
= set(keys
.iter());
365 let remove_s
= set(remove
.iter());
366 let answer
= &keys_s
- &remove_s
;
367 map
.retain(|k
, _
| !remove_map
.contains_key(k
));
370 assert_eq
!(map
.len(), answer
.len());
372 assert
!(map
.contains_key(key
));
375 itertools
::assert_equal(map
.keys(), initial_map
.keys().filter(|&k
| !remove_map
.contains_key(k
)));
378 fn sort_1(keyvals
: Large
<Vec
<(i8, i8)>>) -> () {
379 let mut map
: IndexMap
<_
, _
> = IndexMap
::from_iter(keyvals
.to_vec());
380 let mut answer
= keyvals
.0;
381 answer
.sort_by_key(|t
| t
.0);
383 // reverse dedup: Because IndexMap::from_iter keeps the last value for
386 answer
.dedup_by_key(|t
| t
.0);
389 map
.sort_by(|k1
, _
, k2
, _
| Ord
::cmp(k1
, k2
));
391 // check it contains all the values it should
392 for &(key
, val
) in &answer
{
393 assert_eq
!(map
[&key
], val
);
398 let mapv
= Vec
::from_iter(map
);
399 assert_eq
!(answer
, mapv
);
403 fn sort_2(keyvals
: Large
<Vec
<(i8, i8)>>) -> () {
404 let mut map
: IndexMap
<_
, _
> = IndexMap
::from_iter(keyvals
.to_vec());
405 map
.sort_by(|_
, v1
, _
, v2
| Ord
::cmp(v1
, v2
));
406 assert_sorted_by_key(map
, |t
| t
.1);
409 fn reverse(keyvals
: Large
<Vec
<(i8, i8)>>) -> () {
410 let mut map
: IndexMap
<_
, _
> = IndexMap
::from_iter(keyvals
.to_vec());
412 fn generate_answer(input
: &Vec
<(i8, i8)>) -> Vec
<(i8, i8)> {
413 // to mimic what `IndexMap::from_iter` does:
414 // need to get (A) the unique keys in forward order, and (B) the
415 // last value of each of those keys.
417 // create (A): an iterable that yields the unique keys in ltr order
418 let mut seen_keys
= HashSet
::new();
419 let unique_keys_forward
= input
.iter().filter_map(move |(k
, _
)| {
420 if seen_keys
.contains(k
) { None }
421 else { seen_keys.insert(*k); Some(*k) }
424 // create (B): a mapping of keys to the last value seen for that key
425 // this is the same as reversing the input and taking the first
426 // value seen for that key!
427 let mut last_val_per_key
= HashMap
::new();
428 for &(k
, v
) in input
.iter().rev() {
429 if !last_val_per_key
.contains_key(&k
) {
430 last_val_per_key
.insert(k
, v
);
434 // iterate over the keys in (A) in order, and match each one with
435 // the corresponding last value from (B)
436 let mut ans
: Vec
<_
> = unique_keys_forward
437 .map(|k
| (k
, *last_val_per_key
.get(&k
).unwrap()))
440 // finally, since this test is testing `.reverse()`, reverse the
447 let answer
= generate_answer(&keyvals
.0);
452 // check it contains all the values it should
453 for &(key
, val
) in &answer
{
454 assert_eq
!(map
[&key
], val
);
458 let mapv
= Vec
::from_iter(map
);
459 assert_eq
!(answer
, mapv
);
463 fn assert_sorted_by_key
<I
, Key
, X
>(iterable
: I
, key
: Key
)
466 I
::Item
: Ord
+ Clone
+ Debug
,
467 Key
: Fn(&I
::Item
) -> X
,
470 let input
= Vec
::from_iter(iterable
);
471 let mut sorted
= input
.clone();
472 sorted
.sort_by_key(key
);
473 assert_eq
!(input
, sorted
);
476 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
477 struct Alpha(String
);
479 impl Deref
for Alpha
{
480 type Target
= String
;
481 fn deref(&self) -> &String
{
486 const ALPHABET
: &[u8] = b
"abcdefghijklmnopqrstuvwxyz";
488 impl Arbitrary
for Alpha
{
489 fn arbitrary(g
: &mut Gen
) -> Self {
490 let len
= usize::arbitrary(g
) % g
.size();
491 let len
= min(len
, 16);
494 .map(|_
| ALPHABET
[usize::arbitrary(g
) % ALPHABET
.len()] as char)
499 fn shrink(&self) -> Box
<dyn Iterator
<Item
= Self>> {
500 Box
::new((**self).shrink().map(Alpha
))
504 /// quickcheck Arbitrary adaptor -- make a larger vec
505 #[derive(Clone, Debug)]
508 impl<T
> Deref
for Large
<T
> {
510 fn deref(&self) -> &T
{
515 impl<T
> Arbitrary
for Large
<Vec
<T
>>
519 fn arbitrary(g
: &mut Gen
) -> Self {
520 let len
= usize::arbitrary(g
) % (g
.size() * 10);
521 Large((0..len
).map(|_
| T
::arbitrary(g
)).collect())
524 fn shrink(&self) -> Box
<dyn Iterator
<Item
= Self>> {
525 Box
::new((**self).shrink().map(Large
))