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