Skip to content

Commit

Permalink
move some tests back to libcollections
Browse files Browse the repository at this point in the history
  • Loading branch information
Jorge Aparicio committed Mar 17, 2015
1 parent e09bf82 commit cb5e429
Show file tree
Hide file tree
Showing 12 changed files with 565 additions and 511 deletions.
2 changes: 1 addition & 1 deletion mk/tests.mk
Expand Up @@ -22,7 +22,7 @@ $(eval $(call RUST_CRATE,coretest))
DEPS_collectionstest :=
$(eval $(call RUST_CRATE,collectionstest))

TEST_TARGET_CRATES = $(filter-out collections core unicode,$(TARGET_CRATES)) \
TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) \
collectionstest coretest
TEST_DOC_CRATES = $(DOC_CRATES)
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\
Expand Down
4 changes: 4 additions & 0 deletions src/libcollections/lib.rs
Expand Up @@ -47,6 +47,9 @@ extern crate core;
extern crate unicode;
extern crate alloc;

#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] extern crate test;

pub use binary_heap::BinaryHeap;
pub use bit_vec::BitVec;
pub use bit_set::BitSet;
Expand Down Expand Up @@ -131,6 +134,7 @@ pub mod btree_set {
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
pub use core::ops; // RangeFull
}
Expand Down
191 changes: 191 additions & 0 deletions src/libcollections/linked_list.rs
Expand Up @@ -938,3 +938,194 @@ impl<A: Hash> Hash for LinkedList<A> {
}
}
}

#[cfg(test)]
mod test {
use std::clone::Clone;
use std::iter::{Iterator, IteratorExt};
use std::option::Option::{Some, None, self};
use std::rand;
use std::thread;
use std::vec::Vec;

use super::{LinkedList, Node};

#[cfg(test)]
fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
v.iter().cloned().collect()
}

pub fn check_links<T>(list: &LinkedList<T>) {
let mut len = 0;
let mut last_ptr: Option<&Node<T>> = None;
let mut node_ptr: &Node<T>;
match list.list_head {
None => { assert_eq!(0, list.length); return }
Some(ref node) => node_ptr = &**node,
}
loop {
match (last_ptr, node_ptr.prev.resolve_immut()) {
(None , None ) => {}
(None , _ ) => panic!("prev link for list_head"),
(Some(p), Some(pptr)) => {
assert_eq!(p as *const Node<T>, pptr as *const Node<T>);
}
_ => panic!("prev link is none, not good"),
}
match node_ptr.next {
Some(ref next) => {
last_ptr = Some(node_ptr);
node_ptr = &**next;
len += 1;
}
None => {
len += 1;
break;
}
}
}
assert_eq!(len, list.length);
}

#[test]
fn test_append() {
// Empty to empty
{
let mut m = LinkedList::<i32>::new();
let mut n = LinkedList::new();
m.append(&mut n);
check_links(&m);
assert_eq!(m.len(), 0);
assert_eq!(n.len(), 0);
}
// Non-empty to empty
{
let mut m = LinkedList::new();
let mut n = LinkedList::new();
n.push_back(2);
m.append(&mut n);
check_links(&m);
assert_eq!(m.len(), 1);
assert_eq!(m.pop_back(), Some(2));
assert_eq!(n.len(), 0);
check_links(&m);
}
// Empty to non-empty
{
let mut m = LinkedList::new();
let mut n = LinkedList::new();
m.push_back(2);
m.append(&mut n);
check_links(&m);
assert_eq!(m.len(), 1);
assert_eq!(m.pop_back(), Some(2));
check_links(&m);
}

// Non-empty to non-empty
let v = vec![1,2,3,4,5];
let u = vec![9,8,1,2,3,4,5];
let mut m = list_from(&v);
let mut n = list_from(&u);
m.append(&mut n);
check_links(&m);
let mut sum = v;
sum.push_all(&u);
assert_eq!(sum.len(), m.len());
for elt in sum {
assert_eq!(m.pop_front(), Some(elt))
}
assert_eq!(n.len(), 0);
// let's make sure it's working properly, since we
// did some direct changes to private members
n.push_back(3);
assert_eq!(n.len(), 1);
assert_eq!(n.pop_front(), Some(3));
check_links(&n);
}

