]> git.lizzy.rs Git - rust.git/blob - library/test/src/tests.rs
Rollup merge of #93742 - Mark-Simulacrum:skip-rustc-docs-complete, r=pietroalbini
[rust.git] / library / test / src / tests.rs
1 use super::*;
2
3 use crate::{
4     bench::Bencher,
5     console::OutputLocation,
6     formatters::PrettyFormatter,
7     options::OutputFormat,
8     test::{
9         filter_tests,
10         parse_opts,
11         run_test,
12         DynTestFn,
13         DynTestName,
14         MetricMap,
15         RunIgnored,
16         RunStrategy,
17         ShouldPanic,
18         StaticTestName,
19         TestDesc,
20         TestDescAndFn,
21         TestOpts,
22         TrIgnored,
23         TrOk,
24         // FIXME (introduced by #65251)
25         // ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions,
26         // TestType, TrFailedMsg, TrIgnored, TrOk,
27     },
28     time::{TestTimeOptions, TimeThreshold},
29 };
30 use std::sync::mpsc::channel;
31 use std::time::Duration;
32
33 impl TestOpts {
34     fn new() -> TestOpts {
35         TestOpts {
36             list: false,
37             filters: vec![],
38             filter_exact: false,
39             force_run_in_process: false,
40             exclude_should_panic: false,
41             run_ignored: RunIgnored::No,
42             run_tests: false,
43             bench_benchmarks: false,
44             logfile: None,
45             nocapture: false,
46             color: AutoColor,
47             format: OutputFormat::Pretty,
48             shuffle: false,
49             shuffle_seed: None,
50             test_threads: None,
51             skip: vec![],
52             time_options: None,
53             options: Options::new(),
54         }
55     }
56 }
57
58 fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
59     vec![
60         TestDescAndFn {
61             desc: TestDesc {
62                 name: StaticTestName("1"),
63                 ignore: true,
64                 should_panic: ShouldPanic::No,
65                 compile_fail: false,
66                 no_run: false,
67                 test_type: TestType::Unknown,
68                 #[cfg(bootstrap)]
69                 allow_fail: false,
70             },
71             testfn: DynTestFn(Box::new(move || {})),
72         },
73         TestDescAndFn {
74             desc: TestDesc {
75                 name: StaticTestName("2"),
76                 ignore: false,
77                 should_panic: ShouldPanic::No,
78                 compile_fail: false,
79                 no_run: false,
80                 test_type: TestType::Unknown,
81                 #[cfg(bootstrap)]
82                 allow_fail: false,
83             },
84             testfn: DynTestFn(Box::new(move || {})),
85         },
86     ]
87 }
88
89 #[test]
90 pub fn do_not_run_ignored_tests() {
91     fn f() {
92         panic!();
93     }
94     let desc = TestDescAndFn {
95         desc: TestDesc {
96             name: StaticTestName("whatever"),
97             ignore: true,
98             should_panic: ShouldPanic::No,
99             compile_fail: false,
100             no_run: false,
101             test_type: TestType::Unknown,
102             #[cfg(bootstrap)]
103             allow_fail: false,
104         },
105         testfn: DynTestFn(Box::new(f)),
106     };
107     let (tx, rx) = channel();
108     run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
109     let result = rx.recv().unwrap().result;
110     assert_ne!(result, TrOk);
111 }
112
113 #[test]
114 pub fn ignored_tests_result_in_ignored() {
115     fn f() {}
116     let desc = TestDescAndFn {
117         desc: TestDesc {
118             name: StaticTestName("whatever"),
119             ignore: true,
120             should_panic: ShouldPanic::No,
121             compile_fail: false,
122             no_run: false,
123             test_type: TestType::Unknown,
124             #[cfg(bootstrap)]
125             allow_fail: false,
126         },
127         testfn: DynTestFn(Box::new(f)),
128     };
129     let (tx, rx) = channel();
130     run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
131     let result = rx.recv().unwrap().result;
132     assert_eq!(result, TrIgnored);
133 }
134
135 // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
136 #[test]
137 #[cfg(not(target_os = "emscripten"))]
138 fn test_should_panic() {
139     fn f() {
140         panic!();
141     }
142     let desc = TestDescAndFn {
143         desc: TestDesc {
144             name: StaticTestName("whatever"),
145             ignore: false,
146             should_panic: ShouldPanic::Yes,
147             compile_fail: false,
148             no_run: false,
149             test_type: TestType::Unknown,
150             #[cfg(bootstrap)]
151             allow_fail: false,
152         },
153         testfn: DynTestFn(Box::new(f)),
154     };
155     let (tx, rx) = channel();
156     run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
157     let result = rx.recv().unwrap().result;
158     assert_eq!(result, TrOk);
159 }
160
161 // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
162 #[test]
163 #[cfg(not(target_os = "emscripten"))]
164 fn test_should_panic_good_message() {
165     fn f() {
166         panic!("an error message");
167     }
168     let desc = TestDescAndFn {
169         desc: TestDesc {
170             name: StaticTestName("whatever"),
171             ignore: false,
172             should_panic: ShouldPanic::YesWithMessage("error message"),
173             compile_fail: false,
174             no_run: false,
175             test_type: TestType::Unknown,
176             #[cfg(bootstrap)]
177             allow_fail: false,
178         },
179         testfn: DynTestFn(Box::new(f)),
180     };
181     let (tx, rx) = channel();
182     run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
183     let result = rx.recv().unwrap().result;
184     assert_eq!(result, TrOk);
185 }
186
187 // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
188 #[test]
189 #[cfg(not(target_os = "emscripten"))]
190 fn test_should_panic_bad_message() {
191     use crate::tests::TrFailedMsg;
192     fn f() {
193         panic!("an error message");
194     }
195     let expected = "foobar";
196     let failed_msg = r#"panic did not contain expected string
197       panic message: `"an error message"`,
198  expected substring: `"foobar"`"#;
199     let desc = TestDescAndFn {
200         desc: TestDesc {
201             name: StaticTestName("whatever"),
202             ignore: false,
203             should_panic: ShouldPanic::YesWithMessage(expected),
204             compile_fail: false,
205             no_run: false,
206             test_type: TestType::Unknown,
207             #[cfg(bootstrap)]
208             allow_fail: false,
209         },
210         testfn: DynTestFn(Box::new(f)),
211     };
212     let (tx, rx) = channel();
213     run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
214     let result = rx.recv().unwrap().result;
215     assert_eq!(result, TrFailedMsg(failed_msg.to_string()));
216 }
217
218 // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
219 #[test]
220 #[cfg(not(target_os = "emscripten"))]
221 fn test_should_panic_non_string_message_type() {
222     use crate::tests::TrFailedMsg;
223     use std::any::TypeId;
224     fn f() {
225         std::panic::panic_any(1i32);
226     }
227     let expected = "foobar";
228     let failed_msg = format!(
229         r#"expected panic with string value,
230  found non-string value: `{:?}`
231      expected substring: `"foobar"`"#,
232         TypeId::of::<i32>()
233     );
234     let desc = TestDescAndFn {
235         desc: TestDesc {
236             name: StaticTestName("whatever"),
237             ignore: false,
238             should_panic: ShouldPanic::YesWithMessage(expected),
239             compile_fail: false,
240             no_run: false,
241             test_type: TestType::Unknown,
242             #[cfg(bootstrap)]
243             allow_fail: false,
244         },
245         testfn: DynTestFn(Box::new(f)),
246     };
247     let (tx, rx) = channel();
248     run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
249     let result = rx.recv().unwrap().result;
250     assert_eq!(result, TrFailedMsg(failed_msg));
251 }
252
253 // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
254 #[test]
255 #[cfg(not(target_os = "emscripten"))]
256 fn test_should_panic_but_succeeds() {
257     let should_panic_variants = [ShouldPanic::Yes, ShouldPanic::YesWithMessage("error message")];
258
259     for &should_panic in should_panic_variants.iter() {
260         fn f() {}
261         let desc = TestDescAndFn {
262             desc: TestDesc {
263                 name: StaticTestName("whatever"),
264                 ignore: false,
265                 should_panic,
266                 compile_fail: false,
267                 no_run: false,
268                 test_type: TestType::Unknown,
269                 #[cfg(bootstrap)]
270                 allow_fail: false,
271             },
272             testfn: DynTestFn(Box::new(f)),
273         };
274         let (tx, rx) = channel();
275         run_test(
276             &TestOpts::new(),
277             false,
278             TestId(0),
279             desc,
280             RunStrategy::InProcess,
281             tx,
282             Concurrent::No,
283         );
284         let result = rx.recv().unwrap().result;
285         assert_eq!(
286             result,
287             TrFailedMsg("test did not panic as expected".to_string()),
288             "should_panic == {:?}",
289             should_panic
290         );
291     }
292 }
293
294 fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
295     fn f() {}
296     let desc = TestDescAndFn {
297         desc: TestDesc {
298             name: StaticTestName("whatever"),
299             ignore: false,
300             should_panic: ShouldPanic::No,
301             compile_fail: false,
302             no_run: false,
303             test_type: TestType::Unknown,
304             #[cfg(bootstrap)]
305             allow_fail: false,
306         },
307         testfn: DynTestFn(Box::new(f)),
308     };
309     let time_options = if report_time { Some(TestTimeOptions::default()) } else { None };
310
311     let test_opts = TestOpts { time_options, ..TestOpts::new() };
312     let (tx, rx) = channel();
313     run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
314     let exec_time = rx.recv().unwrap().exec_time;
315     exec_time
316 }
317
318 #[test]
319 fn test_should_not_report_time() {
320     let exec_time = report_time_test_template(false);
321     assert!(exec_time.is_none());
322 }
323
324 #[test]
325 fn test_should_report_time() {
326     let exec_time = report_time_test_template(true);
327     assert!(exec_time.is_some());
328 }
329
330 fn time_test_failure_template(test_type: TestType) -> TestResult {
331     fn f() {}
332     let desc = TestDescAndFn {
333         desc: TestDesc {
334             name: StaticTestName("whatever"),
335             ignore: false,
336             should_panic: ShouldPanic::No,
337             compile_fail: false,
338             no_run: false,
339             test_type,
340             #[cfg(bootstrap)]
341             allow_fail: false,
342         },
343         testfn: DynTestFn(Box::new(f)),
344     };
345     // `Default` will initialize all the thresholds to 0 milliseconds.
346     let mut time_options = TestTimeOptions::default();
347     time_options.error_on_excess = true;
348
349     let test_opts = TestOpts { time_options: Some(time_options), ..TestOpts::new() };
350     let (tx, rx) = channel();
351     run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No);
352     let result = rx.recv().unwrap().result;
353
354     result
355 }
356
357 #[test]
358 fn test_error_on_exceed() {
359     let types = [TestType::UnitTest, TestType::IntegrationTest, TestType::DocTest];
360
361     for test_type in types.iter() {
362         let result = time_test_failure_template(*test_type);
363
364         assert_eq!(result, TestResult::TrTimedFail);
365     }
366
367     // Check that for unknown tests thresholds aren't applied.
368     let result = time_test_failure_template(TestType::Unknown);
369     assert_eq!(result, TestResult::TrOk);
370 }
371
372 fn typed_test_desc(test_type: TestType) -> TestDesc {
373     TestDesc {
374         name: StaticTestName("whatever"),
375         ignore: false,
376         should_panic: ShouldPanic::No,
377         compile_fail: false,
378         no_run: false,
379         test_type,
380         #[cfg(bootstrap)]
381         allow_fail: false,
382     }
383 }
384
385 fn test_exec_time(millis: u64) -> TestExecTime {
386     TestExecTime(Duration::from_millis(millis))
387 }
388
389 #[test]
390 fn test_time_options_threshold() {
391     let unit = TimeThreshold::new(Duration::from_millis(50), Duration::from_millis(100));
392     let integration = TimeThreshold::new(Duration::from_millis(500), Duration::from_millis(1000));
393     let doc = TimeThreshold::new(Duration::from_millis(5000), Duration::from_millis(10000));
394
395     let options = TestTimeOptions {
396         error_on_excess: false,
397         colored: false,
398         unit_threshold: unit.clone(),
399         integration_threshold: integration.clone(),
400         doctest_threshold: doc.clone(),
401     };
402
403     let test_vector = [
404         (TestType::UnitTest, unit.warn.as_millis() - 1, false, false),
405         (TestType::UnitTest, unit.warn.as_millis(), true, false),
406         (TestType::UnitTest, unit.critical.as_millis(), true, true),
407         (TestType::IntegrationTest, integration.warn.as_millis() - 1, false, false),
408         (TestType::IntegrationTest, integration.warn.as_millis(), true, false),
409         (TestType::IntegrationTest, integration.critical.as_millis(), true, true),
410         (TestType::DocTest, doc.warn.as_millis() - 1, false, false),
411         (TestType::DocTest, doc.warn.as_millis(), true, false),
412         (TestType::DocTest, doc.critical.as_millis(), true, true),
413     ];
414
415     for (test_type, time, expected_warn, expected_critical) in test_vector.iter() {
416         let test_desc = typed_test_desc(*test_type);
417         let exec_time = test_exec_time(*time as u64);
418
419         assert_eq!(options.is_warn(&test_desc, &exec_time), *expected_warn);
420         assert_eq!(options.is_critical(&test_desc, &exec_time), *expected_critical);
421     }
422 }
423
424 #[test]
425 fn parse_ignored_flag() {
426     let args = vec!["progname".to_string(), "filter".to_string(), "--ignored".to_string()];
427     let opts = parse_opts(&args).unwrap().unwrap();
428     assert_eq!(opts.run_ignored, RunIgnored::Only);
429 }
430
431 #[test]
432 fn parse_show_output_flag() {
433     let args = vec!["progname".to_string(), "filter".to_string(), "--show-output".to_string()];
434     let opts = parse_opts(&args).unwrap().unwrap();
435     assert!(opts.options.display_output);
436 }
437
438 #[test]
439 fn parse_include_ignored_flag() {
440     let args = vec!["progname".to_string(), "filter".to_string(), "--include-ignored".to_string()];
441     let opts = parse_opts(&args).unwrap().unwrap();
442     assert_eq!(opts.run_ignored, RunIgnored::Yes);
443 }
444
445 #[test]
446 pub fn filter_for_ignored_option() {
447     // When we run ignored tests the test filter should filter out all the
448     // unignored tests and flip the ignore flag on the rest to false
449
450     let mut opts = TestOpts::new();
451     opts.run_tests = true;
452     opts.run_ignored = RunIgnored::Only;
453
454     let tests = one_ignored_one_unignored_test();
455     let filtered = filter_tests(&opts, tests);
456
457     assert_eq!(filtered.len(), 1);
458     assert_eq!(filtered[0].desc.name.to_string(), "1");
459     assert!(!filtered[0].desc.ignore);
460 }
461
462 #[test]
463 pub fn run_include_ignored_option() {
464     // When we "--include-ignored" tests, the ignore flag should be set to false on
465     // all tests and no test filtered out
466
467     let mut opts = TestOpts::new();
468     opts.run_tests = true;
469     opts.run_ignored = RunIgnored::Yes;
470
471     let tests = one_ignored_one_unignored_test();
472     let filtered = filter_tests(&opts, tests);
473
474     assert_eq!(filtered.len(), 2);
475     assert!(!filtered[0].desc.ignore);
476     assert!(!filtered[1].desc.ignore);
477 }
478
479 #[test]
480 pub fn exclude_should_panic_option() {
481     let mut opts = TestOpts::new();
482     opts.run_tests = true;
483     opts.exclude_should_panic = true;
484
485     let mut tests = one_ignored_one_unignored_test();
486     tests.push(TestDescAndFn {
487         desc: TestDesc {
488             name: StaticTestName("3"),
489             ignore: false,
490             should_panic: ShouldPanic::Yes,
491             compile_fail: false,
492             no_run: false,
493             test_type: TestType::Unknown,
494             #[cfg(bootstrap)]
495             allow_fail: false,
496         },
497         testfn: DynTestFn(Box::new(move || {})),
498     });
499
500     let filtered = filter_tests(&opts, tests);
501
502     assert_eq!(filtered.len(), 2);
503     assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
504 }
505
506 #[test]
507 pub fn exact_filter_match() {
508     fn tests() -> Vec<TestDescAndFn> {
509         ["base", "base::test", "base::test1", "base::test2"]
510             .into_iter()
511             .map(|name| TestDescAndFn {
512                 desc: TestDesc {
513                     name: StaticTestName(name),
514                     ignore: false,
515                     should_panic: ShouldPanic::No,
516                     compile_fail: false,
517                     no_run: false,
518                     test_type: TestType::Unknown,
519                     #[cfg(bootstrap)]
520                     allow_fail: false,
521                 },
522                 testfn: DynTestFn(Box::new(move || {})),
523             })
524             .collect()
525     }
526
527     let substr =
528         filter_tests(&TestOpts { filters: vec!["base".into()], ..TestOpts::new() }, tests());
529     assert_eq!(substr.len(), 4);
530
531     let substr =
532         filter_tests(&TestOpts { filters: vec!["bas".into()], ..TestOpts::new() }, tests());
533     assert_eq!(substr.len(), 4);
534
535     let substr =
536         filter_tests(&TestOpts { filters: vec!["::test".into()], ..TestOpts::new() }, tests());
537     assert_eq!(substr.len(), 3);
538
539     let substr =
540         filter_tests(&TestOpts { filters: vec!["base::test".into()], ..TestOpts::new() }, tests());
541     assert_eq!(substr.len(), 3);
542
543     let substr = filter_tests(
544         &TestOpts { filters: vec!["test1".into(), "test2".into()], ..TestOpts::new() },
545         tests(),
546     );
547     assert_eq!(substr.len(), 2);
548
549     let exact = filter_tests(
550         &TestOpts { filters: vec!["base".into()], filter_exact: true, ..TestOpts::new() },
551         tests(),
552     );
553     assert_eq!(exact.len(), 1);
554
555     let exact = filter_tests(
556         &TestOpts { filters: vec!["bas".into()], filter_exact: true, ..TestOpts::new() },
557         tests(),
558     );
559     assert_eq!(exact.len(), 0);
560
561     let exact = filter_tests(
562         &TestOpts { filters: vec!["::test".into()], filter_exact: true, ..TestOpts::new() },
563         tests(),
564     );
565     assert_eq!(exact.len(), 0);
566
567     let exact = filter_tests(
568         &TestOpts { filters: vec!["base::test".into()], filter_exact: true, ..TestOpts::new() },
569         tests(),
570     );
571     assert_eq!(exact.len(), 1);
572
573     let exact = filter_tests(
574         &TestOpts {
575             filters: vec!["base".into(), "base::test".into()],
576             filter_exact: true,
577             ..TestOpts::new()
578         },
579         tests(),
580     );
581     assert_eq!(exact.len(), 2);
582 }
583
584 fn sample_tests() -> Vec<TestDescAndFn> {
585     let names = vec![
586         "sha1::test".to_string(),
587         "isize::test_to_str".to_string(),
588         "isize::test_pow".to_string(),
589         "test::do_not_run_ignored_tests".to_string(),
590         "test::ignored_tests_result_in_ignored".to_string(),
591         "test::first_free_arg_should_be_a_filter".to_string(),
592         "test::parse_ignored_flag".to_string(),
593         "test::parse_include_ignored_flag".to_string(),
594         "test::filter_for_ignored_option".to_string(),
595         "test::run_include_ignored_option".to_string(),
596         "test::sort_tests".to_string(),
597     ];
598     fn testfn() {}
599     let mut tests = Vec::new();
600     for name in &names {
601         let test = TestDescAndFn {
602             desc: TestDesc {
603                 name: DynTestName((*name).clone()),
604                 ignore: false,
605                 should_panic: ShouldPanic::No,
606                 compile_fail: false,
607                 no_run: false,
608                 test_type: TestType::Unknown,
609                 #[cfg(bootstrap)]
610                 allow_fail: false,
611             },
612             testfn: DynTestFn(Box::new(testfn)),
613         };
614         tests.push(test);
615     }
616     tests
617 }
618
619 #[test]
620 pub fn sort_tests() {
621     let mut opts = TestOpts::new();
622     opts.run_tests = true;
623
624     let tests = sample_tests();
625     let filtered = filter_tests(&opts, tests);
626
627     let expected = vec![
628         "isize::test_pow".to_string(),
629         "isize::test_to_str".to_string(),
630         "sha1::test".to_string(),
631         "test::do_not_run_ignored_tests".to_string(),
632         "test::filter_for_ignored_option".to_string(),
633         "test::first_free_arg_should_be_a_filter".to_string(),
634         "test::ignored_tests_result_in_ignored".to_string(),
635         "test::parse_ignored_flag".to_string(),
636         "test::parse_include_ignored_flag".to_string(),
637         "test::run_include_ignored_option".to_string(),
638         "test::sort_tests".to_string(),
639     ];
640
641     for (a, b) in expected.iter().zip(filtered) {
642         assert_eq!(*a, b.desc.name.to_string());
643     }
644 }
645
646 #[test]
647 pub fn shuffle_tests() {
648     let mut opts = TestOpts::new();
649     opts.shuffle = true;
650
651     let shuffle_seed = get_shuffle_seed(&opts).unwrap();
652
653     let left =
654         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
655     let mut right =
656         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
657
658     assert!(left.iter().zip(&right).all(|(a, b)| a.1.desc.name == b.1.desc.name));
659
660     helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice());
661
662     assert!(left.iter().zip(right).any(|(a, b)| a.1.desc.name != b.1.desc.name));
663 }
664
665 #[test]
666 pub fn shuffle_tests_with_seed() {
667     let mut opts = TestOpts::new();
668     opts.shuffle = true;
669
670     let shuffle_seed = get_shuffle_seed(&opts).unwrap();
671
672     let mut left =
673         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
674     let mut right =
675         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
676
677     helpers::shuffle::shuffle_tests(shuffle_seed, left.as_mut_slice());
678     helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice());
679
680     assert!(left.iter().zip(right).all(|(a, b)| a.1.desc.name == b.1.desc.name));
681 }
682
683 #[test]
684 pub fn order_depends_on_more_than_seed() {
685     let mut opts = TestOpts::new();
686     opts.shuffle = true;
687
688     let shuffle_seed = get_shuffle_seed(&opts).unwrap();
689
690     let mut left_tests = sample_tests();
691     let mut right_tests = sample_tests();
692
693     left_tests.pop();
694     right_tests.remove(0);
695
696     let mut left =
697         left_tests.into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
698     let mut right =
699         right_tests.into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
700
701     assert_eq!(left.len(), right.len());
702
703     assert!(left.iter().zip(&right).all(|(a, b)| a.0 == b.0));
704
705     helpers::shuffle::shuffle_tests(shuffle_seed, left.as_mut_slice());
706     helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice());
707
708     assert!(left.iter().zip(right).any(|(a, b)| a.0 != b.0));
709 }
710
711 #[test]
712 pub fn test_metricmap_compare() {
713     let mut m1 = MetricMap::new();
714     let mut m2 = MetricMap::new();
715     m1.insert_metric("in-both-noise", 1000.0, 200.0);
716     m2.insert_metric("in-both-noise", 1100.0, 200.0);
717
718     m1.insert_metric("in-first-noise", 1000.0, 2.0);
719     m2.insert_metric("in-second-noise", 1000.0, 2.0);
720
721     m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0);
722     m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0);
723
724     m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0);
725     m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0);
726
727     m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0);
728     m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0);
729
730     m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0);
731     m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0);
732 }
733
734 #[test]
735 pub fn test_bench_once_no_iter() {
736     fn f(_: &mut Bencher) {}
737     bench::run_once(f);
738 }
739
740 #[test]
741 pub fn test_bench_once_iter() {
742     fn f(b: &mut Bencher) {
743         b.iter(|| {})
744     }
745     bench::run_once(f);
746 }
747
748 #[test]
749 pub fn test_bench_no_iter() {
750     fn f(_: &mut Bencher) {}
751
752     let (tx, rx) = channel();
753
754     let desc = TestDesc {
755         name: StaticTestName("f"),
756         ignore: false,
757         should_panic: ShouldPanic::No,
758         compile_fail: false,
759         no_run: false,
760         test_type: TestType::Unknown,
761         #[cfg(bootstrap)]
762         allow_fail: false,
763     };
764
765     crate::bench::benchmark(TestId(0), desc, tx, true, f);
766     rx.recv().unwrap();
767 }
768
769 #[test]
770 pub fn test_bench_iter() {
771     fn f(b: &mut Bencher) {
772         b.iter(|| {})
773     }
774
775     let (tx, rx) = channel();
776
777     let desc = TestDesc {
778         name: StaticTestName("f"),
779         ignore: false,
780         should_panic: ShouldPanic::No,
781         compile_fail: false,
782         no_run: false,
783         test_type: TestType::Unknown,
784         #[cfg(bootstrap)]
785         allow_fail: false,
786     };
787
788     crate::bench::benchmark(TestId(0), desc, tx, true, f);
789     rx.recv().unwrap();
790 }
791
792 #[test]
793 fn should_sort_failures_before_printing_them() {
794     let test_a = TestDesc {
795         name: StaticTestName("a"),
796         ignore: false,
797         should_panic: ShouldPanic::No,
798         compile_fail: false,
799         no_run: false,
800         test_type: TestType::Unknown,
801         #[cfg(bootstrap)]
802         allow_fail: false,
803     };
804
805     let test_b = TestDesc {
806         name: StaticTestName("b"),
807         ignore: false,
808         should_panic: ShouldPanic::No,
809         compile_fail: false,
810         no_run: false,
811         test_type: TestType::Unknown,
812         #[cfg(bootstrap)]
813         allow_fail: false,
814     };
815
816     let mut out = PrettyFormatter::new(OutputLocation::Raw(Vec::new()), false, 10, false, None);
817
818     let st = console::ConsoleTestState {
819         log_out: None,
820         total: 0,
821         passed: 0,
822         failed: 0,
823         ignored: 0,
824         filtered_out: 0,
825         measured: 0,
826         exec_time: None,
827         metrics: MetricMap::new(),
828         failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
829         options: Options::new(),
830         not_failures: Vec::new(),
831         time_failures: Vec::new(),
832     };
833
834     out.write_failures(&st).unwrap();
835     let s = match out.output_location() {
836         &OutputLocation::Raw(ref m) => String::from_utf8_lossy(&m[..]),
837         &OutputLocation::Pretty(_) => unreachable!(),
838     };
839
840     let apos = s.find("a").unwrap();
841     let bpos = s.find("b").unwrap();
842     assert!(apos < bpos);
843 }