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