#[test]
fn test_insert_prev() {
let mut m = list_from(&[0,2,4,6,8]);
let len = m.len();
{
let mut it = m.iter_mut();
it.insert_next(-2);
loop {
match it.next() {
None => break,
Some(elt) => {
it.insert_next(*elt + 1);
match it.peek_next() {
Some(x) => assert_eq!(*x, *elt + 2),
None => assert_eq!(8, *elt),
}
}
}
}
it.insert_next(0);
it.insert_next(1);
}
check_links(&m);
assert_eq!(m.len(), 3 + len * 2);
assert_eq!(m.into_iter().collect::<Vec<_>>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]);
}

#[test]
fn test_send() {
let n = list_from(&[1,2,3]);
thread::spawn(move || {
check_links(&n);
let a: &[_] = &[&1,&2,&3];
assert_eq!(a, n.iter().collect::<Vec<_>>());
}).join().ok().unwrap();
}

#[test]
fn test_fuzz() {
for _ in 0..25 {
fuzz_test(3);
fuzz_test(16);
fuzz_test(189);
}
}

#[cfg(test)]
fn fuzz_test(sz: i32) {
let mut m: LinkedList<_> = LinkedList::new();
let mut v = vec![];
for i in 0..sz {
check_links(&m);
let r: u8 = rand::random();
match r % 6 {
0 => {
m.pop_back();
v.pop();
}
1 => {
if !v.is_empty() {
m.pop_front();
v.remove(0);
}
}
2 | 4 => {
m.push_front(-i);
v.insert(0, -i);
}
3 | 5 | _ => {
m.push_back(i);
v.push(i);
}
}
}

check_links(&m);

let mut i = 0;
for (a, &b) in m.into_iter().zip(v.iter()) {
i += 1;
assert_eq!(a, b);
}
assert_eq!(i, v.len());
}
}
15 changes: 15 additions & 0 deletions src/libcollections/macros.rs
Expand Up @@ -71,6 +71,7 @@ macro_rules! vec {
/// Note that unlike array expressions this syntax supports all elements
/// which implement `Clone` and the number of elements doesn't have to be
/// a constant.
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
Expand All @@ -83,6 +84,20 @@ macro_rules! vec {
($($x:expr,)*) => (vec![$($x),*])
}

// HACK: `impl [T]` is not available in cfg(test), use `::slice::into_vec`, instead of
// `<[T]>::to_vec`
#[cfg(not(stage0))]
#[cfg(test)]
macro_rules! vec {
($elem:expr; $n:expr) => (
$crate::vec::from_elem($elem, $n)
);
($($x:expr),*) => (
$crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
);
($($x:expr,)*) => (vec![$($x),*])
}

/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
Expand Down
93 changes: 93 additions & 0 deletions src/libcollections/slice.rs
Expand Up @@ -1083,9 +1083,36 @@ impl<T> SliceExt for [T] {
}
}

// HACK: With cfg(test) `impl [T]` is not available, these three functions are actually methods
// that are in `impl [T]` but not in `core::slice::SliceExt` - this is only need for testing
#[cfg(test)]
pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> {
unsafe {
let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len());
mem::forget(b);
xs
}
}

#[cfg(test)]
pub fn permutations<T>(s: &[T]) -> Permutations<T> where T: Clone {
Permutations{
swaps: ElementSwaps::new(s.len()),
v: ::slice::to_vec(s),
}
}

#[cfg(test)]
pub fn to_vec<T>(s: &[T]) -> Vec<T> where T: Clone {
let mut vector = Vec::with_capacity(s.len());
vector.push_all(s);
vector
}

