about summary refs log tree commit diff
path: root/src/libtest
diff options
context:
space:
mode:
authorchansuke <chansuke@georepublic.de>2019-06-12 02:34:34 +0900
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-06-16 14:17:01 +0300
commitc2a57c88ea61de4bc4fbb480f704deb6b01e4d68 (patch)
tree56c69e06390aa146d8589957736736dfa35e4e83 /src/libtest
parentdb55aafd72d88c64a8fe3959625edcd207f0d25d (diff)
downloadrust-c2a57c88ea61de4bc4fbb480f704deb6b01e4d68.tar.gz
rust-c2a57c88ea61de4bc4fbb480f704deb6b01e4d68.zip
Separate libtest module
Diffstat (limited to 'src/libtest')
-rw-r--r--src/libtest/lib.rs456
-rw-r--r--src/libtest/stats.rs577
-rw-r--r--src/libtest/stats/tests.rs574
-rw-r--r--src/libtest/tests.rs453
4 files changed, 1029 insertions, 1031 deletions
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 810a98e4a01..53bf67bdf67 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -1772,458 +1772,4 @@ pub mod bench {
 }
 
 #[cfg(test)]
-mod tests {
-    use crate::bench;
-    use crate::test::{
-        filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
-        ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg,
-        TrIgnored, TrOk,
-    };
-    use crate::Bencher;
-    use crate::Concurrent;
-    use std::sync::mpsc::channel;
-
-    fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
-        vec![
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("1"),
-                    ignore: true,
-                    should_panic: ShouldPanic::No,
-                    allow_fail: false,
-                },
-                testfn: DynTestFn(Box::new(move || {})),
-            },
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("2"),
-                    ignore: false,
-                    should_panic: ShouldPanic::No,
-                    allow_fail: false,
-                },
-                testfn: DynTestFn(Box::new(move || {})),
-            },
-        ]
-    }
-
-    #[test]
-    pub fn do_not_run_ignored_tests() {
-        fn f() {
-            panic!();
-        }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: true,
-                should_panic: ShouldPanic::No,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res != TrOk);
-    }
-
-    #[test]
-    pub fn ignored_tests_result_in_ignored() {
-        fn f() {}
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: true,
-                should_panic: ShouldPanic::No,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrIgnored);
-    }
-
-    #[test]
-    fn test_should_panic() {
-        fn f() {
-            panic!();
-        }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::Yes,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrOk);
-    }
-
-    #[test]
-    fn test_should_panic_good_message() {
-        fn f() {
-            panic!("an error message");
-        }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::YesWithMessage("error message"),
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrOk);
-    }
-
-    #[test]
-    fn test_should_panic_bad_message() {
-        fn f() {
-            panic!("an error message");
-        }
-        let expected = "foobar";
-        let failed_msg = "panic did not include expected string";
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::YesWithMessage(expected),
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected)));
-    }
-
-    #[test]
-    fn test_should_panic_but_succeeds() {
-        fn f() {}
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::Yes,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrFailed);
-    }
-
-    #[test]
-    fn parse_ignored_flag() {
-        let args = vec![
-            "progname".to_string(),
-            "filter".to_string(),
-            "--ignored".to_string(),
-        ];
-        let opts = parse_opts(&args).unwrap().unwrap();
-        assert_eq!(opts.run_ignored, RunIgnored::Only);
-    }
-
-    #[test]
-    fn parse_include_ignored_flag() {
-        let args = vec![
-            "progname".to_string(),
-            "filter".to_string(),
-            "-Zunstable-options".to_string(),
-            "--include-ignored".to_string(),
-        ];
-        let opts = parse_opts(&args).unwrap().unwrap();
-        assert_eq!(opts.run_ignored, RunIgnored::Yes);
-    }
-
-    #[test]
-    pub fn filter_for_ignored_option() {
-        // When we run ignored tests the test filter should filter out all the
-        // unignored tests and flip the ignore flag on the rest to false
-
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-        opts.run_ignored = RunIgnored::Only;
-
-        let tests = one_ignored_one_unignored_test();
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].desc.name.to_string(), "1");
-        assert!(!filtered[0].desc.ignore);
-    }
-
-    #[test]
-    pub fn run_include_ignored_option() {
-        // When we "--include-ignored" tests, the ignore flag should be set to false on
-        // all tests and no test filtered out
-
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-        opts.run_ignored = RunIgnored::Yes;
-
-        let tests = one_ignored_one_unignored_test();
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 2);
-        assert!(!filtered[0].desc.ignore);
-        assert!(!filtered[1].desc.ignore);
-    }
-
-    #[test]
-    pub fn exclude_should_panic_option() {
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-        opts.exclude_should_panic = true;
-
-        let mut tests = one_ignored_one_unignored_test();
-        tests.push(TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("3"),
-                ignore: false,
-                should_panic: ShouldPanic::Yes,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(move || {})),
-        });
-
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 2);
-        assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
-    }
-
-    #[test]
-    pub fn exact_filter_match() {
-        fn tests() -> Vec<TestDescAndFn> {
-            vec!["base", "base::test", "base::test1", "base::test2"]
-                .into_iter()
-                .map(|name| TestDescAndFn {
-                    desc: TestDesc {
-                        name: StaticTestName(name),
-                        ignore: false,
-                        should_panic: ShouldPanic::No,
-                        allow_fail: false,
-                    },
-                    testfn: DynTestFn(Box::new(move || {})),
-                })
-                .collect()
-        }
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("base".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 4);
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("bas".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 4);
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("::test".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 3);
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("base::test".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 3);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("base".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 1);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("bas".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 0);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("::test".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 0);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("base::test".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 1);
-    }
-
-    #[test]
-    pub fn sort_tests() {
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-
-        let names = vec![
-            "sha1::test".to_string(),
-            "isize::test_to_str".to_string(),
-            "isize::test_pow".to_string(),
-            "test::do_not_run_ignored_tests".to_string(),
-            "test::ignored_tests_result_in_ignored".to_string(),
-            "test::first_free_arg_should_be_a_filter".to_string(),
-            "test::parse_ignored_flag".to_string(),
-            "test::parse_include_ignored_flag".to_string(),
-            "test::filter_for_ignored_option".to_string(),
-            "test::run_include_ignored_option".to_string(),
-            "test::sort_tests".to_string(),
-        ];
-        let tests = {
-            fn testfn() {}
-            let mut tests = Vec::new();
-            for name in &names {
-                let test = TestDescAndFn {
-                    desc: TestDesc {
-                        name: DynTestName((*name).clone()),
-                        ignore: false,
-                        should_panic: ShouldPanic::No,
-                        allow_fail: false,
-                    },
-                    testfn: DynTestFn(Box::new(testfn)),
-                };
-                tests.push(test);
-            }
-            tests
-        };
-        let filtered = filter_tests(&opts, tests);
-
-        let expected = vec![
-            "isize::test_pow".to_string(),
-            "isize::test_to_str".to_string(),
-            "sha1::test".to_string(),
-            "test::do_not_run_ignored_tests".to_string(),
-            "test::filter_for_ignored_option".to_string(),
-            "test::first_free_arg_should_be_a_filter".to_string(),
-            "test::ignored_tests_result_in_ignored".to_string(),
-            "test::parse_ignored_flag".to_string(),
-            "test::parse_include_ignored_flag".to_string(),
-            "test::run_include_ignored_option".to_string(),
-            "test::sort_tests".to_string(),
-        ];
-
-        for (a, b) in expected.iter().zip(filtered) {
-            assert!(*a == b.desc.name.to_string());
-        }
-    }
-
-    #[test]
-    pub fn test_metricmap_compare() {
-        let mut m1 = MetricMap::new();
-        let mut m2 = MetricMap::new();
-        m1.insert_metric("in-both-noise", 1000.0, 200.0);
-        m2.insert_metric("in-both-noise", 1100.0, 200.0);
-
-        m1.insert_metric("in-first-noise", 1000.0, 2.0);
-        m2.insert_metric("in-second-noise", 1000.0, 2.0);
-
-        m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0);
-        m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0);
-
-        m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0);
-        m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0);
-
-        m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0);
-        m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0);
-
-        m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0);
-        m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0);
-    }
-
-    #[test]
-    pub fn test_bench_once_no_iter() {
-        fn f(_: &mut Bencher) {}
-        bench::run_once(f);
-    }
-
-    #[test]
-    pub fn test_bench_once_iter() {
-        fn f(b: &mut Bencher) {
-            b.iter(|| {})
-        }
-        bench::run_once(f);
-    }
-
-    #[test]
-    pub fn test_bench_no_iter() {
-        fn f(_: &mut Bencher) {}
-
-        let (tx, rx) = channel();
-
-        let desc = TestDesc {
-            name: StaticTestName("f"),
-            ignore: false,
-            should_panic: ShouldPanic::No,
-            allow_fail: false,
-        };
-
-        crate::bench::benchmark(desc, tx, true, f);
-        rx.recv().unwrap();
-    }
-
-    #[test]
-    pub fn test_bench_iter() {
-        fn f(b: &mut Bencher) {
-            b.iter(|| {})
-        }
-
-        let (tx, rx) = channel();
-
-        let desc = TestDesc {
-            name: StaticTestName("f"),
-            ignore: false,
-            should_panic: ShouldPanic::No,
-            allow_fail: false,
-        };
-
-        crate::bench::benchmark(desc, tx, true, f);
-        rx.recv().unwrap();
-    }
-}
+mod tests;
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
index 5c9421d5ea4..32c30061983 100644
--- a/src/libtest/stats.rs
+++ b/src/libtest/stats.rs
@@ -318,582 +318,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
 // Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
 
 #[cfg(test)]
