about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorStjepan Glavina <stjepang@gmail.com>2017-04-03 16:53:04 +0200
committerStjepan Glavina <stjepang@gmail.com>2017-04-03 20:49:39 +0200
commit13c744f30d1540f36a6437224d16e3aea0a2ff71 (patch)
tree27bb8c23c24ebeddb5b72d7131a05912df5c0242 /src/libcore
parent5309a3e31d88def1f3ea966162ed4f81f161d500 (diff)
Move libXtest into libX/tests
This change moves:

1. `libcoretest` into `libcore/tests`
2. `libcollectionstest` into `libcollections/tests`

This is a follow-up to #39561.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/Cargo.toml4
-rw-r--r--src/libcore/num/bignum.rs2
-rw-r--r--src/libcore/num/diy_float.rs2
-rw-r--r--src/libcore/num/flt2dec/mod.rs2
-rw-r--r--src/libcore/num/mod.rs2
-rw-r--r--src/libcore/tests/any.rs125
-rw-r--r--src/libcore/tests/array.rs28
-rw-r--r--src/libcore/tests/atomic.rs84
-rw-r--r--src/libcore/tests/cell.rs289
-rw-r--r--src/libcore/tests/char.rs404
-rw-r--r--src/libcore/tests/clone.rs25
-rw-r--r--src/libcore/tests/cmp.rs88
-rw-r--r--src/libcore/tests/fmt/builders.rs498
-rw-r--r--src/libcore/tests/fmt/float.rs37
-rw-r--r--src/libcore/tests/fmt/mod.rs40
-rw-r--r--src/libcore/tests/fmt/num.rs152
-rw-r--r--src/libcore/tests/hash/mod.rs111
-rw-r--r--src/libcore/tests/hash/sip.rs342
-rw-r--r--src/libcore/tests/intrinsics.rs30
-rw-r--r--src/libcore/tests/iter.rs1084
-rw-r--r--src/libcore/tests/lib.rs63
-rw-r--r--src/libcore/tests/mem.rs123
-rw-r--r--src/libcore/tests/nonzero.rs100
-rw-r--r--src/libcore/tests/num/bignum.rs249
-rw-r--r--src/libcore/tests/num/dec2flt/mod.rs145
-rw-r--r--src/libcore/tests/num/dec2flt/parse.rs52
-rw-r--r--src/libcore/tests/num/dec2flt/rawfp.rs154
-rw-r--r--src/libcore/tests/num/flt2dec/estimator.rs65
-rw-r--r--src/libcore/tests/num/flt2dec/mod.rs1201
-rw-r--r--src/libcore/tests/num/flt2dec/strategy/dragon.rs74
-rw-r--r--src/libcore/tests/num/flt2dec/strategy/grisu.rs124
-rw-r--r--src/libcore/tests/num/i16.rs11
-rw-r--r--src/libcore/tests/num/i32.rs11
-rw-r--r--src/libcore/tests/num/i64.rs11
-rw-r--r--src/libcore/tests/num/i8.rs11
-rw-r--r--src/libcore/tests/num/int_macros.rs219
-rw-r--r--src/libcore/tests/num/mod.rs400
-rw-r--r--src/libcore/tests/num/u16.rs11
-rw-r--r--src/libcore/tests/num/u32.rs11
-rw-r--r--src/libcore/tests/num/u64.rs11
-rw-r--r--src/libcore/tests/num/u8.rs11
-rw-r--r--src/libcore/tests/num/uint_macros.rs158
-rw-r--r--src/libcore/tests/ops.rs49
-rw-r--r--src/libcore/tests/option.rs272
-rw-r--r--src/libcore/tests/ptr.rs214
-rw-r--r--src/libcore/tests/result.rs204
-rw-r--r--src/libcore/tests/slice.rs291
-rw-r--r--src/libcore/tests/str.rs11
-rw-r--r--src/libcore/tests/tuple.rs68
49 files changed, 7667 insertions, 6 deletions
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
index e847c7fa3a0..5af63aa970f 100644
--- a/src/libcore/Cargo.toml
+++ b/src/libcore/Cargo.toml
@@ -10,8 +10,8 @@ test = false
 bench = false
 
 [[test]]
-name = "coretest"
-path = "../libcoretest/lib.rs"
+name = "coretests"
+path = "../libcore/tests/lib.rs"
 
 [[bench]]
 name = "corebenches"
diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs
index 8904322ca48..b5553fb2947 100644
--- a/src/libcore/num/bignum.rs
+++ b/src/libcore/num/bignum.rs
@@ -19,7 +19,7 @@
 //! inputs, but we don't do so to avoid the code bloat. Each bignum is still
 //! tracked for the actual usages, so it normally doesn't matter.
 
-// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// This module is only for dec2flt and flt2dec, and only public because of coretests.
 // It is not intended to ever be stabilized.
 #![doc(hidden)]
 #![unstable(feature = "core_private_bignum",
diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs
index 11eea753f93..6635d95155f 100644
--- a/src/libcore/num/diy_float.rs
+++ b/src/libcore/num/diy_float.rs
@@ -10,7 +10,7 @@
 
 //! Extended precision "soft float", for internal use only.
 
-// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// This module is only for dec2flt and flt2dec, and only public because of coretests.
 // It is not intended to ever be stabilized.
 #![doc(hidden)]
 #![unstable(feature = "core_private_diy_float",
diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs
index f6c03a59f81..5123e42df61 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -118,7 +118,7 @@ provide a large enough buffer and `Part` array, and to assemble the final
 string from resulting `Part`s itself.
 
 All algorithms and formatting functions are accompanied by extensive tests
