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