# This testcase is part of GDB, the GNU debugger. # Copyright 2019-2023 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 . # 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 compile-support.exp 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 [allow_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-unl 0 -pint-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-unl 0 -pint-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-unl 0 -pint-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-unlimited"} { return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl $val\ -pint-unl 0 -string '' -- $operand" } elseif {$option == "pinteger-unlimited"} { return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl 0\ -pint-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-unl 0 -pint-unl 0\ -string '$str' -- $operand" } set all_options { "-bool" "-enum" "-flag" "-pinteger-unlimited" "-string" "-uinteger-unlimited" "-xx1" "-xx2" } # 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" "-characters" "-elements" "-max-depth" "-memory-tag-violations" "-nibbles" "-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-unl 0 -pint-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-unlimited" or "pinteger-unlimited". proc_with_prefix test-uinteger {variant option} { global all_options set cmd "[make_cmd $variant] -$option" # Test completing an integer 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 == "pinteger-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-unlimited/-pinteger-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-unlimited"} { # -1 is invalid uinteger-unlimited. foreach value {"-1" "-1 "} { res_test_gdb_complete_none \ "1 [expect_none ""]" \ "$cmd $value" } } else { # -1 is valid for pinteger-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-unlimited 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-unlimited" "pinteger-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