nu_test_support/harness/
mod.rs1use std::{
2 num::NonZeroUsize,
3 ops::Deref,
4 process::ExitCode,
5 sync::{LazyLock, atomic::Ordering},
6};
7
8use crate::{
9 self as nu_test_support,
10 harness::{
11 args::{Args, Format},
12 group::{GroupRunner, Grouper},
13 test::TestRunner,
14 },
15};
16
17use kitest::{
18 filter::DefaultFilter,
19 formatter::{pretty::PrettyFormatter, terse::TerseFormatter},
20 group::TestGroupBTreeMap,
21};
22use nu_ansi_term::Color;
23
24#[doc(hidden)]
25pub use linkme;
26
27#[doc(hidden)]
28pub use kitest::prelude::*;
29
30mod args;
31pub(crate) mod group;
32pub(crate) mod test;
33
34pub use test::{Extra, IntoTestResult};
35
36pub mod macros {
37 pub use kitest::{dbg, eprint, eprintln, print, println};
38 pub use linkme::distributed_slice as collect_test;
39 pub use nu_test_support_macros::test;
40 pub use nu_utils::module_path_without_crate;
41}
42
43pub const DEFAULT_THREAD_COUNT_MUL: NonZeroUsize = NonZeroUsize::new(4).unwrap();
44pub static DEFAULT_THREAD_COUNT: LazyLock<NonZeroUsize> = LazyLock::new(|| {
45 std::thread::available_parallelism()
46 .map(|n| n.saturating_mul(DEFAULT_THREAD_COUNT_MUL))
47 .unwrap_or(NonZeroUsize::MIN)
48});
49
50#[linkme::distributed_slice]
52#[linkme(crate = nu_test_support::harness::linkme)]
53pub static TESTS: [kitest::test::Test<Extra>];
54
55pub fn main() -> ExitCode {
56 let args = match Args::parse() {
57 Ok(args) => args,
58 Err(err) => {
59 eprintln!("{}: {err}", Color::Red.bold().paint("error"));
60 eprintln!("help: use `--help` to see valid options");
61 eprintln!();
62 return ExitCode::FAILURE;
63 }
64 };
65
66 if args.help {
67 Args::help();
68 return ExitCode::SUCCESS;
69 }
70
71 if args.no_capture {
72 kitest::capture::CAPTURE_OUTPUT_MACROS.store(false, Ordering::Relaxed);
73 }
74
75 #[cfg(all(feature = "rustls-tls", feature = "network"))]
76 nu_command::tls::CRYPTO_PROVIDER.default();
77
78 let runner = TestRunner::default()
79 .with_thread_count(args.test_threads.unwrap_or(*DEFAULT_THREAD_COUNT))
80 .with_exact(args.exact);
81
82 let filter = DefaultFilter::default()
83 .with_exact(args.exact)
84 .with_filter(args.filter)
85 .with_skip(args.skip)
86 .with_only_ignored(args.ignored);
87
88 let harness = kitest::harness(TESTS.deref())
89 .with_grouper(Grouper::default())
90 .with_group_runner(GroupRunner::default())
91 .with_groups(TestGroupBTreeMap::default())
92 .with_runner(runner)
93 .with_filter(filter);
94
95 let pretty_formatter = PrettyFormatter::default()
96 .with_color_setting(args.color)
97 .with_group_label_from_ctx();
98 let terse_formatter = TerseFormatter::default()
99 .with_color_setting(args.color)
100 .with_group_label_from_ctx();
101
102 match (args.format, args.list) {
103 (Format::Pretty, true) => harness.with_formatter(pretty_formatter).list().exit_code(),
104 (Format::Pretty, false) => harness.with_formatter(pretty_formatter).run().exit_code(),
105 (Format::Terse, true) => harness.with_formatter(terse_formatter).list().exit_code(),
106 (Format::Terse, false) => harness.with_formatter(terse_formatter).run().exit_code(),
107 }
108}