Skip to content

Commit 8bbf1ab

Browse files
committed
shared_from_iter: Add more tests.
1 parent 6b8417b commit 8bbf1ab

File tree

3 files changed

+238
-0
lines changed

3 files changed

+238
-0
lines changed

src/liballoc/tests/arc.rs

+119
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::any::Any;
22
use std::sync::{Arc, Weak};
33
use std::cell::RefCell;
44
use std::cmp::PartialEq;
5+
use std::iter::TrustedLen;
6+
use std::mem;
57

68
#[test]
79
fn uninhabited() {
@@ -85,3 +87,120 @@ fn eq() {
8587
assert!(!(x != x));
8688
assert_eq!(*x.0.borrow(), 0);
8789
}
90+
91+
type Rc<T> = Arc<T>;
92+
93+
const SHARED_ITER_MAX: u16 = 100;
94+
95+
fn assert_trusted_len<I: TrustedLen>(_: &I) {}
96+
97+
#[test]
98+
fn shared_from_iter_normal() {
99+
// Exercise the base implementation for non-`TrustedLen` iterators.
100+
{
101+
// `Filter` is never `TrustedLen` since we don't
102+
// know statically how many elements will be kept:
103+
let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new);
104+
105+
// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
106+
let vec = iter.clone().collect::<Vec<_>>();
107+
let rc = iter.collect::<Rc<[_]>>();
108+
assert_eq!(&*vec, &*rc);
109+
110+
// Clone a bit and let these get dropped.
111+
{
112+
let _rc_2 = rc.clone();
113+
let _rc_3 = rc.clone();
114+
let _rc_4 = Rc::downgrade(&_rc_3);
115+
}
116+
} // Drop what hasn't been here.
117+
}
118+
119+
#[test]
120+
fn shared_from_iter_trustedlen_normal() {
121+
// Exercise the `TrustedLen` implementation under normal circumstances
122+
// where `size_hint()` matches `(_, Some(exact_len))`.
123+
{
124+
let iter = (0..SHARED_ITER_MAX).map(Box::new);
125+
assert_trusted_len(&iter);
126+
127+
// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
128+
let vec = iter.clone().collect::<Vec<_>>();
129+
let rc = iter.collect::<Rc<[_]>>();
130+
assert_eq!(&*vec, &*rc);
131+
assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc));
132+
133+
// Clone a bit and let these get dropped.
134+
{
135+
let _rc_2 = rc.clone();
136+
let _rc_3 = rc.clone();
137+
let _rc_4 = Rc::downgrade(&_rc_3);
138+
}
139+
} // Drop what hasn't been here.
140+
141+
// Try a ZST to make sure it is handled well.
142+
{
143+
let iter = (0..SHARED_ITER_MAX).map(|_| ());
144+
let vec = iter.clone().collect::<Vec<_>>();
145+
let rc = iter.collect::<Rc<[_]>>();
146+
assert_eq!(&*vec, &*rc);
147+
assert_eq!(0, mem::size_of_val(&*rc));
148+
{
149+
let _rc_2 = rc.clone();
150+
let _rc_3 = rc.clone();
151+
let _rc_4 = Rc::downgrade(&_rc_3);
152+
}
153+
}
154+
}
155+
156+
#[test]
157+
#[should_panic = "I've almost got 99 problems."]
158+
fn shared_from_iter_trustedlen_panic() {
159+
// Exercise the `TrustedLen` implementation when `size_hint()` matches
160+
// `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
161+
let iter = (0..SHARED_ITER_MAX)
162+
.map(|val| {
163+
match val {
164+
98 => panic!("I've almost got 99 problems."),
165+
_ => Box::new(val),
166+
}
167+
});
168+
assert_trusted_len(&iter);
169+
let _ = iter.collect::<Rc<[_]>>();
170+
171+
panic!("I am unreachable.");
172+
}
173+
174+
#[test]
175+
fn shared_from_iter_trustedlen_no_fuse() {
176+
// Exercise the `TrustedLen` implementation when `size_hint()` matches
177+
// `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
178+
struct Iter(std::vec::IntoIter<Option<Box<u8>>>);
179+
180+
unsafe impl TrustedLen for Iter {}
181+
182+
impl Iterator for Iter {
183+
fn size_hint(&self) -> (usize, Option<usize>) {
184+
(2, Some(2))
185+
}
186+
187+
type Item = Box<u8>;
188+
189+
fn next(&mut self) -> Option<Self::Item> {
190+
self.0.next().flatten()
191+
}
192+
}
193+
194+
let vec = vec![
195+
Some(Box::new(42)),
196+
Some(Box::new(24)),
197+
None,
198+
Some(Box::new(12)),
199+
];
200+
let iter = Iter(vec.into_iter());
201+
assert_trusted_len(&iter);
202+
assert_eq!(
203+
&[Box::new(42), Box::new(24)],
204+
&*iter.collect::<Rc<[_]>>()
205+
);
206+
}