-in `coretest::num::flt2dec` module. It also shows how to use individual
+in `coretests::num::flt2dec` module. It also shows how to use individual
 functions.
 
 */
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index df343c9d45f..f665cfdee77 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -90,7 +90,7 @@ impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> {
 
 mod wrapping;
 
-// All these modules are technically private and only exposed for libcoretest:
+// All these modules are technically private and only exposed for coretests:
 pub mod flt2dec;
 pub mod dec2flt;
 pub mod bignum;
diff --git a/src/libcore/tests/any.rs b/src/libcore/tests/any.rs
new file mode 100644
index 00000000000..2d3e81aa131
--- /dev/null
+++ b/src/libcore/tests/any.rs
@@ -0,0 +1,125 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::any::*;
+
+#[derive(PartialEq, Debug)]
+struct Test;
+
+static TEST: &'static str = "Test";
+
+#[test]
+fn any_referenced() {
+    let (a, b, c) = (&5 as &Any, &TEST as &Any, &Test as &Any);
+
+    assert!(a.is::<i32>());
+    assert!(!b.is::<i32>());
+    assert!(!c.is::<i32>());
+
+    assert!(!a.is::<&'static str>());
+    assert!(b.is::<&'static str>());
+    assert!(!c.is::<&'static str>());
+
+    assert!(!a.is::<Test>());
+    assert!(!b.is::<Test>());
+    assert!(c.is::<Test>());
+}
+
+#[test]
+fn any_owning() {
+    let (a, b, c) = (box 5_usize as Box<Any>, box TEST as Box<Any>, box Test as Box<Any>);
+
+    assert!(a.is::<usize>());
+    assert!(!b.is::<usize>());
+    assert!(!c.is::<usize>());
+
+    assert!(!a.is::<&'static str>());
+    assert!(b.is::<&'static str>());
+    assert!(!c.is::<&'static str>());
+
+    assert!(!a.is::<Test>());
+    assert!(!b.is::<Test>());
+    assert!(c.is::<Test>());
+}
+
+#[test]
+fn any_downcast_ref() {
+    let a = &5_usize as &Any;
+
+    match a.downcast_ref::<usize>() {
+        Some(&5) => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match a.downcast_ref::<Test>() {
+        None => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+}
+
+#[test]
+fn any_downcast_mut() {
+    let mut a = 5_usize;
+    let mut b: Box<_> = box 7_usize;
+
+    let a_r = &mut a as &mut Any;
+    let tmp: &mut usize = &mut *b;
+    let b_r = tmp as &mut Any;
+
+    match a_r.downcast_mut::<usize>() {
+        Some(x) => {
+            assert_eq!(*x, 5);
+            *x = 612;
+        }
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match b_r.downcast_mut::<usize>() {
+        Some(x) => {
+            assert_eq!(*x, 7);
+            *x = 413;
+        }
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match a_r.downcast_mut::<Test>() {
+        None => (),
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match b_r.downcast_mut::<Test>() {
+        None => (),
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match a_r.downcast_mut::<usize>() {
+        Some(&mut 612) => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match b_r.downcast_mut::<usize>() {
+        Some(&mut 413) => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+}
+
+#[test]
+fn any_fixed_vec() {
+    let test = [0_usize; 8];
+    let test = &test as &Any;
+    assert!(test.is::<[usize; 8]>());
+    assert!(!test.is::<[usize; 10]>());
+}
+
+#[test]
+fn any_unsized() {
+    fn is_any<T: Any + ?Sized>() {}
+    is_any::<[i32]>();
+}
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
new file mode 100644
index 00000000000..6af031dee58
--- /dev/null
+++ b/src/libcore/tests/array.rs
@@ -0,0 +1,28 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+use core::array::FixedSizeArray;
+
+#[test]
+fn fixed_size_array() {
+    let mut array = [0; 64];
+    let mut zero_sized = [(); 64];
+    let mut empty_array = [0; 0];
+    let mut empty_zero_sized = [(); 0];
+
+    assert_eq!(FixedSizeArray::as_slice(&array).len(), 64);
+    assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64);
+    assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0);
+    assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0);
+
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64);
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64);
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0);
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0);
+}
diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs
new file mode 100644
index 00000000000..b6bb5fddf4a
--- /dev/null
+++ b/src/libcore/tests/atomic.rs
@@ -0,0 +1,84 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::sync::atomic::*;
+use core::sync::atomic::Ordering::SeqCst;
+
+#[test]
+fn bool_() {
+    let a = AtomicBool::new(false);
+    assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
+    assert_eq!(a.compare_and_swap(false, true, SeqCst), true);
+
+    a.store(false, SeqCst);
+    assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
+}
+
+#[test]
+fn bool_and() {
+    let a = AtomicBool::new(true);
+    assert_eq!(a.fetch_and(false, SeqCst),true);
+    assert_eq!(a.load(SeqCst),false);
+}
+
+#[test]
+fn uint_and() {
+    let x = AtomicUsize::new(0xf731);
+    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
+}
+
+#[test]
+fn uint_or() {
+    let x = AtomicUsize::new(0xf731);
+    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
+}
+
+#[test]
+fn uint_xor() {
+    let x = AtomicUsize::new(0xf731);
+    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
+}
+
+#[test]
+fn int_and() {
+    let x = AtomicIsize::new(0xf731);
+    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
+}
+
+#[test]
+fn int_or() {
+    let x = AtomicIsize::new(0xf731);
+    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
+}
+
+#[test]
+fn int_xor() {
+    let x = AtomicIsize::new(0xf731);
+    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
+}
+
+static S_FALSE: AtomicBool = AtomicBool::new(false);
+static S_TRUE: AtomicBool = AtomicBool::new(true);
+static S_INT: AtomicIsize  = AtomicIsize::new(0);
+static S_UINT: AtomicUsize = AtomicUsize::new(0);
+
+#[test]
+fn static_init() {
+    assert!(!S_FALSE.load(SeqCst));
+    assert!(S_TRUE.load(SeqCst));
+    assert!(S_INT.load(SeqCst) == 0);
+    assert!(S_UINT.load(SeqCst) == 0);
+}
diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs
new file mode 100644
index 00000000000..8585f2f0871
--- /dev/null
+++ b/src/libcore/tests/cell.rs
@@ -0,0 +1,289 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cell::*;
+use core::default::Default;
+use std::mem::drop;
+
+#[test]
+fn smoketest_cell() {
+    let x = Cell::new(10);
+    assert!(x == Cell::new(10));
+    assert!(x.get() == 10);
+    x.set(20);
+    assert!(x == Cell::new(20));
+    assert!(x.get() == 20);
+
+    let y = Cell::new((30, 40));
+    assert!(y == Cell::new((30, 40)));
+    assert!(y.get() == (30, 40));
+}
+
+#[test]
+fn cell_has_sensible_show() {
+    let x = Cell::new("foo bar");
+    assert!(format!("{:?}", x).contains(x.get()));
+
+    x.set("baz qux");
+    assert!(format!("{:?}", x).contains(x.get()));
+}
+
+#[test]
+fn ref_and_refmut_have_sensible_show() {
+    let refcell = RefCell::new("foo");
+
+    let refcell_refmut = refcell.borrow_mut();
+    assert!(format!("{:?}", refcell_refmut).contains("foo"));
+    drop(refcell_refmut);
+
+    let refcell_ref = refcell.borrow();
+    assert!(format!("{:?}", refcell_ref).contains("foo"));
+    drop(refcell_ref);
+}
+
+#[test]
+fn double_imm_borrow() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow();
+    x.borrow();
+}
+
+#[test]
+fn no_mut_then_imm_borrow() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow_mut();
+    assert!(x.try_borrow().is_err());
+}
+
+#[test]
+fn no_imm_then_borrow_mut() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow();
+    assert!(x.try_borrow_mut().is_err());
+}
+
+#[test]
+fn no_double_borrow_mut() {
+    let x = RefCell::new(0);
+    assert!(x.try_borrow().is_ok());
+    let _b1 = x.borrow_mut();
+    assert!(x.try_borrow().is_err());
+}
+
+#[test]
+fn imm_release_borrow_mut() {
+    let x = RefCell::new(0);
+    {
+        let _b1 = x.borrow();
+    }
+    x.borrow_mut();
+}
+
+#[test]
+fn mut_release_borrow_mut() {
+    let x = RefCell::new(0);
+    {
+        let _b1 = x.borrow_mut();
+    }
+    x.borrow();
+}
+
+#[test]
+fn double_borrow_single_release_no_borrow_mut() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow();
+    {
+        let _b2 = x.borrow();
+    }
+    assert!(x.try_borrow().is_ok());
+    assert!(x.try_borrow_mut().is_err());
+}
+
+#[test]
+#[should_panic]
+fn discard_doesnt_unborrow() {
+    let x = RefCell::new(0);
+    let _b = x.borrow();
+    let _ = _b;
+    let _b = x.borrow_mut();
+}
+
+#[test]
+fn ref_clone_updates_flag() {
+    let x = RefCell::new(0);
+    {
+        let b1 = x.borrow();
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_err());
+        {
+            let _b2 = Ref::clone(&b1);
+            assert!(x.try_borrow().is_ok());
+            assert!(x.try_borrow_mut().is_err());
+        }
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_err());
+    }
+    assert!(x.try_borrow().is_ok());
+    assert!(x.try_borrow_mut().is_ok());
+}
+
+#[test]
+fn ref_map_does_not_update_flag() {
+    let x = RefCell::new(Some(5));
+    {
+        let b1: Ref<Option<u32>> = x.borrow();
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_err());
+        {
+            let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
+            assert_eq!(*b2, 5);
+            assert!(x.try_borrow().is_ok());
+            assert!(x.try_borrow_mut().is_err());
+        }
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_ok());
+    }
+    assert!(x.try_borrow().is_ok());
+    assert!(x.try_borrow_mut().is_ok());
+}
+
+#[test]
+fn ref_map_accessor() {
+    struct X(RefCell<(u32, char)>);
+    impl X {
+        fn accessor(&self) -> Ref<u32> {
+            Ref::map(self.0.borrow(), |tuple| &tuple.0)
+        }
+    }
+    let x = X(RefCell::new((7, 'z')));
+    let d: Ref<u32> = x.accessor();
+    assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_mut_map_accessor() {
+    struct X(RefCell<(u32, char)>);
+    impl X {
+        fn accessor(&self) -> RefMut<u32> {
+            RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
+        }
+    }
+    let x = X(RefCell::new((7, 'z')));
+    {
+        let mut d: RefMut<u32> = x.accessor();
+        assert_eq!(*d, 7);
+        *d += 1;
+    }
+    assert_eq!(*x.0.borrow(), (8, 'z'));
+}
+
+#[test]
+fn as_ptr() {
+    let c1: Cell<usize> = Cell::new(0);
+    c1.set(1);
+    assert_eq!(1, unsafe { *c1.as_ptr() });
+
+    let c2: Cell<usize> = Cell::new(0);
+    unsafe { *c2.as_ptr() = 1; }
+    assert_eq!(1, c2.get());
+
+    let r1: RefCell<usize> = RefCell::new(0);
+    *r1.borrow_mut() = 1;
+    assert_eq!(1, unsafe { *r1.as_ptr() });
+
+    let r2: RefCell<usize> = RefCell::new(0);
+    unsafe { *r2.as_ptr() = 1; }
+    assert_eq!(1, *r2.borrow());
+}
+
+#[test]
+fn cell_default() {
+    let cell: Cell<u32> = Default::default();
+    assert_eq!(0, cell.get());
+}
+
+#[test]
+fn cell_set() {
+    let cell = Cell::new(10);
+    cell.set(20);
+    assert_eq!(20, cell.get());
+
+    let cell = Cell::new("Hello".to_owned());
+    cell.set("World".to_owned());
+    assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_replace() {
+    let cell = Cell::new(10);
+    assert_eq!(10, cell.replace(20));
+    assert_eq!(20, cell.get());
+
+    let cell = Cell::new("Hello".to_owned());
+    assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
+    assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_into_inner() {
+    let cell = Cell::new(10);
+    assert_eq!(10, cell.into_inner());
+
+    let cell = Cell::new("Hello world".to_owned());
+    assert_eq!("Hello world".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn refcell_default() {
+    let cell: RefCell<u64> = Default::default();
+    assert_eq!(0, *cell.borrow());
+}
+
+#[test]
+fn unsafe_cell_unsized() {
+    let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
+    {
+        let val: &mut [i32] = unsafe { &mut *cell.get() };
+        val[0] = 4;
+        val[2] = 5;
+    }
+    let comp: &mut [i32] = &mut [4, 2, 5];
+    assert_eq!(unsafe { &mut *cell.get() }, comp);
+}
+
+#[test]
+fn refcell_unsized() {
+    let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
+    {
+        let b = &mut *cell.borrow_mut();
+        b[0] = 4;
+        b[2] = 5;
+    }
+    let comp: &mut [i32] = &mut [4, 2, 5];
+    assert_eq!(&*cell.borrow(), comp);
+}
+
+#[test]
+fn refcell_ref_coercion() {
+    let cell: RefCell<[i32; 3]> = RefCell::new([1, 2, 3]);
+    {
+        let mut cellref: RefMut<[i32; 3]> = cell.borrow_mut();
+        cellref[0] = 4;
+        let mut coerced: RefMut<[i32]> = cellref;
+        coerced[2] = 5;
+    }
+    {
+        let comp: &mut [i32] = &mut [4, 2, 5];
+        let cellref: Ref<[i32; 3]> = cell.borrow();
+        assert_eq!(&*cellref, comp);
+        let coerced: Ref<[i32]> = cellref;
+        assert_eq!(&*coerced, comp);
+    }
+}
diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs
new file mode 100644
index 00000000000..e4012ec91e2
--- /dev/null
+++ b/src/libcore/tests/char.rs
@@ -0,0 +1,404 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{char,str};
+use std::convert::TryFrom;
+
+#[test]
+fn test_convert() {
+    assert_eq!(u32::from('a'), 0x61);
+    assert_eq!(char::from(b'\0'), '\0');
+    assert_eq!(char::from(b'a'), 'a');
+    assert_eq!(char::from(b'\xFF'), '\u{FF}');
+    assert_eq!(char::try_from(0_u32), Ok('\0'));
+    assert_eq!(char::try_from(0x61_u32), Ok('a'));
+    assert_eq!(char::try_from(0xD7FF_u32), Ok('\u{D7FF}'));
+    assert!(char::try_from(0xD800_u32).is_err());
+    assert!(char::try_from(0xDFFF_u32).is_err());
+    assert_eq!(char::try_from(0xE000_u32), Ok('\u{E000}'));
+    assert_eq!(char::try_from(0x10FFFF_u32), Ok('\u{10FFFF}'));
+    assert!(char::try_from(0x110000_u32).is_err());
+    assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
+}
+
+#[test]
+fn test_is_lowercase() {
+    assert!('a'.is_lowercase());
+    assert!('ö'.is_lowercase());
+    assert!('ß'.is_lowercase());
+    assert!(!'Ü'.is_lowercase());
+    assert!(!'P'.is_lowercase());
+}
+
+#[test]
+fn test_is_uppercase() {
+    assert!(!'h'.is_uppercase());
+    assert!(!'ä'.is_uppercase());
+    assert!(!'ß'.is_uppercase());
+    assert!('Ö'.is_uppercase());
+    assert!('T'.is_uppercase());
+}
+
+#[test]
+fn test_is_whitespace() {
+    assert!(' '.is_whitespace());
+    assert!('\u{2007}'.is_whitespace());
+    assert!('\t'.is_whitespace());
+    assert!('\n'.is_whitespace());
+    assert!(!'a'.is_whitespace());
+    assert!(!'_'.is_whitespace());
+    assert!(!'\u{0}'.is_whitespace());
+}
+
+#[test]
+fn test_to_digit() {
+    assert_eq!('0'.to_digit(10), Some(0));
+    assert_eq!('1'.to_digit(2), Some(1));
+    assert_eq!('2'.to_digit(3), Some(2));
+    assert_eq!('9'.to_digit(10), Some(9));
+    assert_eq!('a'.to_digit(16), Some(10));
+    assert_eq!('A'.to_digit(16), Some(10));
+    assert_eq!('b'.to_digit(16), Some(11));
+    assert_eq!('B'.to_digit(16), Some(11));
+    assert_eq!('z'.to_digit(36), Some(35));
+    assert_eq!('Z'.to_digit(36), Some(35));
+    assert_eq!(' '.to_digit(10), None);
+    assert_eq!('$'.to_digit(36), None);
+}
+
+#[test]
+fn test_to_lowercase() {
+    fn lower(c: char) -> String {
+        let iter: String = c.to_lowercase().collect();
+        let disp: String = c.to_lowercase().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(lower('A'), "a");
+    assert_eq!(lower('Ö'), "ö");
+    assert_eq!(lower('ß'), "ß");
+    assert_eq!(lower('Ü'), "ü");
+    assert_eq!(lower('💩'), "💩");
+    assert_eq!(lower('Σ'), "σ");
+    assert_eq!(lower('Τ'), "τ");
+    assert_eq!(lower('Ι'), "ι");
+    assert_eq!(lower('Γ'), "γ");
+    assert_eq!(lower('Μ'), "μ");
+    assert_eq!(lower('Α'), "α");
+    assert_eq!(lower('Σ'), "σ");
+    assert_eq!(lower('Dž'), "dž");
+    assert_eq!(lower('fi'), "fi");
+    assert_eq!(lower('İ'), "i\u{307}");
+}
+
+#[test]
+fn test_to_uppercase() {
+    fn upper(c: char) -> String {
+        let iter: String = c.to_uppercase().collect();
+        let disp: String = c.to_uppercase().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(upper('a'), "A");
+    assert_eq!(upper('ö'), "Ö");
+    assert_eq!(upper('ß'), "SS"); // not ẞ: Latin capital letter sharp s
+    assert_eq!(upper('ü'), "Ü");
+    assert_eq!(upper('💩'), "💩");
+
+    assert_eq!(upper('σ'), "Σ");
+    assert_eq!(upper('τ'), "Τ");
+    assert_eq!(upper('ι'), "Ι");
+    assert_eq!(upper('γ'), "Γ");
+    assert_eq!(upper('μ'), "Μ");
+    assert_eq!(upper('α'), "Α");
+    assert_eq!(upper('ς'), "Σ");
+    assert_eq!(upper('Dž'), "DŽ");
+    assert_eq!(upper('fi'), "FI");
+    assert_eq!(upper('ᾀ'), "ἈΙ");
+}
+
+#[test]
+fn test_is_control() {
+    assert!('\u{0}'.is_control());
+    assert!('\u{3}'.is_control());
+    assert!('\u{6}'.is_control());
+    assert!('\u{9}'.is_control());
+    assert!('\u{7f}'.is_control());
+    assert!('\u{92}'.is_control());
+    assert!(!'\u{20}'.is_control());
+    assert!(!'\u{55}'.is_control());
+    assert!(!'\u{68}'.is_control());
+}
+
+#[test]
+fn test_is_digit() {
+   assert!('2'.is_numeric());
+   assert!('7'.is_numeric());
+   assert!(!'c'.is_numeric());
+   assert!(!'i'.is_numeric());
+   assert!(!'z'.is_numeric());
+   assert!(!'Q'.is_numeric());
+}
+
+#[test]
+fn test_escape_debug() {
+    fn string(c: char) -> String {
+        let iter: String = c.escape_debug().collect();
+        let disp: String = c.escape_debug().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(string('\n'), "\\n");
+    assert_eq!(string('\r'), "\\r");
+    assert_eq!(string('\''), "\\'");
+    assert_eq!(string('"'), "\\\"");
+    assert_eq!(string(' '), " ");
+    assert_eq!(string('a'), "a");
+    assert_eq!(string('~'), "~");
+    assert_eq!(string('é'), "é");
+    assert_eq!(string('文'), "文");
+    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\x1f'), "\\u{1f}");
+    assert_eq!(string('\x7f'), "\\u{7f}");
+    assert_eq!(string('\u{80}'), "\\u{80}");
+    assert_eq!(string('\u{ff}'), "\u{ff}");
+    assert_eq!(string('\u{11b}'), "\u{11b}");
+    assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}");
+    assert_eq!(string('\u{200b}'),"\\u{200b}");      // zero width space
+    assert_eq!(string('\u{e000}'), "\\u{e000}");     // private use 1
+    assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
+}
+
+#[test]
+fn test_escape_default() {
+    fn string(c: char) -> String {
+        let iter: String = c.escape_default().collect();
+        let disp: String = c.escape_default().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(string('\n'), "\\n");
+    assert_eq!(string('\r'), "\\r");
+    assert_eq!(string('\''), "\\'");
+    assert_eq!(string('"'), "\\\"");
+    assert_eq!(string(' '), " ");
+    assert_eq!(string('a'), "a");
+    assert_eq!(string('~'), "~");
+    assert_eq!(string('é'), "\\u{e9}");
+    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\x1f'), "\\u{1f}");
+    assert_eq!(string('\x7f'), "\\u{7f}");
+    assert_eq!(string('\u{80}'), "\\u{80}");
+    assert_eq!(string('\u{ff}'), "\\u{ff}");
+    assert_eq!(string('\u{11b}'), "\\u{11b}");
+    assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
+    assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space
+    assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
+    assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
+}
+
+#[test]
+fn test_escape_unicode() {
+    fn string(c: char) -> String {
+        let iter: String = c.escape_unicode().collect();
+        let disp: String = c.escape_unicode().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+
+    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\n'), "\\u{a}");
+    assert_eq!(string(' '), "\\u{20}");
+    assert_eq!(string('a'), "\\u{61}");
+    assert_eq!(string('\u{11b}'), "\\u{11b}");
+    assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
+}
+
+#[test]
+fn test_encode_utf8() {
+    fn check(input: char, expect: &[u8]) {
+        let mut buf = [0; 4];
+        let ptr = buf.as_ptr();
+        let s = input.encode_utf8(&mut buf);
+        assert_eq!(s.as_ptr() as usize, ptr as usize);
+        assert!(str::from_utf8(s.as_bytes()).is_ok());
+        assert_eq!(s.as_bytes(), expect);
+    }
+
+    check('x', &[0x78]);
+    check('\u{e9}', &[0xc3, 0xa9]);
+    check('\u{a66e}', &[0xea, 0x99, 0xae]);
+    check('\u{1f4a9}', &[0xf0, 0x9f, 0x92, 0xa9]);
+}
+
+#[test]
+fn test_encode_utf16() {
+    fn check(input: char, expect: &[u16]) {
+        let mut buf = [0; 2];
+        let ptr = buf.as_mut_ptr();
+        let b = input.encode_utf16(&mut buf);
+        assert_eq!(b.as_mut_ptr() as usize, ptr as usize);
+        assert_eq!(b, expect);
+    }
+
+    check('x', &[0x0078]);
+    check('\u{e9}', &[0x00e9]);
+    check('\u{a66e}', &[0xa66e]);
+    check('\u{1f4a9}', &[0xd83d, 0xdca9]);
+}
+
+#[test]
+fn test_len_utf16() {
+    assert!('x'.len_utf16() == 1);
+    assert!('\u{e9}'.len_utf16() == 1);
+    assert!('\u{a66e}'.len_utf16() == 1);
+    assert!('\u{1f4a9}'.len_utf16() == 2);
+}
+
+#[test]
+fn test_decode_utf16() {
+    fn check(s: &[u16], expected: &[Result<char, u16>]) {
+        let v = char::decode_utf16(s.iter().cloned())
+                     .map(|r| r.map_err(|e| e.unpaired_surrogate()))
+                     .collect::<Vec<_>>();
+        assert_eq!(v, expected);
+    }
+    check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
+    check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]);
+}
+
+#[test]
+fn ed_iterator_specializations() {
+    // Check counting
+    assert_eq!('\n'.escape_default().count(), 2);
+    assert_eq!('c'.escape_default().count(), 1);
+    assert_eq!(' '.escape_default().count(), 1);
+    assert_eq!('\\'.escape_default().count(), 2);
+    assert_eq!('\''.escape_default().count(), 2);
+
+    // Check nth
+
+    // Check that OoB is handled correctly
+    assert_eq!('\n'.escape_default().nth(2), None);
+    assert_eq!('c'.escape_default().nth(1), None);
+    assert_eq!(' '.escape_default().nth(1), None);
+    assert_eq!('\\'.escape_default().nth(2), None);
+    assert_eq!('\''.escape_default().nth(2), None);
+
+    // Check the first char
+    assert_eq!('\n'.escape_default().nth(0), Some('\\'));
+    assert_eq!('c'.escape_default().nth(0), Some('c'));
+    assert_eq!(' '.escape_default().nth(0), Some(' '));
+    assert_eq!('\\'.escape_default().nth(0), Some('\\'));
+    assert_eq!('\''.escape_default().nth(0), Some('\\'));
+
+    // Check the second char
+    assert_eq!('\n'.escape_default().nth(1), Some('n'));
+    assert_eq!('\\'.escape_default().nth(1), Some('\\'));
+    assert_eq!('\''.escape_default().nth(1), Some('\''));
+
+    // Check the last char
+    assert_eq!('\n'.escape_default().last(), Some('n'));
+    assert_eq!('c'.escape_default().last(), Some('c'));
+    assert_eq!(' '.escape_default().last(), Some(' '));
+    assert_eq!('\\'.escape_default().last(), Some('\\'));
+    assert_eq!('\''.escape_default().last(), Some('\''));
+}
+
+#[test]
+fn eu_iterator_specializations() {
+    fn check(c: char) {
+        let len = c.escape_unicode().count();
+
+        // Check OoB
+        assert_eq!(c.escape_unicode().nth(len), None);
+
+        // For all possible in-bound offsets
+        let mut iter = c.escape_unicode();
+        for offset in 0..len {
+            // Check last
+            assert_eq!(iter.clone().last(), Some('}'));
+
+            // Check len
+            assert_eq!(iter.len(), len - offset);
+
+            // Check size_hint (= len in ExactSizeIterator)
+            assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len())));
+
+            // Check counting
+            assert_eq!(iter.clone().count(), len - offset);
+
+            // Check nth
+            assert_eq!(c.escape_unicode().nth(offset), iter.next());
+        }
+
+        // Check post-last
+        assert_eq!(iter.clone().last(), None);
+        assert_eq!(iter.clone().count(), 0);
+    }
+
+    check('\u{0}');
+    check('\u{1}');
+    check('\u{12}');
+    check('\u{123}');
+    check('\u{1234}');
+    check('\u{12340}');
+    check('\u{10FFFF}');
+}
+
+#[test]
+fn test_decode_utf8() {
+    macro_rules! assert_decode_utf8 {
+        ($input_bytes: expr, $expected_str: expr) => {
+            let input_bytes: &[u8] = &$input_bytes;
+            let s = char::decode_utf8(input_bytes.iter().cloned())
+                .map(|r_b| r_b.unwrap_or('\u{FFFD}'))
+                .collect::<String>();
+            assert_eq!(s, $expected_str,
+                       "input bytes: {:?}, expected str: {:?}, result: {:?}",
+                       input_bytes, $expected_str, s);
+            assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
+        }
+    }
+
+    assert_decode_utf8!([], "");
+    assert_decode_utf8!([0x41], "A");
+    assert_decode_utf8!([0xC1, 0x81], "��");
+    assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥");
+    assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
+    assert_decode_utf8!([0xE2, 0x99], "�");
+    assert_decode_utf8!([0xE2, 0x99, 0x41], "�A");
+    assert_decode_utf8!([0xC0], "�");
+    assert_decode_utf8!([0xC0, 0x41], "�A");
+    assert_decode_utf8!([0x80], "�");
+    assert_decode_utf8!([0x80, 0x41], "�A");
+    assert_decode_utf8!([0xFE], "�");
+    assert_decode_utf8!([0xFE, 0x41], "�A");
+    assert_decode_utf8!([0xFF], "�");
+    assert_decode_utf8!([0xFF, 0x41], "�A");
+    assert_decode_utf8!([0xC0, 0x80], "��");
+
+    // Surrogates
+    assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
+    assert_decode_utf8!([0xED, 0xA0, 0x80], "���");
+    assert_decode_utf8!([0xED, 0xBF, 0x80], "���");
+    assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
+
+    // char::MAX
+    assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
+    assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A");
+    assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����");
+
+    // 5 and 6 bytes sequence
+    // Part of the original design of UTF-8,
+    // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
+    assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����");
+    assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������");
+}
diff --git a/src/libcore/tests/clone.rs b/src/libcore/tests/clone.rs
new file mode 100644
index 00000000000..91d68ba3344
--- /dev/null
+++ b/src/libcore/tests/clone.rs
@@ -0,0 +1,25 @@
+// Copyright 2014-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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_borrowed_clone() {
+    let x = 5;
+    let y: &i32 = &x;
+    let z: &i32 = (&y).clone();
+    assert_eq!(*z, 5);
+}
+
+#[test]
+fn test_clone_from() {
+    let a = box 5;
+    let mut b = box 10;
+    b.clone_from(&a);
+    assert_eq!(*b, 5);
+}
diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs
new file mode 100644
index 00000000000..e3c65ad8b33
--- /dev/null
+++ b/src/libcore/tests/cmp.rs
@@ -0,0 +1,88 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cmp::Ordering::{Less, Greater, Equal};
+
+#[test]
+fn test_int_totalord() {
+    assert_eq!(5.cmp(&10), Less);
+    assert_eq!(10.cmp(&5), Greater);
+    assert_eq!(5.cmp(&5), Equal);
+    assert_eq!((-5).cmp(&12), Less);
+    assert_eq!(12.cmp(&-5), Greater);
+}
+
+#[test]
+fn test_mut_int_totalord() {
+    assert_eq!((&mut 5).cmp(&&mut 10), Less);
+    assert_eq!((&mut 10).cmp(&&mut 5), Greater);
+    assert_eq!((&mut 5).cmp(&&mut 5), Equal);
+    assert_eq!((&mut -5).cmp(&&mut 12), Less);
+    assert_eq!((&mut 12).cmp(&&mut -5), Greater);
+}
+
+#[test]
+fn test_ordering_reverse() {
+    assert_eq!(Less.reverse(), Greater);
+    assert_eq!(Equal.reverse(), Equal);
+    assert_eq!(Greater.reverse(), Less);
+}
+
+#[test]
+fn test_ordering_order() {
+    assert!(Less < Equal);
+    assert_eq!(Greater.cmp(&Less), Greater);
+}
+
+#[test]
+fn test_ordering_then() {
+    assert_eq!(Equal.then(Less), Less);
+    assert_eq!(Equal.then(Equal), Equal);
+    assert_eq!(Equal.then(Greater), Greater);
+    assert_eq!(Less.then(Less), Less);
+    assert_eq!(Less.then(Equal), Less);
+    assert_eq!(Less.then(Greater), Less);
+    assert_eq!(Greater.then(Less), Greater);
+    assert_eq!(Greater.then(Equal), Greater);
+    assert_eq!(Greater.then(Greater), Greater);
+}
+
+#[test]
+fn test_ordering_then_with() {
+    assert_eq!(Equal.then_with(|| Less), Less);
+    assert_eq!(Equal.then_with(|| Equal), Equal);
+    assert_eq!(Equal.then_with(|| Greater), Greater);
+    assert_eq!(Less.then_with(|| Less), Less);
+    assert_eq!(Less.then_with(|| Equal), Less);
+    assert_eq!(Less.then_with(|| Greater), Less);
+    assert_eq!(Greater.then_with(|| Less), Greater);
+    assert_eq!(Greater.then_with(|| Equal), Greater);
+    assert_eq!(Greater.then_with(|| Greater), Greater);
+}
+
+#[test]
+fn test_user_defined_eq() {
+    // Our type.
+    struct SketchyNum {
+        num : isize
+    }
+
+    // Our implementation of `PartialEq` to support `==` and `!=`.
+    impl PartialEq for SketchyNum {
+        // Our custom eq allows numbers which are near each other to be equal! :D
+        fn eq(&self, other: &SketchyNum) -> bool {
+            (self.num - other.num).abs() < 5
+        }
+    }
+
+    // Now these binary operators will work when applied!
+    assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
+    assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
+}
diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs
new file mode 100644
index 00000000000..e71e61bda5e
--- /dev/null
+++ b/src/libcore/tests/fmt/builders.rs
@@ -0,0 +1,498 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod debug_struct {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo").finish()
+            }
+        }
+
+        assert_eq!("Foo", format!("{:?}", Foo));
+        assert_eq!("Foo", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo { bar: true }", format!("{:?}", Foo));
+        assert_eq!(
+"Foo {
+    bar: true
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo));
+        assert_eq!(
+"Foo {
+    bar: true,
+    baz: 10/20
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Bar")
+                    .field("foo", &Foo)
+                    .field("hello", &"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"Bar {
+    foo: Foo {
+        bar: true,
+        baz: 10/20
+    },
+    hello: \"world\"
+}",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_tuple {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo").finish()
+            }
+        }
+
+        assert_eq!("Foo", format!("{:?}", Foo));
+        assert_eq!("Foo", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo(true)", format!("{:?}", Foo));
+        assert_eq!(
+"Foo(
+    true
+)",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .field(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo));
+        assert_eq!(
+"Foo(
+    true,
+    10/20
+)",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .field(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Bar")
+                    .field(&Foo)
+                    .field(&"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("Bar(Foo(true, 10/20), \"world\")",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"Bar(
+    Foo(
+        true,
+        10/20
+    ),
+    \"world\"
+)",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_map {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map().finish()
+            }
+        }
+
+        assert_eq!("{}", format!("{:?}", Foo));
+        assert_eq!("{}", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("{\"bar\": true}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    \"bar\": true
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .entry(&10, &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    \"bar\": true,
+    10: 10/20
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .entry(&10, &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"foo", &Foo)
+                    .entry(&Foo, &"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \
+                    {\"bar\": true, 10: 10/20}: \"world\"}",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"{
+    \"foo\": {
+        \"bar\": true,
+        10: 10/20
+    },
+    {
+        \"bar\": true,
+        10: 10/20
+    }: \"world\"
+}",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_set {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set().finish()
+            }
+        }
+
+        assert_eq!("{}", format!("{:?}", Foo));
+        assert_eq!("{}", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("{true}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    true
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("{true, 10/20}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    true,
+    10/20
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&Foo)
+                    .entry(&"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("{{true, 10/20}, \"world\"}",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"{
+    {
+        true,
+        10/20
+    },
+    \"world\"
+}",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_list {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list().finish()
+            }
+        }
+
+        assert_eq!("[]", format!("{:?}", Foo));
+        assert_eq!("[]", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("[true]", format!("{:?}", Foo));
+        assert_eq!(
+"[
+    true
+]",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("[true, 10/20]", format!("{:?}", Foo));
+        assert_eq!(
+"[
+    true,
+    10/20
+]",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&Foo)
+                    .entry(&"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("[[true, 10/20], \"world\"]",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"[
+    [
+        true,
+        10/20
+    ],
+    \"world\"
+]",
+                   format!("{:#?}", Bar));
+    }
+}
diff --git a/src/libcore/tests/fmt/float.rs b/src/libcore/tests/fmt/float.rs
new file mode 100644
index 00000000000..695001312e4
--- /dev/null
+++ b/src/libcore/tests/fmt/float.rs
@@ -0,0 +1,37 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_format_f64() {
+    assert_eq!("1", format!("{:.0}", 1.0f64));
+    assert_eq!("9", format!("{:.0}", 9.4f64));
+    assert_eq!("10", format!("{:.0}", 9.9f64));
+    assert_eq!("9.8", format!("{:.1}", 9.849f64));
+    assert_eq!("9.9", format!("{:.1}", 9.851f64));
+    assert_eq!("1", format!("{:.0}", 0.5f64));
+    assert_eq!("1.23456789e6", format!("{:e}", 1234567.89f64));
+    assert_eq!("1.23456789e3", format!("{:e}", 1234.56789f64));
+    assert_eq!("1.23456789E6", format!("{:E}", 1234567.89f64));
+    assert_eq!("1.23456789E3", format!("{:E}", 1234.56789f64));
+}
+
+#[test]
+fn test_format_f32() {
+    assert_eq!("1", format!("{:.0}", 1.0f32));
+    assert_eq!("9", format!("{:.0}", 9.4f32));
+    assert_eq!("10", format!("{:.0}", 9.9f32));
+    assert_eq!("9.8", format!("{:.1}", 9.849f32));
+    assert_eq!("9.9", format!("{:.1}", 9.851f32));
+    assert_eq!("1", format!("{:.0}", 0.5f32));
+    assert_eq!("1.2345679e6", format!("{:e}", 1234567.89f32));
+    assert_eq!("1.2345679e3", format!("{:e}", 1234.56789f32));
+    assert_eq!("1.2345679E6", format!("{:E}", 1234567.89f32));
+    assert_eq!("1.2345679E3", format!("{:E}", 1234.56789f32));
+}
diff --git a/src/libcore/tests/fmt/mod.rs b/src/libcore/tests/fmt/mod.rs
new file mode 100644
index 00000000000..5d204c7d523
--- /dev/null
+++ b/src/libcore/tests/fmt/mod.rs
@@ -0,0 +1,40 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod builders;
+mod float;
+mod num;
+
+#[test]
+fn test_format_flags() {
+    // No residual flags left by pointer formatting
+    let p = "".as_ptr();
+    assert_eq!(format!("{:p} {:x}", p, 16), format!("{:p} 10", p));
+
+    assert_eq!(format!("{: >3}", 'a'), "  a");
+}
+
+#[test]
+fn test_pointer_formats_data_pointer() {
+    let b: &[u8] = b"";
+    let s: &str = "";
+    assert_eq!(format!("{:p}", s), format!("{:p}", s.as_ptr()));
+    assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr()));
+}
+
+#[test]
+fn test_estimated_capacity() {
+    assert_eq!(format_args!("").estimated_capacity(), 0);
+    assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
+    assert_eq!(format_args!("Hello").estimated_capacity(), 5);
+    assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
+    assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
+    assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
+}
diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs
new file mode 100644
index 00000000000..4ddedd91004
--- /dev/null
+++ b/src/libcore/tests/fmt/num.rs
@@ -0,0 +1,152 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_format_int() {
+    // Formatting integers should select the right implementation based off
+    // the type of the argument. Also, hex/octal/binary should be defined
+    // for integers, but they shouldn't emit the negative sign.
+    assert!(format!("{}", 1isize) == "1");
+    assert!(format!("{}", 1i8) == "1");
+    assert!(format!("{}", 1i16) == "1");
+    assert!(format!("{}", 1i32) == "1");
+    assert!(format!("{}", 1i64) == "1");
+    assert!(format!("{}", -1isize) == "-1");
+    assert!(format!("{}", -1i8) == "-1");
+    assert!(format!("{}", -1i16) == "-1");
+    assert!(format!("{}", -1i32) == "-1");
+    assert!(format!("{}", -1i64) == "-1");
+    assert!(format!("{:?}", 1isize) == "1");
+    assert!(format!("{:?}", 1i8) == "1");
+    assert!(format!("{:?}", 1i16) == "1");
+    assert!(format!("{:?}", 1i32) == "1");
+    assert!(format!("{:?}", 1i64) == "1");
+    assert!(format!("{:b}", 1isize) == "1");
+    assert!(format!("{:b}", 1i8) == "1");
+    assert!(format!("{:b}", 1i16) == "1");
+    assert!(format!("{:b}", 1i32) == "1");
+    assert!(format!("{:b}", 1i64) == "1");
+    assert!(format!("{:x}", 1isize) == "1");
+    assert!(format!("{:x}", 1i8) == "1");
+    assert!(format!("{:x}", 1i16) == "1");
+    assert!(format!("{:x}", 1i32) == "1");
+    assert!(format!("{:x}", 1i64) == "1");
+    assert!(format!("{:X}", 1isize) == "1");
+    assert!(format!("{:X}", 1i8) == "1");
+    assert!(format!("{:X}", 1i16) == "1");
+    assert!(format!("{:X}", 1i32) == "1");
+    assert!(format!("{:X}", 1i64) == "1");
+    assert!(format!("{:o}", 1isize) == "1");
+    assert!(format!("{:o}", 1i8) == "1");
+    assert!(format!("{:o}", 1i16) == "1");
+    assert!(format!("{:o}", 1i32) == "1");
+    assert!(format!("{:o}", 1i64) == "1");
+
+    assert!(format!("{}", 1usize) == "1");
+    assert!(format!("{}", 1u8) == "1");
+    assert!(format!("{}", 1u16) == "1");
+    assert!(format!("{}", 1u32) == "1");
+    assert!(format!("{}", 1u64) == "1");
+    assert!(format!("{:?}", 1usize) == "1");
+    assert!(format!("{:?}", 1u8) == "1");
+    assert!(format!("{:?}", 1u16) == "1");
+    assert!(format!("{:?}", 1u32) == "1");
+    assert!(format!("{:?}", 1u64) == "1");
+    assert!(format!("{:b}", 1usize) == "1");
+    assert!(format!("{:b}", 1u8) == "1");
+    assert!(format!("{:b}", 1u16) == "1");
+    assert!(format!("{:b}", 1u32) == "1");
+    assert!(format!("{:b}", 1u64) == "1");
+    assert!(format!("{:x}", 1usize) == "1");
+    assert!(format!("{:x}", 1u8) == "1");
+    assert!(format!("{:x}", 1u16) == "1");
+    assert!(format!("{:x}", 1u32) == "1");
+    assert!(format!("{:x}", 1u64) == "1");
+    assert!(format!("{:X}", 1usize) == "1");
+    assert!(format!("{:X}", 1u8) == "1");
+    assert!(format!("{:X}", 1u16) == "1");
+    assert!(format!("{:X}", 1u32) == "1");
+    assert!(format!("{:X}", 1u64) == "1");
+    assert!(format!("{:o}", 1usize) == "1");
+    assert!(format!("{:o}", 1u8) == "1");
+    assert!(format!("{:o}", 1u16) == "1");
+    assert!(format!("{:o}", 1u32) == "1");
+    assert!(format!("{:o}", 1u64) == "1");
+
+    // Test a larger number
+    assert!(format!("{:b}", 55) == "110111");
+    assert!(format!("{:o}", 55) == "67");
+    assert!(format!("{}", 55) == "55");
+    assert!(format!("{:x}", 55) == "37");
+    assert!(format!("{:X}", 55) == "37");
+}
+
+#[test]
+fn test_format_int_zero() {
+    assert!(format!("{}", 0) == "0");
+    assert!(format!("{:?}", 0) == "0");
+    assert!(format!("{:b}", 0) == "0");
+    assert!(format!("{:o}", 0) == "0");
+    assert!(format!("{:x}", 0) == "0");
+    assert!(format!("{:X}", 0) == "0");
+
+    assert!(format!("{}", 0u32) == "0");
+    assert!(format!("{:?}", 0u32) == "0");
+    assert!(format!("{:b}", 0u32) == "0");
+    assert!(format!("{:o}", 0u32) == "0");
+    assert!(format!("{:x}", 0u32) == "0");
+    assert!(format!("{:X}", 0u32) == "0");
+}
+
+#[test]
+fn test_format_int_flags() {
+    assert!(format!("{:3}", 1) == "  1");
+    assert!(format!("{:>3}", 1) == "  1");
+    assert!(format!("{:>+3}", 1) == " +1");
+    assert!(format!("{:<3}", 1) == "1  ");
+    assert!(format!("{:#}", 1) == "1");
+    assert!(format!("{:#x}", 10) == "0xa");
+    assert!(format!("{:#X}", 10) == "0xA");
+    assert!(format!("{:#5x}", 10) == "  0xa");
+    assert!(format!("{:#o}", 10) == "0o12");
+    assert!(format!("{:08x}", 10) == "0000000a");
+    assert!(format!("{:8x}", 10) == "       a");
+    assert!(format!("{:<8x}", 10) == "a       ");
+    assert!(format!("{:>8x}", 10) == "       a");
+    assert!(format!("{:#08x}", 10) == "0x00000a");
+    assert!(format!("{:08}", -10) == "-0000010");
+    assert!(format!("{:x}", !0u8) == "ff");
+    assert!(format!("{:X}", !0u8) == "FF");
+    assert!(format!("{:b}", !0u8) == "11111111");
+    assert!(format!("{:o}", !0u8) == "377");
+    assert!(format!("{:#x}", !0u8) == "0xff");
+    assert!(format!("{:#X}", !0u8) == "0xFF");
+    assert!(format!("{:#b}", !0u8) == "0b11111111");
+    assert!(format!("{:#o}", !0u8) == "0o377");
+}
+
+#[test]
+fn test_format_int_sign_padding() {
+    assert!(format!("{:+5}", 1) == "   +1");
+    assert!(format!("{:+5}", -1) == "   -1");
+    assert!(format!("{:05}", 1) == "00001");
+    assert!(format!("{:05}", -1) == "-0001");
+    assert!(format!("{:+05}", 1) == "+0001");
+    assert!(format!("{:+05}", -1) == "-0001");
+}
+
+#[test]
+fn test_format_int_twos_complement() {
+    use core::{i8, i16, i32, i64};
+    assert!(format!("{}", i8::MIN) == "-128");
+    assert!(format!("{}", i16::MIN) == "-32768");
+    assert!(format!("{}", i32::MIN) == "-2147483648");
+    assert!(format!("{}", i64::MIN) == "-9223372036854775808");
+}
diff --git a/src/libcore/tests/hash/mod.rs b/src/libcore/tests/hash/mod.rs
new file mode 100644
index 00000000000..53ac17c052f
--- /dev/null
+++ b/src/libcore/tests/hash/mod.rs
@@ -0,0 +1,111 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod sip;
+
+use std::hash::{Hash, Hasher};
+use std::default::Default;
+
+struct MyHasher {
+    hash: u64,
+}
+
+impl Default for MyHasher {
+    fn default() -> MyHasher {
+        MyHasher { hash: 0 }
+    }
+}
+
+impl Hasher for MyHasher {
+    fn write(&mut self, buf: &[u8]) {
+        for byte in buf {
+            self.hash += *byte as u64;
+        }
+    }
+    fn finish(&self) -> u64 { self.hash }
+}
+
+
+#[test]
+fn test_writer_hasher() {
+    fn hash<T: Hash>(t: &T) -> u64 {
+        let mut s = MyHasher { hash: 0 };
+        t.hash(&mut s);
+        s.finish()
+    }
+
+    assert_eq!(hash(&()), 0);
+
+    assert_eq!(hash(&5_u8), 5);
+    assert_eq!(hash(&5_u16), 5);
+    assert_eq!(hash(&5_u32), 5);
+    assert_eq!(hash(&5_u64), 5);
+    assert_eq!(hash(&5_usize), 5);
+
+    assert_eq!(hash(&5_i8), 5);
+    assert_eq!(hash(&5_i16), 5);
+    assert_eq!(hash(&5_i32), 5);
+    assert_eq!(hash(&5_i64), 5);
+    assert_eq!(hash(&5_isize), 5);
+
+    assert_eq!(hash(&false), 0);
+    assert_eq!(hash(&true), 1);
+
+    assert_eq!(hash(&'a'), 97);
+
+    let s: &str = "a";
+    assert_eq!(hash(& s), 97 + 0xFF);
+    let s: Box<str> = String::from("a").into_boxed_str();
+    assert_eq!(hash(& s), 97 + 0xFF);
+    let cs: &[u8] = &[1, 2, 3];
+    assert_eq!(hash(& cs), 9);
+    let cs: Box<[u8]> = Box::new([1, 2, 3]);
+    assert_eq!(hash(& cs), 9);
+
+    // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
+
+    let ptr = 5_usize as *const i32;
+    assert_eq!(hash(&ptr), 5);
+
+    let ptr = 5_usize as *mut i32;
+    assert_eq!(hash(&ptr), 5);
+}
+
+struct Custom { hash: u64 }
+struct CustomHasher { output: u64 }
+
+impl Hasher for CustomHasher {
+    fn finish(&self) -> u64 { self.output }
+    fn write(&mut self, _: &[u8]) { panic!() }
+    fn write_u64(&mut self, data: u64) { self.output = data; }
+}
+
+impl Default for CustomHasher {
+    fn default() -> CustomHasher {
+        CustomHasher { output: 0 }
+    }
+}
+
+impl Hash for Custom {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        state.write_u64(self.hash);
+    }
+}
+
+#[test]
+fn test_custom_state() {
+    fn hash<T: Hash>(t: &T) -> u64 {
+        let mut c = CustomHasher { output: 0 };
+        t.hash(&mut c);
+        c.finish()
+    }
+
+    assert_eq!(hash(&Custom { hash: 5 }), 5);
+}
diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs
new file mode 100644
index 00000000000..4a9657e0340
--- /dev/null
+++ b/src/libcore/tests/hash/sip.rs
@@ -0,0 +1,342 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(deprecated)]
+
+use core::hash::{Hash, Hasher};
+use core::hash::{SipHasher, SipHasher13, SipHasher24};
+use core::{slice, mem};
+
+// Hash just the bytes of the slice, without length prefix
+struct Bytes<'a>(&'a [u8]);
+
+impl<'a> Hash for Bytes<'a> {
+    #[allow(unused_must_use)]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Bytes(v) = *self;
+        state.write(v);
+    }
+}
+
+macro_rules! u8to64_le {
+    ($buf:expr, $i:expr) =>
+    ($buf[0+$i] as u64 |
+     ($buf[1+$i] as u64) << 8 |
+     ($buf[2+$i] as u64) << 16 |
+     ($buf[3+$i] as u64) << 24 |
+     ($buf[4+$i] as u64) << 32 |
+     ($buf[5+$i] as u64) << 40 |
+     ($buf[6+$i] as u64) << 48 |
+     ($buf[7+$i] as u64) << 56);
+    ($buf:expr, $i:expr, $len:expr) =>
+    ({
+        let mut t = 0;
+        let mut out = 0;
+        while t < $len {
+            out |= ($buf[t+$i] as u64) << t*8;
+            t += 1;
+        }
+        out
+    });
+}
+
+fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
+    x.hash(&mut st);
+    st.finish()
+}
+
+fn hash<T: Hash>(x: &T) -> u64 {
+    hash_with(SipHasher::new(), x)
+}
+
+#[test]
+#[allow(unused_must_use)]
+fn test_siphash_1_3() {
+    let vecs : [[u8; 8]; 64] = [
+        [ 0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab ],
+        [ 0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9 ],
+        [ 0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82 ],
+        [ 0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b ],
+        [ 0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf ],
+        [ 0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde ],
+        [ 0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5 ],
+        [ 0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3 ],
+        [ 0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36 ],
+        [ 0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25 ],
+        [ 0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79 ],
+        [ 0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70 ],
+        [ 0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78 ],
+        [ 0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30 ],
+        [ 0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60 ],
+        [ 0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3 ],
+        [ 0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc ],
+        [ 0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c ],
+        [ 0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f ],
+        [ 0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2 ],
+        [ 0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0 ],
+        [ 0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9 ],
+        [ 0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f ],
+        [ 0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52 ],
+        [ 0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4 ],
+        [ 0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45 ],
+        [ 0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a ],
+        [ 0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9 ],
+        [ 0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb ],
+        [ 0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88 ],
+        [ 0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54 ],
+        [ 0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23 ],
+        [ 0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81 ],
+        [ 0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d ],
+        [ 0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75 ],
+        [ 0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce ],
+        [ 0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c ],
+        [ 0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6 ],
+        [ 0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3 ],
+        [ 0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62 ],
+        [ 0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1 ],
+        [ 0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66 ],
+        [ 0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65 ],
+        [ 0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24 ],
+        [ 0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2 ],
+        [ 0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2 ],
+        [ 0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1 ],
+        [ 0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49 ],
+        [ 0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f ],
+        [ 0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6 ],
+        [ 0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e ],
+        [ 0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c ],
+        [ 0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4 ],
+        [ 0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36 ],
+        [ 0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31 ],
+        [ 0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2 ],
+        [ 0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4 ],
+        [ 0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23 ],
+        [ 0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f ],
+        [ 0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8 ],
+        [ 0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6 ],
+        [ 0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae ],
+        [ 0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3 ],
+        [ 0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d ]
+    ];
+
+    let k0 = 0x_07_06_05_04_03_02_01_00;
+    let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+    let mut buf = Vec::new();
+    let mut t = 0;
+    let mut state_inc = SipHasher13::new_with_keys(k0, k1);
+
+    while t < 64 {
+        let vec = u8to64_le!(vecs[t], 0);
+        let out = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
+        assert_eq!(vec, out);
+
+        let full = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
+        let i = state_inc.finish();
+
+        assert_eq!(full, i);
+        assert_eq!(full, vec);
+
+        buf.push(t as u8);
+        Hasher::write(&mut state_inc, &[t as u8]);
+
+        t += 1;
+    }
+}
+
+#[test]
+#[allow(unused_must_use)]
+fn test_siphash_2_4() {
+    let vecs : [[u8; 8]; 64] = [
+        [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
+        [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
+        [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
+        [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
+        [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
+        [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
+        [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
+        [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
+        [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
+        [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
+        [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
+        [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
+        [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
+        [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
+        [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
+        [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
+        [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
+        [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
+        [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
+        [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
+        [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
+        [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
+        [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
+        [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
+        [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
+        [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
+        [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
+        [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
+        [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
+        [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
+        [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
+        [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
+        [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
+        [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
+        [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
+        [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
+        [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
+        [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
+        [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
+        [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
+        [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
+        [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
+        [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
+        [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
+        [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
+        [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
+        [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
+        [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
+        [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
+        [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
+        [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
+        [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
+        [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
+        [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
+        [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
+        [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
+        [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
+        [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
+        [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
+        [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
+        [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
+        [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
+        [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
+        [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
+    ];
+
+    let k0 = 0x_07_06_05_04_03_02_01_00;
+    let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+    let mut buf = Vec::new();
+    let mut t = 0;
+    let mut state_inc = SipHasher24::new_with_keys(k0, k1);
+
+    while t < 64 {
+        let vec = u8to64_le!(vecs[t], 0);
+        let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+        assert_eq!(vec, out);
+
+        let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+        let i = state_inc.finish();
+
+        assert_eq!(full, i);
+        assert_eq!(full, vec);
+
+        buf.push(t as u8);
+        Hasher::write(&mut state_inc, &[t as u8]);
+
+        t += 1;
+    }
+}
+#[test] #[cfg(target_arch = "arm")]
+fn test_hash_usize() {
+    let val = 0xdeadbeef_deadbeef_u64;
+    assert!(hash(&(val as u64)) != hash(&(val as usize)));
+    assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+}
+#[test] #[cfg(target_arch = "x86_64")]
+fn test_hash_usize() {
+    let val = 0xdeadbeef_deadbeef_u64;
+    assert_eq!(hash(&(val as u64)), hash(&(val as usize)));
+    assert!(hash(&(val as u32)) != hash(&(val as usize)));
+}
+#[test] #[cfg(target_arch = "x86")]
+fn test_hash_usize() {
+    let val = 0xdeadbeef_deadbeef_u64;
+    assert!(hash(&(val as u64)) != hash(&(val as usize)));
+    assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+}
+
+#[test]
+fn test_hash_idempotent() {
+    let val64 = 0xdeadbeef_deadbeef_u64;
+    assert_eq!(hash(&val64), hash(&val64));
+    let val32 = 0xdeadbeef_u32;
+    assert_eq!(hash(&val32), hash(&val32));
+}
+
+#[test]
+fn test_hash_no_bytes_dropped_64() {
+    let val = 0xdeadbeef_deadbeef_u64;
+
+    assert!(hash(&val) != hash(&zero_byte(val, 0)));
+    assert!(hash(&val) != hash(&zero_byte(val, 1)));
+    assert!(hash(&val) != hash(&zero_byte(val, 2)));
+    assert!(hash(&val) != hash(&zero_byte(val, 3)));
+    assert!(hash(&val) != hash(&zero_byte(val, 4)));
+    assert!(hash(&val) != hash(&zero_byte(val, 5)));
+    assert!(hash(&val) != hash(&zero_byte(val, 6)));
+    assert!(hash(&val) != hash(&zero_byte(val, 7)));
+
+    fn zero_byte(val: u64, byte: usize) -> u64 {
+        assert!(byte < 8);
+        val & !(0xff << (byte * 8))
+    }
+}
+
+#[test]
+fn test_hash_no_bytes_dropped_32() {
+    let val = 0xdeadbeef_u32;
+
+    assert!(hash(&val) != hash(&zero_byte(val, 0)));
+    assert!(hash(&val) != hash(&zero_byte(val, 1)));
+    assert!(hash(&val) != hash(&zero_byte(val, 2)));
+    assert!(hash(&val) != hash(&zero_byte(val, 3)));
+
+    fn zero_byte(val: u32, byte: usize) -> u32 {
+        assert!(byte < 4);
+        val & !(0xff << (byte * 8))
+    }
+}
+
+#[test]
+fn test_hash_no_concat_alias() {
+    let s = ("aa", "bb");
+    let t = ("aabb", "");
+    let u = ("a", "abb");
+
+    assert!(s != t && t != u);
+    assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
+
+    let u = [1, 0, 0, 0];
+    let v = (&u[..1], &u[1..3], &u[3..]);
+    let w = (&u[..], &u[4..4], &u[4..4]);
+
+    assert!(v != w);
+    assert!(hash(&v) != hash(&w));
+}
+
+#[test]
+fn test_write_short_works() {
+    let test_usize = 0xd0c0b0a0usize;
+    let mut h1 = SipHasher24::new();
+    h1.write_usize(test_usize);
+    h1.write(b"bytes");
+    h1.write(b"string");
+    h1.write_u8(0xFFu8);
+    h1.write_u8(0x01u8);
+    let mut h2 = SipHasher24::new();
+    h2.write(unsafe {
+        slice::from_raw_parts(&test_usize as *const _ as *const u8,
+                              mem::size_of::<usize>())
+    });
+    h2.write(b"bytes");
+    h2.write(b"string");
+    h2.write(&[0xFFu8, 0x01u8]);
+    assert_eq!(h1.finish(), h2.finish());
+}
diff --git a/src/libcore/tests/intrinsics.rs b/src/libcore/tests/intrinsics.rs
new file mode 100644
index 00000000000..2b380abf63c
--- /dev/null
+++ b/src/libcore/tests/intrinsics.rs
@@ -0,0 +1,30 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::any::TypeId;
+
+#[test]
+fn test_typeid_sized_types() {
+    struct X; struct Y(u32);
+
+    assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+    assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+    assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
+
+#[test]
+fn test_typeid_unsized_types() {
+    trait Z {}
+    struct X(str); struct Y(Z + 'static);
+
+    assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+    assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+    assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
new file mode 100644
index 00000000000..08442f9bcbf
--- /dev/null
+++ b/src/libcore/tests/iter.rs
@@ -0,0 +1,1084 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::iter::*;
+use core::{i8, i16, isize};
+use core::usize;
+
+#[test]
+fn test_lt() {
+    let empty: [isize; 0] = [];
+    let xs = [1,2,3];
+    let ys = [1,2,0];
+
+    assert!(!xs.iter().lt(ys.iter()));
+    assert!(!xs.iter().le(ys.iter()));
+    assert!( xs.iter().gt(ys.iter()));
+    assert!( xs.iter().ge(ys.iter()));
+
+    assert!( ys.iter().lt(xs.iter()));
+    assert!( ys.iter().le(xs.iter()));
+    assert!(!ys.iter().gt(xs.iter()));
+    assert!(!ys.iter().ge(xs.iter()));
+
+    assert!( empty.iter().lt(xs.iter()));
+    assert!( empty.iter().le(xs.iter()));
+    assert!(!empty.iter().gt(xs.iter()));
+    assert!(!empty.iter().ge(xs.iter()));
+
+    // Sequence with NaN
+    let u = [1.0f64, 2.0];
+    let v = [0.0f64/0.0, 3.0];
+
+    assert!(!u.iter().lt(v.iter()));
+    assert!(!u.iter().le(v.iter()));
+    assert!(!u.iter().gt(v.iter()));
+    assert!(!u.iter().ge(v.iter()));
+
+    let a = [0.0f64/0.0];
+    let b = [1.0f64];
+    let c = [2.0f64];
+
+    assert!(a.iter().lt(b.iter()) == (a[0] <  b[0]));
+    assert!(a.iter().le(b.iter()) == (a[0] <= b[0]));
+    assert!(a.iter().gt(b.iter()) == (a[0] >  b[0]));
+    assert!(a.iter().ge(b.iter()) == (a[0] >= b[0]));
+
+    assert!(c.iter().lt(b.iter()) == (c[0] <  b[0]));
+    assert!(c.iter().le(b.iter()) == (c[0] <= b[0]));
+    assert!(c.iter().gt(b.iter()) == (c[0] >  b[0]));
+    assert!(c.iter().ge(b.iter()) == (c[0] >= b[0]));
+}
+
+#[test]
+fn test_multi_iter() {
+    let xs = [1,2,3,4];
+    let ys = [4,3,2,1];
+    assert!(xs.iter().eq(ys.iter().rev()));
+    assert!(xs.iter().lt(xs.iter().skip(2)));
+}
+
+#[test]
+fn test_counter_from_iter() {
+    let it = (0..).step_by(5).take(10);
+    let xs: Vec<isize> = FromIterator::from_iter(it);
+    assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+}
+
+#[test]
+fn test_iterator_chain() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+    let it = xs.iter().chain(&ys);
+    let mut i = 0;
+    for &x in it {
+        assert_eq!(x, expected[i]);
+        i += 1;
+    }
+    assert_eq!(i, expected.len());
+
+    let ys = (30..).step_by(10).take(4);
+    let it = xs.iter().cloned().chain(ys);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, expected[i]);
+        i += 1;
+    }
+    assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_iterator_chain_nth() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+    for (i, x) in expected.iter().enumerate() {
+        assert_eq!(Some(x), xs.iter().chain(&ys).nth(i));
+    }
+    assert_eq!(zs.iter().chain(&xs).nth(0), Some(&0));
+
+    let mut it = xs.iter().chain(&zs);
+    assert_eq!(it.nth(5), Some(&5));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_chain_last() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    assert_eq!(xs.iter().chain(&ys).last(), Some(&60));
+    assert_eq!(zs.iter().chain(&ys).last(), Some(&60));
+    assert_eq!(ys.iter().chain(&zs).last(), Some(&60));
+    assert_eq!(zs.iter().chain(&zs).last(), None);
+}
+
+#[test]
+fn test_iterator_chain_count() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    assert_eq!(xs.iter().chain(&ys).count(), 10);
+    assert_eq!(zs.iter().chain(&ys).count(), 4);
+}
+
+#[test]
+fn test_iterator_chain_find() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let mut iter = xs.iter().chain(&ys);
+    assert_eq!(iter.find(|&&i| i == 4), Some(&4));
+    assert_eq!(iter.next(), Some(&5));
+    assert_eq!(iter.find(|&&i| i == 40), Some(&40));
+    assert_eq!(iter.next(), Some(&50));
+    assert_eq!(iter.find(|&&i| i == 100), None);
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_filter_map() {
+    let it = (0..).step_by(1).take(10)
+        .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
+    assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
+}
+
+#[test]
+fn test_iterator_enumerate() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let it = xs.iter().enumerate();
+    for (i, &x) in it {
+        assert_eq!(i, x);
+    }
+}
+
+#[test]
+fn test_iterator_enumerate_nth() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    for (i, &x) in xs.iter().enumerate() {
+        assert_eq!(i, x);
+    }
+
+    let mut it = xs.iter().enumerate();
+    while let Some((i, &x)) = it.nth(0) {
+        assert_eq!(i, x);
+    }
+
+    let mut it = xs.iter().enumerate();
+    while let Some((i, &x)) = it.nth(1) {
+        assert_eq!(i, x);
+    }
+
+    let (i, &x) = xs.iter().enumerate().nth(3).unwrap();
+    assert_eq!(i, x);
+    assert_eq!(i, 3);
+}
+
+#[test]
+fn test_iterator_enumerate_count() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    assert_eq!(xs.iter().count(), 6);
+}
+
+#[test]
+fn test_iterator_filter_count() {
+    let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5);
+}
+
+#[test]
+fn test_iterator_peekable() {
+    let xs = vec![0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().cloned().peekable();
+
+    assert_eq!(it.len(), 6);
+    assert_eq!(it.peek().unwrap(), &0);
+    assert_eq!(it.len(), 6);
+    assert_eq!(it.next().unwrap(), 0);
+    assert_eq!(it.len(), 5);
+    assert_eq!(it.next().unwrap(), 1);
+    assert_eq!(it.len(), 4);
+    assert_eq!(it.next().unwrap(), 2);
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.peek().unwrap(), &3);
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.peek().unwrap(), &3);
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next().unwrap(), 3);
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next().unwrap(), 4);
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.peek().unwrap(), &5);
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next().unwrap(), 5);
+    assert_eq!(it.len(), 0);
+    assert!(it.peek().is_none());
+    assert_eq!(it.len(), 0);
+    assert!(it.next().is_none());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_peekable_count() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [10];
+    let zs: [i32; 0] = [];
+
+    assert_eq!(xs.iter().peekable().count(), 6);
+
+    let mut it = xs.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.count(), 6);
+
+    assert_eq!(ys.iter().peekable().count(), 1);
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.peek(), Some(&&10));
+    assert_eq!(it.count(), 1);
+
+    assert_eq!(zs.iter().peekable().count(), 0);
+
+    let mut it = zs.iter().peekable();
+    assert_eq!(it.peek(), None);
+
+}
+
+#[test]
+fn test_iterator_peekable_nth() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().peekable();
+
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.nth(0), Some(&0));
+    assert_eq!(it.peek(), Some(&&1));
+    assert_eq!(it.nth(1), Some(&2));
+    assert_eq!(it.peek(), Some(&&3));
+    assert_eq!(it.nth(2), Some(&5));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_peekable_last() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [0];
+
+    let mut it = xs.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.last(), Some(&5));
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.last(), Some(&0));
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.next(), Some(&0));
+    assert_eq!(it.peek(), None);
+    assert_eq!(it.last(), None);
+}
+
+/// This is an iterator that follows the Iterator contract,
+/// but it is not fused. After having returned None once, it will start
+/// producing elements if .next() is called again.
+pub struct CycleIter<'a, T: 'a> {
+    index: usize,
+    data: &'a [T],
+}
+
+pub fn cycle<T>(data: &[T]) -> CycleIter<T> {
+    CycleIter {
+        index: 0,
+        data: data,
+    }
+}
+
+impl<'a, T> Iterator for CycleIter<'a, T> {
+    type Item = &'a T;
+    fn next(&mut self) -> Option<Self::Item> {
+        let elt = self.data.get(self.index);
+        self.index += 1;
+        self.index %= 1 + self.data.len();
+        elt
+    }
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_1() {
+    // Check that the loop using .peek() terminates
+    let data = [1, 2, 3];
+    let mut iter = cycle(&data).peekable();
+
+    let mut n = 0;
+    while let Some(_) = iter.next() {
+        let is_the_last = iter.peek().is_none();
+        assert_eq!(is_the_last, n == data.len() - 1);
+        n += 1;
+        if n > data.len() { break; }
+    }
+    assert_eq!(n, data.len());
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_2() {
+    let data = [0];
+    let mut iter = cycle(&data).peekable();
+    iter.next();
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.last(), None);
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_3() {
+    let data = [0];
+    let mut iter = cycle(&data).peekable();
+    iter.peek();
+    assert_eq!(iter.nth(0), Some(&0));
+
+    let mut iter = cycle(&data).peekable();
+    iter.next();
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.nth(0), None);
+}
+
+#[test]
+fn test_iterator_take_while() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [0, 1, 2, 3, 5, 13];
+    let it = xs.iter().take_while(|&x| *x < 15);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(*x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_skip_while() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [15, 16, 17, 19];
+    let it = xs.iter().skip_while(|&x| *x < 15);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(*x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_skip() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+    let ys = [13, 15, 16, 17, 19, 20, 30];
+    let mut it = xs.iter().skip(5);
+    let mut i = 0;
+    while let Some(&x) = it.next() {
+        assert_eq!(x, ys[i]);
+        i += 1;
+        assert_eq!(it.len(), xs.len()-5-i);
+    }
+    assert_eq!(i, ys.len());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_skip_doubleended() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+    let mut it = xs.iter().rev().skip(5);
+    assert_eq!(it.next(), Some(&15));
+    assert_eq!(it.by_ref().rev().next(), Some(&0));
+    assert_eq!(it.next(), Some(&13));
+    assert_eq!(it.by_ref().rev().next(), Some(&1));
+    assert_eq!(it.next(), Some(&5));
+    assert_eq!(it.by_ref().rev().next(), Some(&2));
+    assert_eq!(it.next(), Some(&3));
+    assert_eq!(it.next(), None);
+    let mut it = xs.iter().rev().skip(5).rev();
+    assert_eq!(it.next(), Some(&0));
+    assert_eq!(it.rev().next(), Some(&15));
+    let mut it_base = xs.iter();
+    {
+        let mut it = it_base.by_ref().skip(5).rev();
+        assert_eq!(it.next(), Some(&30));
+        assert_eq!(it.next(), Some(&20));
+        assert_eq!(it.next(), Some(&19));
+        assert_eq!(it.next(), Some(&17));
+        assert_eq!(it.next(), Some(&16));
+        assert_eq!(it.next(), Some(&15));
+        assert_eq!(it.next(), Some(&13));
+        assert_eq!(it.next(), None);
+    }
+    // make sure the skipped parts have not been consumed
+    assert_eq!(it_base.next(), Some(&0));
+    assert_eq!(it_base.next(), Some(&1));
+    assert_eq!(it_base.next(), Some(&2));
+    assert_eq!(it_base.next(), Some(&3));
+    assert_eq!(it_base.next(), Some(&5));
+    assert_eq!(it_base.next(), None);
+    let it = xs.iter().skip(5).rev();
+    assert_eq!(it.last(), Some(&13));
+}
+
+#[test]
+fn test_iterator_skip_nth() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+    let mut it = xs.iter().skip(0);
+    assert_eq!(it.nth(0), Some(&0));
+    assert_eq!(it.nth(1), Some(&2));
+
+    let mut it = xs.iter().skip(5);
+    assert_eq!(it.nth(0), Some(&13));
+    assert_eq!(it.nth(1), Some(&16));
+
+    let mut it = xs.iter().skip(12);
+    assert_eq!(it.nth(0), None);
+
+}
+
+#[test]
+fn test_iterator_skip_count() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+    assert_eq!(xs.iter().skip(0).count(), 12);
+    assert_eq!(xs.iter().skip(1).count(), 11);
+    assert_eq!(xs.iter().skip(11).count(), 1);
+    assert_eq!(xs.iter().skip(12).count(), 0);
+    assert_eq!(xs.iter().skip(13).count(), 0);
+}
+
+#[test]
+fn test_iterator_skip_last() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+    assert_eq!(xs.iter().skip(0).last(), Some(&30));
+    assert_eq!(xs.iter().skip(1).last(), Some(&30));
+    assert_eq!(xs.iter().skip(11).last(), Some(&30));
+    assert_eq!(xs.iter().skip(12).last(), None);
+    assert_eq!(xs.iter().skip(13).last(), None);
+
+    let mut it = xs.iter().skip(5);
+    assert_eq!(it.next(), Some(&13));
+    assert_eq!(it.last(), Some(&30));
+}
+
+#[test]
+fn test_iterator_take() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [0, 1, 2, 3, 5];
+    let mut it = xs.iter().take(5);
+    let mut i = 0;
+    assert_eq!(it.len(), 5);
+    while let Some(&x) = it.next() {
+        assert_eq!(x, ys[i]);
+        i += 1;
+        assert_eq!(it.len(), 5-i);
+    }
+    assert_eq!(i, ys.len());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_take_nth() {
+    let xs = [0, 1, 2, 4, 5];
+    let mut it = xs.iter();
+    {
+        let mut take = it.by_ref().take(3);
+        let mut i = 0;
+        while let Some(&x) = take.nth(0) {
+            assert_eq!(x, i);
+            i += 1;
+        }
+    }
+    assert_eq!(it.nth(1), Some(&5));
+    assert_eq!(it.nth(0), None);
+
+    let xs = [0, 1, 2, 3, 4];
+    let mut it = xs.iter().take(7);
+    let mut i = 1;
+    while let Some(&x) = it.nth(1) {
+        assert_eq!(x, i);
+        i += 2;
+    }
+}
+
+#[test]
+fn test_iterator_take_short() {
+    let xs = [0, 1, 2, 3];
+    let ys = [0, 1, 2, 3];
+    let mut it = xs.iter().take(5);
+    let mut i = 0;
+    assert_eq!(it.len(), 4);
+    while let Some(&x) = it.next() {
+        assert_eq!(x, ys[i]);
+        i += 1;
+        assert_eq!(it.len(), 4-i);
+    }
+    assert_eq!(i, ys.len());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_scan() {
+    // test the type inference
+    fn add(old: &mut isize, new: &usize) -> Option<f64> {
+        *old += *new as isize;
+        Some(*old as f64)
+    }
+    let xs = [0, 1, 2, 3, 4];
+    let ys = [0f64, 1.0, 3.0, 6.0, 10.0];
+
+    let it = xs.iter().scan(0, add);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_flat_map() {
+    let xs = [0, 3, 6];
+    let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_inspect() {
+    let xs = [1, 2, 3, 4];
+    let mut n = 0;
+
+    let ys = xs.iter()
+               .cloned()
+               .inspect(|_| n += 1)
+               .collect::<Vec<usize>>();
+
+    assert_eq!(n, xs.len());
+    assert_eq!(&xs[..], &ys[..]);
+}
+
+#[test]
+fn test_cycle() {
+    let cycle_len = 3;
+    let it = (0..).step_by(1).take(cycle_len).cycle();
+    assert_eq!(it.size_hint(), (usize::MAX, None));
+    for (i, x) in it.take(100).enumerate() {
+        assert_eq!(i % cycle_len, x);
+    }
+
+    let mut it = (0..).step_by(1).take(0).cycle();
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_nth() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+    }
+    assert_eq!(v.iter().nth(v.len()), None);
+}
+
+#[test]
+fn test_iterator_last() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().last().unwrap(), &4);
+    assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_len() {
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().count(), 4);
+    assert_eq!(v[..10].iter().count(), 10);
+    assert_eq!(v[..0].iter().count(), 0);
+}
+
+#[test]
+fn test_iterator_sum() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().sum::<i32>(), 6);
+    assert_eq!(v.iter().cloned().sum::<i32>(), 55);
+    assert_eq!(v[..0].iter().cloned().sum::<i32>(), 0);
+}
+
+#[test]
+fn test_iterator_sum_result() {
+    let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Ok(10));
+    let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(()));
+}
+
+#[test]
+fn test_iterator_product() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().product::<i32>(), 0);
+    assert_eq!(v[1..5].iter().cloned().product::<i32>(), 24);
+    assert_eq!(v[..0].iter().cloned().product::<i32>(), 1);
+}
+
+#[test]
+fn test_iterator_product_result() {
+    let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Ok(24));
+    let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Err(()));
+}
+
+#[test]
+fn test_iterator_max() {
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().max(), Some(3));
+    assert_eq!(v.iter().cloned().max(), Some(10));
+    assert_eq!(v[..0].iter().cloned().max(), None);
+}
+
+#[test]
+fn test_iterator_min() {
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().min(), Some(0));
+    assert_eq!(v.iter().cloned().min(), Some(0));
+    assert_eq!(v[..0].iter().cloned().min(), None);
+}
+
+#[test]
+fn test_iterator_size_hint() {
+    let c = (0..).step_by(1);
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    let v2 = &[10, 11, 12];
+    let vi = v.iter();
+
+    assert_eq!(c.size_hint(), (usize::MAX, None));
+    assert_eq!(vi.clone().size_hint(), (10, Some(10)));
+
+    assert_eq!(c.clone().take(5).size_hint(), (5, Some(5)));
+    assert_eq!(c.clone().skip(5).size_hint().1, None);
+    assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
+    assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
+    assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None));
+    assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None));
+    assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
+    assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
+    assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
+    assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None));
+    assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
+
+    assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5)));
+    assert_eq!(vi.clone().take(12).size_hint(), (10, Some(10)));
+    assert_eq!(vi.clone().skip(3).size_hint(), (7, Some(7)));
+    assert_eq!(vi.clone().skip(12).size_hint(), (0, Some(0)));
+    assert_eq!(vi.clone().take_while(|_| false).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().skip_while(|_| false).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
+    assert_eq!(vi.clone().chain(v2).size_hint(), (13, Some(13)));
+    assert_eq!(vi.clone().zip(v2).size_hint(), (3, Some(3)));
+    assert_eq!(vi.clone().scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
+    assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
+}
+
+#[test]
+fn test_collect() {
+    let a = vec![1, 2, 3, 4, 5];
+    let b: Vec<isize> = a.iter().cloned().collect();
+    assert!(a == b);
+}
+
+#[test]
+fn test_all() {
+    let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
+    assert!(v.iter().all(|&x| x < 10));
+    assert!(!v.iter().all(|&x| x % 2 == 0));
+    assert!(!v.iter().all(|&x| x > 100));
+    assert!(v[..0].iter().all(|_| panic!()));
+}
+
+#[test]
+fn test_any() {
+    let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
+    assert!(v.iter().any(|&x| x < 10));
+    assert!(v.iter().any(|&x| x % 2 == 0));
+    assert!(!v.iter().any(|&x| x > 100));
+    assert!(!v[..0].iter().any(|_| panic!()));
+}
+
+#[test]
+fn test_find() {
+    let v: &[isize] = &[1, 3, 9, 27, 103, 14, 11];
+    assert_eq!(*v.iter().find(|&&x| x & 1 == 0).unwrap(), 14);
+    assert_eq!(*v.iter().find(|&&x| x % 3 == 0).unwrap(), 3);
+    assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
+}
+
+#[test]
+fn test_position() {
+    let v = &[1, 3, 9, 27, 103, 14, 11];
+    assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5);
+    assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1);
+    assert!(v.iter().position(|x| *x % 12 == 0).is_none());
+}
+
+#[test]
+fn test_count() {
+    let xs = &[1, 2, 2, 1, 5, 9, 0, 2];
+    assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3);
+    assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1);
+    assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0);
+}
+
+#[test]
+fn test_max_by_key() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
+}
+
+#[test]
+fn test_max_by() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
+}
+
+#[test]
+fn test_min_by_key() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
+}
+
+#[test]
+fn test_min_by() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
+}
+
+#[test]
+fn test_by_ref() {
+    let mut xs = 0..10;
+    // sum the first five values
+    let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
+    assert_eq!(partial_sum, 10);
+    assert_eq!(xs.next(), Some(5));
+}
+
+#[test]
+fn test_rev() {
+    let xs = [2, 4, 6, 8, 10, 12, 14, 16];
+    let mut it = xs.iter();
+    it.next();
+    it.next();
+    assert!(it.rev().cloned().collect::<Vec<isize>>() ==
+            vec![16, 14, 12, 10, 8, 6]);
+}
+
+#[test]
+fn test_cloned() {
+    let xs = [2, 4, 6, 8];
+
+    let mut it = xs.iter().cloned();
+    assert_eq!(it.len(), 4);
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next(), Some(4));
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next_back(), Some(8));
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next_back(), Some(6));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_map() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().map(|&x| x * -1);
+    assert_eq!(it.next(), Some(-1));
+    assert_eq!(it.next(), Some(-2));
+    assert_eq!(it.next_back(), Some(-6));
+    assert_eq!(it.next_back(), Some(-5));
+    assert_eq!(it.next(), Some(-3));
+    assert_eq!(it.next_back(), Some(-4));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_enumerate() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().cloned().enumerate();
+    assert_eq!(it.next(), Some((0, 1)));
+    assert_eq!(it.next(), Some((1, 2)));
+    assert_eq!(it.next_back(), Some((5, 6)));
+    assert_eq!(it.next_back(), Some((4, 5)));
+    assert_eq!(it.next_back(), Some((3, 4)));
+    assert_eq!(it.next_back(), Some((2, 3)));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_zip() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let ys = [1, 2, 3, 7];
+    let a = xs.iter().cloned();
+    let b = ys.iter().cloned();
+    let mut it = a.zip(b);
+    assert_eq!(it.next(), Some((1, 1)));
+    assert_eq!(it.next(), Some((2, 2)));
+    assert_eq!(it.next_back(), Some((4, 7)));
+    assert_eq!(it.next_back(), Some((3, 3)));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_filter() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().filter(|&x| *x & 1 == 0);
+    assert_eq!(it.next_back().unwrap(), &6);
+    assert_eq!(it.next_back().unwrap(), &4);
+    assert_eq!(it.next().unwrap(), &2);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_filter_map() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None });
+    assert_eq!(it.next_back().unwrap(), 12);
+    assert_eq!(it.next_back().unwrap(), 8);
+    assert_eq!(it.next().unwrap(), 4);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_chain() {
+    let xs = [1, 2, 3, 4, 5];
+    let ys = [7, 9, 11];
+    let mut it = xs.iter().chain(&ys).rev();
+    assert_eq!(it.next().unwrap(), &11);
+    assert_eq!(it.next().unwrap(), &9);
+    assert_eq!(it.next_back().unwrap(), &1);
+    assert_eq!(it.next_back().unwrap(), &2);
+    assert_eq!(it.next_back().unwrap(), &3);
+    assert_eq!(it.next_back().unwrap(), &4);
+    assert_eq!(it.next_back().unwrap(), &5);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back(), None);
+
+
+    // test that .chain() is well behaved with an unfused iterator
+    struct CrazyIterator(bool);
+    impl CrazyIterator { fn new() -> CrazyIterator { CrazyIterator(false) } }
+    impl Iterator for CrazyIterator {
+        type Item = i32;
+        fn next(&mut self) -> Option<i32> {
+            if self.0 { Some(99) } else { self.0 = true; None }
+        }
+    }
+
+    impl DoubleEndedIterator for CrazyIterator {
+        fn next_back(&mut self) -> Option<i32> {
+            self.next()
+        }
+    }
+
+    assert_eq!(CrazyIterator::new().chain(0..10).rev().last(), Some(0));
+    assert!((0..10).chain(CrazyIterator::new()).rev().any(|i| i == 0));
+}
+
+#[test]
+fn test_rposition() {
+    fn f(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+    fn g(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'd' }
+    let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+    assert_eq!(v.iter().rposition(f), Some(3));
+    assert!(v.iter().rposition(g).is_none());
+}
+
+#[test]
+#[should_panic]
+fn test_rposition_panic() {
+    let v: [(Box<_>, Box<_>); 4] =
+        [(box 0, box 0), (box 0, box 0),
+         (box 0, box 0), (box 0, box 0)];
+    let mut i = 0;
+    v.iter().rposition(|_elt| {
+        if i == 2 {
+            panic!()
+        }
+        i += 1;
+        false
+    });
+}
+
+
+#[test]
+fn test_double_ended_flat_map() {
+    let u = [0,1];
+    let v = [5,6,7,8];
+    let mut it = u.iter().flat_map(|x| &v[*x..v.len()]);
+    assert_eq!(it.next_back().unwrap(), &8);
+    assert_eq!(it.next().unwrap(),      &5);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back().unwrap(), &6);
+    assert_eq!(it.next_back().unwrap(), &8);
+    assert_eq!(it.next().unwrap(),      &6);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back(), None);
+    assert_eq!(it.next(),      None);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_range() {
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
+    for _ in (10..0).rev() {
+        panic!("unreachable");
+    }
+
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
+    for _ in (10..0).rev() {
+        panic!("unreachable");
+    }
+}
+
+#[test]
+fn test_range() {
+    assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+    assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
+    assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
+    assert_eq!((200..-5).count(), 0);
+    assert_eq!((200..-5).rev().count(), 0);
+    assert_eq!((200..200).count(), 0);
+    assert_eq!((200..200).rev().count(), 0);
+
+    assert_eq!((0..100).size_hint(), (100, Some(100)));
+    // this test is only meaningful when sizeof usize < sizeof u64
+    assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
+    assert_eq!((-10..-1).size_hint(), (9, Some(9)));
+    assert_eq!((-1..-10).size_hint(), (0, Some(0)));
+
+    assert_eq!((-70..58).size_hint(), (128, Some(128)));
+    assert_eq!((-128..127).size_hint(), (255, Some(255)));
+    assert_eq!((-2..isize::MAX).size_hint(),
+               (isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
+}
+
+#[test]
+fn test_range_step() {
+    assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]);
+    assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
+    assert_eq!((20..0).step_by(-6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
+    assert_eq!((200..255).step_by(50).collect::<Vec<u8>>(), [200, 250]);
+    assert_eq!((200..-5).step_by(1).collect::<Vec<isize>>(), []);
+    assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
+
+    assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20)));
+    assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1)));
+    assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4)));
+    assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4)));
+    assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4)));
+    assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0)));
+    assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0)));
+    assert_eq!((0..1).step_by(0).size_hint(), (0, None));
+    assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2)));
+    assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3)));
+    assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
+}
+
+#[test]
+fn test_repeat() {
+    let mut it = repeat(42);
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), Some(42));
+}
+
+#[test]
+fn test_fuse() {
+    let mut it = 0..3;
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next(), Some(1));
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_fuse_nth() {
+    let xs = [0, 1, 2];
+    let mut it = xs.iter();
+
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.nth(2), Some(&2));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.nth(2), None);
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_fuse_last() {
+    let xs = [0, 1, 2];
+    let it = xs.iter();
+
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.last(), Some(&2));
+}
+
+#[test]
+fn test_fuse_count() {
+    let xs = [0, 1, 2];
+    let it = xs.iter();
+
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.count(), 3);
+    // Can't check len now because count consumes.
+}
+
+#[test]
+fn test_once() {
+    let mut it = once(42);
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_empty() {
+    let mut it = empty::<i32>();
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_chain_fold() {
+    let xs = [1, 2, 3];
+    let ys = [1, 2, 0];
+
+    let mut iter = xs.iter().chain(&ys);
+    iter.next();
+    let mut result = Vec::new();
+    iter.fold((), |(), &elt| result.push(elt));
+    assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
+}
+
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
new file mode 100644
index 00000000000..d92c378160d
--- /dev/null
+++ b/src/libcore/tests/lib.rs
@@ -0,0 +1,63 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(warnings)]
+
+#![feature(box_syntax)]
+#![feature(char_escape_debug)]
+#![feature(const_fn)]
+#![feature(core_private_bignum)]
+#![feature(core_private_diy_float)]
+#![feature(dec2flt)]
+#![feature(decode_utf8)]
+#![feature(fixed_size_array)]
+#![feature(flt2dec)]
+#![feature(fmt_internals)]
+#![feature(libc)]
+#![feature(nonzero)]
+#![feature(rand)]
+#![feature(raw)]
+#![feature(sip_hash_13)]
+#![feature(slice_patterns)]
+#![feature(sort_internals)]
+#![feature(sort_unstable)]
+#![feature(step_by)]
+#![feature(test)]
+#![feature(try_from)]
+#![feature(unicode)]
+#![feature(unique)]
+
+extern crate core;
+extern crate test;
+extern crate libc;
+extern crate std_unicode;
+extern crate rand;
+
+mod any;
+mod array;
+mod atomic;
+mod cell;
+mod char;
+mod clone;
+mod cmp;
+mod fmt;
+mod hash;
+mod intrinsics;
+mod iter;
+mod mem;
+mod nonzero;
+mod num;
+mod ops;
+mod option;
+mod ptr;
+mod result;
+mod slice;
+mod str;
+mod tuple;
diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs
new file mode 100644
index 00000000000..86e59c736ba
--- /dev/null
+++ b/src/libcore/tests/mem.rs
@@ -0,0 +1,123 @@
+// Copyright 2014-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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::mem::*;
+
+#[test]
+fn size_of_basic() {
+    assert_eq!(size_of::<u8>(), 1);
+    assert_eq!(size_of::<u16>(), 2);
+    assert_eq!(size_of::<u32>(), 4);
+    assert_eq!(size_of::<u64>(), 8);
+}
+
+#[test]
+#[cfg(target_pointer_width = "16")]
+fn size_of_16() {
+    assert_eq!(size_of::<usize>(), 2);
+    assert_eq!(size_of::<*const usize>(), 2);
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn size_of_32() {
+    assert_eq!(size_of::<usize>(), 4);
+    assert_eq!(size_of::<*const usize>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn size_of_64() {
+    assert_eq!(size_of::<usize>(), 8);
+    assert_eq!(size_of::<*const usize>(), 8);
+}
+
+#[test]
+fn size_of_val_basic() {
+    assert_eq!(size_of_val(&1u8), 1);
+    assert_eq!(size_of_val(&1u16), 2);
+    assert_eq!(size_of_val(&1u32), 4);
+    assert_eq!(size_of_val(&1u64), 8);
+}
+
+#[test]
+fn align_of_basic() {
+    assert_eq!(align_of::<u8>(), 1);
+    assert_eq!(align_of::<u16>(), 2);
+    assert_eq!(align_of::<u32>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "16")]
+fn align_of_16() {
+    assert_eq!(align_of::<usize>(), 2);
+    assert_eq!(align_of::<*const usize>(), 2);
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn align_of_32() {
+    assert_eq!(align_of::<usize>(), 4);
+    assert_eq!(align_of::<*const usize>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn align_of_64() {
+    assert_eq!(align_of::<usize>(), 8);
+    assert_eq!(align_of::<*const usize>(), 8);
+}
+
+#[test]
+fn align_of_val_basic() {
+    assert_eq!(align_of_val(&1u8), 1);
+    assert_eq!(align_of_val(&1u16), 2);
+    assert_eq!(align_of_val(&1u32), 4);
+}
+
+#[test]
+fn test_swap() {
+    let mut x = 31337;
+    let mut y = 42;
+    swap(&mut x, &mut y);
+    assert_eq!(x, 42);
+    assert_eq!(y, 31337);
+}
+
+#[test]
+fn test_replace() {
+    let mut x = Some("test".to_string());
+    let y = replace(&mut x, None);
+    assert!(x.is_none());
+    assert!(y.is_some());
+}
+
+#[test]
+fn test_transmute_copy() {
+    assert_eq!(1, unsafe { transmute_copy(&1) });
+}
+
+#[test]
+fn test_transmute() {
+    trait Foo { fn dummy(&self) { } }
+    impl Foo for isize {}
+
+    let a = box 100isize as Box<Foo>;
+    unsafe {
+        let x: ::core::raw::TraitObject = transmute(a);
+        assert!(*(x.data as *const isize) == 100);
+        let _x: Box<Foo> = transmute(x);
+    }
+
+    unsafe {
+        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
+    }
+}
+
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
new file mode 100644
index 00000000000..7a367ddeec8
--- /dev/null
+++ b/src/libcore/tests/nonzero.rs
@@ -0,0 +1,100 @@
+// Copyright 2012-2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::nonzero::NonZero;
+use core::option::Option;
+use core::option::Option::{Some, None};
+use std::mem::size_of;
+
+#[test]
+fn test_create_nonzero_instance() {
+    let _a = unsafe {
+        NonZero::new(21)
+    };
+}
+
+#[test]
+fn test_size_nonzero_in_option() {
+    assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>());
+}
+
+#[test]
+fn test_match_on_nonzero_option() {
+    let a = Some(unsafe {
+        NonZero::new(42)
+    });
+    match a {
+        Some(val) => assert_eq!(*val, 42),
+        None => panic!("unexpected None while matching on Some(NonZero(_))")
+    }
+
+    match unsafe { Some(NonZero::new(43)) } {
+        Some(val) => assert_eq!(*val, 43),
+        None => panic!("unexpected None while matching on Some(NonZero(_))")
+    }
+}
+
+#[test]
+fn test_match_option_empty_vec() {
+    let a: Option<Vec<isize>> = Some(vec![]);
+    match a {
+        None => panic!("unexpected None while matching on Some(vec![])"),
+        _ => {}
+    }
+}
+
+#[test]
+fn test_match_option_vec() {
+    let a = Some(vec![1, 2, 3, 4]);
+    match a {
+        Some(v) => assert_eq!(v, [1, 2, 3, 4]),
+        None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
+    }
+}
+
+#[test]
+fn test_match_option_rc() {
+    use std::rc::Rc;
+
+    let five = Rc::new(5);
+    match Some(five) {
+        Some(r) => assert_eq!(*r, 5),
+        None => panic!("unexpected None while matching on Some(Rc::new(5))")
+    }
+}
+
+#[test]
+fn test_match_option_arc() {
+    use std::sync::Arc;
+
+    let five = Arc::new(5);
+    match Some(five) {
+        Some(a) => assert_eq!(*a, 5),
+        None => panic!("unexpected None while matching on Some(Arc::new(5))")
+    }
+}
+
+#[test]
+fn test_match_option_empty_string() {
+    let a = Some(String::new());
+    match a {
+        None => panic!("unexpected None while matching on Some(String::new())"),
+        _ => {}
+    }
+}
+
+#[test]
+fn test_match_option_string() {
+    let five = "Five".to_string();
+    match Some(five) {
+        Some(s) => assert_eq!(s, "Five"),
+        None => panic!("unexpected None while matching on Some(String { ... })")
+    }
+}
diff --git a/src/libcore/tests/num/bignum.rs b/src/libcore/tests/num/bignum.rs
new file mode 100644
index 00000000000..58a9dd1b128
--- /dev/null
+++ b/src/libcore/tests/num/bignum.rs
@@ -0,0 +1,249 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use core::num::bignum::tests::Big8x3 as Big;
+
+#[test]
+#[should_panic]
+fn test_from_u64_overflow() {
+    Big::from_u64(0x1000000);
+}
+
+#[test]
+fn test_add() {
+    assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7));
+    assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3));
+    assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3));
+    assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001));
+    assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665));
+    assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_1() {
+    Big::from_small(1).add(&Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_2() {
+    Big::from_u64(0xffffff).add(&Big::from_small(1));
+}
+
+#[test]
+fn test_add_small() {
+    assert_eq!(*Big::from_small(3).add_small(4), Big::from_small(7));
+    assert_eq!(*Big::from_small(3).add_small(0), Big::from_small(3));
+    assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3));
+    assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257));
+    assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000));
+    assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033));
+    assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165));
+}
+
+#[test]
+#[should_panic]
+fn test_add_small_overflow() {
+    Big::from_u64(0xffffff).add_small(1);
+}
+
+#[test]
+fn test_sub() {
+    assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_1() {
+    Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_2() {
+    Big::from_small(0).sub(&Big::from_u64(0x123456));
+}
+
+#[test]
+fn test_mul_small() {
+    assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
+    assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
+    assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_small_overflow() {
+    Big::from_u64(0x800000).mul_small(2);
+}
+
+#[test]
+fn test_mul_pow2() {
+    assert_eq!(*Big::from_small(0x7).mul_pow2(4), Big::from_small(0x70));
+    assert_eq!(*Big::from_small(0xff).mul_pow2(1), Big::from_u64(0x1fe));
+    assert_eq!(*Big::from_small(0xff).mul_pow2(12), Big::from_u64(0xff000));
+    assert_eq!(*Big::from_small(0x1).mul_pow2(23), Big::from_u64(0x800000));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(0), Big::from_u64(0x123));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(7), Big::from_u64(0x9180));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(15), Big::from_u64(0x918000));
+    assert_eq!(*Big::from_small(0).mul_pow2(23), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_1() {
+    Big::from_u64(0x1).mul_pow2(24);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_2() {
+    Big::from_u64(0x123).mul_pow2(16);
+}
+
+#[test]
+fn test_mul_pow5() {
+    assert_eq!(*Big::from_small(42).mul_pow5(0), Big::from_small(42));
+    assert_eq!(*Big::from_small(1).mul_pow5(2), Big::from_small(25));
+    assert_eq!(*Big::from_small(1).mul_pow5(4), Big::from_u64(25 * 25));
+    assert_eq!(*Big::from_small(4).mul_pow5(3), Big::from_u64(500));
+    assert_eq!(*Big::from_small(140).mul_pow5(2), Big::from_u64(25 * 140));
+    assert_eq!(*Big::from_small(25).mul_pow5(1), Big::from_small(125));
+    assert_eq!(*Big::from_small(125).mul_pow5(7), Big::from_u64(9765625));
+    assert_eq!(*Big::from_small(0).mul_pow5(127), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_1() {
+    Big::from_small(1).mul_pow5(12);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_2() {
+    Big::from_small(230).mul_pow5(8);
+}
+
+#[test]
+fn test_mul_digits() {
+    assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15));
+    assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01));
+    assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
+    assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
+    assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
+    assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
+    assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_1() {
+    Big::from_u64(0x800000).mul_digits(&[2]);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_2() {
+    Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
+}
+
+#[test]
+fn test_div_rem_small() {
+    let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r);
+    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
+    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
+    assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
+    assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
+               (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
+    assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
+               (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
+}
+
+#[test]
+fn test_div_rem() {
+    fn div_rem(n: u64, d: u64) -> (Big, Big) {
+        let mut q = Big::from_small(42);
+        let mut r = Big::from_small(42);
+        Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
+        (q, r)
+    }
+    assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
+    assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
+    assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
+    assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
+    assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
+    assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
+    assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
+    assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
+    assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
+}
+
+#[test]
+fn test_is_zero() {
+    assert!(Big::from_small(0).is_zero());
+    assert!(!Big::from_small(3).is_zero());
+    assert!(!Big::from_u64(0x123).is_zero());
+    assert!(!Big::from_u64(0xffffff).sub(&Big::from_u64(0xfffffe)).is_zero());
+    assert!(Big::from_u64(0xffffff).sub(&Big::from_u64(0xffffff)).is_zero());
+}
+
+#[test]
+fn test_get_bit() {
+    let x = Big::from_small(0b1101);
+    assert_eq!(x.get_bit(0), 1);
+    assert_eq!(x.get_bit(1), 0);
+    assert_eq!(x.get_bit(2), 1);
+    assert_eq!(x.get_bit(3), 1);
+    let y = Big::from_u64(1 << 15);
+    assert_eq!(y.get_bit(14), 0);
+    assert_eq!(y.get_bit(15), 1);
+    assert_eq!(y.get_bit(16), 0);
+}
+
+#[test]
+#[should_panic]
+fn test_get_bit_out_of_range() {
+    Big::from_small(42).get_bit(24);
+}
+
+#[test]
+fn test_bit_length() {
+    assert_eq!(Big::from_small(0).bit_length(), 0);
+    assert_eq!(Big::from_small(1).bit_length(), 1);
+    assert_eq!(Big::from_small(5).bit_length(), 3);
+    assert_eq!(Big::from_small(0x18).bit_length(), 5);
+    assert_eq!(Big::from_u64(0x4073).bit_length(), 15);
+    assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
+}
+
+#[test]
+fn test_ord() {
+    assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
+    assert!(Big::from_u64(0x102) < Big::from_u64(0x201));
+}
+
+#[test]
+fn test_fmt() {
+    assert_eq!(format!("{:?}", Big::from_u64(0)), "0x0");
+    assert_eq!(format!("{:?}", Big::from_u64(0x1)), "0x1");
+    assert_eq!(format!("{:?}", Big::from_u64(0x12)), "0x12");
+    assert_eq!(format!("{:?}", Big::from_u64(0x123)), "0x1_23");
+    assert_eq!(format!("{:?}", Big::from_u64(0x1234)), "0x12_34");
+    assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45");
+    assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56");
+}
+
diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs
new file mode 100644
index 00000000000..5d546c643e7
--- /dev/null
+++ b/src/libcore/tests/num/dec2flt/mod.rs
@@ -0,0 +1,145 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(overflowing_literals)]
+
+use std::{i64, f32, f64};
+
+mod parse;
+mod rawfp;
+
+// Take a float literal, turn it into a string in various ways (that are all trusted
+// to be correct) and see if those strings are parsed back to the value of the literal.
+// Requires a *polymorphic literal*, i.e. one that can serve as f64 as well as f32.
+macro_rules! test_literal {
+    ($x: expr) => ({
+        let x32: f32 = $x;
+        let x64: f64 = $x;
+        let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
+        for input in inputs {
+            assert_eq!(input.parse(), Ok(x64));
+            assert_eq!(input.parse(), Ok(x32));
+            let neg_input = &format!("-{}", input);
+            assert_eq!(neg_input.parse(), Ok(-x64));
+            assert_eq!(neg_input.parse(), Ok(-x32));
+        }
+    })
+}
+
+#[test]
+fn ordinary() {
+    test_literal!(1.0);
+    test_literal!(3e-5);
+    test_literal!(0.1);
+    test_literal!(12345.);
+    test_literal!(0.9999999);
+    test_literal!(2.2250738585072014e-308);
+}
+
+#[test]
+fn special_code_paths() {
+    test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand
+    test_literal!(101e-33); // Triggers the tricky underflow case in AlgorithmM (for f32)
+    test_literal!(1e23); // Triggers AlgorithmR
+    test_literal!(2075e23); // Triggers another path through AlgorithmR
+    test_literal!(8713e-23); // ... and yet another.
+}
+
+#[test]
+fn large() {
+    test_literal!(1e300);
+    test_literal!(123456789.34567e250);
+    test_literal!(943794359898089732078308743689303290943794359843568973207830874368930329.);
+}
+
+#[test]
+fn subnormals() {
+    test_literal!(5e-324);
+    test_literal!(91e-324);
+    test_literal!(1e-322);
+    test_literal!(13245643e-320);
+    test_literal!(2.22507385851e-308);
+    test_literal!(2.1e-308);
+    test_literal!(4.9406564584124654e-324);
+}
+
+#[test]
+fn infinity() {
+    test_literal!(1e400);
+    test_literal!(1e309);
+    test_literal!(2e308);
+    test_literal!(1.7976931348624e308);
+}
+
+#[test]
+fn zero() {
+    test_literal!(0.0);
+    test_literal!(1e-325);
+    test_literal!(1e-326);
+    test_literal!(1e-500);
+}
+
+#[test]
+fn fast_path_correct() {
+    // This number triggers the fast path and is handled incorrectly when compiling on
+    // x86 without SSE2 (i.e., using the x87 FPU stack).
+    test_literal!(1.448997445238699);
+}
+
+#[test]
+fn lonely_dot() {
+    assert!(".".parse::<f32>().is_err());
+    assert!(".".parse::<f64>().is_err());
+}
+
+#[test]
+fn lonely_sign() {
+    assert!("+".parse::<f32>().is_err());
+    assert!("-".parse::<f64>().is_err());
+}
+
+#[test]
+fn whitespace() {
+    assert!(" 1.0".parse::<f32>().is_err());
+    assert!("1.0 ".parse::<f64>().is_err());
+}
+
+#[test]
+fn nan() {
+    assert!("NaN".parse::<f32>().unwrap().is_nan());
+    assert!("NaN".parse::<f64>().unwrap().is_nan());
+}
+
+#[test]
+fn inf() {
+    assert_eq!("inf".parse(), Ok(f64::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+    assert_eq!("inf".parse(), Ok(f32::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
+}
+
+#[test]
+fn massive_exponent() {
+    let max = i64::MAX;
+    assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+    assert_eq!(format!("1e-{}000", max).parse(), Ok(0.0));
+    assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+}
+
+#[test]
+fn borderline_overflow() {
+    let mut s = "0.".to_string();
+    for _ in 0..375 {
+        s.push('3');
+    }
+    // At the time of this writing, this returns Err(..), but this is a bug that should be fixed.
+    // It makes no sense to enshrine that in a test, the important part is that it doesn't panic.
+    let _ = s.parse::<f64>();
+}
diff --git a/src/libcore/tests/num/dec2flt/parse.rs b/src/libcore/tests/num/dec2flt/parse.rs
new file mode 100644
index 00000000000..09acf2bc517
--- /dev/null
+++ b/src/libcore/tests/num/dec2flt/parse.rs
@@ -0,0 +1,52 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::iter;
+use core::num::dec2flt::parse::{Decimal, parse_decimal};
+use core::num::dec2flt::parse::ParseResult::{Valid, Invalid};
+
+#[test]
+fn missing_pieces() {
+    let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
+    for &s in permutations {
+        assert_eq!(parse_decimal(s), Invalid);
+    }
+}
+
+#[test]
+fn invalid_chars() {
+    let invalid = "r,?<j";
+    let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
+    for c in invalid.chars() {
+        for s in valid_strings {
+            for i in 0..s.len() {
+                let mut input = String::new();
+                input.push_str(s);
+                input.insert(i, c);
+                assert!(parse_decimal(&input) == Invalid, "did not reject invalid {:?}", input);
+            }
+        }
+    }
+}
+
+#[test]
+fn valid() {
+    assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789)));
+    assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789)));
+    assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789)));
+    assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0)));
+    assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0)));
+    assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300)));
+    assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300)));
+    assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33)));
+    let zeros: String = iter::repeat('0').take(25).collect();
+    let s = format!("1.5e{}", zeros);
+    assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0)));
+}
diff --git a/src/libcore/tests/num/dec2flt/rawfp.rs b/src/libcore/tests/num/dec2flt/rawfp.rs
new file mode 100644
index 00000000000..1a3533317da
--- /dev/null
+++ b/src/libcore/tests/num/dec2flt/rawfp.rs
@@ -0,0 +1,154 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::f64;
+use std::mem;
+use core::num::diy_float::Fp;
+use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
+
+fn integer_decode(f: f64) -> (u64, i16, i8) {
+    let bits: u64 = unsafe { mem::transmute(f) };
+    let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
+    let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
+    let mantissa = if exponent == 0 {
+        (bits & 0xfffffffffffff) << 1
+    } else {
+        (bits & 0xfffffffffffff) | 0x10000000000000
+    };
+    // Exponent bias + mantissa shift
+    exponent -= 1023 + 52;
+    (mantissa, exponent, sign)
+}
+
+#[test]
+fn fp_to_float_half_to_even() {
+    fn is_normalized(sig: u64) -> bool {
+        // intentionally written without {min,max}_sig() as a sanity check
+        sig >> 52 == 1 && sig >> 53 == 0
+    }
+
+    fn conv(sig: u64) -> u64 {
+        // The significands are perfectly in range, so the exponent should not matter
+        let (m1, e1, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 0 }));
+        assert_eq!(e1, 0 + 64 - 53);
+        let (m2, e2, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 55 }));
+        assert_eq!(e2, 55 + 64 - 53);
+        assert_eq!(m2, m1);
+        let (m3, e3, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: -78 }));
+        assert_eq!(e3, -78 + 64 - 53);
+        assert_eq!(m3, m2);
+        m3
+    }
+
+    let odd = 0x1F_EDCB_A012_345F;
+    let even = odd - 1;
+    assert!(is_normalized(odd));
+    assert!(is_normalized(even));
+    assert_eq!(conv(odd << 11), odd);
+    assert_eq!(conv(even << 11), even);
+    assert_eq!(conv(odd << 11 | 1 << 10), odd + 1);
+    assert_eq!(conv(even << 11 | 1 << 10), even);
+    assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1);
+    assert_eq!(conv(odd << 11 | 1 << 9), odd);
+    assert_eq!(conv(even << 11 | 1 << 9), even);
+    assert_eq!(conv(odd << 11 | 0x7FF), odd + 1);
+    assert_eq!(conv(even << 11 | 0x7FF), even + 1);
+    assert_eq!(conv(odd << 11 | 0x3FF), odd);
+    assert_eq!(conv(even << 11 | 0x3FF), even);
+}
+
+#[test]
+fn integers_to_f64() {
+    assert_eq!(fp_to_float::<f64>(Fp { f: 1, e: 0 }), 1.0);
+    assert_eq!(fp_to_float::<f64>(Fp { f: 42, e: 7 }), (42 << 7) as f64);
+    assert_eq!(fp_to_float::<f64>(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64);
+    assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
+}
+
+const SOME_FLOATS: [f64; 9] =
+    [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997,
+     9843579834.35892, 12456.0e-150, 54389573.0e-150];
+
+
+#[test]
+fn human_f64_roundtrip() {
+    for &x in &SOME_FLOATS {
+        let (f, e, _) = integer_decode(x);
+        let fp = Fp { f: f, e: e};
+        assert_eq!(fp_to_float::<f64>(fp), x);
+    }
+}
+
+#[test]
+fn rounding_overflow() {
+    let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 };
+    let rounded = round_normal::<f64>(x);
+    let adjusted_k = x.e + 64 - 53;
+    assert_eq!(rounded.sig, 1 << 52);
+    assert_eq!(rounded.k, adjusted_k + 1);
+}
+
+#[test]
+fn prev_float_monotonic() {
+    let mut x = 1.0;
+    for _ in 0..100 {
+        let x1 = prev_float(x);
+        assert!(x1 < x);
+        assert!(x - x1 < 1e-15);
+        x = x1;
+    }
+}
+
+const MIN_SUBNORMAL: f64 = 5e-324;
+
+#[test]
+fn next_float_zero() {
+    let tiny = next_float(0.0);
+    assert_eq!(tiny, MIN_SUBNORMAL);
+    assert!(tiny != 0.0);
+}
+
+#[test]
+fn next_float_subnormal() {
+    let second = next_float(MIN_SUBNORMAL);
+    // For subnormals, MIN_SUBNORMAL is the ULP
+    assert!(second != MIN_SUBNORMAL);
+    assert!(second > 0.0);
+    assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL);
+}
+
+#[test]
+fn next_float_inf() {
+    assert_eq!(next_float(f64::MAX), f64::INFINITY);
+    assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
+}
+
+#[test]
+fn next_prev_identity() {
+    for &x in &SOME_FLOATS {
+        assert_eq!(prev_float(next_float(x)), x);
+        assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x);
+        assert_eq!(next_float(prev_float(x)), x);
+        assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x);
+    }
+}
+
+#[test]
+fn next_float_monotonic() {
+    let mut x = 0.49999999999999;
+    assert!(x < 0.5);
+    for _ in 0..200 {
+        let x1 = next_float(x);
+        assert!(x1 > x);
+        assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x);
+        x = x1;
+    }
+    assert!(x > 0.5);
+}
diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs
new file mode 100644
index 00000000000..0bca616ea9a
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/estimator.rs
@@ -0,0 +1,65 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// FIXME https://github.com/kripken/emscripten/issues/4563
+// NB we have to actually not compile this test to avoid
+// an undefined symbol error
+#![cfg(not(target_os = "emscripten"))]
+
+use core::num::flt2dec::estimator::*;
+
+#[test]
+fn test_estimate_scaling_factor() {
+    macro_rules! assert_almost_eq {
+        ($actual:expr, $expected:expr) => ({
+            let actual = $actual;
+            let expected = $expected;
+            println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
+                     expected, actual, expected - actual);
+            assert!(expected == actual || expected == actual + 1,
+                    "expected {}, actual {}", expected, actual);
+        })
+    }
+
+    assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
+    assert_almost_eq!(estimate_scaling_factor(2, 0), 1);
+    assert_almost_eq!(estimate_scaling_factor(10, 0), 1);
+    assert_almost_eq!(estimate_scaling_factor(11, 0), 2);
+    assert_almost_eq!(estimate_scaling_factor(100, 0), 2);
+    assert_almost_eq!(estimate_scaling_factor(101, 0), 3);
+    assert_almost_eq!(estimate_scaling_factor(10000000000000000000, 0), 19);
+    assert_almost_eq!(estimate_scaling_factor(10000000000000000001, 0), 20);
+
+    // 1/2^20 = 0.00000095367...
+    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000, -20), -6);
+    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000 + 1, -20), -5);
+    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5);
+    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4);
+    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4);
+    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3);
+    assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0);
+    assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0);
+    assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1);
+    assert_almost_eq!(estimate_scaling_factor(10485759999999999999, -20), 13);
+    assert_almost_eq!(estimate_scaling_factor(10485760000000000000, -20), 13);
+    assert_almost_eq!(estimate_scaling_factor(10485760000000000001, -20), 14);
+
+    // extreme values:
+    // 2^-1074 = 4.94065... * 10^-324
+    // (2^53-1) * 2^971 = 1.79763... * 10^308
+    assert_almost_eq!(estimate_scaling_factor(1, -1074), -323);
+    assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309);
+
+    for i in -1074..972 {
+        let expected = super::ldexp_f64(1.0, i).log10().ceil();
+        assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
+    }
+}
+
diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs
new file mode 100644
index 00000000000..0f4d19e7092
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/mod.rs
@@ -0,0 +1,1201 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use std::{str, mem, i16, f32, f64, fmt};
+use std::__rand as rand;
+use rand::{Rand, XorShiftRng};
+use rand::distributions::{IndependentSample, Range};
+
+use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
+use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign};
+use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str,
+                         to_exact_exp_str, to_exact_fixed_str};
+
+pub use test::Bencher;
+
+mod estimator;
+mod strategy {
+    mod dragon;
+    mod grisu;
+}
+
+pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+    match decode(v).1 {
+        FullDecoded::Finite(decoded) => decoded,
+        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+    }
+}
+
+macro_rules! check_shortest {
+    ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
+        check_shortest!($f($v) => $buf, $exp;
+                        "shortest mismatch for v={v}: actual {actual:?}, expected {expected:?}",
+                        v = stringify!($v))
+    );
+
+    ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr) => (
+        check_shortest!($f{$($k: $v),+} => $buf, $exp;
+                        "shortest mismatch for {v:?}: actual {actual:?}, expected {expected:?}",
+                        v = Decoded { $($k: $v),+ })
+    );
+
+    ($f:ident($v:expr) => $buf:expr, $exp:expr; $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let mut buf = [b'_'; MAX_SIG_DIGITS];
+        let (len, k) = $f(&decode_finite($v), &mut buf);
+        assert!((&buf[..len], k) == ($buf, $exp),
+                $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($buf).unwrap(), $exp),
+                      $($key = $val),*);
+    });
+
+    ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr;
+                                         $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let mut buf = [b'_'; MAX_SIG_DIGITS];
+        let (len, k) = $f(&Decoded { $($k: $v),+ }, &mut buf);
+        assert!((&buf[..len], k) == ($buf, $exp),
+                $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($buf).unwrap(), $exp),
+                      $($key = $val),*);
+    })
+}
+
+macro_rules! try_exact {
+    ($f:ident($decoded:expr) => $buf:expr, $expected:expr, $expectedk:expr;
+                                $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let (len, k) = $f($decoded, &mut $buf[..$expected.len()], i16::MIN);
+        assert!((&$buf[..len], k) == ($expected, $expectedk),
+                $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($expected).unwrap(), $expectedk),
+                      $($key = $val),*);
+    })
+}
+
+macro_rules! try_fixed {
+    ($f:ident($decoded:expr) => $buf:expr, $request:expr, $expected:expr, $expectedk:expr;
+                                $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let (len, k) = $f($decoded, &mut $buf[..], $request);
+        assert!((&$buf[..len], k) == ($expected, $expectedk),
+                $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($expected).unwrap(), $expectedk),
+                      $($key = $val),*);
+    })
+}
+
+fn ldexp_f32(a: f32, b: i32) -> f32 {
+    ldexp_f64(a as f64, b) as f32
+}
+
+fn ldexp_f64(a: f64, b: i32) -> f64 {
+    extern {
+        fn ldexp(x: f64, n: i32) -> f64;
+    }
+    unsafe { ldexp(a, b) }
+}
+
+fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16)
+        where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    // use a large enough buffer
+    let mut buf = [b'_'; 1024];
+    let mut expected_ = [b'_'; 1024];
+
+    let decoded = decode_finite(v);
+    let cut = expected.iter().position(|&c| c == b' ');
+
+    // check significant digits
+    for i in 1..cut.unwrap_or(expected.len() - 1) {
+        expected_[..i].copy_from_slice(&expected[..i]);
+        let mut expectedk_ = expectedk;
+        if expected[i] >= b'5' {
+            // check if this is a rounding-to-even case.
+            // we avoid rounding ...x5000... (with infinite zeroes) to ...(x+1) when x is even.
+            if !(i+1 < expected.len() && expected[i-1] & 1 == 0 &&
+                                         expected[i] == b'5' &&
+                                         expected[i+1] == b' ') {
+                // if this returns true, expected_[..i] is all `9`s and being rounded up.
+                // we should always return `100..00` (`i` digits) instead, since that's
+                // what we can came up with `i` digits anyway. `round_up` assumes that
+                // the adjustment to the length is done by caller, which we simply ignore.
+                if let Some(_) = round_up(&mut expected_, i) { expectedk_ += 1; }
+            }
+        }
+
+        try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk_;
+                   "exact sigdigit mismatch for v={v}, i={i}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr, i = i);
+        try_fixed!(f(&decoded) => &mut buf, expectedk_ - i as i16, &expected_[..i], expectedk_;
+                   "fixed sigdigit mismatch for v={v}, i={i}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr, i = i);
+    }
+
+    // check exact rounding for zero- and negative-width cases
+    let start;
+    if expected[0] >= b'5' {
+        try_fixed!(f(&decoded) => &mut buf, expectedk, b"1", expectedk + 1;
+                   "zero-width rounding-up mismatch for v={v}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr);
+        start = 1;
+    } else {
+        start = 0;
+    }
+    for i in start..-10 {
+        try_fixed!(f(&decoded) => &mut buf, expectedk - i, b"", expectedk;
+                   "rounding-down mismatch for v={v}, i={i}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr, i = -i);
+    }
+
+    // check infinite zero digits
+    if let Some(cut) = cut {
+        for i in cut..expected.len()-1 {
+            expected_[..cut].copy_from_slice(&expected[..cut]);
+            for c in &mut expected_[cut..i] { *c = b'0'; }
+
+            try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk;
+                       "exact infzero mismatch for v={v}, i={i}: \
+                        actual {actual:?}, expected {expected:?}",
+                       v = vstr, i = i);
+            try_fixed!(f(&decoded) => &mut buf, expectedk - i as i16, &expected_[..i], expectedk;
+                       "fixed infzero mismatch for v={v}, i={i}: \
+                        actual {actual:?}, expected {expected:?}",
+                       v = vstr, i = i);
+        }
+    }
+}
+
+trait TestableFloat : DecodableFloat + fmt::Display {
+    /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`.
+    /// This is used for testing.
+    fn ldexpi(f: i64, exp: isize) -> Self;
+}
+
+impl TestableFloat for f32 {
+    fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
+}
+
+impl TestableFloat for f64 {
+    fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
+}
+
+fn check_exact_one<F, T>(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16)
+        where T: TestableFloat,
+              F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    // use a large enough buffer
+    let mut buf = [b'_'; 1024];
+    let v: T = TestableFloat::ldexpi(x, e);
+    let decoded = decode_finite(v);
+
+    try_exact!(f(&decoded) => &mut buf, &expected, expectedk;
+               "exact mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
+               x = x, e = e, t = tstr);
+    try_fixed!(f(&decoded) => &mut buf, expectedk - expected.len() as i16, &expected, expectedk;
+               "fixed mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
+               x = x, e = e, t = tstr);
+}
+
+macro_rules! check_exact {
+    ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
+        check_exact(|d,b,k| $f(d,b,k), $v, stringify!($v), $buf, $exp)
+    )
+}
+
+macro_rules! check_exact_one {
+    ($f:ident($x:expr, $e:expr; $t:ty) => $buf:expr, $exp:expr) => (
+        check_exact_one::<_, $t>(|d,b,k| $f(d,b,k), $x, $e, stringify!($t), $buf, $exp)
+    )
+}
+
+// in the following comments, three numbers are spaced by 1 ulp apart,
+// and the second one is being formatted.
+//
+// some tests are derived from [1].
+//
+// [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
+//     ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+
+pub fn f32_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    // 0.0999999940395355224609375
+    // 0.100000001490116119384765625
+    // 0.10000000894069671630859375
+    check_shortest!(f(0.1f32) => b"1", 0);
+
+    // 0.333333313465118408203125
+    // 0.3333333432674407958984375 (1/3 in the default rounding)
+    // 0.33333337306976318359375
+    check_shortest!(f(1.0f32/3.0) => b"33333334", 0);
+
+    // 10^1 * 0.31415917873382568359375
+    // 10^1 * 0.31415920257568359375
+    // 10^1 * 0.31415922641754150390625
+    check_shortest!(f(3.141592f32) => b"3141592", 1);
+
+    // 10^18 * 0.31415916243714048
+    // 10^18 * 0.314159196796878848
+    // 10^18 * 0.314159231156617216
+    check_shortest!(f(3.141592e17f32) => b"3141592", 18);
+
+    // regression test for decoders
+    // 10^8 * 0.3355443
+    // 10^8 * 0.33554432
+    // 10^8 * 0.33554436
+    check_shortest!(f(ldexp_f32(1.0, 25)) => b"33554432", 8);
+
+    // 10^39 * 0.340282326356119256160033759537265639424
+    // 10^39 * 0.34028234663852885981170418348451692544
+    // 10^39 * 0.340282366920938463463374607431768211456
+    check_shortest!(f(f32::MAX) => b"34028235", 39);
+
+    // 10^-37 * 0.1175494210692441075487029444849287348827...
+    // 10^-37 * 0.1175494350822287507968736537222245677818...
+    // 10^-37 * 0.1175494490952133940450443629595204006810...
+    check_shortest!(f(f32::MIN_POSITIVE) => b"11754944", -37);
+
+    // 10^-44 * 0
+    // 10^-44 * 0.1401298464324817070923729583289916131280...
+    // 10^-44 * 0.2802596928649634141847459166579832262560...
+    let minf32 = ldexp_f32(1.0, -149);
+    check_shortest!(f(minf32) => b"1", -44);
+}
+
+pub fn f32_exact_sanity_test<F>(mut f: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    let minf32 = ldexp_f32(1.0, -149);
+
+    check_exact!(f(0.1f32)            => b"100000001490116119384765625             ", 0);
+    check_exact!(f(0.5f32)            => b"5                                       ", 0);
+    check_exact!(f(1.0f32/3.0)        => b"3333333432674407958984375               ", 0);
+    check_exact!(f(3.141592f32)       => b"31415920257568359375                    ", 1);
+    check_exact!(f(3.141592e17f32)    => b"314159196796878848                      ", 18);
+    check_exact!(f(f32::MAX)          => b"34028234663852885981170418348451692544  ", 39);
+    check_exact!(f(f32::MIN_POSITIVE) => b"1175494350822287507968736537222245677818", -37);
+    check_exact!(f(minf32)            => b"1401298464324817070923729583289916131280", -44);
+
+    // [1], Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
+    check_exact_one!(f(12676506, -102; f32) => b"2",            -23);
+    check_exact_one!(f(12676506, -103; f32) => b"12",           -23);
+    check_exact_one!(f(15445013,   86; f32) => b"119",           34);
+    check_exact_one!(f(13734123, -138; f32) => b"3941",         -34);
+    check_exact_one!(f(12428269, -130; f32) => b"91308",        -32);
+    check_exact_one!(f(15334037, -146; f32) => b"171900",       -36);
+    check_exact_one!(f(11518287,  -41; f32) => b"5237910",       -5);
+    check_exact_one!(f(12584953, -145; f32) => b"28216440",     -36);
+    check_exact_one!(f(15961084, -125; f32) => b"375243281",    -30);
+    check_exact_one!(f(14915817, -146; f32) => b"1672120916",   -36);
+    check_exact_one!(f(10845484, -102; f32) => b"21388945814",  -23);
+    check_exact_one!(f(16431059,  -61; f32) => b"712583594561", -11);
+
+    // [1], Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
+    check_exact_one!(f(16093626,   69; f32) => b"1",             29);
+    check_exact_one!(f( 9983778,   25; f32) => b"34",            15);
+    check_exact_one!(f(12745034,  104; f32) => b"259",           39);
+    check_exact_one!(f(12706553,   72; f32) => b"6001",          29);
+    check_exact_one!(f(11005028,   45; f32) => b"38721",         21);
+    check_exact_one!(f(15059547,   71; f32) => b"355584",        29);
+    check_exact_one!(f(16015691,  -99; f32) => b"2526831",      -22);
+    check_exact_one!(f( 8667859,   56; f32) => b"62458507",      24);
+    check_exact_one!(f(14855922,  -82; f32) => b"307213267",    -17);
+    check_exact_one!(f(14855922,  -83; f32) => b"1536066333",   -17);
+    check_exact_one!(f(10144164, -110; f32) => b"78147796834",  -26);
+    check_exact_one!(f(13248074,   95; f32) => b"524810279937",  36);
+}
+
+pub fn f64_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    // 0.0999999999999999777955395074968691915273...
+    // 0.1000000000000000055511151231257827021181...
+    // 0.1000000000000000333066907387546962127089...
+    check_shortest!(f(0.1f64) => b"1", 0);
+
+    // this example is explicitly mentioned in the paper.
+    // 10^3 * 0.0999999999999999857891452847979962825775...
+    // 10^3 * 0.1 (exact)
+    // 10^3 * 0.1000000000000000142108547152020037174224...
+    check_shortest!(f(100.0f64) => b"1", 3);
+
+    // 0.3333333333333332593184650249895639717578...
+    // 0.3333333333333333148296162562473909929394... (1/3 in the default rounding)
+    // 0.3333333333333333703407674875052180141210...
+    check_shortest!(f(1.0f64/3.0) => b"3333333333333333", 0);
+
+    // explicit test case for equally closest representations.
+    // Dragon has its own tie-breaking rule; Grisu should fall back.
+    // 10^1 * 0.1000007629394531027955395074968691915273...
+    // 10^1 * 0.100000762939453125 (exact)
+    // 10^1 * 0.1000007629394531472044604925031308084726...
+    check_shortest!(f(1.00000762939453125f64) => b"10000076293945313", 1);
+
+    // 10^1 * 0.3141591999999999718085064159822650253772...
+    // 10^1 * 0.3141592000000000162174274009885266423225...
+    // 10^1 * 0.3141592000000000606263483859947882592678...
+    check_shortest!(f(3.141592f64) => b"3141592", 1);
+
+    // 10^18 * 0.314159199999999936
+    // 10^18 * 0.3141592 (exact)
+    // 10^18 * 0.314159200000000064
+    check_shortest!(f(3.141592e17f64) => b"3141592", 18);
+
+    // regression test for decoders
+    // 10^20 * 0.18446744073709549568
+    // 10^20 * 0.18446744073709551616
+    // 10^20 * 0.18446744073709555712
+    check_shortest!(f(ldexp_f64(1.0, 64)) => b"18446744073709552", 20);
+
+    // pathological case: high = 10^23 (exact). tie breaking should always prefer that.
+    // 10^24 * 0.099999999999999974834176
+    // 10^24 * 0.099999999999999991611392
+    // 10^24 * 0.100000000000000008388608
+    check_shortest!(f(1.0e23f64) => b"1", 24);
+
+    // 10^309 * 0.1797693134862315508561243283845062402343...
+    // 10^309 * 0.1797693134862315708145274237317043567980...
+    // 10^309 * 0.1797693134862315907729305190789024733617...
+    check_shortest!(f(f64::MAX) => b"17976931348623157", 309);
+
+    // 10^-307 * 0.2225073858507200889024586876085859887650...
+    // 10^-307 * 0.2225073858507201383090232717332404064219...
+    // 10^-307 * 0.2225073858507201877155878558578948240788...
+    check_shortest!(f(f64::MIN_POSITIVE) => b"22250738585072014", -307);
+
+    // 10^-323 * 0
+    // 10^-323 * 0.4940656458412465441765687928682213723650...
+    // 10^-323 * 0.9881312916824930883531375857364427447301...
+    let minf64 = ldexp_f64(1.0, -1074);
+    check_shortest!(f(minf64) => b"5", -323);
+}
+
+pub fn f64_exact_sanity_test<F>(mut f: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    let minf64 = ldexp_f64(1.0, -1074);
+
+    check_exact!(f(0.1f64)            => b"1000000000000000055511151231257827021181", 0);
+    check_exact!(f(0.45f64)           => b"4500000000000000111022302462515654042363", 0);
+    check_exact!(f(0.5f64)            => b"5                                       ", 0);
+    check_exact!(f(0.95f64)           => b"9499999999999999555910790149937383830547", 0);
+    check_exact!(f(100.0f64)          => b"1                                       ", 3);
+    check_exact!(f(999.5f64)          => b"9995000000000000000000000000000000000000", 3);
+    check_exact!(f(1.0f64/3.0)        => b"3333333333333333148296162562473909929394", 0);
+    check_exact!(f(3.141592f64)       => b"3141592000000000162174274009885266423225", 1);
+    check_exact!(f(3.141592e17f64)    => b"3141592                                 ", 18);
+    check_exact!(f(1.0e23f64)         => b"99999999999999991611392                 ", 23);
+    check_exact!(f(f64::MAX)          => b"1797693134862315708145274237317043567980", 309);
+    check_exact!(f(f64::MIN_POSITIVE) => b"2225073858507201383090232717332404064219", -307);
+    check_exact!(f(minf64)            => b"4940656458412465441765687928682213723650\
+                                           5980261432476442558568250067550727020875\
+                                           1865299836361635992379796564695445717730\
+                                           9266567103559397963987747960107818781263\
+                                           0071319031140452784581716784898210368871\
+                                           8636056998730723050006387409153564984387\
+                                           3124733972731696151400317153853980741262\
+                                           3856559117102665855668676818703956031062\
+                                           4931945271591492455329305456544401127480\
+                                           1297099995419319894090804165633245247571\
+                                           4786901472678015935523861155013480352649\
+                                           3472019379026810710749170333222684475333\
+                                           5720832431936092382893458368060106011506\
+                                           1698097530783422773183292479049825247307\
+                                           7637592724787465608477820373446969953364\
+                                           7017972677717585125660551199131504891101\
+                                           4510378627381672509558373897335989936648\
+                                           0994116420570263709027924276754456522908\
+                                           7538682506419718265533447265625         ", -323);
+
+    // [1], Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
+    check_exact_one!(f(8511030020275656,  -342; f64) => b"9",                       -87);
+    check_exact_one!(f(5201988407066741,  -824; f64) => b"46",                     -232);
+    check_exact_one!(f(6406892948269899,   237; f64) => b"141",                      88);
+    check_exact_one!(f(8431154198732492,    72; f64) => b"3981",                     38);
+    check_exact_one!(f(6475049196144587,    99; f64) => b"41040",                    46);
+    check_exact_one!(f(8274307542972842,   726; f64) => b"292084",                  235);
+    check_exact_one!(f(5381065484265332,  -456; f64) => b"2891946",                -121);
+    check_exact_one!(f(6761728585499734, -1057; f64) => b"43787718",               -302);
+    check_exact_one!(f(7976538478610756,   376; f64) => b"122770163",               130);
+    check_exact_one!(f(5982403858958067,   377; f64) => b"1841552452",              130);
+    check_exact_one!(f(5536995190630837,    93; f64) => b"54835744350",              44);
+    check_exact_one!(f(7225450889282194,   710; f64) => b"389190181146",            230);
+    check_exact_one!(f(7225450889282194,   709; f64) => b"1945950905732",           230);
+    check_exact_one!(f(8703372741147379,   117; f64) => b"14460958381605",           52);
+    check_exact_one!(f(8944262675275217, -1001; f64) => b"417367747458531",        -285);
+    check_exact_one!(f(7459803696087692,  -707; f64) => b"1107950772878888",       -196);
+    check_exact_one!(f(6080469016670379,  -381; f64) => b"12345501366327440",       -98);
+    check_exact_one!(f(8385515147034757,   721; f64) => b"925031711960365024",      233);
+    check_exact_one!(f(7514216811389786,  -828; f64) => b"4198047150284889840",    -233);
+    check_exact_one!(f(8397297803260511,  -345; f64) => b"11716315319786511046",    -87);
+    check_exact_one!(f(6733459239310543,   202; f64) => b"432810072844612493629",    77);
+    check_exact_one!(f(8091450587292794,  -473; f64) => b"3317710118160031081518", -126);
+
+    // [1], Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
+    check_exact_one!(f(6567258882077402,   952; f64) => b"3",                       303);
+    check_exact_one!(f(6712731423444934,   535; f64) => b"76",                      177);
+    check_exact_one!(f(6712731423444934,   534; f64) => b"378",                     177);
+    check_exact_one!(f(5298405411573037,  -957; f64) => b"4350",                   -272);
+    check_exact_one!(f(5137311167659507,  -144; f64) => b"23037",                   -27);
+    check_exact_one!(f(6722280709661868,   363; f64) => b"126301",                  126);
+    check_exact_one!(f(5344436398034927,  -169; f64) => b"7142211",                 -35);
+    check_exact_one!(f(8369123604277281,  -853; f64) => b"13934574",               -240);
+    check_exact_one!(f(8995822108487663,  -780; f64) => b"141463449",              -218);
+    check_exact_one!(f(8942832835564782,  -383; f64) => b"4539277920",              -99);
+    check_exact_one!(f(8942832835564782,  -384; f64) => b"22696389598",             -99);
+    check_exact_one!(f(8942832835564782,  -385; f64) => b"113481947988",            -99);
+    check_exact_one!(f(6965949469487146,  -249; f64) => b"7700366561890",           -59);
+    check_exact_one!(f(6965949469487146,  -250; f64) => b"38501832809448",          -59);
+    check_exact_one!(f(6965949469487146,  -251; f64) => b"192509164047238",         -59);
+    check_exact_one!(f(7487252720986826,   548; f64) => b"6898586531774201",        181);
+    check_exact_one!(f(5592117679628511,   164; f64) => b"13076622631878654",        66);
+    check_exact_one!(f(8887055249355788,   665; f64) => b"136052020756121240",      217);
+    check_exact_one!(f(6994187472632449,   690; f64) => b"3592810217475959676",     224);
+    check_exact_one!(f(8797576579012143,   588; f64) => b"89125197712484551899",    193);
+    check_exact_one!(f(7363326733505337,   272; f64) => b"558769757362301140950",    98);
+    check_exact_one!(f(8549497411294502,  -448; f64) => b"1176257830728540379990", -118);
+}
+
+pub fn more_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
+                      exp: 0, inclusive: true} => b"1", 18);
+    check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
+                      exp: 0, inclusive: false} => b"99999999999999999", 17);
+}
+
+fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+              V: FnMut(usize) -> Decoded {
+    assert!(k <= 1024);
+
+    let mut npassed = 0; // f(x) = Some(g(x))
+    let mut nignored = 0; // f(x) = None
+
+    for i in 0..n {
+        if (i & 0xfffff) == 0 {
+            println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})",
+                     i, n, nignored, npassed, i - nignored - npassed);
+        }
+
+        let decoded = v(i);
+        let mut buf1 = [0; 1024];
+        if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) {
+            let mut buf2 = [0; 1024];
+            let (len2, e2) = g(&decoded, &mut buf2[..k]);
+            if e1 == e2 && &buf1[..len1] == &buf2[..len2] {
+                npassed += 1;
+            } else {
+                println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}",
+                         i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1,
+                                        str::from_utf8(&buf2[..len2]).unwrap(), e2);
+            }
+        } else {
+            nignored += 1;
+        }
+    }
+    println!("{}({}): done, ignored={} passed={} failed={}",
+             func, k, nignored, npassed, n - nignored - npassed);
+    assert!(nignored + npassed == n,
+            "{}({}): {} out of {} values returns an incorrect value!",
+            func, k, n - nignored - npassed, n);
+    (npassed, nignored)
+}
+
+pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
+    let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000);
+    iterate("f32_random_equivalence_test", k, n, f, g, |_| {
+        let i: u32 = f32_range.ind_sample(&mut rng);
+        let x: f32 = unsafe {mem::transmute(i)};
+        decode_finite(x)
+    });
+}
+
+pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
+    let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
+    iterate("f64_random_equivalence_test", k, n, f, g, |_| {
+        let i: u64 = f64_range.ind_sample(&mut rng);
+        let x: f64 = unsafe {mem::transmute(i)};
+        decode_finite(x)
+    });
+}
+
+pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values,
+    // so why not simply testing all of them?
+    //
+    // this is of course very stressful (and thus should be behind an `#[ignore]` attribute),
+    // but with `-C opt-level=3 -C lto` this only takes about an hour or so.
+
+    // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges
+    let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test",
+                                      k, 0x7f7f_ffff, f, g, |i: usize| {
+        let x: f32 = unsafe {mem::transmute(i as u32 + 1)};
+        decode_finite(x)
+    });
+    assert_eq!((npassed, nignored), (2121451881, 17643158));
+}
+
+fn to_string_with_parts<F>(mut f: F) -> String
+        where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> {
+    let mut buf = [0; 1024];
+    let mut parts = [Part::Zero(0); 16];
+    let formatted = f(&mut buf, &mut parts);
+    let mut ret = vec![0; formatted.len()];
+    assert_eq!(formatted.write(&mut ret), Some(ret.len()));
+    String::from_utf8(ret).unwrap()
+}
+
+pub fn to_shortest_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_shortest_str(|d,b| f(d,b), v, sign,
+                                                          frac_digits, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 0, false), "+0");
+    assert_eq!(to_string(f, -0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     0, false), "-0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
+    assert_eq!(to_string(f,  0.0, Minus,        1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    1,  true), "+0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 1,  true), "+0.0");
+    assert_eq!(to_string(f, -0.0, Minus,        8,  true), "0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     8,  true), "-0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    8,  true), "+0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8,  true), "-0.00000000");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,         0, false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,      0,  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,     0, false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw,  0,  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,         0, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,      1,  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,     8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw, 64,  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,         0, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,      1,  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,     8, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64,  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        0, false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     0, false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    0, false), "+3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 0, false), "+3.14");
+    assert_eq!(to_string(f, -3.14, Minus,        0, false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     0, false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    0, false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3.14");
+    assert_eq!(to_string(f,  3.14, Minus,        1,  true), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     2,  true), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    3,  true), "+3.140");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 4,  true), "+3.1400");
+    assert_eq!(to_string(f, -3.14, Minus,        8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8,  true), "-3.14000000");
+
+    assert_eq!(to_string(f, 7.5e-11, Minus,  0, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus,  3, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
+
+    assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), "199710000000000000000");
+    assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), "199710000000000000000.0");
+    assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), "199710000000000000000.00000000");
+
+    assert_eq!(to_string(f, f32::MAX, Minus, 0, false), format!("34028235{:0>31}", ""));
+    assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", ""));
+    assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", ""));
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus,  0, false), format!("0.{:0>44}1", ""));
+    assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", ""));
+    assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", ""));
+
+    assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
+               format!("17976931348623157{:0>292}", ""));
+    assert_eq!(to_string(f, f64::MAX, Minus, 1, false),
+               format!("17976931348623157{:0>292}.0", ""));
+    assert_eq!(to_string(f, f64::MAX, Minus, 8, false),
+               format!("17976931348623157{:0>292}.00000000", ""));
+
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus,   0, false), format!("0.{:0>323}5", ""));
+    assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", ""));
+    assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", ""));
+
+    // very large output
+    assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", ""));
+}
+
+pub fn to_shortest_exp_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_shortest_exp_str(|d,b| f(d,b), v, sign,
+                                                              exp_bounds, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        (-4, 16), false), "0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     (-4, 16), false), "0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    (-4, 16), false), "+0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, (-4, 16), false), "+0");
+    assert_eq!(to_string(f, -0.0, Minus,        (-4, 16), false), "0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     (-4, 16), false), "-0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    (-4, 16), false), "+0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0");
+    assert_eq!(to_string(f,  0.0, Minus,        ( 0,  0),  true), "0E0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     ( 0,  0), false), "0e0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    (-9, -5),  true), "+0E0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, ( 5,  9), false), "+0e0");
+    assert_eq!(to_string(f, -0.0, Minus,        ( 0,  0),  true), "0E0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     ( 0,  0), false), "-0e0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    (-9, -5),  true), "+0E0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, ( 5,  9), false), "-0e0");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,        (-4, 16), false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,     (-4, 16),  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,    (-4, 16), false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw, (-4, 16),  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,        ( 0,  0), false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,     ( 0,  0),  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,    (-9, -5), false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw, ( 5,  9),  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,        ( 0,  0), false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,     ( 0,  0),  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,    (-9, -5), false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, ( 5,  9),  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        (-4, 16), false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     (-4, 16), false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    (-4, 16), false), "+3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, (-4, 16), false), "+3.14");
+    assert_eq!(to_string(f, -3.14, Minus,        (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f,  3.14, Minus,        ( 0,  0),  true), "3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     ( 0,  0), false), "3.14e0");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    (-9, -5),  true), "+3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, ( 5,  9), false), "+3.14e0");
+    assert_eq!(to_string(f, -3.14, Minus,        ( 0,  0),  true), "-3.14E0");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     ( 0,  0), false), "-3.14e0");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    (-9, -5),  true), "-3.14E0");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, ( 5,  9), false), "-3.14e0");
+
+    assert_eq!(to_string(f,  0.1, Minus,        (-4, 16), false), "0.1");
+    assert_eq!(to_string(f,  0.1, MinusRaw,     (-4, 16), false), "0.1");
+    assert_eq!(to_string(f,  0.1, MinusPlus,    (-4, 16), false), "+0.1");
+    assert_eq!(to_string(f,  0.1, MinusPlusRaw, (-4, 16), false), "+0.1");
+    assert_eq!(to_string(f, -0.1, Minus,        (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f, -0.1, MinusRaw,     (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f, -0.1, MinusPlus,    (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f,  0.1, Minus,        ( 0,  0),  true), "1E-1");
+    assert_eq!(to_string(f,  0.1, MinusRaw,     ( 0,  0), false), "1e-1");
+    assert_eq!(to_string(f,  0.1, MinusPlus,    (-9, -5),  true), "+1E-1");
+    assert_eq!(to_string(f,  0.1, MinusPlusRaw, ( 5,  9), false), "+1e-1");
+    assert_eq!(to_string(f, -0.1, Minus,        ( 0,  0),  true), "-1E-1");
+    assert_eq!(to_string(f, -0.1, MinusRaw,     ( 0,  0), false), "-1e-1");
+    assert_eq!(to_string(f, -0.1, MinusPlus,    (-9, -5),  true), "-1E-1");
+    assert_eq!(to_string(f, -0.1, MinusPlusRaw, ( 5,  9), false), "-1e-1");
+
+    assert_eq!(to_string(f, 7.5e-11, Minus, ( -4, 16), false), "7.5e-11");
+    assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, (-10, 11), false), "7.5e-11");
+
+    assert_eq!(to_string(f, 1.9971e20, Minus, ( -4, 16), false), "1.9971e20");
+    assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), "199710000000000000000");
+    assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), "1.9971e20");
+
+    // the true value of 1.0e23f64 is less than 10^23, but that shouldn't matter here
+    assert_eq!(to_string(f, 1.0e23, Minus, (22, 23), false), "1e23");
+    assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000");
+    assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23");
+
+    assert_eq!(to_string(f, f32::MAX, Minus, ( -4, 16), false), "3.4028235e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus, ( -4, 16), false), "1e-45");
+    assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
+    assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
+
+    assert_eq!(to_string(f, f64::MAX, Minus, (  -4,  16), false),
+               "1.7976931348623157e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, (-308, 309), false),
+               format!("17976931348623157{:0>292}", ""));
+    assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false),
+               "1.7976931348623157e308");
+
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus, (  -4,  16), false), "5e-324");
+    assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
+    assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+
+    assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1");
+}
+
+pub fn to_exact_exp_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_exact_exp_str(|d,b,l| f(d,b,l), v, sign,
+                                                           ndigits, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        1,  true), "0E0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     1, false), "0e0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    1,  true), "+0E0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 1, false), "+0e0");
+    assert_eq!(to_string(f, -0.0, Minus,        1,  true), "0E0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     1, false), "-0e0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    1,  true), "+0E0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0");
+    assert_eq!(to_string(f,  0.0, Minus,        2,  true), "0.0E0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     2, false), "0.0e0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    2,  true), "+0.0E0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 2, false), "+0.0e0");
+    assert_eq!(to_string(f, -0.0, Minus,        8,  true), "0.0000000E0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     8, false), "-0.0000000e0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    8,  true), "+0.0000000E0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,         1, false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,      1,  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,     1, false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw,  1,  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,         8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,      8,  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,     8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw,  8,  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,        64, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,     64,  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,    64, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64,  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        1,  true), "3E0");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     1, false), "3e0");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    1,  true), "+3E0");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 1, false), "+3e0");
+    assert_eq!(to_string(f, -3.14, Minus,        2,  true), "-3.1E0");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     2, false), "-3.1e0");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    2,  true), "-3.1E0");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0");
+    assert_eq!(to_string(f,  3.14, Minus,        3,  true), "3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     3, false), "3.14e0");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    3,  true), "+3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 3, false), "+3.14e0");
+    assert_eq!(to_string(f, -3.14, Minus,        4,  true), "-3.140E0");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     4, false), "-3.140e0");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    4,  true), "-3.140E0");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0");
+
+    assert_eq!(to_string(f,  0.195, Minus,        1, false), "2e-1");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     1,  true), "2E-1");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    1, false), "+2e-1");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 1,  true), "+2E-1");
+    assert_eq!(to_string(f, -0.195, Minus,        2, false), "-2.0e-1");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     2,  true), "-2.0E-1");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    2, false), "-2.0e-1");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2,  true), "-2.0E-1");
+    assert_eq!(to_string(f,  0.195, Minus,        3, false), "1.95e-1");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     3,  true), "1.95E-1");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    3, false), "+1.95e-1");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 3,  true), "+1.95E-1");
+    assert_eq!(to_string(f, -0.195, Minus,        4, false), "-1.950e-1");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     4,  true), "-1.950E-1");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    4, false), "-1.950e-1");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4,  true), "-1.950E-1");
+
+    assert_eq!(to_string(f, 9.5, Minus,  1, false), "1e1");
+    assert_eq!(to_string(f, 9.5, Minus,  2, false), "9.5e0");
+    assert_eq!(to_string(f, 9.5, Minus,  3, false), "9.50e0");
+    assert_eq!(to_string(f, 9.5, Minus, 30, false), "9.50000000000000000000000000000e0");
+
+    assert_eq!(to_string(f, 1.0e25, Minus,  1, false), "1e25");
+    assert_eq!(to_string(f, 1.0e25, Minus,  2, false), "1.0e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 15, false), "1.00000000000000e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 16, false), "1.000000000000000e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 17, false), "1.0000000000000001e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 18, false), "1.00000000000000009e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 19, false), "1.000000000000000091e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 20, false), "1.0000000000000000906e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 21, false), "1.00000000000000009060e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 22, false), "1.000000000000000090597e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 23, false), "1.0000000000000000905970e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 24, false), "1.00000000000000009059697e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 25, false), "1.000000000000000090596966e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 26, false), "1.0000000000000000905969664e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 27, false), "1.00000000000000009059696640e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 30, false), "1.00000000000000009059696640000e25");
+
+    assert_eq!(to_string(f, 1.0e-6, Minus,  1, false), "1e-6");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  2, false), "1.0e-6");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), "1.000000000000000e-6");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), "9.9999999999999995e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), "9.99999999999999955e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), "9.999999999999999547e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), "9.9999999999999995475e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), "9.99999999999999954748111825886e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 40, false),
+               "9.999999999999999547481118258862586856139e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 50, false),
+               "9.9999999999999995474811182588625868561393872369081e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 60, false),
+               "9.99999999999999954748111825886258685613938723690807819366455e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 70, false),
+               "9.999999999999999547481118258862586856139387236908078193664550781250000e-7");
+
+    assert_eq!(to_string(f, f32::MAX, Minus,  1, false), "3e38");
+    assert_eq!(to_string(f, f32::MAX, Minus,  2, false), "3.4e38");
+    assert_eq!(to_string(f, f32::MAX, Minus,  4, false), "3.403e38");
+    assert_eq!(to_string(f, f32::MAX, Minus,  8, false), "3.4028235e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, 16, false), "3.402823466385289e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, 32, false), "3.4028234663852885981170418348452e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, 64, false),
+               "3.402823466385288598117041834845169254400000000000000000000000000e38");
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus,   1, false), "1e-45");
+    assert_eq!(to_string(f, minf32, Minus,   2, false), "1.4e-45");
+    assert_eq!(to_string(f, minf32, Minus,   4, false), "1.401e-45");
+    assert_eq!(to_string(f, minf32, Minus,   8, false), "1.4012985e-45");
+    assert_eq!(to_string(f, minf32, Minus,  16, false), "1.401298464324817e-45");
+    assert_eq!(to_string(f, minf32, Minus,  32, false), "1.4012984643248170709237295832899e-45");
+    assert_eq!(to_string(f, minf32, Minus,  64, false),
+               "1.401298464324817070923729583289916131280261941876515771757068284e-45");
+    assert_eq!(to_string(f, minf32, Minus, 128, false),
+               "1.401298464324817070923729583289916131280261941876515771757068283\
+                 8897910826858606014866381883621215820312500000000000000000000000e-45");
+
+    assert_eq!(to_string(f, f64::MAX, Minus,   1, false), "2e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,   2, false), "1.8e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,   4, false), "1.798e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,   8, false), "1.7976931e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,  16, false), "1.797693134862316e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,  32, false), "1.7976931348623157081452742373170e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,  64, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, 128, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768\
+                 0315726078002853876058955863276687817154045895351438246423432133e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, 256, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768\
+                 0315726078002853876058955863276687817154045895351438246423432132\
+                 6889464182768467546703537516986049910576551282076245490090389328\
+                 9440758685084551339423045832369032229481658085593321233482747978e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, 512, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768\
+                 0315726078002853876058955863276687817154045895351438246423432132\
+                 6889464182768467546703537516986049910576551282076245490090389328\
+                 9440758685084551339423045832369032229481658085593321233482747978\
+                 2620414472316873817718091929988125040402618412485836800000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000e308");
+
+    // okay, this is becoming tough. fortunately for us, this is almost the worst case.
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus,    1, false), "5e-324");
+    assert_eq!(to_string(f, minf64, Minus,    2, false), "4.9e-324");
+    assert_eq!(to_string(f, minf64, Minus,    4, false), "4.941e-324");
+    assert_eq!(to_string(f, minf64, Minus,    8, false), "4.9406565e-324");
+    assert_eq!(to_string(f, minf64, Minus,   16, false), "4.940656458412465e-324");
+    assert_eq!(to_string(f, minf64, Minus,   32, false), "4.9406564584124654417656879286822e-324");
+    assert_eq!(to_string(f, minf64, Minus,   64, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825e-324");
+    assert_eq!(to_string(f, minf64, Minus,  128, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671e-324");
+    assert_eq!(to_string(f, minf64, Minus,  256, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671\
+                 0355939796398774796010781878126300713190311404527845817167848982\
+                 1036887186360569987307230500063874091535649843873124733972731696e-324");
+    assert_eq!(to_string(f, minf64, Minus,  512, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671\
+                 0355939796398774796010781878126300713190311404527845817167848982\
+                 1036887186360569987307230500063874091535649843873124733972731696\
+                 1514003171538539807412623856559117102665855668676818703956031062\
+                 4931945271591492455329305456544401127480129709999541931989409080\
+                 4165633245247571478690147267801593552386115501348035264934720193\
+                 7902681071074917033322268447533357208324319360923828934583680601e-324");
+    assert_eq!(to_string(f, minf64, Minus, 1024, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671\
+                 0355939796398774796010781878126300713190311404527845817167848982\
+                 1036887186360569987307230500063874091535649843873124733972731696\
+                 1514003171538539807412623856559117102665855668676818703956031062\
+                 4931945271591492455329305456544401127480129709999541931989409080\
+                 4165633245247571478690147267801593552386115501348035264934720193\
+                 7902681071074917033322268447533357208324319360923828934583680601\
+                 0601150616980975307834227731832924790498252473077637592724787465\
+                 6084778203734469699533647017972677717585125660551199131504891101\
+                 4510378627381672509558373897335989936648099411642057026370902792\
+                 4276754456522908753868250641971826553344726562500000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000e-324");
+
+    // very large output
+    assert_eq!(to_string(f, 0.0,     Minus, 80000, false), format!("0.{:0>79999}e0", ""));
+    assert_eq!(to_string(f, 1.0e1,   Minus, 80000, false), format!("1.{:0>79999}e1", ""));
+    assert_eq!(to_string(f, 1.0e0,   Minus, 80000, false), format!("1.{:0>79999}e0", ""));
+    assert_eq!(to_string(f, 1.0e-1,  Minus, 80000, false),
+               format!("1.000000000000000055511151231257827021181583404541015625{:0>79945}\
+                        e-1", ""));
+    assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
+               format!("9.999999999999999451532714542095716517295037027873924471077157760\
+                         66783064379706047475337982177734375{:0>79901}e-21", ""));
+}
+
+pub fn to_exact_fixed_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_exact_fixed_str(|d,b,l| f(d,b,l), v, sign,
+                                                             frac_digits, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 0, false), "+0");
+    assert_eq!(to_string(f, -0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     0, false), "-0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
+    assert_eq!(to_string(f,  0.0, Minus,        1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    1,  true), "+0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 1,  true), "+0.0");
+    assert_eq!(to_string(f, -0.0, Minus,        8,  true), "0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     8,  true), "-0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    8,  true), "+0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8,  true), "-0.00000000");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,         0, false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,      1,  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,     8, false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw, 64,  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,         0, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,      1,  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,     8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw, 64,  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,         0, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,      1,  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,     8, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64,  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        0, false), "3");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     0, false), "3");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    0, false), "+3");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 0, false), "+3");
+    assert_eq!(to_string(f, -3.14, Minus,        0, false), "-3");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     0, false), "-3");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    0, false), "-3");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3");
+    assert_eq!(to_string(f,  3.14, Minus,        1,  true), "3.1");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     2,  true), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    3,  true), "+3.140");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 4,  true), "+3.1400");
+    assert_eq!(to_string(f, -3.14, Minus,        8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8,  true), "-3.14000000");
+
+    assert_eq!(to_string(f,  0.195, Minus,        0, false), "0");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     0, false), "0");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 0, false), "+0");
+    assert_eq!(to_string(f, -0.195, Minus,        0, false), "-0");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     0, false), "-0");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    0, false), "-0");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0, false), "-0");
+    assert_eq!(to_string(f,  0.195, Minus,        1,  true), "0.2");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     2,  true), "0.20");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    3,  true), "+0.195");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 4,  true), "+0.1950");
+    assert_eq!(to_string(f, -0.195, Minus,        5,  true), "-0.19500");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     6,  true), "-0.195000");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    7,  true), "-0.1950000");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8,  true), "-0.19500000");
+
+    assert_eq!(to_string(f, 999.5, Minus,  0, false), "1000");
+    assert_eq!(to_string(f, 999.5, Minus,  1, false), "999.5");
+    assert_eq!(to_string(f, 999.5, Minus,  2, false), "999.50");
+    assert_eq!(to_string(f, 999.5, Minus,  3, false), "999.500");
+    assert_eq!(to_string(f, 999.5, Minus, 30, false), "999.500000000000000000000000000000");
+
+    assert_eq!(to_string(f, 0.5, Minus, 0, false), "1");
+    assert_eq!(to_string(f, 0.5, Minus, 1, false), "0.5");
+    assert_eq!(to_string(f, 0.5, Minus, 2, false), "0.50");
+    assert_eq!(to_string(f, 0.5, Minus, 3, false), "0.500");
+
+    assert_eq!(to_string(f, 0.95, Minus,  0, false), "1");
+    assert_eq!(to_string(f, 0.95, Minus,  1, false), "0.9"); // because it really is less than 0.95
+    assert_eq!(to_string(f, 0.95, Minus,  2, false), "0.95");
+    assert_eq!(to_string(f, 0.95, Minus,  3, false), "0.950");
+    assert_eq!(to_string(f, 0.95, Minus, 10, false), "0.9500000000");
+    assert_eq!(to_string(f, 0.95, Minus, 30, false), "0.949999999999999955591079014994");
+
+    assert_eq!(to_string(f, 0.095, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 0.095, Minus,  1, false), "0.1");
+    assert_eq!(to_string(f, 0.095, Minus,  2, false), "0.10");
+    assert_eq!(to_string(f, 0.095, Minus,  3, false), "0.095");
+    assert_eq!(to_string(f, 0.095, Minus,  4, false), "0.0950");
+    assert_eq!(to_string(f, 0.095, Minus, 10, false), "0.0950000000");
+    assert_eq!(to_string(f, 0.095, Minus, 30, false), "0.095000000000000001110223024625");
+
+    assert_eq!(to_string(f, 0.0095, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 0.0095, Minus,  1, false), "0.0");
+    assert_eq!(to_string(f, 0.0095, Minus,  2, false), "0.01");
+    assert_eq!(to_string(f, 0.0095, Minus,  3, false), "0.009"); // really is less than 0.0095
+    assert_eq!(to_string(f, 0.0095, Minus,  4, false), "0.0095");
+    assert_eq!(to_string(f, 0.0095, Minus,  5, false), "0.00950");
+    assert_eq!(to_string(f, 0.0095, Minus, 10, false), "0.0095000000");
+    assert_eq!(to_string(f, 0.0095, Minus, 30, false), "0.009499999999999999764077607267");
+
+    assert_eq!(to_string(f, 7.5e-11, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 7.5e-11, Minus,  3, false), "0.000");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 10, false), "0.0000000001");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 11, false), "0.00000000007"); // ditto
+    assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), "0.00000000007500000000");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), "0.000000000074999999999999999501");
+
+    assert_eq!(to_string(f, 1.0e25, Minus, 0, false), "10000000000000000905969664");
+    assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "10000000000000000905969664.0");
+    assert_eq!(to_string(f, 1.0e25, Minus, 3, false), "10000000000000000905969664.000");
+
+    assert_eq!(to_string(f, 1.0e-6, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  3, false), "0.000");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  6, false), "0.000001");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  9, false), "0.000001000");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 12, false), "0.000001000000");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), "0.0000010000000000000000");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), "0.00000099999999999999995");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), "0.000000999999999999999955");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), "0.0000009999999999999999547");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), "0.00000099999999999999995474811182589");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 45, false),
+               "0.000000999999999999999954748111825886258685614");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 55, false),
+               "0.0000009999999999999999547481118258862586856139387236908");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 65, false),
+               "0.00000099999999999999995474811182588625868561393872369080781936646");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 75, false),
+               "0.000000999999999999999954748111825886258685613938723690807819366455078125000");
+
+    assert_eq!(to_string(f, f32::MAX, Minus, 0, false),
+               "340282346638528859811704183484516925440");
+    assert_eq!(to_string(f, f32::MAX, Minus, 1, false),
+               "340282346638528859811704183484516925440.0");
+    assert_eq!(to_string(f, f32::MAX, Minus, 2, false),
+               "340282346638528859811704183484516925440.00");
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus,   0, false), "0");
+    assert_eq!(to_string(f, minf32, Minus,   1, false), "0.0");
+    assert_eq!(to_string(f, minf32, Minus,   2, false), "0.00");
+    assert_eq!(to_string(f, minf32, Minus,   4, false), "0.0000");
+    assert_eq!(to_string(f, minf32, Minus,   8, false), "0.00000000");
+    assert_eq!(to_string(f, minf32, Minus,  16, false), "0.0000000000000000");
+    assert_eq!(to_string(f, minf32, Minus,  32, false), "0.00000000000000000000000000000000");
+    assert_eq!(to_string(f, minf32, Minus,  64, false),
+               "0.0000000000000000000000000000000000000000000014012984643248170709");
+    assert_eq!(to_string(f, minf32, Minus, 128, false),
+               "0.0000000000000000000000000000000000000000000014012984643248170709\
+                  2372958328991613128026194187651577175706828388979108268586060149");
+    assert_eq!(to_string(f, minf32, Minus, 256, false),
+               "0.0000000000000000000000000000000000000000000014012984643248170709\
+                  2372958328991613128026194187651577175706828388979108268586060148\
+                  6638188362121582031250000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000");
+
+    assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
+               "1797693134862315708145274237317043567980705675258449965989174768\
+                0315726078002853876058955863276687817154045895351438246423432132\
+                6889464182768467546703537516986049910576551282076245490090389328\
+                9440758685084551339423045832369032229481658085593321233482747978\
+                26204144723168738177180919299881250404026184124858368");
+    assert_eq!(to_string(f, f64::MAX, Minus, 10, false),
+               "1797693134862315708145274237317043567980705675258449965989174768\
+                0315726078002853876058955863276687817154045895351438246423432132\
+                6889464182768467546703537516986049910576551282076245490090389328\
+                9440758685084551339423045832369032229481658085593321233482747978\
+                26204144723168738177180919299881250404026184124858368.0000000000");
+
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus, 0, false), "0");
+    assert_eq!(to_string(f, minf64, Minus, 1, false), "0.0");
+    assert_eq!(to_string(f, minf64, Minus, 10, false), "0.0000000000");
+    assert_eq!(to_string(f, minf64, Minus, 100, false),
+               "0.0000000000000000000000000000000000000000000000000000000000000000\
+                  000000000000000000000000000000000000");
+    assert_eq!(to_string(f, minf64, Minus, 1000, false),
+               "0.0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0004940656458412465441765687928682213723650598026143247644255856\
+                  8250067550727020875186529983636163599237979656469544571773092665\
+                  6710355939796398774796010781878126300713190311404527845817167848\
+                  9821036887186360569987307230500063874091535649843873124733972731\
+                  6961514003171538539807412623856559117102665855668676818703956031\
+                  0624931945271591492455329305456544401127480129709999541931989409\
+                  0804165633245247571478690147267801593552386115501348035264934720\
+                  1937902681071074917033322268447533357208324319360923828934583680\
+                  6010601150616980975307834227731832924790498252473077637592724787\
+                  4656084778203734469699533647017972677717585125660551199131504891\
+                  1014510378627381672509558373897335989937");
+
+    // very large output
+    assert_eq!(to_string(f, 0.0,     Minus, 80000, false), format!("0.{:0>80000}", ""));
+    assert_eq!(to_string(f, 1.0e1,   Minus, 80000, false), format!("10.{:0>80000}", ""));
+    assert_eq!(to_string(f, 1.0e0,   Minus, 80000, false), format!("1.{:0>80000}", ""));
+    assert_eq!(to_string(f, 1.0e-1,  Minus, 80000, false),
+               format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", ""));
+    assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
+               format!("0.0000000000000000000099999999999999994515327145420957165172950370\
+                          2787392447107715776066783064379706047475337982177734375{:0>79881}", ""));
+}
+
diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs
new file mode 100644
index 00000000000..4edb0f3df60
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs
@@ -0,0 +1,74 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use super::super::*;
+use core::num::bignum::Big32x40 as Big;
+use core::num::flt2dec::strategy::dragon::*;
+
+#[test]
+fn test_mul_pow10() {
+    let mut prevpow10 = Big::from_small(1);
+    for i in 1..340 {
+        let mut curpow10 = Big::from_small(1);
+        mul_pow10(&mut curpow10, i);
+        assert_eq!(curpow10, *prevpow10.clone().mul_small(10));
+        prevpow10 = curpow10;
+    }
+}
+
+#[test]
+fn shortest_sanity_test() {
+    f64_shortest_sanity_test(format_shortest);
+    f32_shortest_sanity_test(format_shortest);
+    more_shortest_sanity_test(format_shortest);
+}
+
+#[test]
+fn exact_sanity_test() {
+    // This test ends up running what I can only assume is some corner-ish case
+    // of the `exp2` library function, defined in whatever C runtime we're
+    // using. In VS 2013 this function apparently had a bug as this test fails
+    // when linked, but with VS 2015 the bug appears fixed as the test runs just
+    // fine.
+    //
+    // The bug seems to be a difference in return value of `exp2(-1057)`, where
+    // in VS 2013 it returns a double with the bit pattern 0x2 and in VS 2015 it
+    // returns 0x20000.
+    //
+    // For now just ignore this test entirely on MSVC as it's tested elsewhere
+    // anyway and we're not super interested in testing each platform's exp2
+    // implementation.
+    if !cfg!(target_env = "msvc") {
+        f64_exact_sanity_test(format_exact);
+    }
+    f32_exact_sanity_test(format_exact);
+}
+
+#[test]
+fn test_to_shortest_str() {
+    to_shortest_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_shortest_exp_str() {
+    to_shortest_exp_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_exact_exp_str() {
+    to_exact_exp_str_test(format_exact);
+}
+
+#[test]
+fn test_to_exact_fixed_str() {
+    to_exact_fixed_str_test(format_exact);
+}
+
diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs
new file mode 100644
index 00000000000..79e66ee669e
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs
@@ -0,0 +1,124 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::i16;
+use super::super::*;
+use core::num::flt2dec::strategy::grisu::*;
+
+#[test]
+fn test_cached_power() {
+    assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E);
+    assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E);
+
+    for e in -1137..961 { // full range for f64
+        let low = ALPHA - e - 64;
+        let high = GAMMA - e - 64;
+        let (_k, cached) = cached_power(low, high);
+        assert!(low <= cached.e && cached.e <= high,
+                "cached_power({}, {}) = {:?} is incorrect", low, high, cached);
+    }
+}
+
+#[test]
+fn test_max_pow10_no_more_than() {
+    let mut prevtenk = 1;
+    for k in 1..10 {
+        let tenk = prevtenk * 10;
+        assert_eq!(max_pow10_no_more_than(tenk - 1), (k - 1, prevtenk));
+        assert_eq!(max_pow10_no_more_than(tenk), (k, tenk));
+        prevtenk = tenk;
+    }
+}
+
+
+#[test]
+fn shortest_sanity_test() {
+    f64_shortest_sanity_test(format_shortest);
+    f32_shortest_sanity_test(format_shortest);
+    more_shortest_sanity_test(format_shortest);
+}
+
+#[test]
+fn shortest_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
+    f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
+}
+
+#[test] #[ignore] // it is too expensive
+fn shortest_f32_exhaustive_equivalence_test() {
+    // it is hard to directly test the optimality of the output, but we can at least test if
+    // two different algorithms agree to each other.
+    //
+    // this reports the progress and the number of f32 values returned `None`.
+    // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print:
+    // `done, ignored=17643158 passed=2121451881 failed=0`.
+
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
+}
+
+#[test] #[ignore] // it is too expensive
+fn shortest_f64_hard_random_equivalence_test() {
+    // this again probably has to use appropriate rustc flags.
+
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f64_random_equivalence_test(format_shortest_opt, fallback,
+                                         MAX_SIG_DIGITS, 100_000_000);
+}
+
+#[test]
+fn exact_sanity_test() {
+    // See comments in dragon.rs's exact_sanity_test for why this test is
+    // ignored on MSVC
+    if !cfg!(target_env = "msvc") {
+        f64_exact_sanity_test(format_exact);
+    }
+    f32_exact_sanity_test(format_exact);
+}
+
+#[test]
+fn exact_f32_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+    for k in 1..21 {
+        f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
+                                             |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
+    }
+}
+
+#[test]
+fn exact_f64_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+    for k in 1..21 {
+        f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
+                                             |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
+    }
+}
+
+#[test]
+fn test_to_shortest_str() {
+    to_shortest_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_shortest_exp_str() {
+    to_shortest_exp_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_exact_exp_str() {
+    to_exact_exp_str_test(format_exact);
+}
+
+#[test]
+fn test_to_exact_fixed_str() {
+    to_exact_fixed_str_test(format_exact);
+}
+
diff --git a/src/libcore/tests/num/i16.rs b/src/libcore/tests/num/i16.rs
new file mode 100644
index 00000000000..7435831ac6d
--- /dev/null
+++ b/src/libcore/tests/num/i16.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i16, i16);
diff --git a/src/libcore/tests/num/i32.rs b/src/libcore/tests/num/i32.rs
new file mode 100644
index 00000000000..3b3407e1ada
--- /dev/null
+++ b/src/libcore/tests/num/i32.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i32, i32);
diff --git a/src/libcore/tests/num/i64.rs b/src/libcore/tests/num/i64.rs
new file mode 100644
index 00000000000..9e1aec256ee
--- /dev/null
+++ b/src/libcore/tests/num/i64.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i64, i64);
diff --git a/src/libcore/tests/num/i8.rs b/src/libcore/tests/num/i8.rs
new file mode 100644
index 00000000000..f72244239b2
--- /dev/null
+++ b/src/libcore/tests/num/i8.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i8, i8);
diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs
new file mode 100644
index 00000000000..8d791283ab8
--- /dev/null
+++ b/src/libcore/tests/num/int_macros.rs
@@ -0,0 +1,219 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! int_module { ($T:ident, $T_i:ident) => (
+#[cfg(test)]
+mod tests {
+    use core::$T_i::*;
+    use core::isize;
+    use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
+    use core::mem;
+
+    use num;
+
+    #[test]
+    fn test_overflows() {
+        assert!(MAX > 0);
+        assert!(MIN <= 0);
+        assert!(MIN + MAX + 1 == 0);
+    }
+
+    #[test]
+    fn test_num() {
+        num::test_num(10 as $T, 2 as $T);
+    }
+
+    #[test]
+    pub fn test_abs() {
+        assert!((1 as $T).abs() == 1 as $T);
+        assert!((0 as $T).abs() == 0 as $T);
+        assert!((-1 as $T).abs() == 1 as $T);
+    }
+
+    #[test]
+    fn test_signum() {
+        assert!((1 as $T).signum() == 1 as $T);
+        assert!((0 as $T).signum() == 0 as $T);
+        assert!((-0 as $T).signum() == 0 as $T);
+        assert!((-1 as $T).signum() == -1 as $T);
+    }
+
+    #[test]
+    fn test_is_positive() {
+        assert!((1 as $T).is_positive());
+        assert!(!(0 as $T).is_positive());
+        assert!(!(-0 as $T).is_positive());
+        assert!(!(-1 as $T).is_positive());
+    }
+
+    #[test]
+    fn test_is_negative() {
+        assert!(!(1 as $T).is_negative());
+        assert!(!(0 as $T).is_negative());
+        assert!(!(-0 as $T).is_negative());
+        assert!((-1 as $T).is_negative());
+    }
+
+    #[test]
+    fn test_bitwise_operators() {
+        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+        assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
+    }
+
+    const A: $T = 0b0101100;
+    const B: $T = 0b0100001;
+    const C: $T = 0b1111001;
+
+    const _0: $T = 0;
+    const _1: $T = !0;
+
+    #[test]
+    fn test_count_ones() {
+        assert!(A.count_ones() == 3);
+        assert!(B.count_ones() == 2);
+        assert!(C.count_ones() == 5);
+    }
+
+    #[test]
+    fn test_count_zeros() {
+        let bits = mem::size_of::<$T>() * 8;
+        assert!(A.count_zeros() == bits as u32 - 3);
+        assert!(B.count_zeros() == bits as u32 - 2);
+        assert!(C.count_zeros() == bits as u32 - 5);
+    }
+
+    #[test]
+    fn test_rotate() {
+        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+
+        // Rotating these should make no difference
+        //
+        // We test using 124 bits because to ensure that overlong bit shifts do
+        // not cause undefined behaviour. See #10183.
+        assert_eq!(_0.rotate_left(124), _0);
+        assert_eq!(_1.rotate_left(124), _1);
+        assert_eq!(_0.rotate_right(124), _0);
+        assert_eq!(_1.rotate_right(124), _1);
+
+        // Rotating by 0 should have no effect
+        assert_eq!(A.rotate_left(0), A);
+        assert_eq!(B.rotate_left(0), B);
+        assert_eq!(C.rotate_left(0), C);
+        // Rotating by a multiple of word size should also have no effect
+        assert_eq!(A.rotate_left(64), A);
+        assert_eq!(B.rotate_left(64), B);
+        assert_eq!(C.rotate_left(64), C);
+    }
+
+    #[test]
+    fn test_swap_bytes() {
+        assert_eq!(A.swap_bytes().swap_bytes(), A);
+        assert_eq!(B.swap_bytes().swap_bytes(), B);
+        assert_eq!(C.swap_bytes().swap_bytes(), C);
+
+        // Swapping these should make no difference
+        assert_eq!(_0.swap_bytes(), _0);
+        assert_eq!(_1.swap_bytes(), _1);
+    }
+
+    #[test]
+    fn test_le() {
+        assert_eq!($T::from_le(A.to_le()), A);
+        assert_eq!($T::from_le(B.to_le()), B);
+        assert_eq!($T::from_le(C.to_le()), C);
+        assert_eq!($T::from_le(_0), _0);
+        assert_eq!($T::from_le(_1), _1);
+        assert_eq!(_0.to_le(), _0);
+        assert_eq!(_1.to_le(), _1);
+    }
+
+    #[test]
+    fn test_be() {
+        assert_eq!($T::from_be(A.to_be()), A);
+        assert_eq!($T::from_be(B.to_be()), B);
+        assert_eq!($T::from_be(C.to_be()), C);
+        assert_eq!($T::from_be(_0), _0);
+        assert_eq!($T::from_be(_1), _1);
+        assert_eq!(_0.to_be(), _0);
+        assert_eq!(_1.to_be(), _1);
+    }
+
+    #[test]
+    fn test_signed_checked_div() {
+        assert!((10 as $T).checked_div(2) == Some(5));
+        assert!((5 as $T).checked_div(0) == None);
+        assert!(isize::MIN.checked_div(-1) == None);
+    }
+
+    #[test]
+    fn test_from_str() {
+        fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
+            ::std::str::FromStr::from_str(t).ok()
+        }
+        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+        assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
+        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+        assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
+        assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
+        assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
+        assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
+        assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
+
+        assert_eq!(from_str::<$T>(""), None);
+        assert_eq!(from_str::<$T>(" "), None);
+        assert_eq!(from_str::<$T>("x"), None);
+    }
+
+    #[test]
+    fn test_from_str_radix() {
+        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+        assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
+        assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
+        assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
+        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+        assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
+
+        assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
+        assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
+        assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
+        assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
+        assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
+        assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
+        assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
+        assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
+
+        assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
+        assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
+    }
+
+    #[test]
+    fn test_pow() {
+        let mut r = 2 as $T;
+
+        assert_eq!(r.pow(2), 4 as $T);
+        assert_eq!(r.pow(0), 1 as $T);
+        r = -2 as $T;
+        assert_eq!(r.pow(2), 4 as $T);
+        assert_eq!(r.pow(3), -8 as $T);
+    }
+}
+
+)}
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
new file mode 100644
index 00000000000..51737c9c3b4
--- /dev/null
+++ b/src/libcore/tests/num/mod.rs
@@ -0,0 +1,400 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::convert::TryFrom;
+use core::cmp::PartialEq;
+use core::fmt::Debug;
+use core::marker::Copy;
+use core::ops::{Add, Sub, Mul, Div, Rem};
+use core::option::Option;
+use core::option::Option::{Some, None};
+
+#[macro_use]
+mod int_macros;
+
+mod i8;
+mod i16;
+mod i32;
+mod i64;
+
+#[macro_use]
+mod uint_macros;
+
+mod u8;
+mod u16;
+mod u32;
+mod u64;
+
+mod flt2dec;
+mod dec2flt;
+mod bignum;
+
+/// Helper function for testing numeric operations
+pub fn test_num<T>(ten: T, two: T) where
+    T: PartialEq
+     + Add<Output=T> + Sub<Output=T>
+     + Mul<Output=T> + Div<Output=T>
+     + Rem<Output=T> + Debug
+     + Copy
+{
+    assert_eq!(ten.add(two),  ten + two);
+    assert_eq!(ten.sub(two),  ten - two);
+    assert_eq!(ten.mul(two),  ten * two);
+    assert_eq!(ten.div(two),  ten / two);
+    assert_eq!(ten.rem(two),  ten % two);
+}
+
+#[test]
+fn from_str_issue7588() {
+    let u : Option<u8> = u8::from_str_radix("1000", 10).ok();
+    assert_eq!(u, None);
+    let s : Option<i16> = i16::from_str_radix("80000", 10).ok();
+    assert_eq!(s, None);
+}
+
+#[test]
+fn test_int_from_str_overflow() {
+    let mut i8_val: i8 = 127;
+    assert_eq!("127".parse::<i8>().ok(), Some(i8_val));
+    assert_eq!("128".parse::<i8>().ok(), None);
+
+    i8_val = i8_val.wrapping_add(1);
+    assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
+    assert_eq!("-129".parse::<i8>().ok(), None);
+
+    let mut i16_val: i16 = 32_767;
+    assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
+    assert_eq!("32768".parse::<i16>().ok(), None);
+
+    i16_val = i16_val.wrapping_add(1);
+    assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
+    assert_eq!("-32769".parse::<i16>().ok(), None);
+
+    let mut i32_val: i32 = 2_147_483_647;
+    assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
+    assert_eq!("2147483648".parse::<i32>().ok(), None);
+
+    i32_val = i32_val.wrapping_add(1);
+    assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
+    assert_eq!("-2147483649".parse::<i32>().ok(), None);
+
+    let mut i64_val: i64 = 9_223_372_036_854_775_807;
+    assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
+    assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
+
+    i64_val = i64_val.wrapping_add(1);
+    assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
+    assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
+}
+
+#[test]
+fn test_leading_plus() {
+    assert_eq!("+127".parse::<u8>().ok(), Some(127));
+    assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807));
+}
+
+#[test]
+fn test_invalid() {
+    assert_eq!("--129".parse::<i8>().ok(), None);
+    assert_eq!("++129".parse::<i8>().ok(), None);
+    assert_eq!("Съешь".parse::<u8>().ok(), None);
+}
+
+#[test]
+fn test_empty() {
+    assert_eq!("-".parse::<i8>().ok(), None);
+    assert_eq!("+".parse::<i8>().ok(), None);
+    assert_eq!("".parse::<u8>().ok(), None);
+}
+
+macro_rules! test_impl_from {
+    ($fn_name: ident, $Small: ty, $Large: ty) => {
+        #[test]
+        fn $fn_name() {
+            let small_max = <$Small>::max_value();
+            let small_min = <$Small>::min_value();
+            let large_max: $Large = small_max.into();
+            let large_min: $Large = small_min.into();
+            assert_eq!(large_max as $Small, small_max);
+            assert_eq!(large_min as $Small, small_min);
+        }
+    }
+}
+
+// Unsigned -> Unsigned
+test_impl_from! { test_u8u16, u8, u16 }
+test_impl_from! { test_u8u32, u8, u32 }
+test_impl_from! { test_u8u64, u8, u64 }
+test_impl_from! { test_u8usize, u8, usize }
+test_impl_from! { test_u16u32, u16, u32 }
+test_impl_from! { test_u16u64, u16, u64 }
+test_impl_from! { test_u32u64, u32, u64 }
+
+// Signed -> Signed
+test_impl_from! { test_i8i16, i8, i16 }
+test_impl_from! { test_i8i32, i8, i32 }
+test_impl_from! { test_i8i64, i8, i64 }
+test_impl_from! { test_i8isize, i8, isize }
+test_impl_from! { test_i16i32, i16, i32 }
+test_impl_from! { test_i16i64, i16, i64 }
+test_impl_from! { test_i32i64, i32, i64 }
+
+// Unsigned -> Signed
+test_impl_from! { test_u8i16, u8, i16 }
+test_impl_from! { test_u8i32, u8, i32 }
+test_impl_from! { test_u8i64, u8, i64 }
+test_impl_from! { test_u16i32, u16, i32 }
+test_impl_from! { test_u16i64, u16, i64 }
+test_impl_from! { test_u32i64, u32, i64 }
+
+// Signed -> Float
+test_impl_from! { test_i8f32, i8, f32 }
+test_impl_from! { test_i8f64, i8, f64 }
+test_impl_from! { test_i16f32, i16, f32 }
+test_impl_from! { test_i16f64, i16, f64 }
+test_impl_from! { test_i32f64, i32, f64 }
+
+// Unsigned -> Float
+test_impl_from! { test_u8f32, u8, f32 }
+test_impl_from! { test_u8f64, u8, f64 }
+test_impl_from! { test_u16f32, u16, f32 }
+test_impl_from! { test_u16f64, u16, f64 }
+test_impl_from! { test_u32f64, u32, f64 }
+
+// Float -> Float
+#[test]
+fn test_f32f64() {
+    use core::f32;
+
+    let max: f64 = f32::MAX.into();
+    assert_eq!(max as f32, f32::MAX);
+    assert!(max.is_normal());
+
+    let min: f64 = f32::MIN.into();
+    assert_eq!(min as f32, f32::MIN);
+    assert!(min.is_normal());
+
+    let min_positive: f64 = f32::MIN_POSITIVE.into();
+    assert_eq!(min_positive as f32, f32::MIN_POSITIVE);
+    assert!(min_positive.is_normal());
+
+    let epsilon: f64 = f32::EPSILON.into();
+    assert_eq!(epsilon as f32, f32::EPSILON);
+    assert!(epsilon.is_normal());
+
+    let zero: f64 = (0.0f32).into();
+    assert_eq!(zero as f32, 0.0f32);
+    assert!(zero.is_sign_positive());
+
+    let neg_zero: f64 = (-0.0f32).into();
+    assert_eq!(neg_zero as f32, -0.0f32);
+    assert!(neg_zero.is_sign_negative());
+
+    let infinity: f64 = f32::INFINITY.into();
+    assert_eq!(infinity as f32, f32::INFINITY);
+    assert!(infinity.is_infinite());
+    assert!(infinity.is_sign_positive());
+
+    let neg_infinity: f64 = f32::NEG_INFINITY.into();
+    assert_eq!(neg_infinity as f32, f32::NEG_INFINITY);
+    assert!(neg_infinity.is_infinite());
+    assert!(neg_infinity.is_sign_negative());
+
+    let nan: f64 = f32::NAN.into();
+    assert!(nan.is_nan());
+}
+
+macro_rules! test_impl_try_from_always_ok {
+    ($fn_name:ident, $source:ty, $target: ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
+                       max as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
+                       min as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+        }
+    }
+}
+
+test_impl_try_from_always_ok! { test_try_u8u8, u8, u8 }
+test_impl_try_from_always_ok! { test_try_u8u16, u8, u16 }
+test_impl_try_from_always_ok! { test_try_u8u32, u8, u32 }
+test_impl_try_from_always_ok! { test_try_u8u64, u8, u64 }
+test_impl_try_from_always_ok! { test_try_u8i16, u8, i16 }
+test_impl_try_from_always_ok! { test_try_u8i32, u8, i32 }
+test_impl_try_from_always_ok! { test_try_u8i64, u8, i64 }
+
+test_impl_try_from_always_ok! { test_try_u16u16, u16, u16 }
+test_impl_try_from_always_ok! { test_try_u16u32, u16, u32 }
+test_impl_try_from_always_ok! { test_try_u16u64, u16, u64 }
+test_impl_try_from_always_ok! { test_try_u16i32, u16, i32 }
+test_impl_try_from_always_ok! { test_try_u16i64, u16, i64 }
+
+test_impl_try_from_always_ok! { test_try_u32u32, u32, u32 }
+test_impl_try_from_always_ok! { test_try_u32u64, u32, u64 }
+test_impl_try_from_always_ok! { test_try_u32i64, u32, i64 }
+
+test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 }
+
+test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 }
+test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 }
+test_impl_try_from_always_ok! { test_try_i8i32, i8, i32 }
+test_impl_try_from_always_ok! { test_try_i8i64, i8, i64 }
+
+test_impl_try_from_always_ok! { test_try_i16i16, i16, i16 }
+test_impl_try_from_always_ok! { test_try_i16i32, i16, i32 }
+test_impl_try_from_always_ok! { test_try_i16i64, i16, i64 }
+
+test_impl_try_from_always_ok! { test_try_i32i32, i32, i32 }
+test_impl_try_from_always_ok! { test_try_i32i64, i32, i64 }
+
+test_impl_try_from_always_ok! { test_try_i64i64, i64, i64 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            let neg_one: $source = -1;
+            assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
+                       max as $target);
+            assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+            assert!(<$target as TryFrom<$source>>::try_from(neg_one).is_err());
+        }
+    }
+}
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u8, i8, u8 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u16, i8, u16 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u32, i8, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u64, i8, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u16, i16, u16 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u32, i16, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u64, i16, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u32, i32, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u64, i32, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u64, i64, u64 }
+
+macro_rules! test_impl_try_from_unsigned_to_signed_upper_err {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+            assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
+                       min as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+        }
+    }
+}
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u8i8, u8, i8 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i8, u16, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i16, u16, i16 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i8, u32, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i16, u32, i16 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i32, u32, i32 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i8, u64, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i16, u64, i16 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i32, u64, i32 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i64, u64, i64 }
+
+macro_rules! test_impl_try_from_same_sign_err {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            let t_max = <$target>::max_value();
+            let t_min = <$target>::min_value();
+            assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+            if min != 0 {
+                assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+            }
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+                            .unwrap(),
+                       t_max as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+                            .unwrap(),
+                       t_min as $target);
+        }
+    }
+}
+
+test_impl_try_from_same_sign_err! { test_try_u16u8, u16, u8 }
+
+test_impl_try_from_same_sign_err! { test_try_u32u8, u32, u8 }
+test_impl_try_from_same_sign_err! { test_try_u32u16, u32, u16 }
+
+test_impl_try_from_same_sign_err! { test_try_u64u8, u64, u8 }
+test_impl_try_from_same_sign_err! { test_try_u64u16, u64, u16 }
+test_impl_try_from_same_sign_err! { test_try_u64u32, u64, u32 }
+
+test_impl_try_from_same_sign_err! { test_try_i16i8, i16, i8 }
+
+test_impl_try_from_same_sign_err! { test_try_i32i8, i32, i8 }
+test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 }
+
+test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 }
+test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 }
+test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_err {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            let t_max = <$target>::max_value();
+            let t_min = <$target>::min_value();
+            assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+            assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+                            .unwrap(),
+                       t_max as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+                            .unwrap(),
+                       t_min as $target);
+        }
+    }
+}
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }
diff --git a/src/libcore/tests/num/u16.rs b/src/libcore/tests/num/u16.rs
new file mode 100644
index 00000000000..8455207583c
--- /dev/null
+++ b/src/libcore/tests/num/u16.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u16, u16);
diff --git a/src/libcore/tests/num/u32.rs b/src/libcore/tests/num/u32.rs
new file mode 100644
index 00000000000..b44e60f6529
--- /dev/null
+++ b/src/libcore/tests/num/u32.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u32, u32);
diff --git a/src/libcore/tests/num/u64.rs b/src/libcore/tests/num/u64.rs
new file mode 100644
index 00000000000..ffcd1015d58
--- /dev/null
+++ b/src/libcore/tests/num/u64.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u64, u64);
diff --git a/src/libcore/tests/num/u8.rs b/src/libcore/tests/num/u8.rs
new file mode 100644
index 00000000000..4ee14e22f2d
--- /dev/null
+++ b/src/libcore/tests/num/u8.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u8, u8);
diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs
new file mode 100644
index 00000000000..daa1cc3a7f4
--- /dev/null
+++ b/src/libcore/tests/num/uint_macros.rs
@@ -0,0 +1,158 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! uint_module { ($T:ident, $T_i:ident) => (
+#[cfg(test)]
+mod tests {
+    use core::$T_i::*;
+    use num;
+    use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
+    use std::str::FromStr;
+    use std::mem;
+
+    #[test]
+    fn test_overflows() {
+        assert!(MAX > 0);
+        assert!(MIN <= 0);
+        assert!((MIN + MAX).wrapping_add(1) == 0);
+    }
+
+    #[test]
+    fn test_num() {
+        num::test_num(10 as $T, 2 as $T);
+    }
+
+    #[test]
+    fn test_bitwise_operators() {
+        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+        assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
+    }
+
+    const A: $T = 0b0101100;
+    const B: $T = 0b0100001;
+    const C: $T = 0b1111001;
+
+    const _0: $T = 0;
+    const _1: $T = !0;
+
+    #[test]
+    fn test_count_ones() {
+        assert!(A.count_ones() == 3);
+        assert!(B.count_ones() == 2);
+        assert!(C.count_ones() == 5);
+    }
+
+    #[test]
+    fn test_count_zeros() {
+        let bits = mem::size_of::<$T>() * 8;
+        assert!(A.count_zeros() == bits as u32 - 3);
+        assert!(B.count_zeros() == bits as u32 - 2);
+        assert!(C.count_zeros() == bits as u32 - 5);
+    }
+
+    #[test]
+    fn test_rotate() {
+        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+
+        // Rotating these should make no difference
+        //
+        // We test using 124 bits because to ensure that overlong bit shifts do
+        // not cause undefined behaviour. See #10183.
+        assert_eq!(_0.rotate_left(124), _0);
+        assert_eq!(_1.rotate_left(124), _1);
+        assert_eq!(_0.rotate_right(124), _0);
+        assert_eq!(_1.rotate_right(124), _1);
+
+        // Rotating by 0 should have no effect
+        assert_eq!(A.rotate_left(0), A);
+        assert_eq!(B.rotate_left(0), B);
+        assert_eq!(C.rotate_left(0), C);
+        // Rotating by a multiple of word size should also have no effect
+        assert_eq!(A.rotate_left(64), A);
+        assert_eq!(B.rotate_left(64), B);
+        assert_eq!(C.rotate_left(64), C);
+    }
+
+    #[test]
+    fn test_swap_bytes() {
+        assert_eq!(A.swap_bytes().swap_bytes(), A);
+        assert_eq!(B.swap_bytes().swap_bytes(), B);
+        assert_eq!(C.swap_bytes().swap_bytes(), C);
+
+        // Swapping these should make no difference
+        assert_eq!(_0.swap_bytes(), _0);
+        assert_eq!(_1.swap_bytes(), _1);
+    }
+
+    #[test]
+    fn test_le() {
+        assert_eq!($T::from_le(A.to_le()), A);
+        assert_eq!($T::from_le(B.to_le()), B);
+        assert_eq!($T::from_le(C.to_le()), C);
+        assert_eq!($T::from_le(_0), _0);
+        assert_eq!($T::from_le(_1), _1);
+        assert_eq!(_0.to_le(), _0);
+        assert_eq!(_1.to_le(), _1);
+    }
+
+    #[test]
+    fn test_be() {
+        assert_eq!($T::from_be(A.to_be()), A);
+        assert_eq!($T::from_be(B.to_be()), B);
+        assert_eq!($T::from_be(C.to_be()), C);
+        assert_eq!($T::from_be(_0), _0);
+        assert_eq!($T::from_be(_1), _1);
+        assert_eq!(_0.to_be(), _0);
+        assert_eq!(_1.to_be(), _1);
+    }
+
+    #[test]
+    fn test_unsigned_checked_div() {
+        assert!((10 as $T).checked_div(2) == Some(5));
+        assert!((5 as $T).checked_div(0) == None);
+    }
+
+    fn from_str<T: FromStr>(t: &str) -> Option<T> {
+        FromStr::from_str(t).ok()
+    }
+
+    #[test]
+    pub fn test_from_str() {
+        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+        assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
+        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+        assert_eq!(from_str::<$T>(""), None);
+        assert_eq!(from_str::<$T>(" "), None);
+        assert_eq!(from_str::<$T>("x"), None);
+    }
+
+    #[test]
+    pub fn test_parse_bytes() {
+        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+        assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16));
+        assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+
+        assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
+        assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
+    }
+}
+)}
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
new file mode 100644
index 00000000000..1c6c13b0d02
--- /dev/null
+++ b/src/libcore/tests/ops.rs
@@ -0,0 +1,49 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
+
+// Test the Range structs without the syntactic sugar.
+
+#[test]
+fn test_range() {
+    let r = Range { start: 2, end: 10 };
+    let mut count = 0;
+    for (i, ri) in r.enumerate() {
+        assert!(ri == i + 2);
+        assert!(ri >= 2 && ri < 10);
+        count += 1;
+    }
+    assert!(count == 8);
+}
+
+#[test]
+fn test_range_from() {
+    let r = RangeFrom { start: 2 };
+    let mut count = 0;
+    for (i, ri) in r.take(10).enumerate() {
+        assert!(ri == i + 2);
+        assert!(ri >= 2 && ri < 12);
+        count += 1;
+    }
+    assert!(count == 10);
+}
+
+#[test]
+fn test_range_to() {
+    // Not much to test.
+    let _ = RangeTo { end: 42 };
+}
+
+#[test]
+fn test_full_range() {
+    // Not much to test.
+    let _ = RangeFull;
+}
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
new file mode 100644
index 00000000000..51b0655f680
--- /dev/null
+++ b/src/libcore/tests/option.rs
@@ -0,0 +1,272 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::option::*;
+use core::mem;
+use core::clone::Clone;
+
+#[test]
+fn test_get_ptr() {
+    unsafe {
+        let x: Box<_> = box 0;
+        let addr_x: *const isize = mem::transmute(&*x);
+        let opt = Some(x);
+        let y = opt.unwrap();
+        let addr_y: *const isize = mem::transmute(&*y);
+        assert_eq!(addr_x, addr_y);
+    }
+}
+
+#[test]
+fn test_get_str() {
+    let x = "test".to_string();
+    let addr_x = x.as_ptr();
+    let opt = Some(x);
+    let y = opt.unwrap();
+    let addr_y = y.as_ptr();
+    assert_eq!(addr_x, addr_y);
+}
+
+#[test]
+fn test_get_resource() {
+    use std::rc::Rc;
+    use core::cell::RefCell;
+
+    struct R {
+       i: Rc<RefCell<isize>>,
+    }
+
+        impl Drop for R {
+       fn drop(&mut self) {
+            let ii = &*self.i;
+            let i = *ii.borrow();
+            *ii.borrow_mut() = i + 1;
+        }
+    }
+
+    fn r(i: Rc<RefCell<isize>>) -> R {
+        R {
+            i: i
+        }
+    }
+
+    let i = Rc::new(RefCell::new(0));
+    {
+        let x = r(i.clone());
+        let opt = Some(x);
+        let _y = opt.unwrap();
+    }
+    assert_eq!(*i.borrow(), 1);
+}
+
+#[test]
+fn test_option_dance() {
+    let x = Some(());
+    let mut y = Some(5);
+    let mut y2 = 0;
+    for _x in x {
+        y2 = y.take().unwrap();
+    }
+    assert_eq!(y2, 5);
+    assert!(y.is_none());
+}
+
+#[test] #[should_panic]
+fn test_option_too_much_dance() {
+    struct A;
+    let mut y = Some(A);
+    let _y2 = y.take().unwrap();
+    let _y3 = y.take().unwrap();
+}
+
+#[test]
+fn test_and() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.and(Some(2)), Some(2));
+    assert_eq!(x.and(None::<isize>), None);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.and(Some(2)), None);
+    assert_eq!(x.and(None::<isize>), None);
+}
+
+#[test]
+fn test_and_then() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.and_then(|x| Some(x + 1)), Some(2));
+    assert_eq!(x.and_then(|_| None::<isize>), None);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.and_then(|x| Some(x + 1)), None);
+    assert_eq!(x.and_then(|_| None::<isize>), None);
+}
+
+#[test]
+fn test_or() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.or(Some(2)), Some(1));
+    assert_eq!(x.or(None), Some(1));
+
+    let x: Option<isize> = None;
+    assert_eq!(x.or(Some(2)), Some(2));
+    assert_eq!(x.or(None), None);
+}
+
+#[test]
+fn test_or_else() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.or_else(|| Some(2)), Some(1));
+    assert_eq!(x.or_else(|| None), Some(1));
+
+    let x: Option<isize> = None;
+    assert_eq!(x.or_else(|| Some(2)), Some(2));
+    assert_eq!(x.or_else(|| None), None);
+}
+
+#[test]
+fn test_unwrap() {
+    assert_eq!(Some(1).unwrap(), 1);
+    let s = Some("hello".to_string()).unwrap();
+    assert_eq!(s, "hello");
+}
+
+#[test]
+#[should_panic]
+fn test_unwrap_panic1() {
+    let x: Option<isize> = None;
+    x.unwrap();
+}
+
+#[test]
+#[should_panic]
+fn test_unwrap_panic2() {
+    let x: Option<String> = None;
+    x.unwrap();
+}
+
+#[test]
+fn test_unwrap_or() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.unwrap_or(2), 1);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.unwrap_or(2), 2);
+}
+
+#[test]
+fn test_unwrap_or_else() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.unwrap_or_else(|| 2), 1);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.unwrap_or_else(|| 2), 2);
+}
+
+#[test]
+fn test_iter() {
+    let val = 5;
+
+    let x = Some(val);
+    let mut it = x.iter();
+
+    assert_eq!(it.size_hint(), (1, Some(1)));
+    assert_eq!(it.next(), Some(&val));
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert!(it.next().is_none());
+
+    let mut it = (&x).into_iter();
+    assert_eq!(it.next(), Some(&val));
+}
+
+#[test]
+fn test_mut_iter() {
+    let mut val = 5;
+    let new_val = 11;
+
+    let mut x = Some(val);
+    {
+        let mut it = x.iter_mut();
+
+        assert_eq!(it.size_hint(), (1, Some(1)));
+
+        match it.next() {
+            Some(interior) => {
+                assert_eq!(*interior, val);
+                *interior = new_val;
+            }
+            None => assert!(false),
+        }
+
+        assert_eq!(it.size_hint(), (0, Some(0)));
+        assert!(it.next().is_none());
+    }
+    assert_eq!(x, Some(new_val));
+
+    let mut y = Some(val);
+    let mut it = (&mut y).into_iter();
+    assert_eq!(it.next(), Some(&mut val));
+}
+
+#[test]
+fn test_ord() {
+    let small = Some(1.0f64);
+    let big = Some(5.0f64);
+    let nan = Some(0.0f64/0.0);
+    assert!(!(nan < big));
+    assert!(!(nan > big));
+    assert!(small < big);
+    assert!(None < big);
+    assert!(big > None);
+}
+
+#[test]
+fn test_collect() {
+    let v: Option<Vec<isize>> = (0..0).map(|_| Some(0)).collect();
+    assert!(v == Some(vec![]));
+
+    let v: Option<Vec<isize>> = (0..3).map(|x| Some(x)).collect();
+    assert!(v == Some(vec![0, 1, 2]));
+
+    let v: Option<Vec<isize>> = (0..3).map(|x| {
+        if x > 1 { None } else { Some(x) }
+    }).collect();
+    assert!(v == None);
+
+    // test that it does not take more elements than it needs
+    let mut functions: [Box<Fn() -> Option<()>>; 3] =
+        [box || Some(()), box || None, box || panic!()];
+
+    let v: Option<Vec<()>> = functions.iter_mut().map(|f| (*f)()).collect();
+
+    assert!(v == None);
+}
+
+
+#[test]
+fn test_cloned() {
+    let val = 1;
+    let val_ref = &val;
+    let opt_none: Option<&'static u32> = None;
+    let opt_ref = Some(&val);
+    let opt_ref_ref = Some(&val_ref);
+
+    // None works
+    assert_eq!(opt_none.clone(), None);
+    assert_eq!(opt_none.cloned(), None);
+
+    // Immutable ref works
+    assert_eq!(opt_ref.clone(), Some(&val));
+    assert_eq!(opt_ref.cloned(), Some(1));
+
+    // Double Immutable ref works
+    assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
+    assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
+    assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
+}
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
new file mode 100644
index 00000000000..7f6f472bfbb
--- /dev/null
+++ b/src/libcore/tests/ptr.rs
@@ -0,0 +1,214 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::ptr::*;
+use core::cell::RefCell;
+
+#[test]
+fn test() {
+    unsafe {
+        struct Pair {
+            fst: isize,
+            snd: isize
+        };
+        let mut p = Pair {fst: 10, snd: 20};
+        let pptr: *mut Pair = &mut p;
+        let iptr: *mut isize = pptr as *mut isize;
+        assert_eq!(*iptr, 10);
+        *iptr = 30;
+        assert_eq!(*iptr, 30);
+        assert_eq!(p.fst, 30);
+
+        *pptr = Pair {fst: 50, snd: 60};
+        assert_eq!(*iptr, 50);
+        assert_eq!(p.fst, 50);
+        assert_eq!(p.snd, 60);
+
+        let v0 = vec![32000u16, 32001u16, 32002u16];
+        let mut v1 = vec![0u16, 0u16, 0u16];
+
+        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
+        assert!((v1[0] == 0u16 &&
+                 v1[1] == 32001u16 &&
+                 v1[2] == 0u16));
+        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
+        assert!((v1[0] == 32002u16 &&
+                 v1[1] == 32001u16 &&
+                 v1[2] == 0u16));
+        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
+        assert!((v1[0] == 32002u16 &&
+                 v1[1] == 32001u16 &&
+                 v1[2] == 32000u16));
+    }
+}
+
+#[test]
+fn test_is_null() {
+    let p: *const isize = null();
+    assert!(p.is_null());
+
+    let q = unsafe { p.offset(1) };
+    assert!(!q.is_null());
+
+    let mp: *mut isize = null_mut();
+    assert!(mp.is_null());
+
+    let mq = unsafe { mp.offset(1) };
+    assert!(!mq.is_null());
+}
+
+#[test]
+fn test_as_ref() {
+    unsafe {
+        let p: *const isize = null();
+        assert_eq!(p.as_ref(), None);
+
+        let q: *const isize = &2;
+        assert_eq!(q.as_ref().unwrap(), &2);
+
+        let p: *mut isize = null_mut();
+        assert_eq!(p.as_ref(), None);
+
+        let q: *mut isize = &mut 2;
+        assert_eq!(q.as_ref().unwrap(), &2);
+
+        // Lifetime inference
+        let u = 2isize;
+        {
+            let p = &u as *const isize;
+            assert_eq!(p.as_ref().unwrap(), &2);
+        }
+    }
+}
+
+#[test]
+fn test_as_mut() {
+    unsafe {
+        let p: *mut isize = null_mut();
+        assert!(p.as_mut() == None);
+
+        let q: *mut isize = &mut 2;
+        assert!(q.as_mut().unwrap() == &mut 2);
+
+        // Lifetime inference
+        let mut u = 2isize;
+        {
+            let p = &mut u as *mut isize;
+            assert!(p.as_mut().unwrap() == &mut 2);
+        }
+    }
+}
+
+#[test]
+fn test_ptr_addition() {
+    unsafe {
+        let xs = vec![5; 16];
+        let mut ptr = xs.as_ptr();
+        let end = ptr.offset(16);
+
+        while ptr < end {
+            assert_eq!(*ptr, 5);
+            ptr = ptr.offset(1);
+        }
+
+        let mut xs_mut = xs;
+        let mut m_ptr = xs_mut.as_mut_ptr();
+        let m_end = m_ptr.offset(16);
+
+        while m_ptr < m_end {
+            *m_ptr += 5;
+            m_ptr = m_ptr.offset(1);
+        }
+
+        assert!(xs_mut == vec![10; 16]);
+    }
+}
+
+#[test]
+fn test_ptr_subtraction() {
+    unsafe {
+        let xs = vec![0,1,2,3,4,5,6,7,8,9];
+        let mut idx = 9;
+        let ptr = xs.as_ptr();
+
+        while idx >= 0 {
+            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
+            idx = idx - 1;
+        }
+
+        let mut xs_mut = xs;
+        let m_start = xs_mut.as_mut_ptr();
+        let mut m_ptr = m_start.offset(9);
+
+        while m_ptr >= m_start {
+            *m_ptr += *m_ptr;
+            m_ptr = m_ptr.offset(-1);
+        }
+
+        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
+    }
+}
+
+#[test]
+fn test_set_memory() {
+    let mut xs = [0u8; 20];
+    let ptr = xs.as_mut_ptr();
+    unsafe { write_bytes(ptr, 5u8, xs.len()); }
+    assert!(xs == [5u8; 20]);
+}
+
+#[test]
+fn test_unsized_unique() {
+    let xs: &mut [i32] = &mut [1, 2, 3];
+    let ptr = unsafe { Unique::new(xs as *mut [i32]) };
+    let ys = unsafe { &mut **ptr };
+    let zs: &mut [i32] = &mut [1, 2, 3];
+    assert!(ys == zs);
+}
+
+#[test]
+#[allow(warnings)]
+// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
+// ABI, or even point to an actual executable code, because the function itself is never invoked.
+#[no_mangle]
+pub fn test_variadic_fnptr() {
+    use core::hash::{Hash, SipHasher};
+    extern {
+        fn test_variadic_fnptr(_: u64, ...) -> f64;
+    }
+    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
+    let q = p.clone();
+    assert_eq!(p, q);
+    assert!(!(p < q));
+    let mut s = SipHasher::new();
+    assert_eq!(p.hash(&mut s), q.hash(&mut s));
+}
+
+#[test]
+fn write_unaligned_drop() {
+    thread_local! {
+        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
+    }
+
+    struct Dropper(u32);
+
+    impl Drop for Dropper {
+        fn drop(&mut self) {
+            DROPS.with(|d| d.borrow_mut().push(self.0));
+        }
+    }
+
+    {
+        let c = Dropper(0);
+        let mut t = Dropper(1);
+        unsafe { write_unaligned(&mut t, c); }
+    }
+    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
+}
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
new file mode 100644
index 00000000000..4c5f19dee12
--- /dev/null
+++ b/src/libcore/tests/result.rs
@@ -0,0 +1,204 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn op1() -> Result<isize, &'static str> { Ok(666) }
+fn op2() -> Result<isize, &'static str> { Err("sadface") }
+
+#[test]
+fn test_and() {
+    assert_eq!(op1().and(Ok(667)).unwrap(), 667);
+    assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
+               "bad");
+
+    assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
+    assert_eq!(op2().and(Err::<i32,&'static str>("bad")).unwrap_err(),
+               "sadface");
+}
+
+#[test]
+fn test_and_then() {
+    assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
+    assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
+               "bad");
+
+    assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(),
+               "sadface");
+    assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
+               "sadface");
+}
+
+#[test]
+fn test_or() {
+    assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
+    assert_eq!(op1().or(Err("bad")).unwrap(), 666);
+
+    assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
+    assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
+}
+
+#[test]
+fn test_or_else() {
+    assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
+    assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
+
+    assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
+    assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(),
+               "sadface");
+}
+
+#[test]
+fn test_impl_map() {
+    assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
+    assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
+}
+
+#[test]
+fn test_impl_map_err() {
+    assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
+    assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
+}
+
+#[test]
+fn test_collect() {
+    let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
+    assert!(v == Ok(vec![]));
+
+    let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
+    assert!(v == Ok(vec![0, 1, 2]));
+
+    let v: Result<Vec<isize>, isize> = (0..3).map(|x| {
+        if x > 1 { Err(x) } else { Ok(x) }
+    }).collect();
+    assert!(v == Err(2));
+
+    // test that it does not take more elements than it needs
+    let mut functions: [Box<Fn() -> Result<(), isize>>; 3] =
+        [box || Ok(()), box || Err(1), box || panic!()];
+
+    let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
+    assert!(v == Err(1));
+}
+
+#[test]
+fn test_fmt_default() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let err: Result<isize, &'static str> = Err("Err");
+
+    let s = format!("{:?}", ok);
+    assert_eq!(s, "Ok(100)");
+    let s = format!("{:?}", err);
+    assert_eq!(s, "Err(\"Err\")");
+}
+
+#[test]
+fn test_unwrap_or() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let ok_err: Result<isize, &'static str> = Err("Err");
+
+    assert_eq!(ok.unwrap_or(50), 100);
+    assert_eq!(ok_err.unwrap_or(50), 50);
+}
+
+#[test]
+fn test_unwrap_or_else() {
+    fn handler(msg: &'static str) -> isize {
+        if msg == "I got this." {
+            50
+        } else {
+            panic!("BadBad")
+        }
+    }
+
+    let ok: Result<isize, &'static str> = Ok(100);
+    let ok_err: Result<isize, &'static str> = Err("I got this.");
+
+    assert_eq!(ok.unwrap_or_else(handler), 100);
+    assert_eq!(ok_err.unwrap_or_else(handler), 50);
+}
+
+#[test]
+#[should_panic]
+pub fn test_unwrap_or_else_panic() {
+    fn handler(msg: &'static str) -> isize {
+        if msg == "I got this." {
+            50
+        } else {
+            panic!("BadBad")
+        }
+    }
+
+    let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
+    let _ : isize = bad_err.unwrap_or_else(handler);
+}
+
+
+#[test]
+pub fn test_expect_ok() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    assert_eq!(ok.expect("Unexpected error"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected error: \"All good\"")]
+pub fn test_expect_err() {
+    let err: Result<isize, &'static str> = Err("All good");
+    err.expect("Got expected error");
+}
+
+
+#[test]
+pub fn test_expect_err_err() {
+    let ok: Result<&'static str, isize> = Err(100);
+    assert_eq!(ok.expect_err("Unexpected ok"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected ok: \"All good\"")]
+pub fn test_expect_err_ok() {
+    let err: Result<&'static str, isize> = Ok("All good");
+    err.expect_err("Got expected ok");
+}
+
+#[test]
+pub fn test_iter() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let mut it = ok.iter();
+    assert_eq!(it.size_hint(), (1, Some(1)));
+    assert_eq!(it.next(), Some(&100));
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert!(it.next().is_none());
+    assert_eq!((&ok).into_iter().next(), Some(&100));
+
+    let err: Result<isize, &'static str> = Err("error");
+    assert_eq!(err.iter().next(), None);
+}
+
+#[test]
+pub fn test_iter_mut() {
+    let mut ok: Result<isize, &'static str> = Ok(100);
+    for loc in ok.iter_mut() {
+        *loc = 200;
+    }
+    assert_eq!(ok, Ok(200));
+    for loc in &mut ok {
+        *loc = 300;
+    }
+    assert_eq!(ok, Ok(300));
+
+    let mut err: Result<isize, &'static str> = Err("error");
+    for loc in err.iter_mut() {
+        *loc = 200;
+    }
+    assert_eq!(err, Err("error"));
+}
+
+#[test]
+pub fn test_unwrap_or_default() {
+    assert_eq!(op1().unwrap_or_default(), 666);
+    assert_eq!(op2().unwrap_or_default(), 0);
+}
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
new file mode 100644
index 00000000000..ec38345030f
--- /dev/null
+++ b/src/libcore/tests/slice.rs
@@ -0,0 +1,291 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cmp::Ordering::{Equal, Greater, Less};
+use core::slice::heapsort;
+use core::result::Result::{Ok, Err};
+use rand::{Rng, XorShiftRng};
+
+#[test]
+fn test_binary_search() {
+    let b = [1, 2, 4, 6, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
+    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
+    let b = [1, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
+    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
+    let b = [1, 2, 4, 6, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
+    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
+    let b = [1, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
+    let b = [1, 2, 4, 5, 6, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
+    assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
+    let b = [1, 2, 4, 5, 6, 8];
+    assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
+}
+
+#[test]
+fn test_iterator_nth() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+    }
+    assert_eq!(v.iter().nth(v.len()), None);
+
+    let mut iter = v.iter();
+    assert_eq!(iter.nth(2).unwrap(), &v[2]);
+    assert_eq!(iter.nth(1).unwrap(), &v[4]);
+}
+
+#[test]
+fn test_iterator_last() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().last().unwrap(), &4);
+    assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_count() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().count(), 5);
+
+    let mut iter2 = v.iter();
+    iter2.next();
+    iter2.next();
+    assert_eq!(iter2.count(), 3);
+}
+
+#[test]
+fn test_chunks_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.chunks(3);
+    assert_eq!(c.count(), 2);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.chunks(2);
+    assert_eq!(c2.count(), 3);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.chunks(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_chunks_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks(2);
+    assert_eq!(c.nth(1).unwrap()[1], 3);
+    assert_eq!(c.next().unwrap()[0], 4);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks(3);
+    assert_eq!(c2.nth(1).unwrap()[1], 4);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_chunks_last() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.chunks(2);
+    assert_eq!(c.last().unwrap()[1], 5);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.chunks(2);
+    assert_eq!(c2.last().unwrap()[0], 4);
+}
+
+#[test]
+fn test_chunks_mut_count() {
+    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let c = v.chunks_mut(3);
+    assert_eq!(c.count(), 2);
+
+    let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let c2 = v2.chunks_mut(2);
+    assert_eq!(c2.count(), 3);
+
+    let mut v3: &mut [i32] = &mut [];
+    let c3 = v3.chunks_mut(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_chunks_mut_nth() {
+    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks_mut(2);
+    assert_eq!(c.nth(1).unwrap()[1], 3);
+    assert_eq!(c.next().unwrap()[0], 4);
+
+    let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks_mut(3);
+    assert_eq!(c2.nth(1).unwrap()[1], 4);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_chunks_mut_last() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let c = v.chunks_mut(2);
+    assert_eq!(c.last().unwrap()[1], 5);
+
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let c2 = v2.chunks_mut(2);
+    assert_eq!(c2.last().unwrap()[0], 4);
+}
+
+#[test]
+fn test_windows_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.windows(3);
+    assert_eq!(c.count(), 4);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.windows(6);
+    assert_eq!(c2.count(), 0);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.windows(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_windows_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.windows(2);
+    assert_eq!(c.nth(2).unwrap()[1], 3);
+    assert_eq!(c.next().unwrap()[0], 3);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.windows(4);
+    assert_eq!(c2.nth(1).unwrap()[1], 2);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_windows_last() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.windows(2);
+    assert_eq!(c.last().unwrap()[1], 5);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.windows(2);
+    assert_eq!(c2.last().unwrap()[0], 3);
+}
+
+#[test]
+fn get_range() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    assert_eq!(v.get(..), Some(&[0, 1, 2, 3, 4, 5][..]));
+    assert_eq!(v.get(..2), Some(&[0, 1][..]));
+    assert_eq!(v.get(2..), Some(&[2, 3, 4, 5][..]));
+    assert_eq!(v.get(1..4), Some(&[1, 2, 3][..]));
+    assert_eq!(v.get(7..), None);
+    assert_eq!(v.get(7..10), None);
+}
+
+#[test]
+fn get_mut_range() {
+    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..]));
+    assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..]));
+    assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..]));
+    assert_eq!(v.get_mut(1..4), Some(&mut [1, 2, 3][..]));
+    assert_eq!(v.get_mut(7..), None);
+    assert_eq!(v.get_mut(7..10), None);
+}
+
+#[test]
+fn get_unchecked_range() {
+    unsafe {
+        let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+        assert_eq!(v.get_unchecked(..), &[0, 1, 2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked(..2), &[0, 1][..]);
+        assert_eq!(v.get_unchecked(2..), &[2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked(1..4), &[1, 2, 3][..]);
+    }
+}
+
+#[test]
+fn get_unchecked_mut_range() {
+    unsafe {
+        let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+        assert_eq!(v.get_unchecked_mut(..), &mut [0, 1, 2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked_mut(..2), &mut [0, 1][..]);
+        assert_eq!(v.get_unchecked_mut(2..), &mut[2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked_mut(1..4), &mut [1, 2, 3][..]);
+    }
+}
+
+#[test]
+fn sort_unstable() {
+    let mut v = [0; 600];
+    let mut tmp = [0; 600];
+    let mut rng = XorShiftRng::new_unseeded();
+
+    for len in (2..25).chain(500..510) {
+        let v = &mut v[0..len];
+        let tmp = &mut tmp[0..len];
+
+        for &modulus in &[5, 10, 100, 1000] {
+            for _ in 0..100 {
+                for i in 0..len {
+                    v[i] = rng.gen::<i32>() % modulus;
+                }
+
+                // Sort in default order.
+                tmp.copy_from_slice(v);
+                tmp.sort_unstable();
+                assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in ascending order.
+                tmp.copy_from_slice(v);
+                tmp.sort_unstable_by(|a, b| a.cmp(b));
+                assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in descending order.
+                tmp.copy_from_slice(v);
+                tmp.sort_unstable_by(|a, b| b.cmp(a));
+                assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
+
+                // Test heapsort using `<` operator.
+                tmp.copy_from_slice(v);
+                heapsort(tmp, |a, b| a < b);
+                assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+                // Test heapsort using `>` operator.
+                tmp.copy_from_slice(v);
+                heapsort(tmp, |a, b| a > b);
+                assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
+            }
+        }
+    }
+
+    // Sort using a completely random comparison function.
+    // This will reorder the elements *somehow*, but won't panic.
+    for i in 0..v.len() {
+        v[i] = i as i32;
+    }
+    v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
+    v.sort_unstable();
+    for i in 0..v.len() {
+        assert_eq!(v[i], i as i32);
+    }
+
+    // Should not panic.
+    [0i32; 0].sort_unstable();
+    [(); 10].sort_unstable();
+    [(); 100].sort_unstable();
+
+    let mut v = [0xDEADBEEFu64];
+    v.sort_unstable();
+    assert!(v == [0xDEADBEEF]);
+}
diff --git a/src/libcore/tests/str.rs b/src/libcore/tests/str.rs
new file mode 100644
index 00000000000..08daafccc54
--- /dev/null
+++ b/src/libcore/tests/str.rs
@@ -0,0 +1,11 @@
+// Copyright 2014-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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// All `str` tests live in collectionstests::str
diff --git a/src/libcore/tests/tuple.rs b/src/libcore/tests/tuple.rs
new file mode 100644
index 00000000000..4fe5e0a740b
--- /dev/null
+++ b/src/libcore/tests/tuple.rs
@@ -0,0 +1,68 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp::Ordering::{Equal, Less, Greater};
+
+#[test]
+fn test_clone() {
+    let a = (1, "2");
+    let b = a.clone();
+    assert_eq!(a, b);
+}
+
+#[test]
+fn test_tuple_cmp() {
+    let (small, big) = ((1, 2, 3), (3, 2, 1));
+
+    let nan = 0.0f64/0.0;
+
+    // PartialEq
+    assert_eq!(small, small);
+    assert_eq!(big, big);
+    assert!(small != big);
+    assert!(big != small);
+
+    // PartialOrd
+    assert!(small < big);
+    assert!(!(small < small));
+    assert!(!(big < small));
+    assert!(!(big < big));
+
+    assert!(small <= small);
+    assert!(big <= big);
+
+    assert!(big > small);
+    assert!(small >= small);
+    assert!(big >= small);
+    assert!(big >= big);
+
+    assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
+    assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
+    assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
+    assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
+    assert!(((1.0f64, 2.0f64) < (2.0, nan)));
+    assert!(!((2.0f64, 2.0f64) < (2.0, nan)));
+
+    // Ord
+    assert!(small.cmp(&small) == Equal);
+    assert!(big.cmp(&big) == Equal);
+    assert!(small.cmp(&big) == Less);
+    assert!(big.cmp(&small) == Greater);
+}
+
+#[test]
+fn test_show() {
+    let s = format!("{:?}", (1,));
+    assert_eq!(s, "(1,)");
+    let s = format!("{:?}", (1, true));
+    assert_eq!(s, "(1, true)");
+    let s = format!("{:?}", (1, "hi", true));
+    assert_eq!(s, "(1, \"hi\", true)");
+}