#[cfg(not(stage0))]
/// Allocating extension methods for slices.
#[lang = "slice"]
#[cfg(not(test))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> [T] {
/// Sorts the slice, in place, using `compare` to compare
Expand Down Expand Up @@ -2022,7 +2049,13 @@ impl<T> BorrowMut<[T]> for Vec<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> ToOwned for [T] {
type Owned = Vec<T>;
#[cfg(not(test))]
fn to_owned(&self) -> Vec<T> { self.to_vec() }

// HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of
// `<[T]>::to_vec`
#[cfg(test)]
fn to_owned(&self) -> Vec<T> { ::slice::to_vec(self) }
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -2339,3 +2372,63 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
old
}
}

#[cfg(test)]
mod test {
use core::iter::{Iterator, IteratorExt};
use core::option::Option::{None, Some};
use string::ToString;

#[test]
fn test_permutations() {
{
let v: [i32; 0] = [];
let mut it = ::slice::permutations(&v);
let (min_size, max_opt) = it.size_hint();
assert_eq!(min_size, 1);
assert_eq!(max_opt.unwrap(), 1);
assert_eq!(it.next(), Some(::slice::to_vec(&v)));
assert_eq!(it.next(), None);
}
{
let v = ["Hello".to_string()];
let mut it = ::slice::permutations(&v);
let (min_size, max_opt) = it.size_hint();
assert_eq!(min_size, 1);
assert_eq!(max_opt.unwrap(), 1);
assert_eq!(it.next(), Some(::slice::to_vec(&v)));
assert_eq!(it.next(), None);
}
{
let v = [1, 2, 3];
let mut it = ::slice::permutations(&v);
let (min_size, max_opt) = it.size_hint();
assert_eq!(min_size, 3*2);
assert_eq!(max_opt.unwrap(), 3*2);
assert_eq!(it.next().unwrap(), [1,2,3]);
assert_eq!(it.next().unwrap(), [1,3,2]);
assert_eq!(it.next().unwrap(), [3,1,2]);
let (min_size, max_opt) = it.size_hint();
assert_eq!(min_size, 3);
assert_eq!(max_opt.unwrap(), 3);
assert_eq!(it.next().unwrap(), [3,2,1]);
assert_eq!(it.next().unwrap(), [2,3,1]);
assert_eq!(it.next().unwrap(), [2,1,3]);
assert_eq!(it.next(), None);
}
{
// check that we have N! permutations
let v = ['A', 'B', 'C', 'D', 'E', 'F'];
let mut amt = 0;
let mut it = ::slice::permutations(&v);
let (min_size, max_opt) = it.size_hint();
for _perm in it.by_ref() {
amt += 1;
}
assert_eq!(amt, it.swaps.swaps_made);
assert_eq!(amt, min_size);
assert_eq!(amt, 2 * 3 * 4 * 5 * 6);
assert_eq!(amt, max_opt.unwrap());
}
}
}
1 change: 1 addition & 0 deletions src/libcollections/str.rs
Expand Up @@ -1562,6 +1562,7 @@ impl StrExt for str {
#[cfg(not(stage0))]
/// Any string that can be represented as a slice.
#[lang = "str"]
#[cfg(not(test))]
#[stable(feature = "rust1", since = "1.0.0")]
impl str {
/// Escapes each char in `s` with `char::escape_default`.
Expand Down
9 changes: 9 additions & 0 deletions src/libcollections/string.rs
Expand Up @@ -113,10 +113,19 @@ impl String {
#[inline]
#[unstable(feature = "collections",
reason = "needs investigation to see if to_string() can match perf")]
#[cfg(not(test))]
pub fn from_str(string: &str) -> String {
String { vec: <[_]>::to_vec(string.as_bytes()) }
}

// HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of
// `<[T]>::to_vec`
#[inline]
#[cfg(test)]
pub fn from_str(string: &str) -> String {
String { vec: ::slice::to_vec(string.as_bytes()) }
}

/// Returns the vector as a string buffer, if possible, taking care not to
/// copy it.
///
Expand Down

0 comments on commit cb5e429

Please sign in to comment.