src/liballoc/tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#![feature(box_syntax)]
33
#![feature(drain_filter)]
44
#![feature(exact_size_is_empty)]
5+
#![feature(option_flattening)]
56
#![feature(pattern)]
67
#![feature(repeat_generic_slice)]
8+
#![feature(trusted_len)]
79
#![feature(try_reserve)]
810
#![feature(unboxed_closures)]
911
#![deny(rust_2018_idioms)]

src/liballoc/tests/rc.rs

+117
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::any::Any;
22
use std::rc::{Rc, Weak};
33
use std::cell::RefCell;
44
use std::cmp::PartialEq;
5+
use std::mem;
6+
use std::iter::TrustedLen;
57

68
#[test]
79
fn uninhabited() {
@@ -85,3 +87,118 @@ fn eq() {
8587
assert!(!(x != x));
8688
assert_eq!(*x.0.borrow(), 0);
8789
}
90+
91+
const SHARED_ITER_MAX: u16 = 100;
92+
93+
fn assert_trusted_len<I: TrustedLen>(_: &I) {}
94+
95+
#[test]
96+
fn shared_from_iter_normal() {
97+
// Exercise the base implementation for non-`TrustedLen` iterators.
98+
{
99+
// `Filter` is never `TrustedLen` since we don't
100+
// know statically how many elements will be kept:
101+
let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new);
102+
103+
// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
104+
let vec = iter.clone().collect::<Vec<_>>();
105+
let rc = iter.collect::<Rc<[_]>>();
106+
assert_eq!(&*vec, &*rc);
107+
108+
// Clone a bit and let these get dropped.
109+
{
110+
let _rc_2 = rc.clone();
111+
let _rc_3 = rc.clone();
112+
let _rc_4 = Rc::downgrade(&_rc_3);
113+
}
114+
} // Drop what hasn't been here.
115+
}
116+
117+
#[test]
118+
fn shared_from_iter_trustedlen_normal() {
119+
// Exercise the `TrustedLen` implementation under normal circumstances
120+
// where `size_hint()` matches `(_, Some(exact_len))`.
121+
{
122+
let iter = (0..SHARED_ITER_MAX).map(Box::new);
123+
assert_trusted_len(&iter);
124+
125+
// Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
126+
let vec = iter.clone().collect::<Vec<_>>();
127+
let rc = iter.collect::<Rc<[_]>>();
128+
assert_eq!(&*vec, &*rc);
129+
assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc));
130+
131+
// Clone a bit and let these get dropped.
132+
{
133+
let _rc_2 = rc.clone();
134+
let _rc_3 = rc.clone();
135+
let _rc_4 = Rc::downgrade(&_rc_3);
136+
}
137+
} // Drop what hasn't been here.
138+
139+
// Try a ZST to make sure it is handled well.
140+
{
141+
let iter = (0..SHARED_ITER_MAX).map(|_| ());
142+
let vec = iter.clone().collect::<Vec<_>>();
143+
let rc = iter.collect::<Rc<[_]>>();
144+
assert_eq!(&*vec, &*rc);
145+
assert_eq!(0, mem::size_of_val(&*rc));
146+
{
147+
let _rc_2 = rc.clone();
148+
let _rc_3 = rc.clone();
149+
let _rc_4 = Rc::downgrade(&_rc_3);
150+
}
151+
}
152+
}
153+
154+
#[test]
155+
#[should_panic = "I've almost got 99 problems."]
156+
fn shared_from_iter_trustedlen_panic() {
157+
// Exercise the `TrustedLen` implementation when `size_hint()` matches
158+
// `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
159+
let iter = (0..SHARED_ITER_MAX)
160+
.map(|val| {
161+
match val {
162+
98 => panic!("I've almost got 99 problems."),
163+
_ => Box::new(val),
164+
}
165+
});
166+
assert_trusted_len(&iter);
167+
let _ = iter.collect::<Rc<[_]>>();
168+
169+
panic!("I am unreachable.");
170+
}
171+
172+
#[test]
173+
fn shared_from_iter_trustedlen_no_fuse() {
174+
// Exercise the `TrustedLen` implementation when `size_hint()` matches
175+
// `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
176+
struct Iter(std::vec::IntoIter<Option<Box<u8>>>);
177+
178+
unsafe impl TrustedLen for Iter {}
179+
180+
impl Iterator for Iter {
181+
fn size_hint(&self) -> (usize, Option<usize>) {
182+
(2, Some(2))
183+
}
184+
185+
type Item = Box<u8>;
186+
187+
fn next(&mut self) -> Option<Self::Item> {
188+
self.0.next().flatten()
189+
}
190+
}
191+
192+
let vec = vec![
193+
Some(Box::new(42)),
194+
Some(Box::new(24)),
195+
None,
196+
Some(Box::new(12)),
197+
];
198+
let iter = Iter(vec.into_iter());
199+
assert_trusted_len(&iter);
200+
assert_eq!(
201+
&[Box::new(42), Box::new(24)],
202+
&*iter.collect::<Rc<[_]>>()
203+
);
204+
}

0 commit comments

Comments
 (0)