Skip to content

Commit

Permalink
shared_from_iter: Add more tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Jun 21, 2019
1 parent 6b8417b commit 8bbf1ab
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 0 deletions.
119 changes: 119 additions & 0 deletions src/liballoc/tests/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::any::Any;
use std::sync::{Arc, Weak};
use std::cell::RefCell;
use std::cmp::PartialEq;
use std::iter::TrustedLen;
use std::mem;

#[test]
fn uninhabited() {
Expand Down Expand Up @@ -85,3 +87,120 @@ fn eq() {
assert!(!(x != x));
assert_eq!(*x.0.borrow(), 0);
}

type Rc<T> = Arc<T>;

const SHARED_ITER_MAX: u16 = 100;

fn assert_trusted_len<I: TrustedLen>(_: &I) {}

#[test]
fn shared_from_iter_normal() {
// Exercise the base implementation for non-`TrustedLen` iterators.
{
// `Filter` is never `TrustedLen` since we don't
// know statically how many elements will be kept:
let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new);

// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
let vec = iter.clone().collect::<Vec<_>>();
let rc = iter.collect::<Rc<[_]>>();
assert_eq!(&*vec, &*rc);

// Clone a bit and let these get dropped.
{
let _rc_2 = rc.clone();
let _rc_3 = rc.clone();
let _rc_4 = Rc::downgrade(&_rc_3);
}
} // Drop what hasn't been here.
}

#[test]
fn shared_from_iter_trustedlen_normal() {
// Exercise the `TrustedLen` implementation under normal circumstances
// where `size_hint()` matches `(_, Some(exact_len))`.
{
let iter = (0..SHARED_ITER_MAX).map(Box::new);
assert_trusted_len(&iter);

// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
let vec = iter.clone().collect::<Vec<_>>();
let rc = iter.collect::<Rc<[_]>>();
assert_eq!(&*vec, &*rc);
assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc));

// Clone a bit and let these get dropped.
{
let _rc_2 = rc.clone();
let _rc_3 = rc.clone();
let _rc_4 = Rc::downgrade(&_rc_3);
}
} // Drop what hasn't been here.

// Try a ZST to make sure it is handled well.
{
let iter = (0..SHARED_ITER_MAX).map(|_| ());
let vec = iter.clone().collect::<Vec<_>>();
let rc = iter.collect::<Rc<[_]>>();
assert_eq!(&*vec, &*rc);
assert_eq!(0, mem::size_of_val(&*rc));
{
let _rc_2 = rc.clone();
let _rc_3 = rc.clone();
let _rc_4 = Rc::downgrade(&_rc_3);
}
}
}

#[test]
#[should_panic = "I've almost got 99 problems."]
fn shared_from_iter_trustedlen_panic() {
// Exercise the `TrustedLen` implementation when `size_hint()` matches
// `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
let iter = (0..SHARED_ITER_MAX)
.map(|val| {
match val {
98 => panic!("I've almost got 99 problems."),
_ => Box::new(val),
}
});
assert_trusted_len(&iter);
let _ = iter.collect::<Rc<[_]>>();

panic!("I am unreachable.");
}

#[test]
fn shared_from_iter_trustedlen_no_fuse() {
// Exercise the `TrustedLen` implementation when `size_hint()` matches
// `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
struct Iter(std::vec::IntoIter<Option<Box<u8>>>);

unsafe impl TrustedLen for Iter {}

impl Iterator for Iter {
fn size_hint(&self) -> (usize, Option<usize>) {
(2, Some(2))
}

type Item = Box<u8>;

fn next(&mut self) -> Option<Self::Item> {
self.0.next().flatten()
}
}

let vec = vec![
Some(Box::new(42)),
Some(Box::new(24)),
None,
Some(Box::new(12)),
];
let iter = Iter(vec.into_iter());
assert_trusted_len(&iter);
assert_eq!(
&[Box::new(42), Box::new(24)],
&*iter.collect::<Rc<[_]>>()
);
}
2 changes: 2 additions & 0 deletions src/liballoc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
#![feature(box_syntax)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(option_flattening)]
#![feature(pattern)]
#![feature(repeat_generic_slice)]
#![feature(trusted_len)]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![deny(rust_2018_idioms)]
Expand Down
117 changes: 117 additions & 0 deletions src/liballoc/tests/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::any::Any;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::cmp::PartialEq;
use std::mem;
use std::iter::TrustedLen;

