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