Browse Source

Fix broken CVec

Oops, forgot to initiate the pointer after uses of CVec::new()
jD91mZM2 4 years ago
parent
commit
29ad5b75c9
4 changed files with 81 additions and 6 deletions
  1. 65 5
      src/c_vec.rs
  2. 4 0
      tests/expected/stdio/printf.stdout
  3. 12 0
      tests/stdio/printf.c
  4. 0 1
      tests/verify.sh

+ 65 - 5
src/c_vec.rs

@@ -57,8 +57,13 @@ impl<T> CVec<T> {
     }
     unsafe fn resize(&mut self, cap: usize) -> Result<(), AllocError> {
         let size = Self::check_mul(cap, mem::size_of::<T>())?;
-        let ptr = NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T)
-            .ok_or(AllocError)?;
+        let ptr = if cap == 0 {
+            NonNull::dangling()
+        } else if self.cap > 0 {
+            NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T).ok_or(AllocError)?
+        } else {
+            NonNull::new((platform::alloc(size)) as *mut T).ok_or(AllocError)?
+        };
         self.ptr = ptr;
         self.cap = cap;
         Ok(())
@@ -75,13 +80,13 @@ impl<T> CVec<T> {
     // Push stuff
 
     pub fn reserve(&mut self, required: usize) -> Result<(), AllocError> {
-        let reserved_len = self
+        let required_len = self
             .len
             .checked_add(required)
             .ok_or(AllocError)
             .and_then(Self::check_bounds)?;
-        let new_cap = cmp::min(reserved_len.next_power_of_two(), core::isize::MAX as usize);
-        if new_cap > self.cap {
+        if required_len > self.cap {
+            let new_cap = cmp::min(required_len.next_power_of_two(), core::isize::MAX as usize);
             unsafe {
                 self.resize(new_cap)?;
             }
@@ -225,3 +230,58 @@ impl WriteByte for CVec<u8> {
         Ok(())
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::CVec;
+
+    #[test]
+    fn push_pop() {
+        let mut vec = CVec::new();
+        vec.push(1).unwrap();
+        vec.push(2).unwrap();
+        vec.push(3).unwrap();
+        assert_eq!(&vec[..], &[1, 2, 3]);
+        assert_eq!(vec.pop().unwrap(), 3);
+        assert_eq!(&vec[..], &[1, 2]);
+    }
+    #[test]
+    fn extend_from_slice() {
+        use core_io::Write;
+
+        let mut vec = CVec::new();
+        vec.extend_from_slice(&[1, 2, 3]).unwrap();
+        vec.extend_from_slice(&[4, 5, 6]).unwrap();
+        assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6]);
+        assert_eq!(vec.write(&[7, 8, 9]).unwrap(), 3);
+        assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6, 7, 8, 9]);
+    }
+    #[test]
+    fn dropped() {
+        use alloc::rc::Rc;
+
+        let counter = Rc::new(());
+        let mut vec = CVec::with_capacity(3).unwrap();
+        vec.push(Rc::clone(&counter)).unwrap();
+        vec.push(Rc::clone(&counter)).unwrap();
+        vec.push(Rc::clone(&counter)).unwrap();
+        assert_eq!(Rc::strong_count(&counter), 4);
+
+        let popped = vec.pop().unwrap();
+        assert_eq!(Rc::strong_count(&counter), 4);
+        drop(popped);
+        assert_eq!(Rc::strong_count(&counter), 3);
+
+        vec.push(Rc::clone(&counter)).unwrap();
+        vec.push(Rc::clone(&counter)).unwrap();
+        vec.push(Rc::clone(&counter)).unwrap();
+
+        assert_eq!(vec.len(), 5);
+        assert_eq!(Rc::strong_count(&counter), 6);
+        vec.truncate(1);
+        assert_eq!(Rc::strong_count(&counter), 2);
+
+        drop(vec);
+        assert_eq!(Rc::strong_count(&counter), 1);
+    }
+}

+ 4 - 0
tests/expected/stdio/printf.stdout

@@ -60,3 +60,7 @@ Non-finite float madness:
 %F: INF -INF NAN -NAN
 %g: inf -inf nan -nan
 %G: INF -INF NAN -NAN
+Testing asprintf...
+printed: test string, value: 11
+printed: test string 2, value: 13
+printed: test string 2, value: 13

+ 12 - 0
tests/stdio/printf.c

@@ -74,4 +74,16 @@ int main(void) {
         }
         printf("\n");
     }
+
+    puts("Testing asprintf...");
+    char *s = NULL;
+    int res = asprintf(&s, "test string");
+    printf("printed: %s, value: %d\n", s, res);
+    free(s);
+    res = asprintf(&s, "test string %d", 2);
+    printf("printed: %s, value: %d\n", s, res);
+    free(s);
+    res = asprintf(&s, "test %s %d", "string", 2);
+    printf("printed: %s, value: %d\n", s, res);
+    free(s);
 }

+ 0 - 1
tests/verify.sh

@@ -40,6 +40,5 @@ do
     if [ "${status}" != "0" ]
     then
         echo "# ${name}: failed with status ${status} #"
-        exit 1
     fi
 done