| # This testcase is part of GDB, the GNU debugger. |
| |
| # Copyright 2019-2021 Free Software Foundation, Inc. |
| |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 3 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| |
| # Test the gdb::option framework. |
| |
| # The test uses the "maintenance test-options" subcommands to exercise |
| # TAB-completion and option processing. |
| # |
| # It also tests option integration in various commands, including: |
| # |
| # - print |
| # - compile print |
| # - backtrace |
| # - frame apply |
| # - faas |
| # - tfaas |
| # - thread apply |
| # - taas |
| |
| load_lib completion-support.exp |
| |
| standard_testfile .c |
| |
| if {[build_executable "failed to prepare" $testfile $srcfile debug]} { |
| return -1 |
| } |
| |
| clean_restart |
| |
| if { ![readline_is_used] } { |
| untested "no tab completion support without readline" |
| return -1 |
| } |
| |
| set tui_supported_p [expr ![skip_tui_tests]] |
| |
| # Check the completion result, as returned by the "maintenance show |
| # test-options-completion-result" command. TEST is used as test name. |
| proc check_completion_result {expected test} { |
| gdb_test "maintenance show test-options-completion-result" \ |
| "$expected" \ |
| "$test: res=$expected" |
| } |
| |
| # Like test_gdb_complete_unique, but the expected output is expected |
| # to be the input line. I.e., the line is already complete. We're |
| # just checking whether GDB recognizes the option and auto-appends a |
| # space. |
| proc test_completer_recognizes {res input_line} { |
| set expected_re [string_to_regexp $input_line] |
| test_gdb_complete_unique $input_line $expected_re |
| check_completion_result $res $input_line |
| } |
| |
| # Wrapper around test_gdb_complete_multiple that also checks the |
| # completion result is RES. |
| proc res_test_gdb_complete_multiple {res cmd_prefix completion_word args} { |
| test_gdb_complete_multiple $cmd_prefix $completion_word {*}$args |
| check_completion_result $res "$cmd_prefix$completion_word" |
| } |
| |
| # Wrapper around test_gdb_complete_none that also checks the |
| # completion result is RES. |
| proc res_test_gdb_complete_none { res input_line } { |
| test_gdb_complete_none $input_line |
| check_completion_result $res "$input_line" |
| } |
| |
| # Wrapper around test_gdb_complete_unique that also checks the |
| # completion result is RES. |
| proc res_test_gdb_complete_unique { res input_line args} { |
| test_gdb_complete_unique $input_line {*}$args |
| check_completion_result $res "$input_line" |
| } |
| |
| # Make a full command name from VARIANT. VARIANT is either |
| # "require-delimiter", "unknown-is-error" or "unknown-is-operand". |
| proc make_cmd {variant} { |
| return "maint test-options $variant" |
| } |
| |
| # Return a string for the expected result of running "maint |
| # test-options xxx", with no flag/option set. OPERAND is the expected |
| # operand. |
| proc expect_none {operand} { |
| return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '' -- $operand" |
| } |
| |
| # Return a string for the expected result of running "maint |
| # test-options xxx", with -flag set. OPERAND is the expected operand. |
| proc expect_flag {operand} { |
| return "-flag 1 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '' -- $operand" |
| } |
| |
| # Return a string for the expected result of running "maint |
| # test-options xxx", with -bool set. OPERAND is the expected operand. |
| proc expect_bool {operand} { |
| return "-flag 0 -xx1 0 -xx2 0 -bool 1 -enum xxx -uint 0 -zuint-unl 0 -string '' -- $operand" |
| } |
| |
| # Return a string for the expected result of running "maint |
| # test-options xxx", with one of the integer options set to $VAL. |
| # OPTION determines which option to expect set. OPERAND is the |
| # expected operand. |
| proc expect_integer {option val operand} { |
| if {$option == "uinteger"} { |
| return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint $val -zuint-unl 0 -string '' -- $operand" |
| } elseif {$option == "zuinteger-unlimited"} { |
| return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl $val -string '' -- $operand" |
| } else { |
| error "unsupported option: $option" |
| } |
| } |
| |
| # Return a string for the expected result of running "maint |
| # test-options xxx", with -string set to $STR. OPERAND is the |
| # expected operand. |
| proc expect_string {str operand} { |
| # Dequote the string in the expected output. |
| if { ( [string range $str 0 0] == "\"" |
| && [string range $str end end] == "\"") |
| || ([string range $str 0 0] == "'" |
| && [string range $str end end] == "'")} { |
| set str [string range $str 1 end-1] |
| } |
| return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '$str' -- $operand" |
| } |
| |
| set all_options { |
| "-bool" |
| "-enum" |
| "-flag" |
| "-string" |
| "-uinteger" |
| "-xx1" |
| "-xx2" |
| "-zuinteger-unlimited" |
| } |
| |
| # Basic option-machinery + "print" command integration tests. |
| proc_with_prefix test-print {{prefix ""}} { |
| clean_restart |
| |
| # Completing "print" with no argument completes on symbols only, |
| # no options are offered. Since we haven't loaded any symbols, |
| # the match list should be empty. |
| test_gdb_complete_none "${prefix}print " |
| |
| # OTOH, completing at "-" should list all options. |
| test_gdb_complete_multiple "${prefix}print " "-" "" { |
| "-address" |
| "-array" |
| "-array-indexes" |
| "-elements" |
| "-max-depth" |
| "-memory-tag-violations" |
| "-null-stop" |
| "-object" |
| "-pretty" |
| "-raw-values" |
| "-repeats" |
| "-static-members" |
| "-symbol" |
| "-union" |
| "-vtbl" |
| } |
| |
| global binfile |
| clean_restart $binfile |
| |
| if ![runto_main] { |
| return |
| } |
| |
| # Mix options and format. |
| gdb_test "${prefix}print -pretty -- /x 1" " = 0x1" |
| |
| # Smoke test that options actually work. |
| gdb_test "${prefix}print -pretty -- g_s" \ |
| [multi_line \ |
| " = {" \ |
| " a = 1," \ |
| " b = 2," \ |
| " c = 3" \ |
| "}"] |
| |
| test_gdb_complete_unique \ |
| "${prefix}print xxx" \ |
| "${prefix}print xxx1" |
| test_gdb_complete_unique \ |
| "${prefix}print -- xxx" \ |
| "${prefix}print -- xxx1" |
| |
| # Error messages when testing with "compile" are different from |
| # the error messages gdb's internal parser throws. This procedure |
| # hides the difference. EXPECTED_RE is only considered when not |
| # testing with "compile". |
| proc test_invalid_expression {cmd expected_re} { |
| upvar prefix prefix |
| |
| if {$prefix != "compile "} { |
| gdb_test $cmd $expected_re |
| } else { |
| # Error messages depend on compiler version, so we just |
| # look for the last line indicating a failure. |
| gdb_test $cmd "Compilation failed\\." |
| } |
| } |
| |
| # Check that '-XXX' without a "--" is handled as an |
| # expression. |
| gdb_test "${prefix}print -1" " = -1" |
| test_invalid_expression \ |
| "${prefix}print --1" \ |
| "Left operand of assignment is not an lvalue\\." |
| test_invalid_expression \ |
| "${prefix}print -object" \ |
| "No symbol \"object\".*" |
| |
| # Test printing with options and no expression. |
| set test "${prefix}print -object --" |
| if {$prefix != "compile "} { |
| # Regular "print" repeats the last history value. |
| gdb_test $test " = -1" |
| } else { |
| # "compile print" starts a multiline expression. |
| gdb_test_multiple $test $test { |
| -re ">$" { |
| gdb_test "-1\nend" " = -1" \ |
| $test |
| } |
| } |
| } |
| |
| # Check that everything after "-- " is treated as an |
| # expression, not confused with an option. |
| test_invalid_expression \ |
| "${prefix}print -- -address" \ |
| "No symbol.*" |
| gdb_test "${prefix}print -- -1" " = -1" |
| test_invalid_expression \ |
| "${prefix}print -- --1" \ |
| "Left operand of assignment is not an lvalue\\." |
| } |
| |
| # Basic option-machinery + "backtrace" command integration tests. |
| proc_with_prefix test-backtrace {} { |
| clean_restart |
| |
| test_gdb_complete_unique "backtrace" "backtrace" |
| test_gdb_complete_none "backtrace " |
| |
| gdb_test "backtrace -" "Ambiguous option at: -" |
| gdb_test "backtrace --" "No stack\\." |
| gdb_test "backtrace -- -" "No stack\\." |
| |
| test_gdb_complete_multiple "backtrace " "-" "" { |
| "-entry-values" |
| "-frame-arguments" |
| "-frame-info" |
| "-full" |
| "-hide" |
| "-no-filters" |
| "-past-entry" |
| "-past-main" |
| "-raw-frame-arguments" |
| } |
| |
| # Test that we complete the qualifiers, if there's any. |
| test_gdb_complete_unique \ |
| "backtrace ful" \ |
| "backtrace full" |
| test_gdb_complete_unique \ |
| "backtrace hid" \ |
| "backtrace hide" |
| test_gdb_complete_unique \ |
| "backtrace no-fil" \ |
| "backtrace no-filters" |
| |
| global binfile |
| clean_restart $binfile |
| |
| if ![runto_main] { |
| return |
| } |
| |
| # COUNT in "backtrace COUNT" is parsed as an expression. Check |
| # that we complete expressions. |
| |
| test_gdb_complete_unique \ |
| "backtrace xxx" \ |
| "backtrace xxx1" |
| |
| test_gdb_complete_unique \ |
| "backtrace -xxx" \ |
| "backtrace -xxx1" |
| |
| test_gdb_complete_unique \ |
| "backtrace 1 + xxx" \ |
| "backtrace 1 + xxx1" |
| |
| test_gdb_complete_unique \ |
| "backtrace (1 + xxx" \ |
| "backtrace (1 + xxx1" |
| } |
| |
| # Basic option-machinery + "frame apply" command integration tests. |
| proc_with_prefix test-frame-apply {} { |
| global tui_supported_p |
| |
| test_gdb_complete_unique "frame apply all" "frame apply all" |
| |
| gdb_test "frame apply level 0-" \ |
| "Please specify a command to apply on the selected frames" |
| test_gdb_complete_none "frame apply level 0-" |
| |
| foreach cmd { |
| "frame apply all" |
| "frame apply 1" |
| "frame apply level 0" |
| "faas" |
| "tfaas" |
| } { |
| test_gdb_completion_offers_commands "$cmd " |
| |
| # tfaas is silent on command error by design. This procedure |
| # hides that aspect. EXPECTED_RE is only considered when not |
| # testing with "faas"/"tfaas". |
| proc test_error_cmd {cmd arg expected_re} { |
| if {$cmd == "tfaas"} { |
| gdb_test_no_output "$cmd$arg" |
| } else { |
| gdb_test "$cmd$arg" $expected_re |
| } |
| } |
| # Same, but for tests where both "faas" and "tfaas" are |
| # expected to be silent. |
| proc test_error_cmd2 {cmd arg expected_re} { |
| if {$cmd == "tfaas" || $cmd == "faas"} { |
| gdb_test_no_output "$cmd$arg" |
| } else { |
| gdb_test "$cmd$arg" $expected_re |
| } |
| } |
| |
| test_error_cmd $cmd " -" "Ambiguous option at: -" |
| test_gdb_complete_multiple "$cmd " "-" "" { |
| "-c" |
| "-past-entry" |
| "-past-main" |
| "-q" |
| "-s" |
| } |
| |
| with_test_prefix "no-trailing-space" { |
| test_error_cmd $cmd " --" \ |
| "Please specify a command to apply on the selected frames" |
| test_gdb_complete_unique "$cmd --" "$cmd --" |
| } |
| |
| with_test_prefix "trailing-space" { |
| test_error_cmd $cmd " -- " \ |
| "Please specify a command to apply on the selected frames" |
| test_gdb_completion_offers_commands "$cmd -- " |
| } |
| |
| if { $tui_supported_p } { |
| # '-' is a valid TUI command. |
| test_error_cmd2 $cmd " -- -" \ |
| "Cannot enable the TUI when output is not a terminal" |
| test_gdb_complete_unique \ |
| "$cmd -- -" \ |
| "$cmd -- -" |
| } |
| |
| test_error_cmd2 $cmd " -foo" \ |
| "Undefined command: \"-foo\". Try \"help\"\\." |
| test_gdb_complete_none "$cmd -foo" |
| |
| test_gdb_completion_offers_commands "$cmd -s " |
| } |
| } |
| |
| # Basic option-machinery + "thread apply" command integration tests. |
| proc_with_prefix test-thread-apply {} { |
| global tui_supported_p |
| |
| test_gdb_complete_unique "thread apply all" "thread apply all" |
| test_gdb_complete_unique "taas" "taas" |
| |
| gdb_test "thread apply 1-" \ |
| "inverted range" |
| test_gdb_complete_none "frame apply level 1-" |
| |
| foreach cmd { |
| "thread apply all" |
| "thread apply 1" |
| "taas" |
| } { |
| test_gdb_completion_offers_commands "$cmd " |
| |
| # taas is silent on command error by design. This procedure |
| # hides the difference. EXPECTED_RE is only considered when |
| # not testing with "taas". |
| proc test_invalid_cmd {cmd arg expected_re} { |
| if {$cmd != "taas"} { |
| gdb_test "$cmd$arg" $expected_re |
| } else { |
| gdb_test_no_output "$cmd$arg" |
| } |
| } |
| |
| gdb_test "$cmd -" "Ambiguous option at: -" |
| |
| if {$cmd != "thread apply 1"} { |
| test_gdb_complete_multiple "$cmd " "-" "" { |
| "-ascending" |
| "-c" |
| "-q" |
| "-s" |
| } |
| } else { |
| # "-ascending" only works with "all". |
| test_gdb_complete_multiple "$cmd " "-" "" { |
| "-c" |
| "-q" |
| "-s" |
| } |
| } |
| |
| if {$cmd == "thread apply all" || $cmd == "taas"} { |
| set errmsg \ |
| "Please specify a command at the end of 'thread apply all'" |
| } elseif {$cmd == "thread apply 1"} { |
| set errmsg \ |
| "Please specify a command following the thread ID list" |
| } else { |
| error "unexpected cmd: $cmd" |
| } |
| |
| with_test_prefix "no-trailing-space" { |
| gdb_test "$cmd --" $errmsg |
| test_gdb_complete_unique "$cmd --" "$cmd --" |
| } |
| |
| with_test_prefix "trailing-space" { |
| gdb_test "$cmd -- " $errmsg |
| test_gdb_completion_offers_commands "$cmd -- " |
| } |
| |
| if { $tui_supported_p } { |
| # '-' is a valid TUI command. |
| test_invalid_cmd "$cmd" " -- -" \ |
| "Cannot enable the TUI when output is not a terminal" |
| test_gdb_complete_unique \ |
| "$cmd -- -" \ |
| "$cmd -- -" |
| } |
| |
| test_invalid_cmd $cmd " -foo" \ |
| "Undefined command: \"-foo\". Try \"help\"\\." |
| test_gdb_complete_none "$cmd -foo" |
| |
| test_gdb_completion_offers_commands "$cmd -c " |
| } |
| } |
| |
| # Basic option-machinery + "info threads" command integration tests. |
| proc_with_prefix test-info-threads {} { |
| test_gdb_complete_multiple "info threads " "" "" { |
| "-gid" |
| "ID" |
| } |
| |
| test_gdb_complete_unique \ |
| "info threads -" \ |
| "info threads -gid" |
| |
| # "ID" isn't really something the user can type. |
| test_gdb_complete_none "info threads I" |
| } |
| |
| # Miscellaneous tests. |
| proc_with_prefix test-misc {variant} { |
| global all_options |
| |
| set cmd [make_cmd $variant] |
| |
| # Call test command with no arguments at all. |
| gdb_test "$cmd" [expect_none ""] |
| |
| # Now with a single dash. |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -" [expect_none "-"] |
| } else { |
| gdb_test "$cmd -" "Ambiguous option at: -" |
| } |
| |
| # Completing at "-" should list all options. |
| res_test_gdb_complete_multiple \ |
| "1 [expect_none "-"]" \ |
| "$cmd " "-" "" $all_options |
| |
| # Now with a double dash. |
| gdb_test "$cmd --" [expect_none ""] |
| |
| # "--" is recognized by options completer, gdb auto-appends a |
| # space. |
| test_completer_recognizes \ |
| "1 [expect_none "--"]" \ |
| "$cmd --" |
| |
| # Now with a double dash, plus a dash as operand. |
| gdb_test "$cmd -- -" [expect_none "-"] |
| res_test_gdb_complete_none "0 -" "$cmd -- -" |
| |
| # Completing an unambiguous option just appends an empty space. |
| test_completer_recognizes \ |
| "1 [expect_none "-flag"]" \ |
| "$cmd -flag" |
| |
| # Try running an ambiguous option. |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -xx" [expect_none "-xx"] |
| } else { |
| gdb_test "$cmd -xx" "Ambiguous option at: -xx" |
| } |
| |
| # Check that options are not case insensitive. |
| gdb_test "$cmd -flag --" [expect_flag ""] |
| |
| # Check how the different modes behave on unknown option, with a |
| # delimiter. |
| gdb_test "$cmd -FLAG --" \ |
| "Unrecognized option at: -FLAG --" |
| |
| # Check how the different modes behave on unknown option, without |
| # a delimiter. |
| if {$variant == "unknown-is-error"} { |
| gdb_test "$cmd -FLAG" \ |
| "Unrecognized option at: -FLAG" |
| } else { |
| gdb_test "$cmd -FLAG" [expect_none "-FLAG"] |
| } |
| |
| # Test parsing stops at a negative integer. |
| gdb_test "$cmd -1 --" \ |
| "Unrecognized option at: -1 --" |
| gdb_test "$cmd -2 --" \ |
| "Unrecognized option at: -2 --" |
| } |
| |
| # Flag option tests. |
| proc_with_prefix test-flag {variant} { |
| global all_options |
| |
| set cmd [make_cmd $variant] |
| |
| # Completing a flag just appends a space. |
| test_completer_recognizes \ |
| "1 [expect_none "-flag"]" \ |
| "$cmd -flag" |
| |
| # Add a dash, and all options should be shown. |
| res_test_gdb_complete_multiple \ |
| "1 [expect_flag "-"]" \ |
| "$cmd -flag " "-" "" $all_options |
| |
| # Basic smoke tests of accepted / not accepted values. |
| |
| # Check all the different variants a bool option may be specified. |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -flag 999" [expect_none "-flag 999"] |
| } else { |
| gdb_test "$cmd -flag 999" [expect_flag "999"] |
| } |
| gdb_test "$cmd -flag -- 999" [expect_flag "999"] |
| |
| # If the "--" separator is present, then GDB errors out if the |
| # flag option is passed some value -- check that too. |
| gdb_test "$cmd -flag xxx 999 --" "Unrecognized option at: xxx 999 --" |
| gdb_test "$cmd -flag o 999 --" "Unrecognized option at: o 999 --" |
| gdb_test "$cmd -flag 1 999 --" "Unrecognized option at: 1 999 --" |
| |
| # Extract twice the same flag, separated by one space. |
| gdb_test "$cmd -flag -flag -- non flags args" \ |
| [expect_flag "non flags args"] |
| |
| # Extract twice the same flag, separated by one space. |
| gdb_test "$cmd -xx1 -xx2 -xx1 -xx2 -xx1 -- non flags args" \ |
| "-flag 0 -xx1 1 -xx2 1 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '' -- non flags args" |
| |
| # Extract 2 known flags in front of unknown flags. |
| gdb_test "$cmd -xx1 -xx2 -a -b -c -xx1 --" \ |
| "Unrecognized option at: -a -b -c -xx1 --" |
| |
| # Check that combined flags are not recognised. |
| gdb_test "$cmd -xx1 -xx1xx2 -xx1 --" \ |
| "Unrecognized option at: -xx1xx2 -xx1 --" |
| |
| # Make sure the completer don't confuse a flag option with a |
| # boolean option. Specifically, "o" should not complete to |
| # "on/off". |
| |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_none \ |
| "1 [expect_flag "o"]" \ |
| "$cmd -flag o" |
| |
| gdb_test "$cmd -flag o" [expect_none "-flag o"] |
| } else { |
| res_test_gdb_complete_none "0 o" "$cmd -flag o" |
| |
| gdb_test "$cmd -flag o" [expect_flag "o"] |
| } |
| } |
| |
| # Boolean option tests. |
| proc_with_prefix test-boolean {variant} { |
| global all_options |
| |
| set cmd [make_cmd $variant] |
| |
| # Boolean option's values are optional -- "on" is implied. Check |
| # that: |
| # |
| # - For require-delimiter commands, completing after a boolean |
| # option lists all other options, plus "on/off". This is |
| # because operands won't be processed until we see a "--" |
| # delimiter. |
| # |
| # - For !require-delimiter commands, completing after a boolean |
| # option completes as an operand, since that will tend to be |
| # more common than typing "on/off". |
| # E.g., "frame apply all -past-main COMMAND". |
| |
| if {$variant == "require-delimiter"} { |
| set match_list $all_options |
| lappend match_list "off" "on" |
| res_test_gdb_complete_multiple \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool " "" "" $match_list |
| } else { |
| res_test_gdb_complete_none "0 " "$cmd -bool " |
| } |
| |
| # Add another dash, and "on/off" are no longer offered: |
| res_test_gdb_complete_multiple \ |
| "1 [expect_bool "-"]" \ |
| "$cmd -bool " "-" "" $all_options |
| |
| # Basic smoke tests of accepted / not accepted values. |
| |
| # The command accepts all of "1/0/enable/disable/yes/no" too, even |
| # though like the "set" command, we don't offer those as |
| # completion candidates if you complete right after the boolean |
| # command's name, like: |
| # |
| # (gdb) maint test-options require-delimiter -bool [TAB] |
| # off on |
| # |
| # However, the completer does recognize them if you start typing |
| # the boolean value. |
| foreach value {"0" "1"} { |
| test_completer_recognizes \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool $value" |
| } |
| foreach value {"of" "off"} { |
| res_test_gdb_complete_unique \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool $value" \ |
| "$cmd -bool off" |
| } |
| foreach value {"y" "ye" "yes"} { |
| res_test_gdb_complete_unique \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool $value" \ |
| "$cmd -bool yes" |
| } |
| foreach value {"n" "no"} { |
| res_test_gdb_complete_unique \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool $value" \ |
| "$cmd -bool no" |
| } |
| foreach value { |
| "e" |
| "en" |
| "ena" |
| "enab" |
| "enabl" |
| "enable" |
| } { |
| res_test_gdb_complete_unique \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool $value" \ |
| "$cmd -bool enable" |
| } |
| foreach value { |
| "d" |
| "di" |
| "dis" |
| "disa" |
| "disab" |
| "disabl" |
| "disable" |
| } { |
| res_test_gdb_complete_unique \ |
| "1 [expect_none ""]" \ |
| "$cmd -bool $value" \ |
| "$cmd -bool disable" |
| } |
| |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_none \ |
| "1 [expect_none "xxx"]" \ |
| "$cmd -bool xxx" |
| } else { |
| res_test_gdb_complete_none "0 xxx" "$cmd -bool xxx" |
| } |
| |
| # The command accepts abbreviations of "enable/disable/yes/no", |
| # even though we don't offer those for completion. |
| foreach value { |
| "1" |
| "y" "ye" "yes" |
| "e" |
| "en" |
| "ena" |
| "enab" |
| "enabl" |
| "enable"} { |
| gdb_test "$cmd -bool $value --" [expect_bool ""] |
| } |
| foreach value { |
| "0" |
| "of" "off" |
| "n" "no" |
| "d" |
| "di" |
| "dis" |
| "disa" |
| "disab" |
| "disabl" |
| "disable"} { |
| gdb_test "$cmd -bool $value --" [expect_none ""] |
| } |
| |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -bool 999" [expect_none "-bool 999"] |
| } else { |
| gdb_test "$cmd -bool 999" [expect_bool "999"] |
| } |
| gdb_test "$cmd -bool -- 999" [expect_bool "999"] |
| |
| # Since "on" is implied after a boolean option, for |
| # !require-delimiter commands, anything that is not |
| # yes/no/1/0/on/off/enable/disable should be considered as the raw |
| # input after the last option. Also check "o", which might look |
| # like "on" or "off", but it's treated the same. |
| |
| foreach arg {"xxx" "o"} { |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -bool $arg" [expect_none "-bool $arg"] |
| } else { |
| gdb_test "$cmd -bool $arg" [expect_bool "$arg"] |
| } |
| } |
| # Also try -1. "unknown-is-error" commands error out saying that |
| # that's not a valid option. |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -bool -1" \ |
| [expect_none "-bool -1"] |
| } elseif {$variant == "unknown-is-error"} { |
| gdb_test "$cmd -bool -1" \ |
| "Unrecognized option at: -1" |
| } else { |
| gdb_test "$cmd -bool -1" [expect_bool "-1"] |
| } |
| |
| # OTOH, if the "--" separator is present, then GDB errors out if |
| # the boolean option is passed an invalid value -- check that too. |
| gdb_test "$cmd -bool -1 999 --" \ |
| "Unrecognized option at: -1 999 --" |
| gdb_test "$cmd -bool xxx 999 --" \ |
| "Value given for `-bool' is not a boolean: xxx" |
| gdb_test "$cmd -bool o 999 --" \ |
| "Value given for `-bool' is not a boolean: o" |
| |
| # Completing after a boolean option + "o" does list "on/off", |
| # though. |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_multiple \ |
| "1 [expect_none "o"]" \ |
| "$cmd -bool " "o" "" { |
| "off" |
| "on" |
| } |
| } else { |
| res_test_gdb_complete_multiple "0 o" "$cmd -bool " "o" "" { |
| "off" |
| "on" |
| } |
| } |
| } |
| |
| # Uinteger option tests. OPTION is which integer option we're |
| # testing. Can be "uinteger" or "zuinteger-unlimited". |
| proc_with_prefix test-uinteger {variant option} { |
| global all_options |
| |
| set cmd "[make_cmd $variant] -$option" |
| |
| # Test completing a uinteger option: |
| res_test_gdb_complete_multiple \ |
| "1 [expect_none ""]" \ |
| "$cmd " "" "" { |
| "NUMBER" |
| "unlimited" |
| } |
| |
| # NUMBER above is just a placeholder, make sure we don't complete |
| # it as a valid option. |
| res_test_gdb_complete_none \ |
| "1 [expect_none "NU"]" \ |
| "$cmd NU" |
| |
| # "unlimited" is valid though. |
| res_test_gdb_complete_unique \ |
| "1 [expect_none "u"]" \ |
| "$cmd u" \ |
| "$cmd unlimited" |
| |
| # Basic smoke test of accepted / not accepted values. |
| gdb_test "$cmd 1 -- 999" [expect_integer $option "1" "999"] |
| gdb_test "$cmd unlimited -- 999" \ |
| [expect_integer $option "unlimited" "999"] |
| if {$option == "zuinteger-unlimited"} { |
| gdb_test "$cmd -1 --" [expect_integer $option "unlimited" ""] |
| gdb_test "$cmd 0 --" [expect_integer $option "0" ""] |
| } else { |
| gdb_test "$cmd -1 --" "integer -1 out of range" |
| gdb_test "$cmd 0 --" [expect_integer $option "unlimited" ""] |
| } |
| gdb_test "$cmd xxx --" \ |
| "Expected integer at: xxx --" |
| gdb_test "$cmd unlimitedx --" \ |
| "Expected integer at: unlimitedx --" |
| |
| # Don't offer completions until we're past the |
| # -uinteger/-zuinteger-unlimited argument. |
| res_test_gdb_complete_none \ |
| "1 [expect_none ""]" \ |
| "$cmd 1" |
| |
| # A number of invalid values. |
| foreach value {"x" "x " "1a" "1a " "1-" "1- " "unlimitedx"} { |
| res_test_gdb_complete_none \ |
| "1 [expect_none $value]" \ |
| "$cmd $value" |
| } |
| |
| # Try "-1". |
| if {$option == "uinteger"} { |
| # -1 is invalid uinteger. |
| foreach value {"-1" "-1 "} { |
| res_test_gdb_complete_none \ |
| "1 [expect_none ""]" \ |
| "$cmd $value" |
| } |
| } else { |
| # -1 is valid for zuinteger-unlimited. |
| res_test_gdb_complete_none \ |
| "1 [expect_none ""]" \ |
| "$cmd -1" |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_multiple \ |
| "1 [expect_integer $option "unlimited" ""]" \ |
| "$cmd -1 " "" "-" $all_options |
| } else { |
| res_test_gdb_complete_none "0 " "$cmd -1 " |
| } |
| } |
| |
| # Check that after a fully parsed option: |
| # |
| # - for require-delimiter commands, completion offers all |
| # options. |
| # |
| # - for !require-delimiter commands, completion offers nothing |
| # and returns false. |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_multiple \ |
| "1 [expect_integer $option 1 ""]" \ |
| "$cmd 1 " "" "-" $all_options |
| } else { |
| res_test_gdb_complete_none "0 " "$cmd 1 " |
| } |
| |
| # Test completing non-option arguments after "-uinteger 1 ". |
| foreach operand {"x" "x " "1a" "1a " "1-" "1- "} { |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_none \ |
| "1 [expect_integer $option 1 $operand]" \ |
| "$cmd 1 $operand" |
| } else { |
| res_test_gdb_complete_none "0 $operand" "$cmd 1 $operand" |
| } |
| } |
| # These look like options, but they aren't. |
| foreach operand {"-1" "-1 "} { |
| if {$variant == "unknown-is-operand"} { |
| res_test_gdb_complete_none "0 $operand" "$cmd 1 $operand" |
| } else { |
| res_test_gdb_complete_none \ |
| "1 [expect_integer $option 1 $operand]" \ |
| "$cmd 1 $operand" |
| } |
| } |
| } |
| |
| # Enum option tests. |
| proc_with_prefix test-enum {variant} { |
| set cmd [make_cmd $variant] |
| |
| res_test_gdb_complete_multiple \ |
| "1 [expect_none ""]" \ |
| "$cmd -enum " "" "" { |
| "xxx" |
| "yyy" |
| "zzz" |
| } |
| |
| # Check that "-" where a value is expected does not show the |
| # command's options. I.e., an enum's value is not optional. |
| # Check both completion and running the command. |
| res_test_gdb_complete_none \ |
| "1 [expect_none "-"]" \ |
| "$cmd -enum -" |
| gdb_test "$cmd -enum --"\ |
| "Requires an argument. Valid arguments are xxx, yyy, zzz\\." |
| |
| # Try passing an undefined item to an enum option. |
| gdb_test "$cmd -enum www --" "Undefined item: \"www\"." |
| } |
| |
| # String option tests. |
| proc_with_prefix test-string {variant} { |
| global all_options |
| |
| set cmd [make_cmd $variant] |
| |
| res_test_gdb_complete_none \ |
| "1 [expect_none ""]" \ |
| "$cmd -string " |
| |
| # Check that "-" where a value is expected does not show the |
| # command's options. I.e., a string's value is not optional. |
| # Check both completion and running the command. |
| res_test_gdb_complete_none \ |
| "1 [expect_none ""]" \ |
| "$cmd -string -" |
| gdb_test "$cmd -string --"\ |
| "-string requires an argument" |
| if {$variant == "require-delimiter"} { |
| gdb_test "$cmd -string" [expect_none "-string"] |
| } else { |
| gdb_test "$cmd -string"\ |
| "-string requires an argument" |
| } |
| |
| foreach_with_prefix str { |
| "STR" |
| "\"STR\"" |
| "\\\"STR" |
| "'STR'" |
| "\\'STR" |
| "\"STR AAA\"" |
| "'STR BBB'" |
| "\"STR 'CCC' DDD\"" |
| "'STR \"EEE\" FFF'" |
| "\"STR \\\"GGG\\\" HHH\"" |
| "'STR \\\'III\\\' JJJ'" |
| } { |
| res_test_gdb_complete_none \ |
| "1 [expect_none ""]" \ |
| "$cmd -string ${str}" |
| gdb_test "$cmd -string ${str} --" [expect_string "${str}" ""] |
| |
| # Completing at "-" after parsing STR should list all options. |
| res_test_gdb_complete_multiple \ |
| "1 [expect_string "${str}" "-"]" \ |
| "$cmd -string ${str} " "-" "" $all_options |
| |
| # Check that only $STR is considered part of the string's value. |
| # I.e., that we stop parsing the string at the first |
| # whitespace or after the closing quote of $STR. |
| if {$variant == "require-delimiter"} { |
| res_test_gdb_complete_none \ |
| "1 [expect_string "${str}" "BAR"]" \ |
| "$cmd -string ${str} BAR" |
| } else { |
| res_test_gdb_complete_none "0 BAR" "$cmd -string ${str} BAR" |
| } |
| gdb_test "$cmd -string ${str} BAR --" "Unrecognized option at: BAR --" |
| } |
| } |
| |
| # Run the options framework tests first. |
| foreach_with_prefix cmd { |
| "require-delimiter" |
| "unknown-is-error" |
| "unknown-is-operand" |
| } { |
| test-misc $cmd |
| test-flag $cmd |
| test-boolean $cmd |
| foreach subcmd {"uinteger" "zuinteger-unlimited" } { |
| test-uinteger $cmd $subcmd |
| } |
| test-enum $cmd |
| test-string $cmd |
| } |
| |
| # Run the print integration tests, both as "standalone", and under |
| # "frame/thread apply". The latter checks that the "frame/thread |
| # apply ... COMMAND" commands recurse the completion machinery for |
| # COMMAND completion correctly. |
| foreach prefix { |
| "" |
| "frame apply all " |
| "frame apply 1 " |
| "frame apply level 0 " |
| "thread apply all " |
| "thread apply 1 " |
| "thread apply 1 frame apply 1 " |
| } { |
| test-print $prefix |
| } |
| |
| # Same for "compile print". Not really a wrapper prefix command like |
| # "frame apply", but similar enough that we test pretty much the same |
| # things. |
| if ![skip_compile_feature_tests] { |
| test-print "compile " |
| } |
| |
| # Basic "backtrace" integration tests. |
| test-backtrace |
| |
| # Basic "frame apply" integration tests. |
| test-frame-apply |
| |
| # Basic "thread apply" integration tests. |
| test-thread-apply |
| |
| # Basic "info threads" integration tests. |
| test-info-threads |