use doubly_linked_list::*; #[test] fn is_generic() { struct Foo; LinkedList::::new(); } // ——————————————————————————————————————————————————————————— // Tests for Step 1: push / pop at front and back // ——————————————————————————————————————————————————————————— #[test] #[ignore] fn basics_empty_list() { let list: LinkedList = LinkedList::new(); assert_eq!(list.len(), 0); assert!(list.is_empty()); } // push / pop at back ———————————————————————————————————————— #[test] #[ignore] fn basics_single_element_back() { let mut list: LinkedList = LinkedList::new(); list.push_back(5); assert_eq!(list.len(), 1); assert!(!list.is_empty()); assert_eq!(list.pop_back(), Some(5)); assert_eq!(list.len(), 0); assert!(list.is_empty()); } #[test] #[ignore] fn basics_push_pop_at_back() { let mut list: LinkedList = LinkedList::new(); for i in 0..10 { list.push_back(i); assert_eq!(list.len(), i as usize + 1); assert!(!list.is_empty()); } for i in (0..10).rev() { assert_eq!(list.len(), i as usize + 1); assert!(!list.is_empty()); assert_eq!(i, list.pop_back().unwrap()); } assert_eq!(list.len(), 0); assert!(list.is_empty()); } // push / pop at front ——————————————————————————————————————— #[test] #[ignore] fn basics_single_element_front() { let mut list: LinkedList = LinkedList::new(); list.push_front(5); assert_eq!(list.len(), 1); assert!(!list.is_empty()); assert_eq!(list.pop_front(), Some(5)); assert_eq!(list.len(), 0); assert!(list.is_empty()); } #[test] #[ignore] fn basics_push_pop_at_front() { let mut list: LinkedList = LinkedList::new(); for i in 0..10 { list.push_front(i); assert_eq!(list.len(), i as usize + 1); assert!(!list.is_empty()); } for i in (0..10).rev() { assert_eq!(list.len(), i as usize + 1); assert!(!list.is_empty()); assert_eq!(i, list.pop_front().unwrap()); } assert_eq!(list.len(), 0); assert!(list.is_empty()); } // push / pop at mixed sides ————————————————————————————————— #[test] #[ignore] fn basics_push_front_pop_back() { let mut list: LinkedList = LinkedList::new(); for i in 0..10 { list.push_front(i); assert_eq!(list.len(), i as usize + 1); assert!(!list.is_empty()); } for i in 0..10 { assert_eq!(list.len(), 10 - i as usize); assert!(!list.is_empty()); assert_eq!(i, list.pop_back().unwrap()); } assert_eq!(list.len(), 0); assert!(list.is_empty()); } #[test] #[ignore] fn basics_push_back_pop_front() { let mut list: LinkedList = LinkedList::new(); for i in 0..10 { list.push_back(i); assert_eq!(list.len(), i as usize + 1); assert!(!list.is_empty()); } for i in 0..10 { assert_eq!(list.len(), 10 - i as usize); assert!(!list.is_empty()); assert_eq!(i, list.pop_front().unwrap()); } assert_eq!(list.len(), 0); assert!(list.is_empty()); } // ——————————————————————————————————————————————————————————— // Tests for Step 2: iteration // ——————————————————————————————————————————————————————————— #[test] #[ignore] fn iter() { let mut list: LinkedList = LinkedList::new(); for num in 0..10 { list.push_back(num); } for (num, &entered_num) in (0..10).zip(list.iter()) { assert_eq!(num, entered_num); } } // ——————————————————————————————————————————————————————————— // Tests for Step 3: full cursor functionality // ——————————————————————————————————————————————————————————— #[test] #[ignore] fn cursor_insert_before_on_empty_list() { // insert_after on empty list is already tested via push_back() let mut list = LinkedList::new(); list.cursor_front().insert_before(0); assert_eq!(Some(0), list.pop_front()); } #[test] #[ignore] fn cursor_insert_after_in_middle() { let mut list = (0..10).collect::>(); { let mut cursor = list.cursor_front(); let didnt_run_into_end = cursor.seek_forward(4); assert!(didnt_run_into_end); for n in (0..10).rev() { cursor.insert_after(n); } } assert_eq!(list.len(), 20); let expected = (0..5).chain(0..10).chain(5..10); assert!(expected.eq(list.iter().cloned())); } #[test] #[ignore] fn cursor_insert_before_in_middle() { let mut list = (0..10).collect::>(); { let mut cursor = list.cursor_back(); let didnt_run_into_end = cursor.seek_backward(4); assert!(didnt_run_into_end); for n in 0..10 { cursor.insert_before(n); } } assert_eq!(list.len(), 20); let expected = (0..5).chain(0..10).chain(5..10); assert!(expected.eq(list.iter().cloned())); } // "iterates" via next() and checks that it visits the right elements #[test] #[ignore] fn cursor_next_and_peek() { let mut list = (0..10).collect::>(); let mut cursor = list.cursor_front(); assert_eq!(cursor.peek_mut(), Some(&mut 0)); for n in 1..10 { let next = cursor.next().cloned(); assert_eq!(next, Some(n)); assert_eq!(next, cursor.peek_mut().cloned()); } } // "iterates" via prev() and checks that it visits the right elements #[test] #[ignore] fn cursor_prev_and_peek() { let mut list = (0..10).collect::>(); let mut cursor = list.cursor_back(); assert_eq!(cursor.peek_mut(), Some(&mut 9)); for n in (0..9).rev() { let prev = cursor.prev().cloned(); assert_eq!(prev, Some(n)); assert_eq!(prev, cursor.peek_mut().cloned()); } } // removes all elements starting from the middle #[test] #[ignore] fn cursor_take() { let mut list = (0..10).collect::>(); let mut cursor = list.cursor_front(); cursor.seek_forward(5); for expected in (5..10).chain((0..5).rev()) { assert_eq!(cursor.take(), Some(expected)); } } // ——————————————————————————————————————————————————————————— // Tests for Step 4: clean-up via `Drop` // ——————————————————————————————————————————————————————————— // The leak tests that are also for this step are separated into // their own files so that nothing else interferes with the allocator // whilst they run // checks number of drops // may pass for incorrect programs if double frees happen // exactly as often as destructor leaks #[test] #[ignore] fn drop_no_double_frees() { use std::cell::Cell; struct DropCounter<'a>(&'a Cell); impl<'a> Drop for DropCounter<'a> { fn drop(&mut self) { let num = self.0.get(); self.0.set(num + 1); } } const N: usize = 15; let counter = Cell::new(0); let list = std::iter::repeat_with(|| DropCounter(&counter)) .take(N) .collect::>(); assert_eq!(list.len(), N); drop(list); assert_eq!(counter.get(), N); } #[test] #[ignore] fn drop_large_list() { drop((0..2_000_000).collect::>()); } // ——————————————————————————————————————————————————————————— // Tests for Step 5 (advanced): covariance and Send/Sync // ——————————————————————————————————————————————————————————— // These are compile time tests. They won't compile unless your // code passes. // Additional tests for code that must *not* compile are in // pre_implemented.rs for technical reasons. #[cfg(feature = "advanced")] #[test] #[ignore] fn advanced_linked_list_is_send_sync() { trait AssertSend: Send {} trait AssertSync: Sync {} impl AssertSend for LinkedList {} impl AssertSync for LinkedList {} } #[cfg(feature = "advanced")] #[allow(dead_code)] #[test] #[ignore] fn advanced_is_covariant() { fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { x } fn a_iter<'a>(i: Iter<'static, &'static str>) -> Iter<'a, &'a str> { i } }