From 99d63c21f1c4c5ddc3ff7a0df54dc8580d7f6294 Mon Sep 17 00:00:00 2001 From: Nahor Date: Thu, 2 Apr 2026 13:44:53 -0700 Subject: [PATCH] Add tests to exercise all builtin error messages With a few exceptions, only one test is added for a given message, even when there are multiple ways to trigger the same message (e.g. different invalid option combinations, or triggered in shared functions such as `builtin_unknown_option`) Includes a few very minor fixes, such as missing a newline, or using the wrong var name. Closes #12603 --- src/builtins/fish_key_reader.rs | 2 +- src/builtins/path.rs | 4 +- src/builtins/type.rs | 7 +- tests/checks/abbr.fish | 51 +++++++++++ tests/checks/argparse.fish | 67 ++++++++++++--- tests/checks/basic.fish | 7 ++ tests/checks/bg.fish | 3 + tests/checks/bind.fish | 8 +- tests/checks/breakpoint.fish | 9 ++ tests/checks/cd.fish | 33 +++++++ tests/checks/commandline.fish | 138 ++++++++++++++++++++++++++++++ tests/checks/complete.fish | 16 +++- tests/checks/disown.fish | 12 +++ tests/checks/fg.fish | 22 +++++ tests/checks/fish_key_reader.fish | 19 ++++ tests/checks/function.fish | 18 ++++ tests/checks/functions.fish | 64 ++++++++++++++ tests/checks/history.fish | 9 ++ tests/checks/indent.fish | 22 +++-- tests/checks/jobs.fish | 3 + tests/checks/math.fish | 9 ++ tests/checks/path.fish | 46 ++++++++++ tests/checks/print-help.fish | 18 ++-- tests/checks/printf.fish | 34 +++++++- tests/checks/read.fish | 58 +++++++++++++ tests/checks/realpath.fish | 6 +- tests/checks/return.fish | 14 +++ tests/checks/set.fish | 100 ++++++++++++++++++++++ tests/checks/set_color.fish | 7 ++ tests/checks/signal.fish | 11 +++ tests/checks/source.fish | 9 ++ tests/checks/status.fish | 52 ++++++++++- tests/checks/string.fish | 105 +++++++++++++++++++++++ tests/checks/test.fish | 7 ++ tests/checks/tmux-breakpoint.fish | 11 +++ tests/checks/tmux-set.fish | 13 +++ tests/checks/tmux-source.fish | 13 +++ tests/checks/type.fish | 3 + tests/checks/ulimit.fish | 68 +++++++++++++++ tests/checks/wait.fish | 3 + 40 files changed, 1065 insertions(+), 36 deletions(-) create mode 100644 tests/checks/breakpoint.fish create mode 100644 tests/checks/fish_key_reader.fish create mode 100644 tests/checks/tmux-breakpoint.fish create mode 100644 tests/checks/tmux-set.fish create mode 100644 tests/checks/tmux-source.fish diff --git a/src/builtins/fish_key_reader.rs b/src/builtins/fish_key_reader.rs index 340d93705..58760e05d 100644 --- a/src/builtins/fish_key_reader.rs +++ b/src/builtins/fish_key_reader.rs @@ -220,7 +220,7 @@ fn parse_flags( return ControlFlow::Break(Err(STATUS_CMD_ERROR)); } '?' => { - streams.err.append(&wgettext_fmt!( + streams.err.appendln(&wgettext_fmt!( BUILTIN_ERR_UNKNOWN, "fish_key_reader", w.argv[w.wopt_index - 1] diff --git a/src/builtins/path.rs b/src/builtins/path.rs index 74540ee93..2269fe8b3 100644 --- a/src/builtins/path.rs +++ b/src/builtins/path.rs @@ -283,7 +283,7 @@ fn parse_opts<'args>( let types_args = split_string_tok(w.woptarg.unwrap(), L!(","), None); for t in types_args { let Ok(r#type) = t.try_into() else { - path_error!(streams, "%s: Invalid type '%s'", "path", t); + path_error!(streams, "%s: Invalid type '%s'", cmd, t); return Err(STATUS_INVALID_ARGS); }; *types |= r#type; @@ -295,7 +295,7 @@ fn parse_opts<'args>( let perms_args = split_string_tok(w.woptarg.unwrap(), L!(","), None); for p in perms_args { let Ok(perm) = p.try_into() else { - path_error!(streams, "%s: Invalid permission '%s'", "path", p); + path_error!(streams, "%s: Invalid permission '%s'", cmd, p); return Err(STATUS_INVALID_ARGS); }; *perms |= perm; diff --git a/src/builtins/type.rs b/src/builtins/type.rs index 136c270c2..44252869a 100644 --- a/src/builtins/type.rs +++ b/src/builtins/type.rs @@ -78,7 +78,12 @@ pub fn r#type(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> B } } - if opts.query as i64 + opts.path as i64 + opts.get_type as i64 + opts.force_path as i64 > 1 { + if [opts.query, opts.path, opts.get_type, opts.force_path] + .into_iter() + .filter(|&b| b) + .count() + > 1 + { streams.err.appendln(&wgettext_fmt!(BUILTIN_ERR_COMBO, cmd)); return Err(STATUS_INVALID_ARGS); } diff --git a/tests/checks/abbr.fish b/tests/checks/abbr.fish index caec134db..f718b8b28 100644 --- a/tests/checks/abbr.fish +++ b/tests/checks/abbr.fish @@ -234,3 +234,54 @@ abbr | grep __abbr_coexist # CHECK: abbr -a --position anywhere --command bar -- __abbr_coexist_2 'bar command' abbr -e --command foo __abbr_coexist abbr -e --command bar __abbr_coexist_2 + +abbr --add foo --rename foo fuu --show --list --erase foo --query foo +# CHECKERR: abbr: Cannot combine options add, rename, show, list, erase, query + +abbr --add foo +# CHECKERR: abbr --add: Requires at least two arguments + +abbr --add foo --function foobar extra +# CHECKERR: abbr: too many arguments + +abbr --add foo --command=foobar --position=command bar +# CHECKERR: abbr: --command cannot be combined with --position=command + +abbr --list --regex "." +# CHECKERR: abbr: --regex option requires --add + +abbr --add --regex "a." --regex ".b" foo bar +# CHECKERR: abbr: Cannot specify multiple regex patterns + +abbr --show --set-cursor=marker +# CHECKERR: abbr: --set-cursor option requires --add + +abbr --add --set-cursor=marker --set-cursor=marker +# CHECKERR: abbr: Cannot specify multiple set-cursor options + +abbr --add foo --set-cursor= foo +# CHECKERR: abbr: --set-cursor argument cannot be empty + +abbr --list foo +# CHECKERR: abbr --list: Unexpected argument -- 'foo' + +abbr --rename "" bar +# CHECKERR: abbr --rename: Name cannot be empty + +abbr --rename foo "" +# CHECKERR: abbr --rename: Name cannot be empty + +abbr sub1 -c foo -c bar foo_1 +abbr sub2 -c foo -c bar foo_1 +abbr --rename -c foo -c bar sub1 sub2 +# CHECKERR: abbr --rename: Abbreviation sub2 already exists for commands foo, bar, cannot rename sub1 +abbr --erase sub1 --command={foo,bar} +abbr --erase sub2 --command={foo,bar} + +abbr --erase (abbr --list) +abbr -U +# CHECKERR: abbr: Warning: Option '-U' was removed and is now ignored +# CHECKERR: {{.*}}checks/abbr.fish (line {{\d+}}): +# CHECKERR: abbr -U +# CHECKERR: ^ +# CHECKERR: (Type 'help abbr' for related documentation) diff --git a/tests/checks/argparse.fish b/tests/checks/argparse.fish index 77593005b..fb5f6906a 100644 --- a/tests/checks/argparse.fish +++ b/tests/checks/argparse.fish @@ -36,41 +36,47 @@ end # Invalid option specs argparse h- -argparse / -argparse +help -argparse h/help: -argparse h-help:: -argparse h-help=x #CHECKERR: argparse: Invalid option spec 'h-' at char '-' #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): #CHECKERR: argparse h- #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) +argparse / #CHECKERR: argparse: Short flag '/' invalid, must be alphanum or '#' #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): #CHECKERR: argparse / #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) +argparse +help #CHECKERR: argparse: Short flag '+' invalid, must be alphanum or '#' #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): #CHECKERR: argparse +help #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) +argparse h/help: #CHECKERR: argparse: Invalid option spec 'h/help:' at char ':' #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): #CHECKERR: argparse h/help: #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) +argparse h-help:: #CHECKERR: argparse: Invalid option spec 'h-help::' at char ':' #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): #CHECKERR: argparse h-help:: #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) +argparse h-help=x #CHECKERR: argparse: Invalid option spec 'h-help=x' at char 'x' #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): #CHECKERR: argparse h-help=x #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) +argparse h/ +#CHECKERR: argparse: Invalid option spec 'h/' at char '/' +#CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): +#CHECKERR: argparse h/ +#CHECKERR: ^ +#CHECKERR: (Type 'help argparse' for related documentation) # --max-args and --min-args work begin @@ -90,6 +96,19 @@ begin #CHECKERR: min-max: expected <= 1 arguments; got 2 argparse --name min-max --max-args 1 -- arg1 arg2 #CHECKERR: min-max: expected <= 1 arguments; got 2 + + argparse --name min-max --min-args -1 -- + #CHECKERR: argparse: Invalid --min-args value '-1' + #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): + #CHECKERR: argparse --name min-max --min-args -1 -- + #CHECKERR: ^ + #CHECKERR: (Type 'help argparse' for related documentation) + argparse --name min-max --max-args -1 -- + #CHECKERR: argparse: Invalid --max-args value '-1' + #CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): + #CHECKERR: argparse --name min-max --max-args -1 -- + #CHECKERR: ^ + #CHECKERR: (Type 'help argparse' for related documentation) end # Invalid \"#-val\" spec @@ -136,6 +155,13 @@ begin #CHECKERR: argparse '#-val' x/xray 'v#val' -- -s -x --long #CHECKERR: ^ #CHECKERR: (Type 'help argparse' for related documentation) + + argparse 'v#val' x/xray '#-val' -- -s -x --long + # CHECKERR: argparse: Implicit int flag 'v' already defined + # CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): + # CHECKERR: argparse 'v#val' x/xray '#-val' -- -s -x --long + # CHECKERR: ^ + # CHECKERR: (Type 'help argparse' for related documentation) end # Defining an implicit int flag with modifiers @@ -304,7 +330,7 @@ and echo unexpected argparse return status >&2 # CHECKERR: argparse: Value 'a1' for flag 'm' is not an integer begin -# Check the exit status from argparse validation + # Check the exit status from argparse validation argparse 'm#max!set -l | grep "^_flag_"; function x; return 57; end; x' -- argle --max=83 bargle 2>&1 set -l saved_status $status test $saved_status -eq 57 @@ -420,7 +446,6 @@ begin # CHECK: argv_opts '--long=value' '--long' end - begin argparse -u b/break -- "-b kubectl get pods -l name=foo" set -l @@ -726,9 +751,8 @@ begin # CHECK: argv_opts end - begin - argparse 'd=?&' a b -- -d -d3 -ad -bd345 + argparse 'd=?&' a b -- -d -d3 -ad -bd345 set -l # CHECK: _flag_a -a # CHECK: _flag_b -b @@ -738,7 +762,7 @@ begin end begin - argparse 'd&' a b 'v=' -- 0 -adbv124 1 -abdv125 2 -dabv124 3 -vd3 + argparse 'd&' a b 'v=' -- 0 -adbv124 1 -abdv125 2 -dabv124 3 -vd3 set -l # CHECK: _flag_a '-a' '-a' '-a' # CHECK: _flag_b '-b' '-b' '-b' @@ -795,5 +819,28 @@ begin # CHECK: argv_opts '-o' '-oval' '--opt' '--opt=456' end +# Check --exclusive +begin + argparse --exclusive=a a/abc b/bcd -- + # CHECKERR: argparse: exclusive flag string 'a' is not valid + + argparse --exclusive=a,bcd a/abc b/bcd -- + argparse -x a,bcd a/abc b/bcd -- + + argparse --exclusive=a,bcd,e a/abc b/bcd -- + # CHECKERR: argparse: exclusive flag 'e' is not valid +end + +begin + # Many, many long options + argparse (for i in (seq 0 6400); echo "o$i"; end) -- + # CHECKERR: argparse: Too many long-only options + # CHECKERR: {{.*}}checks/argparse.fish (line {{\d+}}): + # CHECKERR: argparse (for i in (seq 0 6400); echo "o$i"; end) -- + # CHECKERR: ^ + # CHECKERR: (Type 'help argparse' for related documentation) + set -l +end + # Check that the argparse's are properly wrapped in begin blocks set -l diff --git a/tests/checks/basic.fish b/tests/checks/basic.fish index ae94d6eab..9a5c5064b 100644 --- a/tests/checks/basic.fish +++ b/tests/checks/basic.fish @@ -233,6 +233,8 @@ contains -i -- -- a b c; or echo nothing #CHECK: nothing contains -i -- -- a b c -- v #CHECK: 4 +contains +#CHECKERR: contains: Key not specified # Test if, else, and else if if true @@ -447,6 +449,11 @@ $dyn_break -h continue -h #CHECKERR: Documentation for continue +for i in abc + break foo +end +#CHECKERR: break: foo: unknown option + # Test implicit cd. This should do nothing. ./ diff --git a/tests/checks/bg.fish b/tests/checks/bg.fish index 50557339f..bd56b7d92 100644 --- a/tests/checks/bg.fish +++ b/tests/checks/bg.fish @@ -6,3 +6,6 @@ bg -- -1 # CHECKERR: bg: '-1' is not a valid process ID bg -- -(math 2 ^ 31) # CHECKERR: bg: '-2147483648' is not a valid process ID + +bg +# CHECKERR: bg: There are no suitable jobs diff --git a/tests/checks/bind.fish b/tests/checks/bind.fish index 2ace10655..e58eb4d2f 100644 --- a/tests/checks/bind.fish +++ b/tests/checks/bind.fish @@ -138,7 +138,6 @@ bind \ef forward-word bind \ef # CHECK: bind alt-f forward-word - # Erasing bindings bind --erase tab bind tab @@ -179,6 +178,9 @@ bind ctrl-shift-a bind ctrl-shift-ä # CHECKERR: bind: No binding found for key 'ctrl-shift-ä' +bind '\n' +# CHECKERR: bind: No binding found for key sequence '\\n' + # Verify binds from all modes are returned when querying a sequence fish_vi_key_bindings bind --preset ctrl-q 'echo preset' @@ -190,6 +192,10 @@ bind ctrl-q # CHECK: bind ctrl-q 'echo default' # CHECK: bind -M insert ctrl-q 'echo insert' # CHECK: bind -M replace ctrl-q 'echo replace' + +bind --user --preset ctrl-q 'echo preset' +# CHECKERR: bind: --preset --user: options cannot be used together + fish_default_key_bindings exit 0 diff --git a/tests/checks/breakpoint.fish b/tests/checks/breakpoint.fish new file mode 100644 index 000000000..2c03a96e8 --- /dev/null +++ b/tests/checks/breakpoint.fish @@ -0,0 +1,9 @@ +# RUN: fish=%fish %fish %s + +breakpoint foo +# CHECKERR: breakpoint: expected 0 arguments; got 1 + +# no breakpoint in non-interactive shell +breakpoint +echo $status +# CHECK: 1 diff --git a/tests/checks/cd.fish b/tests/checks/cd.fish index ec931d3d1..e90103135 100644 --- a/tests/checks/cd.fish +++ b/tests/checks/cd.fish @@ -36,6 +36,15 @@ test (pwd) = "$link" || echo "(pwd) != \$link:"\n "\$PWD: "(pwd)\n "\$link: $lin test (pwd -P) = "$real" || echo "(pwd -P) != \$real:"\n "\$PWD: $PWD"\n "\$real: $real"\n test (pwd -P -L) = "$link" || echo "(pwd -P -L) != \$link:"\n "\$PWD: $PWD"\n "\$link: $link"\n # Expect no output on success. +pwd abc +# CHECKERR: pwd: expected 0 arguments; got 1 + +mkdir -p $base/pwd_real/subdir +ln -s $base/pwd_real $base/pwd_link +cd $base/pwd_link/subdir +rmdir $base/pwd_real/subdir $base/pwd_real +pwd -P +# CHECKERR: pwd: realpath failed: No such file or directory # Create a symlink and verify logical completion. # create directory $base/through/the/looking/glass @@ -309,3 +318,27 @@ else chmod -R +rx $tmp # we must be able to list the directory to delete its children rm -rf $tmp end + +HOME="" cd +# CHECKERR: cd: Could not find home directory + +ln -s loop1 loop2 +ln -s loop2 loop1 +cd loop1 +# CHECKERR: cd: Too many levels of symbolic links: 'loop1' +# CHECKERR: {{.*}}/cd.fish (line {{\d+}}): +# CHECKERR: builtin cd $argv +# CHECKERR: ^ +# CHECKERR: in function 'cd' with arguments 'loop1' +# CHECKERR: called on line {{\d+}} of file {{.*}}/cd.fish + +# According to https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits, +# the longest filename supported is with Reiser4 (3976 bytes) +cd (string repeat 4096 a) +# CHECKERR: cd: {{.+}} +# CHECKERR: cd: Unknown error trying to locate directory '{{.*}}' +# CHECKERR: {{.*}}/cd.fish (line {{\d+}}): +# CHECKERR: builtin cd $argv +# CHECKERR: ^ +# CHECKERR: in function 'cd' with arguments '{{.*}}' +# CHECKERR: called on line {{\d+}} of file {{.*}}/cd.fish diff --git a/tests/checks/commandline.fish b/tests/checks/commandline.fish index 25d681a2b..fcacd9f71 100644 --- a/tests/checks/commandline.fish +++ b/tests/checks/commandline.fish @@ -72,3 +72,141 @@ $fish -c 'commandline foo' # CHECKERR: commandline foo # CHECKERR: ^ # CHECKERR: (Type 'help commandline' for related documentation) + +commandline --tokens-expanded --tokens-raw +# CHECKERR: commandline: invalid option combination, --tokens options are mutually exclusive +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --tokens-expanded --tokens-raw +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --tokens-expanded --tokenize +# CHECKERR: commandline: invalid option combination, --tokens options are mutually exclusive +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --tokens-expanded --tokenize +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --function --current-buffer +# CHECKERR: commandline: invalid option combination +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --function --current-buffer +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --function foo +# CHECKERR: commandline: Unknown input function 'foo' +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --function foo +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --selection-start foo +# CHECKERR: commandline: too many arguments +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --selection-start foo +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) +commandline --selection-end foo +# CHECKERR: commandline: too many arguments +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --selection-end foo +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --line 1 2 +# CHECKERR: commandline: too many arguments +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --line 1 2 +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --cut-at-cursor --cursor +# CHECKERR: commandline: invalid option combination +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --cut-at-cursor --cursor +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --cut-at-cursor --tokens-expanded abc +# CHECKERR: commandline: invalid option combination, --cut-at-cursor and token options can not be used when setting the commandline +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --cut-at-cursor --tokens-expanded abc +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --search-field --tokens-expanded +# CHECKERR: commandline: invalid option combination +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --search-field --tokens-expanded +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --insert-smart 0 --search-field +# CHECKERR: commandline: --insert-smart --search-field: options cannot be used together +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --insert-smart 0 --search-field +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --insert-smart 0 --current-token +# CHECKERR: commandline: --insert-smart --current-token: options cannot be used together +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --insert-smart 0 --current-token +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --line abc +# CHECKERR: commandline: abc: invalid integer +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --line abc +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) +commandline --line 0 +# CHECKERR: commandline: line/column index starts at 1 +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --line 0 +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) +commandline --line 1 +# OK +commandline --line 2 +# CHECKERR: commandline: there is no line 2 +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --line 2 +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) +commandline --line 3 +# CHECKERR: commandline: there is no line 3 +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --line 3 +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +commandline --column abc +# CHECKERR: commandline: abc: invalid integer +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --column abc +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) +commandline --column 0 +# CHECKERR: commandline: line/column index starts at 1 +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --column 0 +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) +commandline --column 1 +# OK +commandline --column 2 +# CHECKERR: commandline: column 2 exceeds line length +# CHECKERR: {{.*}}/commandline.fish (line {{\d+}}): +# CHECKERR: commandline --column 2 +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) + +$fish -ic "commandline --cursor abc" +# CHECKERR: commandline: abc: invalid integer +# CHECKERR: Standard input (line 1): +# CHECKERR: commandline --cursor abc +# CHECKERR: ^ +# CHECKERR: (Type 'help commandline' for related documentation) diff --git a/tests/checks/complete.fish b/tests/checks/complete.fish index cc43e3a40..d61b210d9 100644 --- a/tests/checks/complete.fish +++ b/tests/checks/complete.fish @@ -482,6 +482,8 @@ complete -C"cmd_with_fancy_completion /dev/null 2>>/dev/null >?/dev/ complete -c thing -x -F # CHECKERR: complete: invalid option combination, '--exclusive' and '--force-files' +complete -c thing -F -f +# CHECKERR: complete: invalid option combination, '--no-files' and '--force-files' # Multiple conditions complete -f -c shot complete -fc shot -n 'test (count (commandline -xpc) -eq 1' -n 'test (commandline -xpc)[-1] = shot' -a through @@ -697,6 +699,18 @@ begin chmod +x "$TMPDIR/-command-starting-with-dash" set -l PATH "$TMPDIR" $PATH - complete -C"-command-starting-with" + complete -C-command-starting-with # CHECK: -command-starting-with-dash{{\t}}command end + +complete --command="foo\\" +# CHECKERR: complete: Invalid token 'foo\' + +complete -c foo -a "foo\\" +# CHECKERR: complete: foo\: contains a syntax error +# CHECKERR: complete: Expected a string, but found an incomplete token +# CHECKERR: foo\ +# CHECKERR: ^ + +complete -C +# CHECKERR: complete: Can not get commandline in non-interactive mode diff --git a/tests/checks/disown.fish b/tests/checks/disown.fish index 078fb8b62..536880d2c 100644 --- a/tests/checks/disown.fish +++ b/tests/checks/disown.fish @@ -6,3 +6,15 @@ disown -- -1 # CHECKERR: disown: '-1' is not a valid process ID disown -- -(math 2 ^ 31) # CHECKERR: disown: '-2147483648' is not a valid process ID +disown +# CHECKERR: disown: There are no suitable jobs + +# So jobs can be resumed by disown +status job-control full +sleep 1 & +set -l pid (jobs -lp) +kill -SIGSTOP $pid +disown +# CHECKERR: disown: job 1 ('sleep 1 &') was stopped and has been signalled to continue. +echo $status +# CHECK: 0 diff --git a/tests/checks/fg.fish b/tests/checks/fg.fish index cb77c4c6d..04d193511 100644 --- a/tests/checks/fg.fish +++ b/tests/checks/fg.fish @@ -15,6 +15,9 @@ fg (math 2 ^ 31) fg 0 2>| string match --max-matches=1 '*' >&2 # CHECKERR: fg: '0' is not a valid process ID +fg +# CHECKERR: fg: There are no suitable jobs + builtin fg -- -1 2>| string match --max-matches=1 '*' >&2 # CHECKERR: fg: '-1' is not a valid process ID @@ -23,3 +26,22 @@ builtin fg -- -1 2>| string match --max-matches=1 '*' >&2 builtin fg -- -(math 2 ^ 31) 2>| string match --max-matches=1 '*' >&2 # CHECKERR: fg: '-2147483648' is not a valid process ID + +builtin fg 1 2 +# CHECKERR: fg: '1' is not a job +# CHECKERR: {{.*}}/fg.fish (line {{\d+}}): +# CHECKERR: builtin fg 1 2 +# CHECKERR: ^ +# CHECKERR: (Type 'help fg' for related documentation) + +sleep 1 & +sleep 1 & +builtin fg (jobs --pid) +# CHECKERR: fg: Ambiguous job +# CHECKERR: {{.*}}/fg.fish (line {{\d+}}): +# CHECKERR: builtin fg (jobs --pid) +# CHECKERR: ^ +# CHECKERR: (Type 'help fg' for related documentation) +set -l pid (jobs -lp) +fg $pid +# CHECKERR: fg: Can't put job {{\d+}}, 'sleep 1 &' to foreground because it is not under job control diff --git a/tests/checks/fish_key_reader.fish b/tests/checks/fish_key_reader.fish new file mode 100644 index 000000000..ffd426779 --- /dev/null +++ b/tests/checks/fish_key_reader.fish @@ -0,0 +1,19 @@ +#RUN: fish=%fish %fish %s + +# See `tests/pexpects/fkr.py` for non-error tests + +fish_key_reader --continuous=invalid +# CHECKERR: fish_key_reader: --continuous=invalid: option does not take an argument + +fish_key_reader --invalid-opt +# CHECKERR: fish_key_reader: --invalid-opt: unknown option + +fish_key_reader some-unexpected-args +# CHECKERR: Expected no arguments, got 1 + +echo | builtin fish_key_reader +# CHECKERR: Stdin must be attached to a tty. + +set -l dir (dirname $fish) +echo | command $dir/fish_key_reader +# CHECKERR: Stdin must be attached to a tty. diff --git a/tests/checks/function.fish b/tests/checks/function.fish index 57e997f0f..d2fbdecf2 100644 --- a/tests/checks/function.fish +++ b/tests/checks/function.fish @@ -244,4 +244,22 @@ for flag in --on-process-exit --on-job-exit # CHECKERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ end +function handle_some_sig --on-signal SOME_SIG +end +#CHECKERR: {{.*}}/function.fish (line {{\d+}}): function: Unknown signal 'SOME_SIG' +#CHECKERR: function handle_some_sig --on-signal SOME_SIG +#CHECKERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + +function handle_exit_invalid_pid -j caller +end +#CHECKERR: {{.*}}/function.fish (line {{\d+}}): function: calling job for event handler not found +#CHECKERR: function handle_exit_invalid_pid -j caller +#CHECKERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + +function fn_with_args -- arg +end +#CHECKERR: {{.*}}/function.fish (line {{\d+}}): function: arg: unexpected positional argument +#CHECKERR: function fn_with_args -- arg +#CHECKERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~^ + exit 0 diff --git a/tests/checks/functions.fish b/tests/checks/functions.fish index 374b440c7..4828d0ece 100644 --- a/tests/checks/functions.fish +++ b/tests/checks/functions.fish @@ -147,6 +147,50 @@ functions -Dv t2 #CHECK: scope-shadowing #CHECK: +functions -c first +# CHECKERR: functions: Expected exactly two names (current function name, and new function name) +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -c first +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + +functions -c first second third +# CHECKERR: functions: Expected exactly two names (current function name, and new function name) +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -c first second third +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + +functions -c unknown_function copy +# CHECKERR: functions: Function 'unknown_function' does not exist +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -c unknown_function copy +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + +function to_copy +end +functions -c -- to_copy -invalid_name +# CHECKERR: functions: Illegal function name '-invalid_name' +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -c -- to_copy -invalid_name +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + +functions -c -- to_copy function +# CHECKERR: functions: Illegal function name 'function' +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -c -- to_copy function +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + +functions -c -- to_copy to_copy +# CHECKERR: functions: Function 'to_copy' already exists. Cannot create copy of 'to_copy' +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -c -- to_copy to_copy +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + echo "functions -c t t3" | source functions t3 # CHECK: # Defined via `source`, copied via `source` @@ -190,6 +234,9 @@ functions --handlers-type signal # CHECK: SIGTERM term2 # CHECK: SIGTERM term3 +functions -t invalid_type +# CHECKERR: functions: Expected generic | variable | signal | exit | job-id for --handlers-type + # See how --names and --all work. # We don't want to list all of our functions here, # so we just match a few that we know are there. @@ -244,6 +291,9 @@ end functions --color=invalid # CHECKERR: functions: Invalid value for '--color' option: 'invalid'. Expected 'always', 'never', or 'auto' +functions --color +# CHECKERR: functions: --color: option requires an argument + functions --no-details --color=never test_color_option # CHECK: function test_color_option # CHECK: echo hello @@ -253,3 +303,17 @@ string escape (functions --no-details --color=always test_color_option) # CHECK: function\ \e\[36mtest_color_option\e\[32m # CHECK: \e\[39m\ \ \ \ echo\ \e\[36mhello\e\[32m # CHECK: \e\[39mend\e\[32m\e\[39m + +functions --names --query +# CHECKERR: functions: invalid option combination +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions --names --query +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) + +functions -d desc unknown_function +# CHECKERR: functions: Function 'unknown_function' does not exist +# CHECKERR: {{.*}}/checks/functions.fish (line {{\d+}}): +# CHECKERR: functions -d desc unknown_function +# CHECKERR: ^ +# CHECKERR: (Type 'help functions' for related documentation) diff --git a/tests/checks/history.fish b/tests/checks/history.fish index 53a62d463..cdbc4ee72 100644 --- a/tests/checks/history.fish +++ b/tests/checks/history.fish @@ -70,3 +70,12 @@ builtin history save set -g fish_private_mode 1 builtin history merge #CHECKERR: history: can't merge history in private mode + +builtin history -n abc +#CHECKERR: history: abc: invalid integer + +builtin history delete --prefix abc +#CHECKERR: builtin history delete only supports --exact + +builtin history delete --exact abc +#CHECKERR: builtin history delete --exact requires --case-sensitive diff --git a/tests/checks/indent.fish b/tests/checks/indent.fish index 2145e49cf..020233fe8 100644 --- a/tests/checks/indent.fish +++ b/tests/checks/indent.fish @@ -5,6 +5,17 @@ fish_indent --no-such-option #CHECKERR: fish_indent: --no-such-option: unknown option +fish_indent --check=foo +#CHECKERR: fish_indent: --check=foo: option does not take an argument + +fish_indent -w +#CHECKERR: Expected file path to read/write for -w: +#CHECKERR: +#CHECKERR: {{ }}$ fish -w foo.fish + +fish_indent -w nonexistent +#CHECKERR: Opening "nonexistent" failed: No such file or directory (os error {{\d+}}) + echo 'echo foo \\ | cat' | $fish_indent #CHECK: echo foo \ @@ -36,7 +47,6 @@ brot' | $fish_indent #CHECK: echo foo \ #CHECK: brot - echo 'echo rabarber \\ banana' | $fish_indent #CHECK: echo rabarber \ @@ -225,7 +235,6 @@ echo < stdin >>appended yes 2>&1 no > stdout maybe 2>& 4 | cat 2>| cat ' | $fish_indent #CHECK: echo >appended yes 2>&1 no >stdout maybe 2>&4 | cat 2>| cat - # issue 7252 echo -n ' begin @@ -265,7 +274,6 @@ end #CHECK: {{^ }}{{ }}continuation #CHECK: {{^}}end - echo -n ' i\ f true @@ -624,7 +632,6 @@ end' | $fish_indent --only-unindent # CHECK: {{^}} not indented properly # CHECK: {{^}}end - echo 'echo ( if true echo @@ -671,11 +678,16 @@ end # CHECK: {{^}}) set -l tmpdir (mktemp -d) -echo 'echo "foo" "bar"' > $tmpdir/indent_test.fish +echo 'echo "foo" "bar"' >$tmpdir/indent_test.fish $fish_indent --write $tmpdir/indent_test.fish cat $tmpdir/indent_test.fish # CHECK: echo foo bar +echo 'echo "foo" "bar"' >$tmpdir/indent_test.fish +chmod 400 $tmpdir/indent_test.fish +$fish_indent --write $tmpdir/indent_test.fish +# CHECKERR: Opening "{{.*}}/indent_test.fish" failed: {{.*}}) + # See that the builtin can be redirected printf %s\n a b c | builtin fish_indent | grep b # CHECK: b diff --git a/tests/checks/jobs.fish b/tests/checks/jobs.fish index cd7413264..37bbc9360 100644 --- a/tests/checks/jobs.fish +++ b/tests/checks/jobs.fish @@ -133,3 +133,6 @@ end disown 252 # CHECKERR: disown: Could not find job '252' + +jobs %abc +# CHECKERR: jobs: '%abc' is not a valid job ID diff --git a/tests/checks/math.fish b/tests/checks/math.fish index 9a4d6715f..46cdfdd3d 100644 --- a/tests/checks/math.fish +++ b/tests/checks/math.fish @@ -25,6 +25,12 @@ math --scale=max '5 / 3' # CHECK: 1.666666666666667 math --scale=1 --base=16 "2 / 3 - 1" # CHECKERR: math: invalid option combination, non-zero scale value only valid for base 10 +math --scale=abc '5 / 3' +# CHECKERR: math: abc: invalid scale +math --scale=-1 '5 / 3' +# CHECKERR: math: -1: invalid scale +math --scale=16 '5 / 3' +# CHECKERR: math: 16: invalid scale math "7^2" # CHECK: 49 math -1 + 1 @@ -429,3 +435,6 @@ math -s 6 --scale-mode=ceiling "1 / 3 - 1" # CHECK: -0.666666 math -s 6 --scale-mode=ceiling "2 / 3 - 1" # CHECK: -0.333333 + +math -s 6 --scale-mode=random "2 / 3 - 1" +# CHECKERR: math: random: invalid mode diff --git a/tests/checks/path.fish b/tests/checks/path.fish index 4d051dc64..865f339e3 100644 --- a/tests/checks/path.fish +++ b/tests/checks/path.fish @@ -337,3 +337,49 @@ path basename -E foo.txt /usr/local/foo.bar /foo.tar.gz path basename --null-out bar baz | string escape # CHECK: bar\x00baz\x00 + +path basename --quiet=foo +# CHECKERR: path basename: --quiet=foo: option does not take an argument + +path basename --unknown-option +# CHECKERR: path basename: --unknown-option: unknown option +# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}): +# CHECKERR: path basename --unknown-option +# CHECKERR: ^ +# CHECKERR: (Type 'help path' for related documentation) + +path filter -t invalid_type +# CHECKERR: path filter: Invalid type 'invalid_type' + +path filter -p 999 +# CHECKERR: path filter: Invalid permission '999' + +path sort --relative +# CHECKERR: path sort: --relative: unknown option +# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}): +# CHECKERR: path sort --relative +# CHECKERR: ^ +# CHECKERR: (Type 'help path' for related documentation) + +path change-extension +# CHECKERR: path change-extension: missing argument + +echo some.file | path basename other.file +# CHECKERR: path basename: too many arguments + +path sort --key=invalid-key +# CHECKERR: path sort: Invalid sort key 'invalid-key' + +path +# CHECKERR: path: missing subcommand +# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}): +# CHECKERR: path +# CHECKERR: ^ +# CHECKERR: (Type 'help path' for related documentation) + +path invalid-subcmd +# CHECKERR: path: invalid-subcmd: invalid subcommand +# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}): +# CHECKERR: path invalid-subcmd +# CHECKERR: ^ +# CHECKERR: (Type 'help path' for related documentation) diff --git a/tests/checks/print-help.fish b/tests/checks/print-help.fish index ca8d54223..7d6daff0b 100644 --- a/tests/checks/print-help.fish +++ b/tests/checks/print-help.fish @@ -1,16 +1,16 @@ # RUN: %fish %s -# Test redirecting builtin help with a pipe # REQUIRES: command -v man -set -lx __fish_data_dir (mktemp -d) -mkdir -p $__fish_data_dir/man/man1 -# Create $__fish_data_dir/man/man1/and.1 -echo '.\" Test manpage for and (not real). -.TH "AND" "1" "Feb 02, 2024" "3.7" "fish-shell" -.SH NAME -and \- conditionally execute a command' >$__fish_data_dir/man/man1/and.1 - +# Test redirecting builtin help with a pipe # help should be redirected to grep instead of appearing on STDOUT builtin and --help 2>| grep -q "Documentation for and" echo $status #CHECK: 0 + +function __fish_print_help + return 2 +end +builtin and --help +# CHECKERR: fish: and: missing man page +# CHECKERR: Documentation may not be installed. +# CHECKERR: `help and` will show an online version diff --git a/tests/checks/printf.fish b/tests/checks/printf.fish index 72c6038f1..bc9203820 100644 --- a/tests/checks/printf.fish +++ b/tests/checks/printf.fish @@ -31,6 +31,12 @@ printf "%-20d%d\n" 5 10 printf "%*d\n" 10 100 # CHECK: 100 +printf "%*s\n" 2147483648 abc +# CHECKERR: invalid field width: 2147483648 + +printf "%*s\n" -2147483649 abc +# CHECKERR: invalid field width: -2147483649 + printf "%%\"\\\n" printf "%s\b%s\n" x y # CHECK: %"\nxy @@ -80,9 +86,11 @@ printf 'long hex2 %X\n' 498216206234 printf 'long hex3 %X\n' 0xABCDEF1234567890 # CHECK: long hex3 ABCDEF1234567890 printf 'long hex4 %X\n' 0xABCDEF12345678901 +printf '\n' +# CHECK: long hex4 # CHECKERR: 0xABCDEF12345678901: Number out of range printf 'long decimal %d\n' 498216206594 -# CHECK: long hex4 long decimal 498216206594 +# CHECK: long decimal 498216206594 printf 'long signed %d\n' -498216206595 # CHECK: long signed -498216206595 printf 'long signed to unsigned %u\n' -498216206596 @@ -124,6 +132,12 @@ printf '%d\n' 0g echo $status # CHECK: 1 +printf '%d\n' abc +# CHECKERR: abc: expected a numeric value + +printf '%d\n' "" +# CHECK: 0 + printf '%f\n' 0x2 # CHECK: 2.000000 @@ -133,6 +147,12 @@ printf '%f\n' 0x2p3 printf '%.1f\n' -0X1.5P8 # CHECK: -336.0 +printf '%.*f\n' 2147483648 1 +# CHECKERR: invalid precision: 2147483648 + +printf '%lb\n' 1 +# CHECKERR: %lb: invalid conversion specification + # Test that we ignore options printf -a printf --foo @@ -156,7 +176,7 @@ printf %18446744073709551616s # CHECKERR: Number out of range # Test non-ASCII behavior -printf '|%3s|\n' 'ö' +printf '|%3s|\n' ö # CHECK: | ö| printf '|%3s|\n' '🇺🇳' #CHECK: | 🇺🇳| @@ -168,16 +188,24 @@ printf '|%.3s|\n' 'aa🇺🇳' #CHECK: |aa| printf '|%3.3s|\n' 'aa🇺🇳' #CHECK: | aa| -printf '|%.1s|\n' '𒈙a' +printf '|%.1s|\n' 𒈙a #CHECK: |𒈙| printf '|%3.3s|\n' '👨‍👨‍👧‍👧' #CHECK: | 👨‍👨‍👧‍👧| +printf '\xxyz' +# CHECKERR: missing hexadecimal number in escape +printf '\uxyz' +# CHECKERR: Missing hexadecimal number in Unicode escape + # Check handling of chars we use in our internal PUA encoding. printf '\uf641' | display_bytes # CHECK: 0000000 357 231 201 # CHECK: 0000003 +printf '\U110000' +# CHECKERR: Not a valid Unicode character: \U00110000 + # UTF-8 representation of \uf641 printf '%s' \xef\x99\x81 | display_bytes # CHECK: 0000000 357 231 201 diff --git a/tests/checks/read.fish b/tests/checks/read.fish index d6fc79c11..9d19f54e4 100644 --- a/tests/checks/read.fish +++ b/tests/checks/read.fish @@ -142,6 +142,15 @@ echo $bar echo test | read -n 1 foo echo $foo #CHECK: t +echo test | read -n 2147483647 foo +echo $foo +#CHECK: test +echo test | read -n 2147483648 foo +#CHECKERR: read: Argument '2147483648' is out of range +#CHECKERR: {{.*}}/checks/read.fish (line {{\d+}}): +#CHECKERR: echo test | read -n 2147483648 foo +#CHECKERR: ^ +#CHECKERR: (Type 'help read' for related documentation) # read -z tests echo -n testing | read -lz foo @@ -455,6 +464,25 @@ set -S rawlist_null # CHECK: $rawlist_null[7]: |line| # CHECK: $rawlist_null[8]: |\n| +echo 'foo "&" bar' | read -al --tokenize --tokenize tokens +set -S tokens +# CHECK: $tokens: set in local scope, unexported, with 3 elements +# CHECK: $tokens[1]: |foo| +# CHECK: $tokens[2]: |&| +# CHECK: $tokens[3]: |bar| +echo 'foo "&" bar' | read -al --tokenize-raw --tokenize-raw tokens +set -S tokens +# CHECK: $tokens: set in local scope, unexported, with 3 elements +# CHECK: $tokens[1]: |foo| +# CHECK: $tokens[2]: |"&"| +# CHECK: $tokens[3]: |bar| +echo 'foo "&" bar' | read -al --tokenize --tokenize-raw tokens +# CHECKERR: read: invalid option combination, --tokenize and --tokenize-raw are mutually exclusive +# CHECKERR: {{.*}}checks/read.fish (line {{\d+}}): +# CHECKERR: echo 'foo "&" bar' | read -al --tokenize --tokenize-raw tokens +# CHECKERR: ^ +# CHECKERR: (Type 'help read' for related documentation) + echo '1 {} "{}"' | read -lat var echo $var # CHECK: 1 {} {} @@ -467,3 +495,33 @@ set -S out_of_range_codepoint printf \xff | { read invalid_utf8; set -S invalid_utf8 } # CHECK: $invalid_utf8: set in global scope, unexported, with 1 elements # CHECK: $invalid_utf8[1]: |\Xff| + +echo foo | read -l -p "echo little-p" -P big-P var +# CHECKERR: read: Options -p and -P cannot be used together +# CHECKERR: {{.*}}checks/read.fish (line {{\d+}}): +# CHECKERR: echo foo | read -l -p "echo little-p" -P big-P var +# CHECKERR: ^ +# CHECKERR: (Type 'help read' for related documentation) + +echo foo | read -d ";" -L var +# CHECKERR: read: Options --delimiter and --line cannot be used together +echo foo | read --null -L var +# CHECKERR: read: Options -z and --line cannot be used together +echo foo | read -d "&" --tokenize +# CHECKERR: read: --delimiter --tokenize: options cannot be used together +echo foo | read -L --tokenize-raw +# CHECKERR: read: --line --tokenize-raw: options cannot be used together + +echo foo | read -lxu var +# CHECKERR: read: cannot both export and unexport +# CHECKERR: {{.*}}checks/read.fish (line {{\d+}}): +# CHECKERR: echo foo | read -lxu var +# CHECKERR: ^ +# CHECKERR: (Type 'help read' for related documentation) + +echo foo | read -lf var +# CHECKERR: read: scope can be only one of: universal function global local +# CHECKERR: {{.*}}checks/read.fish (line {{\d+}}): +# CHECKERR: echo foo | read -lf var +# CHECKERR: ^ +# CHECKERR: (Type 'help read' for related documentation) diff --git a/tests/checks/realpath.fish b/tests/checks/realpath.fish index 1ff80b9fa..3b727f53c 100644 --- a/tests/checks/realpath.fish +++ b/tests/checks/realpath.fish @@ -44,11 +44,15 @@ builtin realpath /def/// # Verify `realpath .` when cwd is a deleted directory gives a no such file or dir error. set -l tmpdir (mktemp -d) pushd $tmpdir +mkdir subdir +cd subdir # Solaris rmdir tries to protect against deleting $PWD. # But that's what we want to test, so we weasel around it. -sh -c "cd ..; rmdir $tmpdir" +sh -c "cd ../..; rmdir $tmpdir/subdir $tmpdir" builtin realpath . # CHECKERR: builtin realpath: .: No such file or directory +builtin realpath -s . +# CHECKERR: builtin realpath: realpath failed: No such file or directory popd # A single symlink to a directory is correctly resolved. diff --git a/tests/checks/return.fish b/tests/checks/return.fish index f1c19eceb..50523f540 100644 --- a/tests/checks/return.fish +++ b/tests/checks/return.fish @@ -35,3 +35,17 @@ for i in (seq -- -550 -1) end end # CHECK: + +$fish -c "return 1 2" +# CHECKERR: return: too many arguments +# CHECKERR: Standard input (line 1): +# CHECKERR: return 1 2 +# CHECKERR: ^ +# CHECKERR: (Type 'help return' for related documentation) + +$fish -c "return abc" +# CHECKERR: return: abc: invalid integer +# CHECKERR: Standard input (line 1): +# CHECKERR: return abc +# CHECKERR: ^ +# CHECKERR: (Type 'help return' for related documentation) diff --git a/tests/checks/set.fish b/tests/checks/set.fish index 25fe71a99..9c31b13ba 100644 --- a/tests/checks/set.fish +++ b/tests/checks/set.fish @@ -638,6 +638,19 @@ set -p # CHECKERR: ^ # CHECKERR: (Type 'help set' for related documentation) +set -a foo[1] +# CHECKERR: set: Cannot use --append or --prepend when assigning to a slice +# CHECKERR: {{.*}}checks/set.fish (line {{\d+}}): +# CHECKERR: set -a foo[1] +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) +set -p foo[1] +# CHECKERR: set: Cannot use --append or --prepend when assigning to a slice +# CHECKERR: {{.*}}checks/set.fish (line {{\d+}}): +# CHECKERR: set -p foo[1] +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + # Setting local scope when no local scope of the var uses the closest scope set -g var6 ghi jkl begin @@ -999,6 +1012,11 @@ set -e undefined[..1] set -l negative_oob 1 2 3 set -q negative_oob[-10..1] +set foo[1 2 3] a b +# CHECKERR: set: given 3 indexes but 2 values +set foo[1 2 3] a b c d +# CHECKERR: set: given 3 indexes but 4 values + # --no-event function onevent --on-variable nonevent @@ -1046,4 +1064,86 @@ set line[0] "" echo Still here # CHECK: Still here +set -o xtrace +# CHECKERR: Fish does not have shell options. See `help fish_for_bash_users`. +# CHECKERR: set: -o: unknown option + +set -o vi +# CHECKERR: Fish does not have shell options. See `help fish_for_bash_users`. +# CHECKERR: To enable vi-mode, run `fish_vi_key_bindings`. +# CHECKERR: set: -o: unknown option + +set -o ed +# CHECKERR: Fish does not have shell options. See `help fish_for_bash_users`. +# CHECKERR: ? +# CHECKERR: ? +# CHECKERR: ? +# CHECKERR: set: -o: unknown option + +set -q -e foo +# CHECKERR: set: invalid option combination +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -q -e foo +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -q -n +# CHECKERR: set: invalid option combination +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -q -n +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -e -n +# CHECKERR: set: invalid option combination +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -e -n +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -l -g foo bar +# CHECKERR: set: scope can be only one of: universal function global local +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -l -g foo bar +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -u -x foo +# CHECKERR: set: cannot both export and unexport +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -u -x foo +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -e -x foo +# CHECKERR: set: invalid option combination +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -e -x foo +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -e -u foo +# CHECKERR: set: invalid option combination +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -e -u foo +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set --path --unpath foo +# CHECKERR: set: cannot both path and unpath +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set --path --unpath foo +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set -s -l +# CHECKERR: set: invalid option combination +# CHECKERR: {{.*}}set.fish (line {{\d+}}): +# CHECKERR: set -s -l +# CHECKERR: ^ +# CHECKERR: (Type 'help set' for related documentation) + +set umask abc +# CHECKERR: set: Tried to modify the special variable 'umask' to an invalid value + exit 0 diff --git a/tests/checks/set_color.fish b/tests/checks/set_color.fish index aa6119f7d..50933dde7 100644 --- a/tests/checks/set_color.fish +++ b/tests/checks/set_color.fish @@ -138,3 +138,10 @@ string escape (set_color --underline=off) string escape (set_color --reset f00 --background=00f --underline-color=0f0 --bold --dim --italics --reverse --strikethrough --underline=curly) # CHECK: \e\[\;38\;2\;255\;0\;0\;48\;2\;0\;0\;255\;58:2::0:255:0\;1\;4:3\;2\;3m\e\[7\;9m + +set_color --unknown-opt +# CHECKERR: set_color: --unknown-opt: unknown option +# CHECKERR: {{.*}}checks/set_color.fish (line {{\d+}}): +# CHECKERR: set_color --unknown-opt +# CHECKERR: ^ +# CHECKERR: (Type 'help set_color' for related documentation) diff --git a/tests/checks/signal.fish b/tests/checks/signal.fish index 249d1d5f8..6145af9d2 100644 --- a/tests/checks/signal.fish +++ b/tests/checks/signal.fish @@ -73,4 +73,15 @@ echo "Now event handler should have run" # CHECK: PROCESS_EXIT 0 # CHECK: JOB_EXIT 0 # CHECK: Now event handler should have run + +begin + block --erase --local + # CHECKERR: block: Can not specify scope when removing block + block --erase --global + # CHECKERR: block: Can not specify scope when removing block + block --erase + # CHECKERR: block: No blocks defined +end + +exit 0 # CHECK: PROCESS_EXIT 0 diff --git a/tests/checks/source.fish b/tests/checks/source.fish index e8f589416..b166ebb83 100644 --- a/tests/checks/source.fish +++ b/tests/checks/source.fish @@ -9,3 +9,12 @@ echo $status # CHECKERR: error: Unable to read input file: Is a directory # CHECKERR: source: Error while reading file '/' # CHECK: 1 + +source unknown-file +# CHECKERR: source: Error encountered while sourcing file 'unknown-file': +# CHECKERR: source: {{.+}} + +source <&- +# CHECKERR: source: stdin is closed +source - <&- +# CHECKERR: source: stdin is closed diff --git a/tests/checks/status.fish b/tests/checks/status.fish index b861d2f88..f9f9310f1 100644 --- a/tests/checks/status.fish +++ b/tests/checks/status.fish @@ -86,7 +86,7 @@ echo $status # Verify errors from writes - see #7857. if test -e /dev/full # Failed writes to stdout produce 1. - echo foo > /dev/full + echo foo >/dev/full if test $status -ne 1 echo "Wrong status when writing to /dev/full" end @@ -94,7 +94,7 @@ if test -e /dev/full # Here the builtin should fail with status 2, # and also the write should fail with status 1. # The builtin has precedence. - builtin string --not-a-valid-option 2> /dev/full + builtin string --not-a-valid-option 2>/dev/full if test $status -ne 2 echo "Wrong status for failing builtin" end @@ -140,3 +140,51 @@ and should have failed on unrecognized feature # CHECKERR: status test-terminal-feature: unrecognized feature 'unrecognized-feature' status test-terminal-feature scroll-content-up and should have failed when running without a TTY + +status -L abc +# CHECKERR: status: abc: invalid integer +status -L 9999999999999999999999 +# CHECKERR: status: Invalid level value '9999999999999999999999' + +status unknown-subcmd +# CHECKERR: status: unknown-subcmd: invalid subcommand + +status job-control abc cdf +# CHECKERR: status: job-control: expected 1 arguments; got 2 + +status test-feature +# CHECKERR: status: test-feature: expected 1 arguments; got 0 +status test-feature one two +# CHECKERR: status: test-feature: expected 1 arguments; got 2 + +status get-file +# CHECKERR: status: get-file: expected 1 arguments; got 0 +status get-file one two +# CHECKERR: status: get-file: expected 1 arguments; got 2 + +if status buildinfo | string match -q "*localize-messages*" + echo Skipped +else + set -l result "$(status language 2>&1)" + if string match -q "fish was built with the `localize-messages` feature disabled. The `status language` command is unavailable." -- "$result" + echo Success + else + echo "Failed: $result" + end +end +# CHECK: {{Skipped|Success}} + +if not { status buildinfo | string match -q "*localize-messages*" } + echo Skipped +else + set -l result "$(status language foo 2>&1)" + if string match -q "status language: foo: invalid subcommand" -- "$result" + echo Success + else + echo "Failed: $result" + end +end +# CHECK: {{Skipped|Success}} + +status build-info other-arg +# CHECKERR: status: build-info: expected 0 arguments; got 1 diff --git a/tests/checks/string.fish b/tests/checks/string.fish index aab6aaa65..5b1bc9722 100644 --- a/tests/checks/string.fish +++ b/tests/checks/string.fish @@ -1,6 +1,27 @@ #RUN: fish=%fish %fish %s # Tests for string builtin. Mostly taken from man page examples. +string +# CHECKERR: string: missing subcommand +# CHECKERR: {{.*}}checks/string.fish (line {{\d+}}): +# CHECKERR: string +# CHECKERR: ^ +# CHECKERR: (Type 'help string' for related documentation) + +string abc +# CHECKERR: string: abc: invalid subcommand +# CHECKERR: {{.*}}checks/string.fish (line {{\d+}}): +# CHECKERR: string abc +# CHECKERR: ^ +# CHECKERR: (Type 'help string' for related documentation) + +string --abc +# CHECKERR: string: --abc: invalid subcommand +# CHECKERR: {{.*}}checks/string.fish (line {{\d+}}): +# CHECKERR: string --abc +# CHECKERR: ^ +# CHECKERR: (Type 'help string' for related documentation) + string match -r -v "c.*" dog can cat diz; and echo "exit 0" # CHECK: dog # CHECK: diz @@ -36,6 +57,12 @@ string match -q -r -v x y; and echo "exit 0" string match -q -r -v x x; or echo "exit 1" # CHECK: exit 1 +string match -v -g foo foo +# CHECKERR: match: invalid option combination, --invert and --groups-only are mutually exclusive + +string match +# CHECKERR: string match: missing argument + string length "hello, world" # CHECK: 12 @@ -55,6 +82,8 @@ string pad -r -w 7 --chars - --center foo # might overflow when converting sign string sub --start -9223372036854775808 abc # CHECK: abc +string sub --start 0 abc +# CHECKERR: string sub: Invalid start value '0' string pad --width 7 -c '=' foo # CHECK: ====foo @@ -137,6 +166,9 @@ string pad -c ab -w4 . string pad -c \u07 . # CHECKERR: string pad: Invalid padding character of width zero {{'\a'}} +string pad --width=-1 foo +# CHECKERR: string pad: Invalid width value '-1' + # Visible length. Let's start off simple, colors are ignored: string length --visible (set_color red)abc # CHECK: 3 @@ -185,6 +217,9 @@ string sub --length 2 abcde string sub -s 2 -l 2 abcde # CHECK: bc +string sub --length=-1 abcde +# CHECKERR: string sub: Invalid length value '-1' + string sub --start=-2 abcde # CHECK: de @@ -194,6 +229,9 @@ string sub --end=3 abcde string sub --end=-4 abcde # CHECK: a +string sub --end=0 abcde +# CHECKERR: string sub: Invalid end value '0' + string sub --start=2 --end=-2 abcde # CHECK: bc @@ -212,6 +250,9 @@ string sub -s -50 -e -100 abcde string sub -s 2 -e -5 abcde # CHECK: +string sub -s 2 -e -5 -l 3 abcde +# CHECKERR: sub: invalid option combination, --end and --length are mutually exclusive + string split . example.com # CHECK: example # CHECK: com @@ -225,10 +266,16 @@ string split "" abc # CHECK: b # CHECK: c +string split +# CHECKERR: string split: missing argument + string split --max 1 --right 12 AB12CD # CHECK: AB # CHECK: CD +string split --max=-1 --right 12 AB12CD +# CHECKERR: string split: Invalid max value '-1' + string split --fields=2 "" abc # CHECK: b @@ -288,9 +335,15 @@ string split -f1 ' ' 'a b' 'c d' string split --allow-empty --fields=2,9 "" abc # CHECK: b +string split --allow-empty "" abc +# CHECKERR: split: invalid option combination, --allow-empty is only valid with --fields + seq 3 | string join ... # CHECK: 1...2...3 +string join +# CHECKERR: string join: missing argument + string trim " abc " # CHECK: abc @@ -361,6 +414,9 @@ world" # CHECK: \^this is a literal string # CHECK: hello\nworld +string escape --style=unknown-style +# CHECKERR: string escape: Invalid escape style 'unknown-style' + ### Verify that we can correctly unescape the same strings # we tested escaping above. set x (string unescape (echo \x07 | string escape)) @@ -395,6 +451,9 @@ string unescape --style=var (string escape --style=var '_a_b_c_') string unescape --style=var -- (string escape --style=var -- -) # CHECK: - +string unescape --style=unknown-style +# CHECKERR: string unescape: Invalid style value 'unknown-style' + ### Verify that we can correctly match strings. string match "*" a # CHECK: a @@ -431,6 +490,9 @@ string match -r -a -n at ratatat string match -r -i "0x[0-9a-f]{1,8}" "int magic = 0xBadC0de;" # CHECK: 0xBadC0de +string match -r -i "0x[0-9a-f]{1,8}" "int magic = 0xBadC0de;" +# CHECK: 0xBadC0de + string replace is was "blue is my favorite" # CHECK: blue was my favorite @@ -531,6 +593,9 @@ echo foo | string repeat -n 2 echo foo | string repeat 2 # CHECK: foofoo +string repeat +# CHECKERR: string repeat: missing argument + string repeat foo # CHECKERR: string repeat: Invalid count value 'foo' @@ -717,6 +782,12 @@ or echo exit 1 # CHECK: caabxyxz # CHECK: xyx +string match --entire --index foo foo +# CHECKERR: match: invalid option combination, --entire and --index are mutually exclusive + +string match --entire --groups-only -r foo foo +# CHECKERR: match: invalid option combination, --entire and --groups-only are mutually exclusive + # 'string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz' string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz or echo exit 1 @@ -1006,6 +1077,9 @@ string shorten --max 4 -c /// foobarnana string shorten --max 2 --char "" foo # CHECK: fo +string shorten --max=-1 --char "" foo +# CHECKERR: string shorten: Invalid max value '-1' + string shorten foo foobar # CHECK: foo # CHECK: fo… @@ -1200,6 +1274,12 @@ printf "dog\ncat\nbat\ngnat\n" | string match -m2 "*at" # CHECK: cat # CHECK: bat +string match -m0 foo +# CHECKERR: string match: Invalid max matches value '0' + +string match -m999999999999999999999999999999999999999 foo +# CHECKERR: string match: Invalid max matches value '999999999999999999999999999999999999999' + printf "dog\ncat\nbat\nhog\n" | string match -rvm1 'at$' # CHECK: dog @@ -1212,3 +1292,28 @@ printf "dog\ncat\nbat\n" | string replace -r --max-matches 1 '^c' h $fish --features="no-regex-easyesc" -c "string replace -r o '\c' -- foo" # CHECKERR: string replace: Invalid escape sequence in pattern "\c" + +string replace --max-matches abc +# CHECKERR: string replace: Invalid max matches value 'abc' +string replace --max-matches -1 +# CHECKERR: string replace: Invalid max matches value '-1' +string replace --max-matches 99999999999999999999 +# CHECKERR: string replace: Invalid max matches value '99999999999999999999' + +string replace +# CHECKERR: string replace: missing argument +string replace one +# CHECKERR: string replace: expected 1 arguments; got 2 + +string replace -r o '${bad_name}' foobar +# CHECKERR: string replace: Regular expression substitute error: unknown substring + +string match --unknown-opt +# CHECKERR: string match: --unknown-opt: unknown option +# CHECKERR: {{.*}}checks/string.fish (line {{\d+}}): +# CHECKERR: string match --unknown-opt +# CHECKERR: ^ +# CHECKERR: (Type 'help string' for related documentation) + +string match --regex=abc +# CHECKERR: string match: --regex=abc: option does not take an argument diff --git a/tests/checks/test.fish b/tests/checks/test.fish index 9b738ce9a..35cd8bfb1 100644 --- a/tests/checks/test.fish +++ b/tests/checks/test.fish @@ -142,3 +142,10 @@ test #CHECKERR: test #CHECKERR: ^ #CHECKERR: (Type 'help test' for related documentation) + +[ -z +#CHECKERR: [: the last argument must be ']' +#CHECKERR: {{.*}}test.fish (line {{\d+}}): +#CHECKERR: [ -z +#CHECKERR: ^ +#CHECKERR: (Type 'help [' for related documentation) diff --git a/tests/checks/tmux-breakpoint.fish b/tests/checks/tmux-breakpoint.fish new file mode 100644 index 000000000..9e1f049ed --- /dev/null +++ b/tests/checks/tmux-breakpoint.fish @@ -0,0 +1,11 @@ +#RUN: %fish %s +#REQUIRES: command -v tmux + +isolated-tmux-start +isolated-tmux send-keys breakpoint Enter + +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 0> breakpoint +# CHECK: breakpoint: Command not valid at an interactive prompt +# CHECK: prompt 1> diff --git a/tests/checks/tmux-set.fish b/tests/checks/tmux-set.fish new file mode 100644 index 000000000..51e686725 --- /dev/null +++ b/tests/checks/tmux-set.fish @@ -0,0 +1,13 @@ +#RUN: %fish %s +#REQUIRES: command -v tmux + +isolated-tmux-start +isolated-tmux send-keys 'set -g g_u_var foobar' Enter +isolated-tmux send-keys 'set -U g_u_var barfoo' Enter + +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 0> set -g g_u_var foobar +# CHECK: prompt 0> set -U g_u_var barfoo +# CHECK: set: successfully set universal 'g_u_var'; but a global by that name shadows it +# CHECK: prompt 0> diff --git a/tests/checks/tmux-source.fish b/tests/checks/tmux-source.fish new file mode 100644 index 000000000..4592785fc --- /dev/null +++ b/tests/checks/tmux-source.fish @@ -0,0 +1,13 @@ +#RUN: %fish %s +#REQUIRES: command -v tmux + +isolated-tmux-start +isolated-tmux send-keys source Enter +isolated-tmux send-keys 'source -' Enter + +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 0> source +# CHECK: source: missing filename argument or input redirection +# CHECK: prompt 1> source - +# CHECK: prompt 1> diff --git a/tests/checks/type.fish b/tests/checks/type.fish index 8e5ddfeb7..74fa00530 100644 --- a/tests/checks/type.fish +++ b/tests/checks/type.fish @@ -140,3 +140,6 @@ chmod +x ./test PATH=.:$PATH type -P test # CHECK: ./test + +type -p -q type +# CHECKERR: type: invalid option combination diff --git a/tests/checks/ulimit.fish b/tests/checks/ulimit.fish index d6142f30f..b45c2a055 100644 --- a/tests/checks/ulimit.fish +++ b/tests/checks/ulimit.fish @@ -14,3 +14,71 @@ ulimit 4352353252352352334 #CHECKERR: ^ #CHECKERR: (Type 'help ulimit' for related documentation) +# Try to increase a hard limit +# Since limits vary between OSes and distributions, we need to find +# a non-unlimited dynamically +set -l ulimit_opts -c -d -f -n -s -t -u +for ulimit_opt in $ulimit_opts + set -l max (ulimit -H $ulimit_opt 2>/dev/null) + if contains -- "$max" "" unlimited + continue + end + set found true + echo "Using $ulimit_opt to increase hard limit" >&2 + ulimit -H $ulimit_opt (math $max + 1) >/dev/null + break +end +if not set -q found + echo "All common hard ulimits are unlimited, cannot increase them" >&2 +end +#CHECKERR: Using {{-.}} to increase hard limit +#CHECKERR: ulimit: Permission denied when changing resource of type '{{.+}}' + +# Try to lower a hard limit below its soft one +set -e found +for ulimit_opt in $ulimit_opts + set -l min (ulimit -S $ulimit_opt 2>/dev/null) + if contains -- "$min" "" 0 + continue + end + if test $min = unlimited + set min 1024 + end + set found true + echo "Using $ulimit_opt to lower hard limit" >&2 + ulimit -H $ulimit_opt (math $min - 1) >/dev/null + and if test (__fish_uname) = FreeBSD + echo "ulimit: FreeBSD doesn't fail unlike other platforms, so fake it" >&2 + end + break +end +if not set -q found + echo "All common soft ulimits are 0, cannot decrease hard ulimits below them" >&2 +end +#CHECKERR: Using {{-.}} to lower hard limit +#CHECKERR: ulimit: {{.+}} + +if test (__fish_uname) = Linux + ulimit -K 1024 +else + ulimit -q 1024 +end +#CHECKERR: ulimit: Resource limit not available on this operating system +#CHECKERR: {{.*}}checks/ulimit.fish (line {{\d+}}): +#CHECKERR: ulimit -{{.}} 1024 +#CHECKERR: ^ +#CHECKERR: (Type 'help ulimit' for related documentation) + +ulimit --core-size 0 1 2 +#CHECKERR: ulimit: too many arguments +#CHECKERR: {{.*}}checks/ulimit.fish (line {{\d+}}): +#CHECKERR: ulimit --core-size 0 1 2 +#CHECKERR: ^ +#CHECKERR: (Type 'help ulimit' for related documentation) + +ulimit --core-size abc +#CHECKERR: ulimit: Invalid limit 'abc' +#CHECKERR: {{.*}}checks/ulimit.fish (line {{\d+}}): +#CHECKERR: ulimit --core-size abc +#CHECKERR: ^ +#CHECKERR: (Type 'help ulimit' for related documentation) diff --git a/tests/checks/wait.fish b/tests/checks/wait.fish index 3f89647be..3a132df5c 100644 --- a/tests/checks/wait.fish +++ b/tests/checks/wait.fish @@ -76,3 +76,6 @@ wait -- -1 # CHECKERR: wait: Could not find child processes with the name '-1' wait -- -(math 2 ^ 31) # CHECKERR: wait: Could not find child processes with the name '-2147483648' + +wait 999999999 +# CHECKERR: wait: Could not find a job with process ID '999999999'