nushell/crates/nu-command/tests/commands
Piepmatz 66bc0542e0
Refactor I/O Errors (#14927)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

As mentioned in #10698, we have too many `ShellError` variants, with
some even overlapping in meaning. This PR simplifies and improves I/O
error handling by restructuring `ShellError` related to I/O issues.
Previously, `ShellError::IOError` only contained a message string,
making it convenient but overly generic. It was widely used without
providing spans (#4323).

This PR introduces a new `ShellError::Io` variant that consolidates
multiple I/O-related errors (except for `ShellError::NetworkFailure`,
which remains distinct for now). The new `ShellError::Io` variant
replaces the following:

- `FileNotFound`
- `FileNotFoundCustom`
- `IOInterrupted`
- `IOError`
- `IOErrorSpanned`
- `NotADirectory`
- `DirectoryNotFound`
- `MoveNotPossible`
- `CreateNotPossible`
- `ChangeAccessTimeNotPossible`
- `ChangeModifiedTimeNotPossible`
- `RemoveNotPossible`
- `ReadingFile`

## The `IoError`
`IoError` includes the following fields:

1. **`kind`**: Extends `std::io::ErrorKind` to specify the type of I/O
error without needing new `ShellError` variants. This aligns with the
approach used in `std::io::Error`. This adds a second dimension to error
reporting by combining the `kind` field with `ShellError` variants,
making it easier to describe errors in more detail. As proposed by
@kubouch in [#design-discussion on
Discord](https://discord.com/channels/601130461678272522/615329862395101194/1323699197165178930),
this helps reduce the number of `ShellError` variants. In the error
report, the `kind` field is displayed as the "source" of the error,
e.g., "I/O error," followed by the specific kind of I/O error.
2. **`span`**: A non-optional field to encourage providing spans for
better error reporting (#4323).
3. **`path`**: Optional `PathBuf` to give context about the file or
directory involved in the error (#7695). If provided, it’s shown as a
help entry in error reports.
4. **`additional_context`**: Allows adding custom messages when the
span, kind, and path are insufficient. This is rendered in the error
report at the labeled span.
5. **`location`**: Sometimes, I/O errors occur in the engine itself and
are not caused directly by user input. In such cases, if we don’t have a
span and must set it to `Span::unknown()`, we need another way to
reference the error. For this, the `location` field uses the new
`Location` struct, which records the Rust file and line number where the
error occurred. This ensures that we at least know the Rust code
location that failed, helping with debugging. To make this work, a new
`location!` macro was added, which retrieves `file!`, `line!`, and
`column!` values accurately. If `Location::new` is used directly, it
issues a warning to remind developers to use the macro instead, ensuring
consistent and correct usage.

### Constructor Behavior
`IoError` provides five constructor methods:
- `new` and `new_with_additional_context`: Used for errors caused by
user input and require a valid (non-unknown) span to ensure precise
error reporting.
- `new_internal` and `new_internal_with_path`: Used for internal errors
where a span is not available. These methods require additional context
and the `Location` struct to pinpoint the source of the error in the
engine code.
- `factory`: Returns a closure that maps an `std::io::Error` to an
`IoError`. This is useful for handling multiple I/O errors that share
the same span and path, streamlining error handling in such cases.

## New Report Look
This is simulation how the I/O errors look like (the `open crates` is
simulated to show how internal errors are referenced now):
![Screenshot 2025-01-25
190426](https://github.com/user-attachments/assets/a41b6aa6-a440-497d-bbcc-3ac0121c9226)

## `Span::test_data()`
To enable better testing, `Span::test_data()` now returns a value
distinct from `Span::unknown()`. Both `Span::test_data()` and
`Span::unknown()` refer to invalid source code, but having a separate
value for test data helps identify issues during testing while keeping
spans unique.

## Cursed Sneaky Error Transfers
I removed the conversions between `std::io::Error` and `ShellError` as
they often removed important information and were used too broadly to
handle I/O errors. This also removed the problematic implementation
found here:

7ea4895513/crates/nu-protocol/src/errors/shell_error.rs (L1534-L1583)

which hid some downcasting from I/O errors and made it hard to trace
where `ShellError` was converted into `std::io::Error`. To address this,
I introduced a new struct called `ShellErrorBridge`, which explicitly
defines this transfer behavior. With `ShellErrorBridge`, we can now
easily grep the codebase to locate and manage such conversions.

## Miscellaneous
- Removed the OS error added in #14640, as it’s no longer needed.
- Improved error messages in `glob_from` (#14679).
- Trying to open a directory with `open` caused a permissions denied
error (it's just what the OS provides). I added a `is_dir` check to
provide a better error in that case.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

- Error outputs now include more detailed information and are formatted
differently, including updated error codes.
- The structure of `ShellError` has changed, requiring plugin authors
and embedders to update their implementations.

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

I updated tests to account for the new I/O error structure and
formatting changes.

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->

This PR closes #7695 and closes #14892 and partially addresses #4323 and
#10698.

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2025-01-28 16:03:31 -06:00
..
assignment Change append operator to concatenation operator (#14344) 2024-11-24 10:59:54 -08:00
base Replace the old encode base64 and decode base64 with new-base64 commands (#14018) 2024-10-08 11:01:43 +08:00
bytes Implementing ByteStream interuption on infinite stream (#13552) 2025-01-11 13:28:08 -08:00
conversions Change behavior of into record on lists to be more useful (#13637) 2024-08-22 11:38:43 +02:00
database more closure serialization (#14698) 2025-01-07 11:51:22 -06:00
date fix format date based on users locale (#11908) 2024-02-20 11:08:49 -06:00
debug Make timeit take only closures as an argument (#14483) 2024-12-10 23:08:53 +08:00
hash_ Replace the old encode base64 and decode base64 with new-base64 commands (#14018) 2024-10-08 11:01:43 +08:00
math Improve and fix filesize formatting/display (#14397) 2025-01-22 22:24:51 -08:00
move_ Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
network Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
path Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
platform ansi name for clear-scrollback code (#14184) 2024-10-29 07:01:32 -05:00
query Feature cleanup (#7182) 2022-11-22 16:58:11 -08:00
random support filesize arguments in random binary/chars (#14068) 2024-10-12 14:49:05 +08:00
skip Add string/binary type color to ByteStream (#12897) 2024-05-20 00:35:32 +00:00
str_ Improves commands that support range input (#13113) 2024-06-18 07:19:13 -05:00
take Add string/binary type color to ByteStream (#12897) 2024-05-20 00:35:32 +00:00
url Change append operator to concatenation operator (#14344) 2024-11-24 10:59:54 -08:00
alias.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00
all.rs Rewrite run_external.rs (#12921) 2024-05-23 02:05:27 +00:00
any.rs Rewrite run_external.rs (#12921) 2024-05-23 02:05:27 +00:00
append.rs fix(nu-command/tests): further remove unnecessary pipeline() and cwd() (#8793) 2023-04-07 14:09:55 -07:00
break_.rs don't allow break/continue in each and items command (#13398) 2024-07-19 00:21:02 -07:00
cal.rs Suppress column index for default cal output (#13188) 2024-06-22 07:41:29 -05:00
cd.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
chunk_by.rs Implement chunk_by operation (#14410) 2024-11-29 13:37:27 -08:00
chunks.rs Deprecate group in favor of chunks (#13377) 2024-07-16 03:49:00 +00:00
compact.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
complete.rs Make assignment and const consistent with let/mut (#13385) 2024-07-30 18:55:22 -05:00
config_env_default.rs Command: Add config env/nu --default to print defaults (#10480) 2023-09-25 08:00:59 -05:00
config_nu_default.rs Command: Add config env/nu --default to print defaults (#10480) 2023-09-25 08:00:59 -05:00
continue_.rs fix(nu-command/tests): further remove unnecessary pipeline() and cwd() (#8793) 2023-04-07 14:09:55 -07:00
debug_info.rs Make debug info lazy (#10728) 2023-10-24 12:48:05 -05:00
def.rs make command signature parsing more strict (#14309) 2024-11-18 08:01:52 +08:00
default.rs Remove default list-diving behaviour (#13386) 2024-07-16 03:54:24 +00:00
detect_columns.rs Improves commands that support range input (#13113) 2024-06-18 07:19:13 -05:00
do_.rs deprecate --ignore-shell-errors and --ignore-program-errors in do (#14385) 2024-11-27 09:36:30 +08:00
drop.rs Refactor drop columns to fix issues (#10903) 2023-11-09 13:51:46 +01:00
du.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
each.rs Remove group command (#14056) 2024-10-11 06:43:12 -05:00
echo.rs Change echo to print when not redirected (#10338) 2023-09-13 06:35:01 +12:00
empty.rs fix(nu-command/tests): further remove unnecessary pipeline() and cwd() (#8793) 2023-04-07 14:09:55 -07:00
error_make.rs Change the error style during tests to plain (#13061) 2024-06-18 21:37:24 -07:00
every.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00
exec.rs Isolate tests from user config (#12437) 2024-04-10 06:27:46 +08:00
export_def.rs Removes unnecessary cwd and pipeline from various tests (#9202) 2023-05-17 18:55:26 -05:00
fill.rs Removes unnecessary cwd and pipeline from various tests (#9202) 2023-05-17 18:55:26 -05:00
filter.rs Fix return in filter closure eval (#12292) 2024-03-26 17:50:36 +01:00
find.rs fixed issue with find not working with symbols that should be escaped (#13792) 2024-09-06 07:22:03 +08:00
first.rs Add string/binary type color to ByteStream (#12897) 2024-05-20 00:35:32 +00:00
flatten.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
for_.rs Change echo to print when not redirected (#10338) 2023-09-13 06:35:01 +12:00
format.rs Improve and fix filesize formatting/display (#14397) 2025-01-22 22:24:51 -08:00
generate.rs Add input support to generate (#14804) 2025-01-14 11:44:31 -06:00
get.rs Make get const (#14751) 2025-01-04 16:41:03 -05:00
glob.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00
griddle.rs make grid throw an error when not enough columns (#12672) 2024-04-26 06:33:00 -05:00
group_by.rs Add run-time type checking for command pipeline input (#14741) 2025-01-08 23:09:47 +01:00
headers.rs Fix: remove unnecessary r#"..."# (#8670) (#9764) 2023-07-21 17:32:37 +02:00
help.rs Change the usage misnomer to "description" (#13598) 2024-08-22 12:02:08 +02:00
histogram.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
ignore.rs Change the ignore command to use drain() instead of collecting a value (#12120) 2024-03-08 02:18:26 -05:00
insert.rs Remove lazy records (#12682) 2024-05-03 08:36:10 +08:00
inspect.rs fix inspect and explore panics on empty records (#13893) 2024-09-25 07:48:16 -05:00
interleave.rs Isolate tests from user config (#12437) 2024-04-10 06:27:46 +08:00
into_datetime.rs add table -> table to into datetime (#9775) 2023-07-23 20:14:51 +02:00
into_filesize.rs Improve and fix filesize formatting/display (#14397) 2025-01-22 22:24:51 -08:00
into_int.rs add --signed flag for binary into int conversions (#11902) 2024-02-27 15:05:26 +00:00
join.rs support table literal syntax in join right-table argument (#14190) 2024-10-29 06:37:44 -05:00
last.rs Add string/binary type color to ByteStream (#12897) 2024-05-20 00:35:32 +00:00
length.rs support binary input in length (#14224) 2024-11-04 03:39:24 +00:00
let_.rs fix error when exporting consts with type signatures in modules (#14118) 2024-10-22 11:54:31 +02:00
lines.rs fix panic with lines on an error (#9967) 2023-08-09 14:12:58 +02:00
loop_.rs Change echo to print when not redirected (#10338) 2023-09-13 06:35:01 +12:00
ls.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
match_.rs support raw strings in match patterns (#14573) 2024-12-13 06:55:57 -06:00
merge_deep.rs Add merge deep command (#14525) 2024-12-18 06:36:04 -06:00
merge.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
mktemp.rs Path migration part 4: various tests (#13373) 2024-08-03 10:09:13 +02:00
mod.rs Fix improperly escaped strings in stor update (#14921) 2025-01-26 07:20:39 -06:00
mut_.rs raise ParseError if assign to a non-variable or non-mutable-variable (#14405) 2024-11-29 23:02:21 +01:00
nu_check.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
open.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
par_each.rs Fix: remove unnecessary r#"..."# (#8670) (#9764) 2023-07-21 17:32:37 +02:00
parse.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00
prepend.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00
print.rs Add --raw switch to print for binary data (#13597) 2024-08-12 17:29:25 +08:00
redirection.rs Overhaul $in expressions (#13357) 2024-07-17 16:02:42 -05:00
reduce.rs Add run-time type checking for command pipeline input (#14741) 2025-01-08 23:09:47 +01:00
reject.rs Fix reject regression (#14931) 2025-01-27 18:23:44 -05:00
rename.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
return_.rs Fix return setting last exit code (#14120) 2024-10-18 03:05:58 +00:00
reverse.rs Clean up tests containing unnecessary cwd: tokens (#9692) 2023-07-17 18:43:51 +02:00
rm.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
roll.rs Fix: remove unnecessary r#"..."# (#8670) (#9764) 2023-07-21 17:32:37 +02:00
rotate.rs Fix panic in rotate; Add safe record creation function (#11718) 2024-02-03 13:23:16 +02:00
run_external.rs Remove required positional arguments from run-external and exec (#14765) 2025-01-16 06:10:28 +08:00
save.rs Refactor I/O Errors (#14927) 2025-01-28 16:03:31 -06:00
select.rs allow select to stream more (#14492) 2024-12-03 20:45:31 -06:00
semicolon.rs Slim down tests (#9021) 2023-04-28 13:25:44 +02:00
seq_char.rs Seq char update will work on all char (#14261) 2024-11-15 21:05:29 +01:00
seq_date.rs seq date: generalize to allow any duration for --increment argument (#14903) 2025-01-25 13:24:39 -06:00
seq.rs Slim down tests (#9021) 2023-04-28 13:25:44 +02:00
slice.rs Rename/deprecate range to slice (#14825) 2025-01-17 06:21:32 -06:00
sort_by.rs to json -r not removing whitespaces fix (#11948) 2024-03-20 22:14:31 +01:00
sort.rs Rework sorting and add cell path and closure comparators to sort-by (#13154) 2024-10-09 19:18:16 -07:00
source_env.rs Path migration part 2: nu-test-support (#13329) 2024-07-12 02:43:10 +00:00
split_column.rs Add --number flag to split column (#13831) 2024-09-12 07:16:33 -05:00
split_row.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00
start.rs non-HTTP(s) URLs now works with start (#14370) 2025-01-23 17:14:31 -08:00
stor.rs Fix improperly escaped strings in stor update (#14921) 2025-01-26 07:20:39 -06:00
table.rs Fix #14842 (#14885) 2025-01-22 06:49:25 -06:00
tee.rs Make tee work more nicely with non-collections (#13652) 2024-09-01 19:03:46 +02:00
terminal.rs Add is-terminal to determine if stdin/out/err are a terminal (#10970) 2023-11-21 20:48:39 -06:00
to_text.rs Make to text line endings consistent for list (streams) (#14166) 2024-11-05 09:33:54 +01:00
transpose.rs Defensive handling of errors when transposing (#14096) 2024-10-22 11:30:48 -05:00
try_.rs add rendered and json error messages in try/catch (#14082) 2024-10-20 23:14:11 +02:00
ucp.rs Improve and fix filesize formatting/display (#14397) 2025-01-22 22:24:51 -08:00
ulimit.rs FreeBSD compatibility patches (#11869) 2024-02-17 20:04:59 +01:00
umkdir.rs [umkdir][tests] get umask instead of assuming it (#14046) 2024-10-11 14:13:42 +02:00
uname.rs Initial implementation for uutils uname (#11684) 2024-03-25 16:51:50 -05:00
uniq_by.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
uniq.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
update.rs Remove lazy records (#12682) 2024-05-03 08:36:10 +08:00
upsert.rs Remove lazy records (#12682) 2024-05-03 08:36:10 +08:00
use_.rs Change tests which may invoke externals to use non-conflicting names (#14516) 2024-12-04 19:26:48 -06:00
utouch.rs Make utouch the new touch (#14721) 2025-01-02 06:26:46 -06:00
where_.rs Add new operators has and not-has (#14841) 2025-01-17 06:20:00 -06:00
which.rs change the output of which to be more explicit (#9646) 2023-07-20 19:10:53 -05:00
while_.rs Change echo to print when not redirected (#10338) 2023-09-13 06:35:01 +12:00
window.rs Refactor window (#13401) 2024-07-19 04:16:09 +00:00
with_env.rs Improve with-env robustness (#12523) 2024-04-16 19:08:58 +08:00
wrap.rs Remove file I/O from tests that don't need it (#11182) 2023-11-29 23:21:34 +01:00
zip.rs Avoid taking unnecessary ownership of intermediates (#12740) 2024-05-04 00:53:15 +00:00