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
;
22 use indexmap
::map
::Entry
as OEntry
;
23 use std
::collections
::hash_map
::Entry
as HEntry
;
25 fn set
<'a
, T
: 'a
, I
>(iter
: I
) -> HashSet
<T
>
27 I
: IntoIterator
<Item
= &'a T
>,
30 iter
.into_iter().copied().collect()
33 fn indexmap
<'a
, T
: 'a
, I
>(iter
: I
) -> IndexMap
<T
, ()>
35 I
: IntoIterator
<Item
= &'a T
>,
38 IndexMap
::from_iter(iter
.into_iter().copied().map(|k
| (k
, ())))
41 // Helper macro to allow us to use smaller quickcheck limits under miri.
42 macro_rules
! quickcheck_limit
{
43 (@as_items $
($i
:item
)*) => ($
($i
)*);
47 fn $fn_name
:ident($
($arg_name
:ident
: $arg_ty
:ty
),*) -> $ret
:ty
{
52 quickcheck
::quickcheck
! {
58 fn prop($
($arg_name
: $arg_ty
),*) -> $ret
{
61 let mut quickcheck
= QuickCheck
::new();
63 quickcheck
= quickcheck
69 quickcheck
.quickcheck(prop
as fn($
($arg_ty
),*) -> $ret
);
77 fn contains(insert
: Vec
<u32>) -> bool
{
78 let mut map
= IndexMap
::new();
82 insert
.iter().all(|&key
| map
.get(&key
).is_some())
85 fn contains_not(insert
: Vec
<u8>, not
: Vec
<u8>) -> bool
{
86 let mut map
= IndexMap
::new();
90 let nots
= &set(¬
) - &set(&insert
);
91 nots
.iter().all(|&key
| map
.get(&key
).is_none())
94 fn insert_remove(insert
: Vec
<u8>, remove
: Vec
<u8>) -> bool
{
95 let mut map
= IndexMap
::new();
100 map
.swap_remove(&key
);
102 let elements
= &set(&insert
) - &set(&remove
);
103 map
.len() == elements
.len() && map
.iter().count() == elements
.len() &&
104 elements
.iter().all(|k
| map
.get(k
).is_some())
107 fn insertion_order(insert
: Vec
<u32>) -> bool
{
108 let mut map
= IndexMap
::new();
109 for &key
in &insert
{
112 itertools
::assert_equal(insert
.iter().unique(), map
.keys());
116 fn pop(insert
: Vec
<u8>) -> bool
{
117 let mut map
= IndexMap
::new();
118 for &key
in &insert
{
121 let mut pops
= Vec
::new();
122 while let Some((key
, _v
)) = map
.pop() {
127 itertools
::assert_equal(insert
.iter().unique(), &pops
);
131 fn with_cap(template
: Vec
<()>) -> bool
{
132 let cap
= template
.len();
133 let map
: IndexMap
<u8, u8> = IndexMap
::with_capacity(cap
);
134 println
!("wish: {}, got: {} (diff: {})", cap
, map
.capacity(), map
.capacity() as isize - cap
as isize);
135 map
.capacity() >= cap
138 fn drain_full(insert
: Vec
<u8>) -> bool
{
139 let mut map
= IndexMap
::new();
140 for &key
in &insert
{
143 let mut clone
= map
.clone();
144 let drained
= clone
.drain(..);
145 for (key
, _
) in drained
{
146 map
.swap_remove(&key
);
151 fn drain_bounds(insert
: Vec
<u8>, range
: (Bound
<usize>, Bound
<usize>)) -> TestResult
{
152 let mut map
= IndexMap
::new();
153 for &key
in &insert
{
157 // First see if `Vec::drain` is happy with this range.
158 let result
= std
::panic
::catch_unwind(|| {
159 let mut keys
: Vec
<u8> = map
.keys().copied().collect();
164 if let Ok(keys
) = result
{
166 // Check that our `drain` matches the same key order.
167 assert
!(map
.keys().eq(&keys
));
168 // Check that hash lookups all work too.
169 assert
!(keys
.iter().all(|key
| map
.contains_key(key
)));
172 // If `Vec::drain` panicked, so should we.
173 TestResult
::must_fail(move || { map.drain(range); }
)
177 fn shift_remove(insert
: Vec
<u8>, remove
: Vec
<u8>) -> bool
{
178 let mut map
= IndexMap
::new();
179 for &key
in &insert
{
182 for &key
in &remove
{
183 map
.shift_remove(&key
);
185 let elements
= &set(&insert
) - &set(&remove
);
187 // Check that order is preserved after removals
188 let mut iter
= map
.keys();
189 for &key
in insert
.iter().unique() {
190 if elements
.contains(&key
) {
191 assert_eq
!(Some(&key
), iter
.next());
195 map
.len() == elements
.len() && map
.iter().count() == elements
.len() &&
196 elements
.iter().all(|k
| map
.get(k
).is_some())
199 fn indexing(insert
: Vec
<u8>) -> bool
{
200 let mut map
: IndexMap
<_
, _
> = insert
.into_iter().map(|x
| (x
, x
)).collect();
201 let set
: IndexSet
<_
> = map
.keys().copied().collect();
202 assert_eq
!(map
.len(), set
.len());
204 for (i
, &key
) in set
.iter().enumerate() {
205 assert_eq
!(map
.get_index(i
), Some((&key
, &key
)));
206 assert_eq
!(set
.get_index(i
), Some(&key
));
207 assert_eq
!(map
[i
], key
);
208 assert_eq
!(set
[i
], key
);
210 *map
.get_index_mut(i
).unwrap().1 >>= 1;
214 set
.iter().enumerate().all(|(i
, &key
)| {
215 let value
= key
& !1;
216 map
[&key
] == value
&& map
[i
] == value
220 // Use `u8` test indices so quickcheck is less likely to go out of bounds.
221 fn swap_indices(vec
: Vec
<u8>, a
: u8, b
: u8) -> TestResult
{
222 let mut set
= IndexSet
::<u8>::from_iter(vec
);
223 let a
= usize::from(a
);
224 let b
= usize::from(b
);
226 if a
>= set
.len() || b
>= set
.len() {
227 return TestResult
::discard();
230 let mut vec
= Vec
::from_iter(set
.iter().cloned());
233 set
.swap_indices(a
, b
);
235 // Check both iteration order and hash lookups
236 assert
!(set
.iter().eq(vec
.iter()));
237 assert
!(vec
.iter().enumerate().all(|(i
, x
)| {
238 set
.get_index_of(x
) == Some(i
)
243 // Use `u8` test indices so quickcheck is less likely to go out of bounds.
244 fn move_index(vec
: Vec
<u8>, from
: u8, to
: u8) -> TestResult
{
245 let mut set
= IndexSet
::<u8>::from_iter(vec
);
246 let from
= usize::from(from
);
247 let to
= usize::from(to
);
249 if from
>= set
.len() || to
>= set
.len() {
250 return TestResult
::discard();
253 let mut vec
= Vec
::from_iter(set
.iter().cloned());
254 let x
= vec
.remove(from
);
257 set
.move_index(from
, to
);
259 // Check both iteration order and hash lookups
260 assert
!(set
.iter().eq(vec
.iter()));
261 assert
!(vec
.iter().enumerate().all(|(i
, x
)| {
262 set
.get_index_of(x
) == Some(i
)
269 #[derive(Copy, Clone, Debug)]
277 impl<K
, V
> Arbitrary
for Op
<K
, V
>
282 fn arbitrary(g
: &mut Gen
) -> Self {
283 match u32::arbitrary(g
) % 4 {
284 0 => Add(K
::arbitrary(g
), V
::arbitrary(g
)),
285 1 => AddEntry(K
::arbitrary(g
), V
::arbitrary(g
)),
286 2 => Remove(K
::arbitrary(g
)),
287 _
=> RemoveEntry(K
::arbitrary(g
)),
292 fn do_ops
<K
, V
, S
>(ops
: &[Op
<K
, V
>], a
: &mut IndexMap
<K
, V
, S
>, b
: &mut HashMap
<K
, V
>)
294 K
: Hash
+ Eq
+ Clone
,
300 Add(ref k
, ref v
) => {
301 a
.insert(k
.clone(), v
.clone());
302 b
.insert(k
.clone(), v
.clone());
304 AddEntry(ref k
, ref v
) => {
305 a
.entry(k
.clone()).or_insert_with(|| v
.clone());
306 b
.entry(k
.clone()).or_insert_with(|| v
.clone());
312 RemoveEntry(ref k
) => {
313 if let OEntry
::Occupied(ent
) = a
.entry(k
.clone()) {
314 ent
.swap_remove_entry();
316 if let HEntry
::Occupied(ent
) = b
.entry(k
.clone()) {
321 //println!("{:?}", a);
325 fn assert_maps_equivalent
<K
, V
>(a
: &IndexMap
<K
, V
>, b
: &HashMap
<K
, V
>) -> bool
327 K
: Hash
+ Eq
+ Debug
,
330 assert_eq
!(a
.len(), b
.len());
331 assert_eq
!(a
.iter().next().is_some(), b
.iter().next().is_some());
332 for key
in a
.keys() {
333 assert
!(b
.contains_key(key
), "b does not contain {:?}", key
);
335 for key
in b
.keys() {
336 assert
!(a
.get(key
).is_some(), "a does not contain {:?}", key
);
338 for key
in a
.keys() {
339 assert_eq
!(a
[key
], b
[key
]);
345 fn operations_i8(ops
: Large
<Vec
<Op
<i8, i8>>>) -> bool
{
346 let mut map
= IndexMap
::new();
347 let mut reference
= HashMap
::new();
348 do_ops(&ops
, &mut map
, &mut reference
);
349 assert_maps_equivalent(&map
, &reference
)
352 fn operations_string(ops
: Vec
<Op
<Alpha
, i8>>) -> bool
{
353 let mut map
= IndexMap
::new();
354 let mut reference
= HashMap
::new();
355 do_ops(&ops
, &mut map
, &mut reference
);
356 assert_maps_equivalent(&map
, &reference
)
359 fn keys_values(ops
: Large
<Vec
<Op
<i8, i8>>>) -> bool
{
360 let mut map
= IndexMap
::new();
361 let mut reference
= HashMap
::new();
362 do_ops(&ops
, &mut map
, &mut reference
);
363 let mut visit
= IndexMap
::new();
364 for (k
, v
) in map
.keys().zip(map
.values()) {
365 assert_eq
!(&map
[k
], v
);
366 assert
!(!visit
.contains_key(k
));
367 visit
.insert(*k
, *v
);
369 assert_eq
!(visit
.len(), reference
.len());
373 fn keys_values_mut(ops
: Large
<Vec
<Op
<i8, i8>>>) -> bool
{
374 let mut map
= IndexMap
::new();
375 let mut reference
= HashMap
::new();
376 do_ops(&ops
, &mut map
, &mut reference
);
377 let mut visit
= IndexMap
::new();
378 let keys
= Vec
::from_iter(map
.keys().copied());
379 for (k
, v
) in keys
.iter().zip(map
.values_mut()) {
380 assert_eq
!(&reference
[k
], v
);
381 assert
!(!visit
.contains_key(k
));
382 visit
.insert(*k
, *v
);
384 assert_eq
!(visit
.len(), reference
.len());
388 fn equality(ops1
: Vec
<Op
<i8, i8>>, removes
: Vec
<usize>) -> bool
{
389 let mut map
= IndexMap
::new();
390 let mut reference
= HashMap
::new();
391 do_ops(&ops1
, &mut map
, &mut reference
);
392 let mut ops2
= ops1
.clone();
394 if !ops2
.is_empty() {
395 let i
= r
% ops2
.len();
399 let mut map2
= IndexMapFnv
::default();
400 let mut reference2
= HashMap
::new();
401 do_ops(&ops2
, &mut map2
, &mut reference2
);
402 assert_eq
!(map
== map2
, reference
== reference2
);
406 fn retain_ordered(keys
: Large
<Vec
<i8>>, remove
: Large
<Vec
<i8>>) -> () {
407 let mut map
= indexmap(keys
.iter());
408 let initial_map
= map
.clone(); // deduplicated in-order input
409 let remove_map
= indexmap(remove
.iter());
410 let keys_s
= set(keys
.iter());
411 let remove_s
= set(remove
.iter());
412 let answer
= &keys_s
- &remove_s
;
413 map
.retain(|k
, _
| !remove_map
.contains_key(k
));
416 assert_eq
!(map
.len(), answer
.len());
418 assert
!(map
.contains_key(key
));
421 itertools
::assert_equal(map
.keys(), initial_map
.keys().filter(|&k
| !remove_map
.contains_key(k
)));
424 fn sort_1(keyvals
: Large
<Vec
<(i8, i8)>>) -> () {
425 let mut map
: IndexMap
<_
, _
> = IndexMap
::from_iter(keyvals
.to_vec());
426 let mut answer
= keyvals
.0;
427 answer
.sort_by_key(|t
| t
.0);
429 // reverse dedup: Because IndexMap::from_iter keeps the last value for
432 answer
.dedup_by_key(|t
| t
.0);
435 map
.sort_by(|k1
, _
, k2
, _
| Ord
::cmp(k1
, k2
));
437 // check it contains all the values it should
438 for &(key
, val
) in &answer
{
439 assert_eq
!(map
[&key
], val
);
444 let mapv
= Vec
::from_iter(map
);
445 assert_eq
!(answer
, mapv
);
449 fn sort_2(keyvals
: Large
<Vec
<(i8, i8)>>) -> () {
450 let mut map
: IndexMap
<_
, _
> = IndexMap
::from_iter(keyvals
.to_vec());
451 map
.sort_by(|_
, v1
, _
, v2
| Ord
::cmp(v1
, v2
));
452 assert_sorted_by_key(map
, |t
| t
.1);
455 fn reverse(keyvals
: Large
<Vec
<(i8, i8)>>) -> () {
456 let mut map
: IndexMap
<_
, _
> = IndexMap
::from_iter(keyvals
.to_vec());
458 fn generate_answer(input
: &Vec
<(i8, i8)>) -> Vec
<(i8, i8)> {
459 // to mimic what `IndexMap::from_iter` does:
460 // need to get (A) the unique keys in forward order, and (B) the
461 // last value of each of those keys.
463 // create (A): an iterable that yields the unique keys in ltr order
464 let mut seen_keys
= HashSet
::new();
465 let unique_keys_forward
= input
.iter().filter_map(move |(k
, _
)| {
466 if seen_keys
.contains(k
) { None }
467 else { seen_keys.insert(*k); Some(*k) }
470 // create (B): a mapping of keys to the last value seen for that key
471 // this is the same as reversing the input and taking the first
472 // value seen for that key!
473 let mut last_val_per_key
= HashMap
::new();
474 for &(k
, v
) in input
.iter().rev() {
475 if !last_val_per_key
.contains_key(&k
) {
476 last_val_per_key
.insert(k
, v
);
480 // iterate over the keys in (A) in order, and match each one with
481 // the corresponding last value from (B)
482 let mut ans
: Vec
<_
> = unique_keys_forward
483 .map(|k
| (k
, *last_val_per_key
.get(&k
).unwrap()))
486 // finally, since this test is testing `.reverse()`, reverse the
493 let answer
= generate_answer(&keyvals
.0);
498 // check it contains all the values it should
499 for &(key
, val
) in &answer
{
500 assert_eq
!(map
[&key
], val
);
504 let mapv
= Vec
::from_iter(map
);
505 assert_eq
!(answer
, mapv
);
509 fn assert_sorted_by_key
<I
, Key
, X
>(iterable
: I
, key
: Key
)
512 I
::Item
: Ord
+ Clone
+ Debug
,
513 Key
: Fn(&I
::Item
) -> X
,
516 let input
= Vec
::from_iter(iterable
);
517 let mut sorted
= input
.clone();
518 sorted
.sort_by_key(key
);
519 assert_eq
!(input
, sorted
);
522 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
523 struct Alpha(String
);
525 impl Deref
for Alpha
{
526 type Target
= String
;
527 fn deref(&self) -> &String
{
532 const ALPHABET
: &[u8] = b
"abcdefghijklmnopqrstuvwxyz";
534 impl Arbitrary
for Alpha
{
535 fn arbitrary(g
: &mut Gen
) -> Self {
536 let len
= usize::arbitrary(g
) % g
.size();
537 let len
= min(len
, 16);
540 .map(|_
| ALPHABET
[usize::arbitrary(g
) % ALPHABET
.len()] as char)
545 fn shrink(&self) -> Box
<dyn Iterator
<Item
= Self>> {
546 Box
::new((**self).shrink().map(Alpha
))
550 /// quickcheck Arbitrary adaptor -- make a larger vec
551 #[derive(Clone, Debug)]
554 impl<T
> Deref
for Large
<T
> {
556 fn deref(&self) -> &T
{
561 impl<T
> Arbitrary
for Large
<Vec
<T
>>
565 fn arbitrary(g
: &mut Gen
) -> Self {
566 let len
= usize::arbitrary(g
) % (g
.size() * 10);
567 Large((0..len
).map(|_
| T
::arbitrary(g
)).collect())
570 fn shrink(&self) -> Box
<dyn Iterator
<Item
= Self>> {
571 Box
::new((**self).shrink().map(Large
))