]> git.lizzy.rs Git - rust.git/blob - library/test/src/tests.rs
Rollup merge of #104359 - Nilstrieb:plus-one, r=fee1-dead
[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);
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);
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);
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);
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);
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);
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(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx);
271         let result = rx.recv().unwrap().result;
272         assert_eq!(
273             result,
274             TrFailedMsg("test did not panic as expected".to_string()),
275             "should_panic == {:?}",
276             should_panic
277         );
278     }
279 }
280
281 fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
282     fn f() -> Result<(), String> {
283         Ok(())
284     }
285     let desc = TestDescAndFn {
286         desc: TestDesc {
287             name: StaticTestName("whatever"),
288             ignore: false,
289             ignore_message: None,
290             should_panic: ShouldPanic::No,
291             compile_fail: false,
292             no_run: false,
293             test_type: TestType::Unknown,
294         },
295         testfn: DynTestFn(Box::new(f)),
296     };
297     let time_options = if report_time { Some(TestTimeOptions::default()) } else { None };
298
299     let test_opts = TestOpts { time_options, ..TestOpts::new() };
300     let (tx, rx) = channel();
301     run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx);
302     let exec_time = rx.recv().unwrap().exec_time;
303     exec_time
304 }
305
306 #[test]
307 fn test_should_not_report_time() {
308     let exec_time = report_time_test_template(false);
309     assert!(exec_time.is_none());
310 }
311
312 #[test]
313 fn test_should_report_time() {
314     let exec_time = report_time_test_template(true);
315     assert!(exec_time.is_some());
316 }
317
318 fn time_test_failure_template(test_type: TestType) -> TestResult {
319     fn f() -> Result<(), String> {
320         Ok(())
321     }
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);
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 || Ok(()))),
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 || Ok(()))),
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() -> Result<(), String> {
584         Ok(())
585     }
586     let mut tests = Vec::new();
587     for name in &names {
588         let test = TestDescAndFn {
589             desc: TestDesc {
590                 name: DynTestName((*name).clone()),
591                 ignore: false,
592                 ignore_message: None,
593                 should_panic: ShouldPanic::No,
594                 compile_fail: false,
595                 no_run: false,
596                 test_type: TestType::Unknown,
597             },
598             testfn: DynTestFn(Box::new(testfn)),
599         };
600         tests.push(test);
601     }
602     tests
603 }
604
605 #[test]
606 pub fn shuffle_tests() {
607     let mut opts = TestOpts::new();
608     opts.shuffle = true;
609
610     let shuffle_seed = get_shuffle_seed(&opts).unwrap();
611
612     let left =
613         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
614     let mut right =
615         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
616
617     assert!(left.iter().zip(&right).all(|(a, b)| a.1.desc.name == b.1.desc.name));
618
619     helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice());
620
621     assert!(left.iter().zip(right).any(|(a, b)| a.1.desc.name != b.1.desc.name));
622 }
623
624 #[test]
625 pub fn shuffle_tests_with_seed() {
626     let mut opts = TestOpts::new();
627     opts.shuffle = true;
628
629     let shuffle_seed = get_shuffle_seed(&opts).unwrap();
630
631     let mut left =
632         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
633     let mut right =
634         sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
635
636     helpers::shuffle::shuffle_tests(shuffle_seed, left.as_mut_slice());
637     helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice());
638
639     assert!(left.iter().zip(right).all(|(a, b)| a.1.desc.name == b.1.desc.name));
640 }
641
642 #[test]
643 pub fn order_depends_on_more_than_seed() {
644     let mut opts = TestOpts::new();
645     opts.shuffle = true;
646
647     let shuffle_seed = get_shuffle_seed(&opts).unwrap();
648
649     let mut left_tests = sample_tests();
650     let mut right_tests = sample_tests();
651
652     left_tests.pop();
653     right_tests.remove(0);
654
655     let mut left =
656         left_tests.into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
657     let mut right =
658         right_tests.into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::<Vec<_>>();
659
660     assert_eq!(left.len(), right.len());
661
662     assert!(left.iter().zip(&right).all(|(a, b)| a.0 == b.0));
663
664     helpers::shuffle::shuffle_tests(shuffle_seed, left.as_mut_slice());
665     helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice());
666
667     assert!(left.iter().zip(right).any(|(a, b)| a.0 != b.0));
668 }
669
670 #[test]
671 pub fn test_metricmap_compare() {
672     let mut m1 = MetricMap::new();
673     let mut m2 = MetricMap::new();
674     m1.insert_metric("in-both-noise", 1000.0, 200.0);
675     m2.insert_metric("in-both-noise", 1100.0, 200.0);
676
677     m1.insert_metric("in-first-noise", 1000.0, 2.0);
678     m2.insert_metric("in-second-noise", 1000.0, 2.0);
679
680     m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0);
681     m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0);
682
683     m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0);
684     m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0);
685
686     m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0);
687     m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0);
688
689     m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0);
690     m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0);
691 }
692
693 #[test]
694 pub fn test_bench_once_no_iter() {
695     fn f(_: &mut Bencher) -> Result<(), String> {
696         Ok(())
697     }
698     bench::run_once(f).unwrap();
699 }
700
701 #[test]
702 pub fn test_bench_once_iter() {
703     fn f(b: &mut Bencher) -> Result<(), String> {
704         b.iter(|| {});
705         Ok(())
706     }
707     bench::run_once(f).unwrap();
708 }
709
710 #[test]
711 pub fn test_bench_no_iter() {
712     fn f(_: &mut Bencher) -> Result<(), String> {
713         Ok(())
714     }
715
716     let (tx, rx) = channel();
717
718     let desc = TestDesc {
719         name: StaticTestName("f"),
720         ignore: false,
721         ignore_message: None,
722         should_panic: ShouldPanic::No,
723         compile_fail: false,
724         no_run: false,
725         test_type: TestType::Unknown,
726     };
727
728     crate::bench::benchmark(TestId(0), desc, tx, true, f);
729     rx.recv().unwrap();
730 }
731
732 #[test]
733 pub fn test_bench_iter() {
734     fn f(b: &mut Bencher) -> Result<(), String> {
735         b.iter(|| {});
736         Ok(())
737     }
738
739     let (tx, rx) = channel();
740
741     let desc = TestDesc {
742         name: StaticTestName("f"),
743         ignore: false,
744         ignore_message: None,
745         should_panic: ShouldPanic::No,
746         compile_fail: false,
747         no_run: false,
748         test_type: TestType::Unknown,
749     };
750
751     crate::bench::benchmark(TestId(0), desc, tx, true, f);
752     rx.recv().unwrap();
753 }
754
755 #[test]
756 fn should_sort_failures_before_printing_them() {
757     let test_a = TestDesc {
758         name: StaticTestName("a"),
759         ignore: false,
760         ignore_message: None,
761         should_panic: ShouldPanic::No,
762         compile_fail: false,
763         no_run: false,
764         test_type: TestType::Unknown,
765     };
766
767     let test_b = TestDesc {
768         name: StaticTestName("b"),
769         ignore: false,
770         ignore_message: None,
771         should_panic: ShouldPanic::No,
772         compile_fail: false,
773         no_run: false,
774         test_type: TestType::Unknown,
775     };
776
777     let mut out = PrettyFormatter::new(OutputLocation::Raw(Vec::new()), false, 10, false, None);
778
779     let st = console::ConsoleTestState {
780         log_out: None,
781         total: 0,
782         passed: 0,
783         failed: 0,
784         ignored: 0,
785         filtered_out: 0,
786         measured: 0,
787         exec_time: None,
788         metrics: MetricMap::new(),
789         failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
790         options: Options::new(),
791         not_failures: Vec::new(),
792         time_failures: Vec::new(),
793     };
794
795     out.write_failures(&st).unwrap();
796     let s = match out.output_location() {
797         &OutputLocation::Raw(ref m) => String::from_utf8_lossy(&m[..]),
798         &OutputLocation::Pretty(_) => unreachable!(),
799     };
800
801     let apos = s.find("a").unwrap();
802     let bpos = s.find("b").unwrap();
803     assert!(apos < bpos);
804 }
805
806 #[test]
807 #[cfg(not(target_os = "emscripten"))]
808 fn test_dyn_bench_returning_err_fails_when_run_as_test() {
809     fn f(_: &mut Bencher) -> Result<(), String> {
810         Result::Err("An error".into())
811     }
812     let desc = TestDescAndFn {
813         desc: TestDesc {
814             name: StaticTestName("whatever"),
815             ignore: false,
816             ignore_message: None,
817             should_panic: ShouldPanic::No,
818             compile_fail: false,
819             no_run: false,
820             test_type: TestType::Unknown,
821         },
822         testfn: DynBenchFn(Box::new(f)),
823     };
824     let (tx, rx) = channel();
825     let notify = move |event: TestEvent| {
826         if let TestEvent::TeResult(result) = event {
827             tx.send(result).unwrap();
828         }
829         Ok(())
830     };
831     run_tests(&TestOpts { run_tests: true, ..TestOpts::new() }, vec![desc], notify).unwrap();
832     let result = rx.recv().unwrap().result;
833     assert_eq!(result, TrFailed);
834 }