-mod tests {
-    use crate::stats::Stats;
-    use crate::stats::Summary;
-    use std::f64;
-    use std::io::prelude::*;
-    use std::io;
-
-    macro_rules! assert_approx_eq {
-        ($a: expr, $b: expr) => {{
-            let (a, b) = (&$a, &$b);
-            assert!(
-                (*a - *b).abs() < 1.0e-6,
-                "{} is not approximately equal to {}",
-                *a,
-                *b
-            );
-        }};
-    }
-
-    fn check(samples: &[f64], summ: &Summary) {
-        let summ2 = Summary::new(samples);
-
-        let mut w = io::sink();
-        let w = &mut w;
-        (write!(w, "\n")).unwrap();
-
-        assert_eq!(summ.sum, summ2.sum);
-        assert_eq!(summ.min, summ2.min);
-        assert_eq!(summ.max, summ2.max);
-        assert_eq!(summ.mean, summ2.mean);
-        assert_eq!(summ.median, summ2.median);
-
-        // We needed a few more digits to get exact equality on these
-        // but they're within float epsilon, which is 1.0e-6.
-        assert_approx_eq!(summ.var, summ2.var);
-        assert_approx_eq!(summ.std_dev, summ2.std_dev);
-        assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
-        assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
-        assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
-
-        assert_eq!(summ.quartiles, summ2.quartiles);
-        assert_eq!(summ.iqr, summ2.iqr);
-    }
-
-    #[test]
-    fn test_min_max_nan() {
-        let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
-        let summary = Summary::new(xs);
-        assert_eq!(summary.min, 1.0);
-        assert_eq!(summary.max, 4.0);
-    }
-
-    #[test]
-    fn test_norm2() {
-        let val = &[958.0000000000, 924.0000000000];
-        let summ = &Summary {
-            sum: 1882.0000000000,
-            min: 924.0000000000,
-            max: 958.0000000000,
-            mean: 941.0000000000,
-            median: 941.0000000000,
-            var: 578.0000000000,
-            std_dev: 24.0416305603,
-            std_dev_pct: 2.5549022912,
-            median_abs_dev: 25.2042000000,
-            median_abs_dev_pct: 2.6784484591,
-            quartiles: (932.5000000000, 941.0000000000, 949.5000000000),
-            iqr: 17.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm10narrow() {
-        let val = &[
-            966.0000000000,
-            985.0000000000,
-            1110.0000000000,
-            848.0000000000,
-            821.0000000000,
-            975.0000000000,
-            962.0000000000,
-            1157.0000000000,
-            1217.0000000000,
-            955.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 9996.0000000000,
-            min: 821.0000000000,
-            max: 1217.0000000000,
-            mean: 999.6000000000,
-            median: 970.5000000000,
-            var: 16050.7111111111,
-            std_dev: 126.6914010938,
-            std_dev_pct: 12.6742097933,
-            median_abs_dev: 102.2994000000,
-            median_abs_dev_pct: 10.5408964451,
-            quartiles: (956.7500000000, 970.5000000000, 1078.7500000000),
-            iqr: 122.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm10medium() {
-        let val = &[
-            954.0000000000,
-            1064.0000000000,
-            855.0000000000,
-            1000.0000000000,
-            743.0000000000,
-            1084.0000000000,
-            704.0000000000,
-            1023.0000000000,
-            357.0000000000,
-            869.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 8653.0000000000,
-            min: 357.0000000000,
-            max: 1084.0000000000,
-            mean: 865.3000000000,
-            median: 911.5000000000,
-            var: 48628.4555555556,
-            std_dev: 220.5186059170,
-            std_dev_pct: 25.4846418487,
-            median_abs_dev: 195.7032000000,
-            median_abs_dev_pct: 21.4704552935,
-            quartiles: (771.0000000000, 911.5000000000, 1017.2500000000),
-            iqr: 246.2500000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm10wide() {
-        let val = &[
-            505.0000000000,
-            497.0000000000,
-            1591.0000000000,
-            887.0000000000,
-            1026.0000000000,
-            136.0000000000,
-            1580.0000000000,
-            940.0000000000,
-            754.0000000000,
-            1433.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 9349.0000000000,
-            min: 136.0000000000,
-            max: 1591.0000000000,
-            mean: 934.9000000000,
-            median: 913.5000000000,
-            var: 239208.9888888889,
-            std_dev: 489.0899599142,
-            std_dev_pct: 52.3146817750,
-            median_abs_dev: 611.5725000000,
-            median_abs_dev_pct: 66.9482758621,
-            quartiles: (567.2500000000, 913.5000000000, 1331.2500000000),
-            iqr: 764.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm25verynarrow() {
-        let val = &[
-            991.0000000000,
-            1018.0000000000,
-            998.0000000000,
-            1013.0000000000,
-            974.0000000000,
-            1007.0000000000,
-            1014.0000000000,
-            999.0000000000,
-            1011.0000000000,
-            978.0000000000,
-            985.0000000000,
-            999.0000000000,
-            983.0000000000,
-            982.0000000000,
-            1015.0000000000,
-            1002.0000000000,
-            977.0000000000,
-            948.0000000000,
-            1040.0000000000,
-            974.0000000000,
-            996.0000000000,
-            989.0000000000,
-            1015.0000000000,
-            994.0000000000,
-            1024.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 24926.0000000000,
-            min: 948.0000000000,
-            max: 1040.0000000000,
-            mean: 997.0400000000,
-            median: 998.0000000000,
-            var: 393.2066666667,
-            std_dev: 19.8294393937,
-            std_dev_pct: 1.9888308788,
-            median_abs_dev: 22.2390000000,
-            median_abs_dev_pct: 2.2283567134,
-            quartiles: (983.0000000000, 998.0000000000, 1013.0000000000),
-            iqr: 30.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp10a() {
-        let val = &[
-            23.0000000000,
-            11.0000000000,
-            2.0000000000,
-            57.0000000000,
-            4.0000000000,
-            12.0000000000,
-            5.0000000000,
-            29.0000000000,
-            3.0000000000,
-            21.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 167.0000000000,
-            min: 2.0000000000,
-            max: 57.0000000000,
-            mean: 16.7000000000,
-            median: 11.5000000000,
-            var: 287.7888888889,
-            std_dev: 16.9643416875,
-            std_dev_pct: 101.5828843560,
-            median_abs_dev: 13.3434000000,
-            median_abs_dev_pct: 116.0295652174,
-            quartiles: (4.2500000000, 11.5000000000, 22.5000000000),
-            iqr: 18.2500000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp10b() {
-        let val = &[
-            24.0000000000,
-            17.0000000000,
-            6.0000000000,
-            38.0000000000,
-            25.0000000000,
-            7.0000000000,
-            51.0000000000,
-            2.0000000000,
-            61.0000000000,
-            32.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 263.0000000000,
-            min: 2.0000000000,
-            max: 61.0000000000,
-            mean: 26.3000000000,
-            median: 24.5000000000,
-            var: 383.5666666667,
-            std_dev: 19.5848580967,
-            std_dev_pct: 74.4671410520,
-            median_abs_dev: 22.9803000000,
-            median_abs_dev_pct: 93.7971428571,
-            quartiles: (9.5000000000, 24.5000000000, 36.5000000000),
-            iqr: 27.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp10c() {
-        let val = &[
-            71.0000000000,
-            2.0000000000,
-            32.0000000000,
-            1.0000000000,
-            6.0000000000,
-            28.0000000000,
-            13.0000000000,
-            37.0000000000,
-            16.0000000000,
-            36.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 242.0000000000,
-            min: 1.0000000000,
-            max: 71.0000000000,
-            mean: 24.2000000000,
-            median: 22.0000000000,
-            var: 458.1777777778,
-            std_dev: 21.4050876611,
-            std_dev_pct: 88.4507754589,
-            median_abs_dev: 21.4977000000,
-            median_abs_dev_pct: 97.7168181818,
-            quartiles: (7.7500000000, 22.0000000000, 35.0000000000),
-            iqr: 27.2500000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp25() {
-        let val = &[
-            3.0000000000,
-            24.0000000000,
-            1.0000000000,
-            19.0000000000,
-            7.0000000000,
-            5.0000000000,
-            30.0000000000,
-            39.0000000000,
-            31.0000000000,
-            13.0000000000,
-            25.0000000000,
-            48.0000000000,
-            1.0000000000,
-            6.0000000000,
-            42.0000000000,
-            63.0000000000,
-            2.0000000000,
-            12.0000000000,
-            108.0000000000,
-            26.0000000000,
-            1.0000000000,
-            7.0000000000,
-            44.0000000000,
-            25.0000000000,
-            11.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 593.0000000000,
-            min: 1.0000000000,
-            max: 108.0000000000,
-            mean: 23.7200000000,
-            median: 19.0000000000,
-            var: 601.0433333333,
-            std_dev: 24.5161851301,
-            std_dev_pct: 103.3565983562,
-            median_abs_dev: 19.2738000000,
-            median_abs_dev_pct: 101.4410526316,
-            quartiles: (6.0000000000, 19.0000000000, 31.0000000000),
-            iqr: 25.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_binom25() {
-        let val = &[
-            18.0000000000,
-            17.0000000000,
-            27.0000000000,
-            15.0000000000,
-            21.0000000000,
-            25.0000000000,
-            17.0000000000,
-            24.0000000000,
-            25.0000000000,
-            24.0000000000,
-            26.0000000000,
-            26.0000000000,
-            23.0000000000,
-            15.0000000000,
-            23.0000000000,
-            17.0000000000,
-            18.0000000000,
-            18.0000000000,
-            21.0000000000,
-            16.0000000000,
-            15.0000000000,
-            31.0000000000,
-            20.0000000000,
-            17.0000000000,
-            15.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 514.0000000000,
-            min: 15.0000000000,
-            max: 31.0000000000,
-            mean: 20.5600000000,
-            median: 20.0000000000,
-            var: 20.8400000000,
-            std_dev: 4.5650848842,
-            std_dev_pct: 22.2037202539,
-            median_abs_dev: 5.9304000000,
-            median_abs_dev_pct: 29.6520000000,
-            quartiles: (17.0000000000, 20.0000000000, 24.0000000000),
-            iqr: 7.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_pois25lambda30() {
-        let val = &[
-            27.0000000000,
-            33.0000000000,
-            34.0000000000,
-            34.0000000000,
-            24.0000000000,
-            39.0000000000,
-            28.0000000000,
-            27.0000000000,
-            31.0000000000,
-            28.0000000000,
-            38.0000000000,
-            21.0000000000,
-            33.0000000000,
-            36.0000000000,
-            29.0000000000,
-            37.0000000000,
-            32.0000000000,
-            34.0000000000,
-            31.0000000000,
-            39.0000000000,
-            25.0000000000,
-            31.0000000000,
-            32.0000000000,
-            40.0000000000,
-            24.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 787.0000000000,
-            min: 21.0000000000,
-            max: 40.0000000000,
-            mean: 31.4800000000,
-            median: 32.0000000000,
-            var: 26.5933333333,
-            std_dev: 5.1568724372,
-            std_dev_pct: 16.3814245145,
-            median_abs_dev: 5.9304000000,
-            median_abs_dev_pct: 18.5325000000,
-            quartiles: (28.0000000000, 32.0000000000, 34.0000000000),
-            iqr: 6.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_pois25lambda40() {
-        let val = &[
-            42.0000000000,
-            50.0000000000,
-            42.0000000000,
-            46.0000000000,
-            34.0000000000,
-            45.0000000000,
-            34.0000000000,
-            49.0000000000,
-            39.0000000000,
-            28.0000000000,
-            40.0000000000,
-            35.0000000000,
-            37.0000000000,
-            39.0000000000,
-            46.0000000000,
-            44.0000000000,
-            32.0000000000,
-            45.0000000000,
-            42.0000000000,
-            37.0000000000,
-            48.0000000000,
-            42.0000000000,
-            33.0000000000,
-            42.0000000000,
-            48.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 1019.0000000000,
-            min: 28.0000000000,
-            max: 50.0000000000,
-            mean: 40.7600000000,
-            median: 42.0000000000,
-            var: 34.4400000000,
-            std_dev: 5.8685603004,
-            std_dev_pct: 14.3978417577,
-            median_abs_dev: 5.9304000000,
-            median_abs_dev_pct: 14.1200000000,
-            quartiles: (37.0000000000, 42.0000000000, 45.0000000000),
-            iqr: 8.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_pois25lambda50() {
-        let val = &[
-            45.0000000000,
-            43.0000000000,
-            44.0000000000,
-            61.0000000000,
-            51.0000000000,
-            53.0000000000,
-            59.0000000000,
-            52.0000000000,
-            49.0000000000,
-            51.0000000000,
-            51.0000000000,
-            50.0000000000,
-            49.0000000000,
-            56.0000000000,
-            42.0000000000,
-            52.0000000000,
-            51.0000000000,
-            43.0000000000,
-            48.0000000000,
-            48.0000000000,
-            50.0000000000,
-            42.0000000000,
-            43.0000000000,
-            42.0000000000,
-            60.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 1235.0000000000,
-            min: 42.0000000000,
-            max: 61.0000000000,
-            mean: 49.4000000000,
-            median: 50.0000000000,
-            var: 31.6666666667,
-            std_dev: 5.6273143387,
-            std_dev_pct: 11.3913245723,
-            median_abs_dev: 4.4478000000,
-            median_abs_dev_pct: 8.8956000000,
-            quartiles: (44.0000000000, 50.0000000000, 52.0000000000),
-            iqr: 8.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_unif25() {
-        let val = &[
-            99.0000000000,
-            55.0000000000,
-            92.0000000000,
-            79.0000000000,
-            14.0000000000,
-            2.0000000000,
-            33.0000000000,
-            49.0000000000,
-            3.0000000000,
-            32.0000000000,
-            84.0000000000,
-            59.0000000000,
-            22.0000000000,
-            86.0000000000,
-            76.0000000000,
-            31.0000000000,
-            29.0000000000,
-            11.0000000000,
-            41.0000000000,
-            53.0000000000,
-            45.0000000000,
-            44.0000000000,
-            98.0000000000,
-            98.0000000000,
-            7.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 1242.0000000000,
-            min: 2.0000000000,
-            max: 99.0000000000,
-            mean: 49.6800000000,
-            median: 45.0000000000,
-            var: 1015.6433333333,
-            std_dev: 31.8691595957,
-            std_dev_pct: 64.1488719719,
-            median_abs_dev: 45.9606000000,
-            median_abs_dev_pct: 102.1346666667,
-            quartiles: (29.0000000000, 45.0000000000, 79.0000000000),
-            iqr: 50.0000000000,
-        };
-        check(val, summ);
-    }
-
-    #[test]
-    fn test_sum_f64s() {
-        assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999);
-    }
-    #[test]
-    fn test_sum_f64_between_ints_that_sum_to_0() {
-        assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2);
-    }
-}
+mod tests;
 
 #[cfg(test)]
 mod bench {
diff --git a/src/libtest/stats/tests.rs b/src/libtest/stats/tests.rs
new file mode 100644
index 00000000000..59f93645360
--- /dev/null
+++ b/src/libtest/stats/tests.rs
@@ -0,0 +1,574 @@
+use crate::stats::Stats;
+use crate::stats::Summary;
+use std::f64;
+use std::io::prelude::*;
+use std::io;
+
+macro_rules! assert_approx_eq {
+    ($a: expr, $b: expr) => {{
+        let (a, b) = (&$a, &$b);
+        assert!(
+            (*a - *b).abs() < 1.0e-6,
+            "{} is not approximately equal to {}",
+            *a,
+            *b
+        );
+    }};
+}
+
+fn check(samples: &[f64], summ: &Summary) {
+    let summ2 = Summary::new(samples);
+
+    let mut w = io::sink();
+    let w = &mut w;
+    (write!(w, "\n")).unwrap();
+
+    assert_eq!(summ.sum, summ2.sum);
+    assert_eq!(summ.min, summ2.min);
+    assert_eq!(summ.max, summ2.max);
+    assert_eq!(summ.mean, summ2.mean);
+    assert_eq!(summ.median, summ2.median);
+
+    // We needed a few more digits to get exact equality on these
+    // but they're within float epsilon, which is 1.0e-6.
+    assert_approx_eq!(summ.var, summ2.var);
+    assert_approx_eq!(summ.std_dev, summ2.std_dev);
+    assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
+    assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
+    assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
+
+    assert_eq!(summ.quartiles, summ2.quartiles);
+    assert_eq!(summ.iqr, summ2.iqr);
+}
+
+#[test]
+fn test_min_max_nan() {
+    let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
+    let summary = Summary::new(xs);
+    assert_eq!(summary.min, 1.0);
+    assert_eq!(summary.max, 4.0);
+}
+
+#[test]
+fn test_norm2() {
+    let val = &[958.0000000000, 924.0000000000];
+    let summ = &Summary {
+        sum: 1882.0000000000,
+        min: 924.0000000000,
+        max: 958.0000000000,
+        mean: 941.0000000000,
+        median: 941.0000000000,
+        var: 578.0000000000,
+        std_dev: 24.0416305603,
+        std_dev_pct: 2.5549022912,
+        median_abs_dev: 25.2042000000,
+        median_abs_dev_pct: 2.6784484591,
+        quartiles: (932.5000000000, 941.0000000000, 949.5000000000),
+        iqr: 17.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_norm10narrow() {
+    let val = &[
+        966.0000000000,
+        985.0000000000,
+        1110.0000000000,
+        848.0000000000,
+        821.0000000000,
+        975.0000000000,
+        962.0000000000,
+        1157.0000000000,
+        1217.0000000000,
+        955.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 9996.0000000000,
+        min: 821.0000000000,
+        max: 1217.0000000000,
+        mean: 999.6000000000,
+        median: 970.5000000000,
+        var: 16050.7111111111,
+        std_dev: 126.6914010938,
+        std_dev_pct: 12.6742097933,
+        median_abs_dev: 102.2994000000,
+        median_abs_dev_pct: 10.5408964451,
+        quartiles: (956.7500000000, 970.5000000000, 1078.7500000000),
+        iqr: 122.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_norm10medium() {
+    let val = &[
+        954.0000000000,
+        1064.0000000000,
+        855.0000000000,
+        1000.0000000000,
+        743.0000000000,
+        1084.0000000000,
+        704.0000000000,
+        1023.0000000000,
+        357.0000000000,
+        869.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 8653.0000000000,
+        min: 357.0000000000,
+        max: 1084.0000000000,
+        mean: 865.3000000000,
+        median: 911.5000000000,
+        var: 48628.4555555556,
+        std_dev: 220.5186059170,
+        std_dev_pct: 25.4846418487,
+        median_abs_dev: 195.7032000000,
+        median_abs_dev_pct: 21.4704552935,
+        quartiles: (771.0000000000, 911.5000000000, 1017.2500000000),
+        iqr: 246.2500000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_norm10wide() {
+    let val = &[
+        505.0000000000,
+        497.0000000000,
+        1591.0000000000,
+        887.0000000000,
+        1026.0000000000,
+        136.0000000000,
+        1580.0000000000,
+        940.0000000000,
+        754.0000000000,
+        1433.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 9349.0000000000,
+        min: 136.0000000000,
+        max: 1591.0000000000,
+        mean: 934.9000000000,
+        median: 913.5000000000,
+        var: 239208.9888888889,
+        std_dev: 489.0899599142,
+        std_dev_pct: 52.3146817750,
+        median_abs_dev: 611.5725000000,
+        median_abs_dev_pct: 66.9482758621,
+        quartiles: (567.2500000000, 913.5000000000, 1331.2500000000),
+        iqr: 764.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_norm25verynarrow() {
+    let val = &[
+        991.0000000000,
+        1018.0000000000,
+        998.0000000000,
+        1013.0000000000,
+        974.0000000000,
+        1007.0000000000,
+        1014.0000000000,
+        999.0000000000,
+        1011.0000000000,
+        978.0000000000,
+        985.0000000000,
+        999.0000000000,
+        983.0000000000,
+        982.0000000000,
+        1015.0000000000,
+        1002.0000000000,
+        977.0000000000,
+        948.0000000000,
+        1040.0000000000,
+        974.0000000000,
+        996.0000000000,
+        989.0000000000,
+        1015.0000000000,
+        994.0000000000,
+        1024.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 24926.0000000000,
+        min: 948.0000000000,
+        max: 1040.0000000000,
+        mean: 997.0400000000,
+        median: 998.0000000000,
+        var: 393.2066666667,
+        std_dev: 19.8294393937,
+        std_dev_pct: 1.9888308788,
+        median_abs_dev: 22.2390000000,
+        median_abs_dev_pct: 2.2283567134,
+        quartiles: (983.0000000000, 998.0000000000, 1013.0000000000),
+        iqr: 30.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_exp10a() {
+    let val = &[
+        23.0000000000,
+        11.0000000000,
+        2.0000000000,
+        57.0000000000,
+        4.0000000000,
+        12.0000000000,
+        5.0000000000,
+        29.0000000000,
+        3.0000000000,
+        21.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 167.0000000000,
+        min: 2.0000000000,
+        max: 57.0000000000,
+        mean: 16.7000000000,
+        median: 11.5000000000,
+        var: 287.7888888889,
+        std_dev: 16.9643416875,
+        std_dev_pct: 101.5828843560,
+        median_abs_dev: 13.3434000000,
+        median_abs_dev_pct: 116.0295652174,
+        quartiles: (4.2500000000, 11.5000000000, 22.5000000000),
+        iqr: 18.2500000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_exp10b() {
+    let val = &[
+        24.0000000000,
+        17.0000000000,
+        6.0000000000,
+        38.0000000000,
+        25.0000000000,
+        7.0000000000,
+        51.0000000000,
+        2.0000000000,
+        61.0000000000,
+        32.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 263.0000000000,
+        min: 2.0000000000,
+        max: 61.0000000000,
+        mean: 26.3000000000,
+        median: 24.5000000000,
+        var: 383.5666666667,
+        std_dev: 19.5848580967,
+        std_dev_pct: 74.4671410520,
+        median_abs_dev: 22.9803000000,
+        median_abs_dev_pct: 93.7971428571,
+        quartiles: (9.5000000000, 24.5000000000, 36.5000000000),
+        iqr: 27.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_exp10c() {
+    let val = &[
+        71.0000000000,
+        2.0000000000,
+        32.0000000000,
+        1.0000000000,
+        6.0000000000,
+        28.0000000000,
+        13.0000000000,
+        37.0000000000,
+        16.0000000000,
+        36.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 242.0000000000,
+        min: 1.0000000000,
+        max: 71.0000000000,
+        mean: 24.2000000000,
+        median: 22.0000000000,
+        var: 458.1777777778,
+        std_dev: 21.4050876611,
+        std_dev_pct: 88.4507754589,
+        median_abs_dev: 21.4977000000,
+        median_abs_dev_pct: 97.7168181818,
+        quartiles: (7.7500000000, 22.0000000000, 35.0000000000),
+        iqr: 27.2500000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_exp25() {
+    let val = &[
+        3.0000000000,
+        24.0000000000,
+        1.0000000000,
+        19.0000000000,
+        7.0000000000,
+        5.0000000000,
+        30.0000000000,
+        39.0000000000,
+        31.0000000000,
+        13.0000000000,
+        25.0000000000,
+        48.0000000000,
+        1.0000000000,
+        6.0000000000,
+        42.0000000000,
+        63.0000000000,
+        2.0000000000,
+        12.0000000000,
+        108.0000000000,
+        26.0000000000,
+        1.0000000000,
+        7.0000000000,
+        44.0000000000,
+        25.0000000000,
+        11.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 593.0000000000,
+        min: 1.0000000000,
+        max: 108.0000000000,
+        mean: 23.7200000000,
+        median: 19.0000000000,
+        var: 601.0433333333,
+        std_dev: 24.5161851301,
+        std_dev_pct: 103.3565983562,
+        median_abs_dev: 19.2738000000,
+        median_abs_dev_pct: 101.4410526316,
+        quartiles: (6.0000000000, 19.0000000000, 31.0000000000),
+        iqr: 25.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_binom25() {
+    let val = &[
+        18.0000000000,
+        17.0000000000,
+        27.0000000000,
+        15.0000000000,
+        21.0000000000,
+        25.0000000000,
+        17.0000000000,
+        24.0000000000,
+        25.0000000000,
+        24.0000000000,
+        26.0000000000,
+        26.0000000000,
+        23.0000000000,
+        15.0000000000,
+        23.0000000000,
+        17.0000000000,
+        18.0000000000,
+        18.0000000000,
+        21.0000000000,
+        16.0000000000,
+        15.0000000000,
+        31.0000000000,
+        20.0000000000,
+        17.0000000000,
+        15.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 514.0000000000,
+        min: 15.0000000000,
+        max: 31.0000000000,
+        mean: 20.5600000000,
+        median: 20.0000000000,
+        var: 20.8400000000,
+        std_dev: 4.5650848842,
+        std_dev_pct: 22.2037202539,
+        median_abs_dev: 5.9304000000,
+        median_abs_dev_pct: 29.6520000000,
+        quartiles: (17.0000000000, 20.0000000000, 24.0000000000),
+        iqr: 7.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_pois25lambda30() {
+    let val = &[
+        27.0000000000,
+        33.0000000000,
+        34.0000000000,
+        34.0000000000,
+        24.0000000000,
+        39.0000000000,
+        28.0000000000,
+        27.0000000000,
+        31.0000000000,
+        28.0000000000,
+        38.0000000000,
+        21.0000000000,
+        33.0000000000,
+        36.0000000000,
+        29.0000000000,
+        37.0000000000,
+        32.0000000000,
+        34.0000000000,
+        31.0000000000,
+        39.0000000000,
+        25.0000000000,
+        31.0000000000,
+        32.0000000000,
+        40.0000000000,
+        24.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 787.0000000000,
+        min: 21.0000000000,
+        max: 40.0000000000,
+        mean: 31.4800000000,
+        median: 32.0000000000,
+        var: 26.5933333333,
+        std_dev: 5.1568724372,
+        std_dev_pct: 16.3814245145,
+        median_abs_dev: 5.9304000000,
+        median_abs_dev_pct: 18.5325000000,
+        quartiles: (28.0000000000, 32.0000000000, 34.0000000000),
+        iqr: 6.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_pois25lambda40() {
+    let val = &[
+        42.0000000000,
+        50.0000000000,
+        42.0000000000,
+        46.0000000000,
+        34.0000000000,
+        45.0000000000,
+        34.0000000000,
+        49.0000000000,
+        39.0000000000,
+        28.0000000000,
+        40.0000000000,
+        35.0000000000,
+        37.0000000000,
+        39.0000000000,
+        46.0000000000,
+        44.0000000000,
+        32.0000000000,
+        45.0000000000,
+        42.0000000000,
+        37.0000000000,
+        48.0000000000,
+        42.0000000000,
+        33.0000000000,
+        42.0000000000,
+        48.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 1019.0000000000,
+        min: 28.0000000000,
+        max: 50.0000000000,
+        mean: 40.7600000000,
+        median: 42.0000000000,
+        var: 34.4400000000,
+        std_dev: 5.8685603004,
+        std_dev_pct: 14.3978417577,
+        median_abs_dev: 5.9304000000,
+        median_abs_dev_pct: 14.1200000000,
+        quartiles: (37.0000000000, 42.0000000000, 45.0000000000),
+        iqr: 8.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_pois25lambda50() {
+    let val = &[
+        45.0000000000,
+        43.0000000000,
+        44.0000000000,
+        61.0000000000,
+        51.0000000000,
+        53.0000000000,
+        59.0000000000,
+        52.0000000000,
+        49.0000000000,
+        51.0000000000,
+        51.0000000000,
+        50.0000000000,
+        49.0000000000,
+        56.0000000000,
+        42.0000000000,
+        52.0000000000,
+        51.0000000000,
+        43.0000000000,
+        48.0000000000,
+        48.0000000000,
+        50.0000000000,
+        42.0000000000,
+        43.0000000000,
+        42.0000000000,
+        60.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 1235.0000000000,
+        min: 42.0000000000,
+        max: 61.0000000000,
+        mean: 49.4000000000,
+        median: 50.0000000000,
+        var: 31.6666666667,
+        std_dev: 5.6273143387,
+        std_dev_pct: 11.3913245723,
+        median_abs_dev: 4.4478000000,
+        median_abs_dev_pct: 8.8956000000,
+        quartiles: (44.0000000000, 50.0000000000, 52.0000000000),
+        iqr: 8.0000000000,
+    };
+    check(val, summ);
+}
+#[test]
+fn test_unif25() {
+    let val = &[
+        99.0000000000,
+        55.0000000000,
+        92.0000000000,
+        79.0000000000,
+        14.0000000000,
+        2.0000000000,
+        33.0000000000,
+        49.0000000000,
+        3.0000000000,
+        32.0000000000,
+        84.0000000000,
+        59.0000000000,
+        22.0000000000,
+        86.0000000000,
+        76.0000000000,
+        31.0000000000,
+        29.0000000000,
+        11.0000000000,
+        41.0000000000,
+        53.0000000000,
+        45.0000000000,
+        44.0000000000,
+        98.0000000000,
+        98.0000000000,
+        7.0000000000,
+    ];
+    let summ = &Summary {
+        sum: 1242.0000000000,
+        min: 2.0000000000,
+        max: 99.0000000000,
+        mean: 49.6800000000,
+        median: 45.0000000000,
+        var: 1015.6433333333,
+        std_dev: 31.8691595957,
+        std_dev_pct: 64.1488719719,
+        median_abs_dev: 45.9606000000,
+        median_abs_dev_pct: 102.1346666667,
+        quartiles: (29.0000000000, 45.0000000000, 79.0000000000),
+        iqr: 50.0000000000,
+    };
+    check(val, summ);
+}
+
+#[test]
+fn test_sum_f64s() {
+    assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999);
+}
+#[test]
+fn test_sum_f64_between_ints_that_sum_to_0() {
+    assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2);
+}
diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs
new file mode 100644
index 00000000000..d8734d8caa0
--- /dev/null
+++ b/src/libtest/tests.rs
@@ -0,0 +1,453 @@
+use crate::bench;
+use crate::test::{
+    filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
+    ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg,
+    TrIgnored, TrOk,
+};
+use crate::Bencher;
+use crate::Concurrent;
+use std::sync::mpsc::channel;
+
+fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
+    vec![
+        TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("1"),
+                ignore: true,
+                should_panic: ShouldPanic::No,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(move || {})),
+        },
+        TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("2"),
+                ignore: false,
+                should_panic: ShouldPanic::No,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(move || {})),
+        },
+    ]
+}
+
+#[test]
+pub fn do_not_run_ignored_tests() {
+    fn f() {
+        panic!();
+    }
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: true,
+            should_panic: ShouldPanic::No,
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    let (tx, rx) = channel();
+    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    let (_, res, _) = rx.recv().unwrap();
+    assert!(res != TrOk);
+}
+
+#[test]
+pub fn ignored_tests_result_in_ignored() {
+    fn f() {}
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: true,
+            should_panic: ShouldPanic::No,
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    let (tx, rx) = channel();
+    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    let (_, res, _) = rx.recv().unwrap();
+    assert!(res == TrIgnored);
+}
+
+#[test]
+fn test_should_panic() {
+    fn f() {
+        panic!();
+    }
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: false,
+            should_panic: ShouldPanic::Yes,
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    let (tx, rx) = channel();
+    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    let (_, res, _) = rx.recv().unwrap();
+    assert!(res == TrOk);
+}
+
+#[test]
+fn test_should_panic_good_message() {
+    fn f() {
+        panic!("an error message");
+    }
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: false,
+            should_panic: ShouldPanic::YesWithMessage("error message"),
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    let (tx, rx) = channel();
+    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    let (_, res, _) = rx.recv().unwrap();
+    assert!(res == TrOk);
+}
+
+#[test]
+fn test_should_panic_bad_message() {
+    fn f() {
+        panic!("an error message");
+    }
+    let expected = "foobar";
+    let failed_msg = "panic did not include expected string";
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: false,
+            should_panic: ShouldPanic::YesWithMessage(expected),
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    let (tx, rx) = channel();
+    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    let (_, res, _) = rx.recv().unwrap();
+    assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected)));
+}
+
+#[test]
+fn test_should_panic_but_succeeds() {
+    fn f() {}
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: false,
+            should_panic: ShouldPanic::Yes,
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    let (tx, rx) = channel();
+    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    let (_, res, _) = rx.recv().unwrap();
+    assert!(res == TrFailed);
+}
+
+#[test]
+fn parse_ignored_flag() {
+    let args = vec![
+        "progname".to_string(),
+        "filter".to_string(),
+        "--ignored".to_string(),
+    ];
+    let opts = parse_opts(&args).unwrap().unwrap();
+    assert_eq!(opts.run_ignored, RunIgnored::Only);
+}
+
+#[test]
+fn parse_include_ignored_flag() {
+    let args = vec![
+        "progname".to_string(),
+        "filter".to_string(),
+        "-Zunstable-options".to_string(),
+        "--include-ignored".to_string(),
+    ];
+    let opts = parse_opts(&args).unwrap().unwrap();
+    assert_eq!(opts.run_ignored, RunIgnored::Yes);
+}
+
+#[test]
+pub fn filter_for_ignored_option() {
+    // When we run ignored tests the test filter should filter out all the
+    // unignored tests and flip the ignore flag on the rest to false
+
+    let mut opts = TestOpts::new();
+    opts.run_tests = true;
+    opts.run_ignored = RunIgnored::Only;
+
+    let tests = one_ignored_one_unignored_test();
+    let filtered = filter_tests(&opts, tests);
+
+    assert_eq!(filtered.len(), 1);
+    assert_eq!(filtered[0].desc.name.to_string(), "1");
+    assert!(!filtered[0].desc.ignore);
+}
+
+#[test]
+pub fn run_include_ignored_option() {
+    // When we "--include-ignored" tests, the ignore flag should be set to false on
+    // all tests and no test filtered out
+
+    let mut opts = TestOpts::new();
+    opts.run_tests = true;
+    opts.run_ignored = RunIgnored::Yes;
+
+    let tests = one_ignored_one_unignored_test();
+    let filtered = filter_tests(&opts, tests);
+
+    assert_eq!(filtered.len(), 2);
+    assert!(!filtered[0].desc.ignore);
+    assert!(!filtered[1].desc.ignore);
+}
+
+#[test]
+pub fn exclude_should_panic_option() {
+    let mut opts = TestOpts::new();
+    opts.run_tests = true;
+    opts.exclude_should_panic = true;
+
+    let mut tests = one_ignored_one_unignored_test();
+    tests.push(TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("3"),
+            ignore: false,
+            should_panic: ShouldPanic::Yes,
+            allow_fail: false,
+        },
+        testfn: DynTestFn(Box::new(move || {})),
+    });
+
+    let filtered = filter_tests(&opts, tests);
+
+    assert_eq!(filtered.len(), 2);
+    assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
+}
+
+#[test]
+pub fn exact_filter_match() {
+    fn tests() -> Vec<TestDescAndFn> {
+        vec!["base", "base::test", "base::test1", "base::test2"]
+            .into_iter()
+            .map(|name| TestDescAndFn {
+                desc: TestDesc {
+                    name: StaticTestName(name),
+                    ignore: false,
+                    should_panic: ShouldPanic::No,
+                    allow_fail: false,
+                },
+                testfn: DynTestFn(Box::new(move || {})),
+            })
+            .collect()
+    }
+
+    let substr = filter_tests(
+        &TestOpts {
+            filter: Some("base".into()),
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(substr.len(), 4);
+
+    let substr = filter_tests(
+        &TestOpts {
+            filter: Some("bas".into()),
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(substr.len(), 4);
+
+    let substr = filter_tests(
+        &TestOpts {
+            filter: Some("::test".into()),
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(substr.len(), 3);
+
+    let substr = filter_tests(
+        &TestOpts {
+            filter: Some("base::test".into()),
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(substr.len(), 3);
+
+    let exact = filter_tests(
+        &TestOpts {
+            filter: Some("base".into()),
+            filter_exact: true,
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(exact.len(), 1);
+
+    let exact = filter_tests(
+        &TestOpts {
+            filter: Some("bas".into()),
+            filter_exact: true,
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(exact.len(), 0);
+
+    let exact = filter_tests(
+        &TestOpts {
+            filter: Some("::test".into()),
+            filter_exact: true,
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(exact.len(), 0);
+
+    let exact = filter_tests(
+        &TestOpts {
+            filter: Some("base::test".into()),
+            filter_exact: true,
+            ..TestOpts::new()
+        },
+        tests(),
+    );
+    assert_eq!(exact.len(), 1);
+}
+
+#[test]
+pub fn sort_tests() {
+    let mut opts = TestOpts::new();
+    opts.run_tests = true;
+
+    let names = vec![
+        "sha1::test".to_string(),
+        "isize::test_to_str".to_string(),
+        "isize::test_pow".to_string(),
+        "test::do_not_run_ignored_tests".to_string(),
+        "test::ignored_tests_result_in_ignored".to_string(),
+        "test::first_free_arg_should_be_a_filter".to_string(),
+        "test::parse_ignored_flag".to_string(),
+        "test::parse_include_ignored_flag".to_string(),
+        "test::filter_for_ignored_option".to_string(),
+        "test::run_include_ignored_option".to_string(),
+        "test::sort_tests".to_string(),
+    ];
+    let tests = {
+        fn testfn() {}
+        let mut tests = Vec::new();
+        for name in &names {
+            let test = TestDescAndFn {
+                desc: TestDesc {
+                    name: DynTestName((*name).clone()),
+                    ignore: false,
+                    should_panic: ShouldPanic::No,
+                    allow_fail: false,
+                },
+                testfn: DynTestFn(Box::new(testfn)),
+            };
+            tests.push(test);
+        }
+        tests
+    };
+    let filtered = filter_tests(&opts, tests);
+
+    let expected = vec![
+        "isize::test_pow".to_string(),
+        "isize::test_to_str".to_string(),
+        "sha1::test".to_string(),
+        "test::do_not_run_ignored_tests".to_string(),
+        "test::filter_for_ignored_option".to_string(),
+        "test::first_free_arg_should_be_a_filter".to_string(),
+        "test::ignored_tests_result_in_ignored".to_string(),
+        "test::parse_ignored_flag".to_string(),
+        "test::parse_include_ignored_flag".to_string(),
+        "test::run_include_ignored_option".to_string(),
+        "test::sort_tests".to_string(),
+    ];
+
+    for (a, b) in expected.iter().zip(filtered) {
+        assert!(*a == b.desc.name.to_string());
+    }
+}
+
+#[test]
+pub fn test_metricmap_compare() {
+    let mut m1 = MetricMap::new();
+    let mut m2 = MetricMap::new();
+    m1.insert_metric("in-both-noise", 1000.0, 200.0);
+    m2.insert_metric("in-both-noise", 1100.0, 200.0);
+
+    m1.insert_metric("in-first-noise", 1000.0, 2.0);
+    m2.insert_metric("in-second-noise", 1000.0, 2.0);
+
+    m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0);
+    m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0);
+
+    m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0);
+    m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0);
+
+    m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0);
+    m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0);
+
+    m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0);
+    m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0);
+}
+
+#[test]
+pub fn test_bench_once_no_iter() {
+    fn f(_: &mut Bencher) {}
+    bench::run_once(f);
+}
+
+#[test]
+pub fn test_bench_once_iter() {
+    fn f(b: &mut Bencher) {
+        b.iter(|| {})
+    }
+    bench::run_once(f);
+}
+
+#[test]
+pub fn test_bench_no_iter() {
+    fn f(_: &mut Bencher) {}
+
+    let (tx, rx) = channel();
+
+    let desc = TestDesc {
+        name: StaticTestName("f"),
+        ignore: false,
+        should_panic: ShouldPanic::No,
+        allow_fail: false,
+    };
+
+    crate::bench::benchmark(desc, tx, true, f);
+    rx.recv().unwrap();
+}
+
+#[test]
+pub fn test_bench_iter() {
+    fn f(b: &mut Bencher) {
+        b.iter(|| {})
+    }
+
+    let (tx, rx) = channel();
+
+    let desc = TestDesc {
+        name: StaticTestName("f"),
+        ignore: false,
+        should_panic: ShouldPanic::No,
+        allow_fail: false,
+    };
+
+    crate::bench::benchmark(desc, tx, true, f);
+    rx.recv().unwrap();
+}