#[test]
fn uninhabited() {
Expand Down Expand Up @@ -85,3 +87,118 @@ fn eq() {
assert!(!(x != x));
assert_eq!(*x.0.borrow(), 0);
}

const SHARED_ITER_MAX: u16 = 100;

fn assert_trusted_len<I: TrustedLen>(_: &I) {}

#[test]
fn shared_from_iter_normal() {
// Exercise the base implementation for non-`TrustedLen` iterators.
{
// `Filter` is never `TrustedLen` since we don't
// know statically how many elements will be kept:
let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new);

// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
let vec = iter.clone().collect::<Vec<_>>();
let rc = iter.collect::<Rc<[_]>>();
assert_eq!(&*vec, &*rc);

// Clone a bit and let these get dropped.
{
let _rc_2 = rc.clone();
let _rc_3 = rc.clone();
let _rc_4 = Rc::downgrade(&_rc_3);
}
} // Drop what hasn't been here.
}

#[test]
fn shared_from_iter_trustedlen_normal() {
// Exercise the `TrustedLen` implementation under normal circumstances
// where `size_hint()` matches `(_, Some(exact_len))`.
{
let iter = (0..SHARED_ITER_MAX).map(Box::new);
assert_trusted_len(&iter);

// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
let vec = iter.clone().collect::<Vec<_>>();
let rc = iter.collect::<Rc<[_]>>();
assert_eq!(&*vec, &*rc);
assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc));

// Clone a bit and let these get dropped.
{
let _rc_2 = rc.clone();
let _rc_3 = rc.clone();
let _rc_4 = Rc::downgrade(&_rc_3);
}
} // Drop what hasn't been here.

// Try a ZST to make sure it is handled well.
{
let iter = (0..SHARED_ITER_MAX).map(|_| ());
let vec = iter.clone().collect::<Vec<_>>();
let rc = iter.collect::<Rc<[_]>>();
assert_eq!(&*vec, &*rc);
assert_eq!(0, mem::size_of_val(&*rc));
{
let _rc_2 = rc.clone();
let _rc_3 = rc.clone();
let _rc_4 = Rc::downgrade(&_rc_3);
}
}
}

#[test]
#[should_panic = "I've almost got 99 problems."]
fn shared_from_iter_trustedlen_panic() {
// Exercise the `TrustedLen` implementation when `size_hint()` matches
// `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
let iter = (0..SHARED_ITER_MAX)
.map(|val| {
match val {
98 => panic!("I've almost got 99 problems."),
_ => Box::new(val),
}
});
assert_trusted_len(&iter);
let _ = iter.collect::<Rc<[_]>>();

panic!("I am unreachable.");
}

#[test]
fn shared_from_iter_trustedlen_no_fuse() {
// Exercise the `TrustedLen` implementation when `size_hint()` matches
// `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
struct Iter(std::vec::IntoIter<Option<Box<u8>>>);

unsafe impl TrustedLen for Iter {}

impl Iterator for Iter {
fn size_hint(&self) -> (usize, Option<usize>) {
(2, Some(2))
}

type Item = Box<u8>;

fn next(&mut self) -> Option<Self::Item> {
self.0.next().flatten()
}
}

let vec = vec![
Some(Box::new(42)),
Some(Box::new(24)),
None,
Some(Box::new(12)),
];
let iter = Iter(vec.into_iter());
assert_trusted_len(&iter);
assert_eq!(
&[Box::new(42), Box::new(24)],
&*iter.collect::<Rc<[_]>>()
);
}

0 comments on commit 8bbf1ab

Please sign in to comment.