diff --git a/src/poolable.rs b/src/poolable.rs index 23fd0cc..320036f 100644 --- a/src/poolable.rs +++ b/src/poolable.rs @@ -41,11 +41,21 @@ impl Realloc for Vec { use std::cmp::Ordering::*; assert!(new_size > 0); - match new_size.cmp(&self.capacity()) { - Greater => self.resize(new_size, T::default()), + match new_size.cmp(&self.len()) { + Greater => { + self.reserve_exact(new_size - self.len()); + debug_assert_eq!(self.capacity(), new_size); + self.resize(new_size, T::default()); + debug_assert_eq!(self.len(), new_size); + + // Check that resize() did not reserve additional space. + debug_assert_eq!(self.capacity(), new_size); + } Less => { self.truncate(new_size); + debug_assert_eq!(self.len(), new_size); self.shrink_to_fit(); + debug_assert_eq!(self.capacity(), new_size); } Equal => {} } @@ -74,3 +84,31 @@ where } } } + +#[cfg(test)] +mod tests { + use super::*; + + /// Regression test for `Realloc` trait implementation of `Vec`. + /// + /// Previously `Realloc::realloc()` called `self.capacity()` instead + /// of `self.len()` when checking whether the vector should be expanded. + /// As a result, it sometimes attempted to shrink the vector + /// when it should be expanded, and effectively did nothing. + #[test] + fn realloc_vec() { + let mut v: Vec = Poolable::alloc(100); + + for i in 1..100 { + let new_size = Poolable::capacity(&v) + i; + v.realloc(new_size); + assert_eq!(Poolable::capacity(&v), new_size); + + // Length of the vectory and underlying buffer + // for poolable vectors should + // be exactly of the requested size. + assert_eq!(v.len(), new_size); + assert_eq!(v.capacity(), new_size); + } + } +}