From 3302656247438d89936bbbfd55fe696c82fa98e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 30 Oct 2018 13:56:19 +0100 Subject: [PATCH] More extensive slice and vec tests Not all of them pass validation... --- tests/run-pass/slice-of-zero-size-elements.rs | 56 ------ tests/run-pass/slices.rs | 178 ++++++++++++++++++ tests/run-pass/vecs.rs | 38 ++++ 3 files changed, 216 insertions(+), 56 deletions(-) delete mode 100644 tests/run-pass/slice-of-zero-size-elements.rs create mode 100644 tests/run-pass/slices.rs diff --git a/tests/run-pass/slice-of-zero-size-elements.rs b/tests/run-pass/slice-of-zero-size-elements.rs deleted file mode 100644 index aa9d117d726f..000000000000 --- a/tests/run-pass/slice-of-zero-size-elements.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::slice; - -fn foo(v: &[T]) -> Option<&[T]> { - let mut it = v.iter(); - for _ in 0..5 { - let _ = it.next(); - } - Some(it.as_slice()) -} - -fn foo_mut(v: &mut [T]) -> Option<&mut [T]> { - let mut it = v.iter_mut(); - for _ in 0..5 { - let _ = it.next(); - } - Some(it.into_slice()) -} - -pub fn main() { - // In a slice of zero-size elements the pointer is meaningless. - // Ensure iteration still works even if the pointer is at the end of the address space. - let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) }; - assert_eq!(slice.len(), 10); - assert_eq!(slice.iter().count(), 10); - - // .nth() on the iterator should also behave correctly - let mut it = slice.iter(); - assert!(it.nth(5).is_some()); - assert_eq!(it.count(), 4); - - // Converting Iter to a slice should never have a null pointer - assert!(foo(slice).is_some()); - - // Test mutable iterators as well - let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) }; - assert_eq!(slice.len(), 10); - assert_eq!(slice.iter_mut().count(), 10); - - { - let mut it = slice.iter_mut(); - assert!(it.nth(5).is_some()); - assert_eq!(it.count(), 4); - } - - assert!(foo_mut(slice).is_some()) -} diff --git a/tests/run-pass/slices.rs b/tests/run-pass/slices.rs new file mode 100644 index 000000000000..119c9b90a05c --- /dev/null +++ b/tests/run-pass/slices.rs @@ -0,0 +1,178 @@ +// FIXME: Still investigating whether there is UB here +// compile-flags: -Zmiri-disable-validation + +use std::slice; + +fn slice_of_zst() { + fn foo(v: &[T]) -> Option<&[T]> { + let mut it = v.iter(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.as_slice()) + } + + fn foo_mut(v: &mut [T]) -> Option<&mut [T]> { + let mut it = v.iter_mut(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.into_slice()) + } + + // In a slice of zero-size elements the pointer is meaningless. + // Ensure iteration still works even if the pointer is at the end of the address space. + let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter().count(), 10); + + // .nth() on the iterator should also behave correctly + let mut it = slice.iter(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + + // Converting Iter to a slice should never have a null pointer + assert!(foo(slice).is_some()); + + // Test mutable iterators as well + let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter_mut().count(), 10); + + { + let mut it = slice.iter_mut(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + } + + assert!(foo_mut(slice).is_some()) +} + +fn test_iter_ref_consistency() { + use std::fmt::Debug; + + fn test(x : T) { + let v : &[T] = &[x, x, x]; + let v_ptrs : [*const T; 3] = match v { + [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _], + _ => unreachable!() + }; + let len = v.len(); + + // nth(i) + for i in 0..len { + assert_eq!(&v[i] as *const _, v_ptrs[i]); // check the v_ptrs array, just to be sure + let nth = v.iter().nth(i).unwrap(); + assert_eq!(nth as *const _, v_ptrs[i]); + } + assert_eq!(v.iter().nth(len), None, "nth(len) should return None"); + + // stepping through with nth(0) + { + let mut it = v.iter(); + for i in 0..len { + let next = it.nth(0).unwrap(); + assert_eq!(next as *const _, v_ptrs[i]); + } + assert_eq!(it.nth(0), None); + } + + // next() + { + let mut it = v.iter(); + for i in 0..len { + let remaining = len - i; + assert_eq!(it.size_hint(), (remaining, Some(remaining))); + + let next = it.next().unwrap(); + assert_eq!(next as *const _, v_ptrs[i]); + } + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None, "The final call to next() should return None"); + } + + // next_back() + { + let mut it = v.iter(); + for i in 0..len { + let remaining = len - i; + assert_eq!(it.size_hint(), (remaining, Some(remaining))); + + let prev = it.next_back().unwrap(); + assert_eq!(prev as *const _, v_ptrs[remaining-1]); + } + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next_back(), None, "The final call to next_back() should return None"); + } + } + + fn test_mut(x : T) { + let v : &mut [T] = &mut [x, x, x]; + let v_ptrs : [*mut T; 3] = match v { + [ref v1, ref v2, ref v3] => + [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _], + _ => unreachable!() + }; + let len = v.len(); + + // nth(i) + for i in 0..len { + assert_eq!(&mut v[i] as *mut _, v_ptrs[i]); // check the v_ptrs array, just to be sure + let nth = v.iter_mut().nth(i).unwrap(); + assert_eq!(nth as *mut _, v_ptrs[i]); + } + assert_eq!(v.iter().nth(len), None, "nth(len) should return None"); + + // stepping through with nth(0) + { + let mut it = v.iter(); + for i in 0..len { + let next = it.nth(0).unwrap(); + assert_eq!(next as *const _, v_ptrs[i]); + } + assert_eq!(it.nth(0), None); + } + + // next() + { + let mut it = v.iter_mut(); + for i in 0..len { + let remaining = len - i; + assert_eq!(it.size_hint(), (remaining, Some(remaining))); + + let next = it.next().unwrap(); + assert_eq!(next as *mut _, v_ptrs[i]); + } + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None, "The final call to next() should return None"); + } + + // next_back() + { + let mut it = v.iter_mut(); + for i in 0..len { + let remaining = len - i; + assert_eq!(it.size_hint(), (remaining, Some(remaining))); + + let prev = it.next_back().unwrap(); + assert_eq!(prev as *mut _, v_ptrs[remaining-1]); + } + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next_back(), None, "The final call to next_back() should return None"); + } + } + + // Make sure iterators and slice patterns yield consistent addresses for various types, + // including ZSTs. + test(0u32); + test(()); + test([0u32; 0]); // ZST with alignment > 0 + test_mut(0u32); + test_mut(()); + test_mut([0u32; 0]); // ZST with alignment > 0 +} + +fn main() { + slice_of_zst(); + test_iter_ref_consistency(); +} diff --git a/tests/run-pass/vecs.rs b/tests/run-pass/vecs.rs index 776791bbc9b9..bb9e5068f91e 100644 --- a/tests/run-pass/vecs.rs +++ b/tests/run-pass/vecs.rs @@ -24,13 +24,45 @@ fn vec_into_iter() -> u8 { .fold(0, |x, y| x + y) } +fn vec_into_iter_rev() -> u8 { + vec![1, 2, 3, 4] + .into_iter() + .map(|x| x * x) + .fold(0, |x, y| x + y) +} + fn vec_into_iter_zst() -> usize { vec![[0u64; 0], [0u64; 0]] .into_iter() + .rev() .map(|x| x.len()) .sum() } +fn vec_into_iter_rev_zst() -> usize { + vec![[0u64; 0], [0u64; 0]] + .into_iter() + .rev() + .map(|x| x.len()) + .sum() +} + +fn vec_iter_and_mut() { + let mut v = vec![1,2,3,4]; + for i in v.iter_mut() { + *i += 1; + } + assert_eq!(v.iter().sum::(), 2+3+4+5); +} + +fn vec_iter_and_mut_rev() { + let mut v = vec![1,2,3,4]; + for i in v.iter_mut().rev() { + *i += 1; + } + assert_eq!(v.iter().sum::(), 2+3+4+5); +} + fn vec_reallocate() -> Vec { let mut v = vec![1, 2]; v.push(3); @@ -41,8 +73,14 @@ fn vec_reallocate() -> Vec { fn main() { assert_eq!(vec_reallocate().len(), 5); + assert_eq!(vec_into_iter(), 30); + assert_eq!(vec_into_iter_rev(), 30); + vec_iter_and_mut(); assert_eq!(vec_into_iter_zst(), 0); + assert_eq!(vec_into_iter_rev_zst(), 0); + vec_iter_and_mut_rev(); + assert_eq!(make_vec().capacity(), 4); assert_eq!(make_vec_macro(), [1, 2]); assert_eq!(make_vec_macro_repeat(), [42; 5]);