Skip to main content

nu_test_support/harness/
mod.rs

1use 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/// All collected tests.
51#[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}