nushell/crates/nu-protocol/tests/test_config.rs
Ian Manske 3d008e2c4e
Error on non-zero exit statuses (#13515)
# Description
This PR makes it so that non-zero exit codes and termination by signal
are treated as a normal `ShellError`. Currently, these are silent
errors. That is, if an external command fails, then it's code block is
aborted, but the parent block can sometimes continue execution. E.g.,
see #8569 and this example:
```nushell
[1 2] | each { ^false }
```

Before this would give:
```
╭───┬──╮
│ 0 │  │
│ 1 │  │
╰───┴──╯
```

Now, this shows an error:
```
Error: nu:🐚:eval_block_with_input

  × Eval block failed with pipeline input
   ╭─[entry #1:1:2]
 1 │ [1 2] | each { ^false }
   ·  ┬
   ·  ╰── source value
   ╰────

Error: nu:🐚:non_zero_exit_code

  × External command had a non-zero exit code
   ╭─[entry #1:1:17]
 1 │ [1 2] | each { ^false }
   ·                 ──┬──
   ·                   ╰── exited with code 1
   ╰────
```

This PR fixes #12874, fixes #5960, fixes #10856, and fixes #5347. This
PR also partially addresses #10633 and #10624 (only the last command of
a pipeline is currently checked). It looks like #8569 is already fixed,
but this PR will make sure it is definitely fixed (fixes #8569).

# User-Facing Changes
- Non-zero exit codes and termination by signal now cause an error to be
thrown.
- The error record value passed to a `catch` block may now have an
`exit_code` column containing the integer exit code if the error was due
to an external command.
- Adds new config values, `display_errors.exit_code` and
`display_errors.termination_signal`, which determine whether an error
message should be printed in the respective error cases. For
non-interactive sessions, these are set to `true`, and for interactive
sessions `display_errors.exit_code` is false (via the default config).

# Tests
Added a few tests.

# After Submitting
- Update docs and book.
- Future work:
- Error if other external commands besides the last in a pipeline exit
with a non-zero exit code. Then, deprecate `do -c` since this will be
the default behavior everywhere.
- Add a better mechanism for exit codes and deprecate
`$env.LAST_EXIT_CODE` (it's buggy).
2024-09-07 06:44:26 +00:00

116 lines
3.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use nu_test_support::{nu, nu_repl_code};
#[test]
fn filesize_metric_true() {
let code = &[
r#"$env.config = { filesize: { metric: true, format:"mb" } }"#,
r#"20mib | into string"#,
];
let actual = nu!(nu_repl_code(code));
assert_eq!(actual.out, "21.0 MB");
}
#[test]
fn filesize_metric_false() {
let code = &[
r#"$env.config = { filesize: { metric: false, format:"mib" } }"#,
r#"20mib | into string"#,
];
let actual = nu!(nu_repl_code(code));
assert_eq!(actual.out, "20.0 MiB");
}
#[test]
fn filesize_metric_overrides_format() {
let code = &[
r#"$env.config = { filesize: { metric: false, format:"mb" } }"#,
r#"20mib | into string"#,
];
let actual = nu!(nu_repl_code(code));
assert_eq!(actual.out, "20.0 MiB");
}
#[test]
fn filesize_format_auto_metric_true() {
let code = &[
r#"$env.config = { filesize: { metric: true, format:"auto" } }"#,
r#"[2mb 2gb 2tb] | into string | to nuon"#,
];
let actual = nu!(nu_repl_code(code));
assert_eq!(actual.out, r#"["2.0 MB", "2.0 GB", "2.0 TB"]"#);
}
#[test]
fn filesize_format_auto_metric_false() {
let code = &[
r#"$env.config = { filesize: { metric: false, format:"auto" } }"#,
r#"[2mb 2gb 2tb] | into string | to nuon"#,
];
let actual = nu!(nu_repl_code(code));
assert_eq!(actual.out, r#"["1.9 MiB", "1.9 GiB", "1.8 TiB"]"#);
}
#[test]
fn fancy_default_errors() {
let code = nu_repl_code(&[
r#"def force_error [x] {
error make {
msg: "oh no!"
label: {
text: "here's the error"
span: (metadata $x).span
}
}
}"#,
r#"force_error "My error""#,
]);
let actual = nu!(format!("try {{ {code}; null }}"));
assert_eq!(
actual.err,
"Error: \u{1b}[31m×\u{1b}[0m oh no!\n ╭─[\u{1b}[36;1;4mline1\u{1b}[0m:1:13]\n \u{1b}[2m1\u{1b}[0m │ force_error \"My error\"\n · \u{1b}[35;1m ─────┬────\u{1b}[0m\n · \u{1b}[35;1m╰── \u{1b}[35;1mhere's the error\u{1b}[0m\u{1b}[0m\n ╰────\n\n\n"
);
}
#[test]
fn narratable_errors() {
let code = nu_repl_code(&[
r#"$env.config = { error_style: "plain" }"#,
r#"def force_error [x] {
error make {
msg: "oh no!"
label: {
text: "here's the error"
span: (metadata $x).span
}
}
}"#,
r#"force_error "my error""#,
]);
let actual = nu!(format!("try {{ {code}; null }}"));
assert_eq!(
actual.err,
r#"Error: oh no!
Diagnostic severity: error
Begin snippet for line2 starting at line 1, column 1
snippet line 1: force_error "my error"
label at line 1, columns 13 to 22: here's the error
"#,
);
}
#[test]
fn plugins() {
let code = &[
r#"$env.config = { plugins: { nu_plugin_config: { key: value } } }"#,
r#"$env.config.plugins"#,
];
let actual = nu!(nu_repl_code(code));
assert_eq!(actual.out, r#"{nu_plugin_config: {key: value}}"#);
}