Test and fix store::List::retain
This commit is contained in:
		| @@ -57,3 +57,9 @@ impl From<StreamId> for u32 { | |||||||
|         src.0 |         src.0 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl PartialEq<u32> for StreamId { | ||||||
|  |     fn eq(&self, other: &u32) -> bool { | ||||||
|  |         self.0 == *other | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -229,12 +229,17 @@ impl<B> List<B> { | |||||||
|                         let next = N::take_next(&mut store[curr]); |                         let next = N::take_next(&mut store[curr]); | ||||||
|                         N::set_next(&mut store[prev], next); |                         N::set_next(&mut store[prev], next); | ||||||
|  |  | ||||||
|  |                         match next { | ||||||
|  |                             Some(next) => { | ||||||
|  |                                 curr = next; | ||||||
|  |                             } | ||||||
|  |                             None => { | ||||||
|                                 // current is last element, but guaranteed to not be the |                                 // current is last element, but guaranteed to not be the | ||||||
|                                 // only one |                                 // only one | ||||||
|                         if next.is_none() { |  | ||||||
|                                 idxs.tail = prev; |                                 idxs.tail = prev; | ||||||
|                                 break; |                                 break; | ||||||
|                             } |                             } | ||||||
|  |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         if let Some(next) = N::take_next(&mut store[curr]) { |                         if let Some(next) = N::take_next(&mut store[curr]) { | ||||||
|                             curr = next; |                             curr = next; | ||||||
| @@ -323,3 +328,169 @@ impl<'a, B> VacantEntry<'a, B> { | |||||||
|         Key(key) |         Key(key) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test { | ||||||
|  |     use super::*; | ||||||
|  |     use super::stream::Next; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_retain_empty_list_and_store() { | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = List::new(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         retain(&mut store, &mut list, |_| panic!()); | ||||||
|  |  | ||||||
|  |         assert!(store.slab.is_empty()); | ||||||
|  |         assert!(list.is_empty()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_retain_one_item() { | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = list_with(&mut store, &[1]); | ||||||
|  |  | ||||||
|  |         // Keep | ||||||
|  |         retain(&mut store, &mut list, |s| true); | ||||||
|  |  | ||||||
|  |         let ids = get(&store, &list); | ||||||
|  |         assert_eq!(ids, &[1]); | ||||||
|  |  | ||||||
|  |         // Drop | ||||||
|  |         retain(&mut store, &mut list, |s| false); | ||||||
|  |  | ||||||
|  |         assert!(list.is_empty()); | ||||||
|  |         assert_eq!(1, store.slab.len()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_retain_none_long_list() { | ||||||
|  |         let mut expect = vec![1, 2, 3, 4, 5]; | ||||||
|  |  | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = list_with(&mut store, &expect); | ||||||
|  |  | ||||||
|  |         retain(&mut store, &mut list, |s| { | ||||||
|  |             assert_eq!(s.id, expect.remove(0)); | ||||||
|  |             false | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         assert!(list.is_empty()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_retain_last_elem_long_list() { | ||||||
|  |         let mut expect = vec![1, 2, 3, 4, 5]; | ||||||
|  |  | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = list_with(&mut store, &expect); | ||||||
|  |  | ||||||
|  |         retain(&mut store, &mut list, |s| { | ||||||
|  |             if expect.len() > 1 { | ||||||
|  |                 assert_eq!(s.id, expect.remove(0)); | ||||||
|  |                 false | ||||||
|  |             } else { | ||||||
|  |                 assert_eq!(s.id, 5); | ||||||
|  |                 true | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         let ids = get(&store, &list); | ||||||
|  |         assert_eq!(ids, &[5]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_retain_first_elem_long_list() { | ||||||
|  |         let mut expect = vec![1, 2, 3, 4, 5]; | ||||||
|  |  | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = list_with(&mut store, &expect); | ||||||
|  |  | ||||||
|  |         retain(&mut store, &mut list, |s| { | ||||||
|  |             let e = expect.remove(0); | ||||||
|  |             assert_eq!(s.id, e); | ||||||
|  |             e == 1 | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         let ids = get(&store, &list); | ||||||
|  |         assert_eq!(ids, &[1]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_drop_middle_elem_long_list() { | ||||||
|  |         let mut expect = vec![1, 2, 3, 4, 5]; | ||||||
|  |  | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = list_with(&mut store, &expect); | ||||||
|  |  | ||||||
|  |         retain(&mut store, &mut list, |s| { | ||||||
|  |             let e = expect.remove(0); | ||||||
|  |             assert_eq!(s.id, e); | ||||||
|  |             e != 3 | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         let ids = get(&store, &list); | ||||||
|  |         assert_eq!(ids, &[1, 2, 4, 5]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_drop_two_middle_elem_long_list() { | ||||||
|  |         let mut expect = vec![1, 2, 3, 4, 5]; | ||||||
|  |  | ||||||
|  |         let mut store = new_store(); | ||||||
|  |         let mut list = list_with(&mut store, &expect); | ||||||
|  |  | ||||||
|  |         retain(&mut store, &mut list, |s| { | ||||||
|  |             let e = expect.remove(0); | ||||||
|  |             assert_eq!(s.id, e); | ||||||
|  |             e != 3 | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         let ids = get(&store, &list); | ||||||
|  |         assert_eq!(ids, &[1, 2, 4, 5]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn new_store() -> Store<()> { | ||||||
|  |         Store::new() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn push(store: &mut Store<()>, list: &mut List<()>, id: u32) { | ||||||
|  |         let id = StreamId::from(id); | ||||||
|  |         let mut ptr = store.insert(id, Stream::new(id)); | ||||||
|  |         list.push::<Next>(&mut ptr); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn list_with(store: &mut Store<()>, ids: &[u32]) -> List<()> { | ||||||
|  |         let mut list = List::new(); | ||||||
|  |  | ||||||
|  |         for &id in ids { | ||||||
|  |             push(store, &mut list, id); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         list | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn pop(store: &mut Store<()>, list: &mut List<()>) -> Option<StreamId> { | ||||||
|  |         list.pop::<Next>(store).map(|p| p.id) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn retain<F>(store: &mut Store<()>, list: &mut List<()>, f: F) | ||||||
|  |         where F: FnMut(&mut Stream<()>) -> bool | ||||||
|  |     { | ||||||
|  |         list.retain::<Next, F>(store, f); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn get(store: &Store<()>, list: &List<()>) -> Vec<StreamId> { | ||||||
|  |         let mut dst = vec![]; | ||||||
|  |  | ||||||
|  |         let mut curr = list.indices.map(|i| i.head); | ||||||
|  |  | ||||||
|  |         while let Some(c) = curr { | ||||||
|  |             dst.push(store[c].id); | ||||||
|  |             curr = store[c].next; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         dst | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user