aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.python
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.python')
-rw-r--r--gdb/testsuite/gdb.python/py-cmd.exp85
-rw-r--r--gdb/testsuite/gdb.python/py-color.exp12
-rw-r--r--gdb/testsuite/gdb.python/py-parameter-prefix.exp382
-rw-r--r--gdb/testsuite/gdb.python/py-parameter.exp187
-rw-r--r--gdb/testsuite/gdb.python/py-source-styling-2.exp24
-rw-r--r--gdb/testsuite/gdb.python/py-symbol.exp1
-rw-r--r--gdb/testsuite/gdb.python/py-warning.exp63
7 files changed, 739 insertions, 15 deletions
diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index f76c176..5ac5712 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -328,4 +328,89 @@ proc_with_prefix test_command_redefining_itself {} {
"call command redefining itself 2"
}
+# Try to create commands using unknown prefixes and check GDB gives an
+# error. There's also a test in here for an ambiguous prefix, which
+# gives the same error.
+proc_with_prefix test_unknown_prefix {} {
+ clean_restart
+
+ gdb_test_no_output "python gdb.Command('foo1', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('foo cmd', gdb.COMMAND_NONE)"
+
+ foreach prefix { "xxx" "foo xxx" "foo1 xxx" } {
+ gdb_test "python gdb.Command('$prefix cmd', gdb.COMMAND_NONE)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+
+ gdb_test_no_output "python gdb.Command('foo2', gdb.COMMAND_NONE, prefix=True)"
+
+ foreach prefix { "foo" "foo xxx" "foo1 xxx" "foo2 xxx" } {
+ gdb_test "python gdb.Command('$prefix cmd2', gdb.COMMAND_NONE)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+}
+
+# Check what happens if a command object is called without an 'invoke'
+# method.
+proc_with_prefix test_deleting_invoke_methods {} {
+ clean_restart
+
+ gdb_test_multiline "create 'foo' prefix command" \
+ "python" "" \
+ "class test_prefix(gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super().__init__ (\"foo\", gdb.COMMAND_USER, prefix=True)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print(\"In 'foo' invoke: %s\" % arg)" "" \
+ "foo = test_prefix()" "" \
+ "end" ""
+
+ gdb_test_multiline "create 'foo bar' command" \
+ "python" "" \
+ "class test_cmd(gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super().__init__ (\"foo bar\", gdb.COMMAND_USER)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print(\"In 'foo bar' invoke: %s\" % arg)" "" \
+ "foo_bar = test_cmd()" "" \
+ "end" ""
+
+ gdb_test "foo def" "In 'foo' invoke: def" \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" "In 'foo bar' invoke: def" \
+ "call 'foo bar' with arguments"
+
+ gdb_test_no_output "python del(foo_bar.__class__.invoke)" \
+ "delete invoke from test_cmd class"
+
+ with_test_prefix "after deleting test_cmd.invoke" {
+ gdb_test "foo def" "In 'foo' invoke: def" \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo bar' with arguments"
+ }
+
+ gdb_test_no_output "python del(foo.__class__.invoke)" \
+ "delete invoke from test_prefix class"
+
+ with_test_prefix "after deleting test_prefix.invoke" {
+ gdb_test "foo def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo bar' with arguments"
+ }
+}
+
test_command_redefining_itself
+test_unknown_prefix
+test_deleting_invoke_methods
diff --git a/gdb/testsuite/gdb.python/py-color.exp b/gdb/testsuite/gdb.python/py-color.exp
index 3563d22..2601cf3 100644
--- a/gdb/testsuite/gdb.python/py-color.exp
+++ b/gdb/testsuite/gdb.python/py-color.exp
@@ -19,8 +19,10 @@ load_lib gdb-python.exp
require allow_python_tests
-# Start with a fresh gdb.
-clean_restart
+# Start with a fresh GDB, but enable color support.
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_test_no_output "python get_color_attrs = lambda c: \"%s %s %s %s %s\" % (str(c), c.colorspace, c.is_none, c.is_indexed, c.is_direct)" \
"get_color_attrs helper"
@@ -115,6 +117,12 @@ gdb_test [concat "python print (c_red.escape_sequence (is_foreground = True) + "
"\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \
"escape sequences using keyword arguments"
+# Ensure that turning styling off means no escape sequences.
+gdb_test_no_output "set style enabled off"
+gdb_test_no_output "python print (c_red.escape_sequence (True), end='')"
+gdb_test_no_output "python print (c_red.escape_sequence (False), end='')"
+gdb_test_no_output "set style enabled on"
+
gdb_test_multiline "Try to sub-class gdb.Color" \
"python" "" \
"class my_color(gdb.Color):" "" \
diff --git a/gdb/testsuite/gdb.python/py-parameter-prefix.exp b/gdb/testsuite/gdb.python/py-parameter-prefix.exp
new file mode 100644
index 0000000..eb09fe7
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-parameter-prefix.exp
@@ -0,0 +1,382 @@
+# Copyright (C) 2025 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/>.
+
+# This file is part of the GDB testsuite. It tests
+# gdb.ParameterPrefix. See each of the test procs for a full
+# description of what is being tested.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+clean_restart
+
+# Helper proc to generate the output of 'show PREFIX' commands for the
+# case where the prefix command doesn't handle unknown sub-commands.
+# In this case GDB will list the value of every sub-command under
+# PREFIX.
+proc make_show_prefix_re { prefix } {
+ return "$prefix param-1:\\s+The current value of '$prefix param-1' is \"off\"\\."
+}
+
+# Helper proc to generate the help text that describes all of the sub
+# commands under PREFIX. The MODE is either 'set' or 'show'. This
+# output will appear for 'help MODE PREFIX' and also for 'set PREFIX'.
+proc make_sub_cmd_help_re { mode prefix } {
+ if { $mode == "set" } {
+ set word "Set"
+ } else {
+ set word "Show"
+ }
+
+ return \
+ [multi_line \
+ "List of \"$mode $prefix\" subcommands:" \
+ "" \
+ "$mode $prefix param-1 -- $word the current value of '$prefix param-1'\\." \
+ "" \
+ "Type \"help $mode $prefix\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."]
+}
+
+# Helper proc to generate the output of 'help MODE PREFIX', where MODE
+# will be either 'set' or 'show'. The HELP_TEXT is the expected help
+# text for this prefix command, this should not be a regexp, as this
+# proc converts the text to a regexp.
+#
+# Return a single regexp which should match the output.
+proc make_help_re { mode prefix help_text } {
+ set help_re [string_to_regexp $help_text]
+
+ return \
+ [multi_line \
+ "$help_re" \
+ "" \
+ [make_sub_cmd_help_re $mode $prefix]]
+}
+
+# Create gdb.ParameterPrefix without using a sub-class, both with, and
+# without a doc string. For the doc string case, test single line,
+# and multi-line doc strings.
+proc_with_prefix test_basic_usage {} {
+ gdb_test_multiline "some basic ParameterPrefix usage" \
+ "python" "" \
+ "gdb.ParameterPrefix('prefix-1', gdb.COMMAND_NONE)" "" \
+ "gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.ParameterPrefix('prefix-2', gdb.COMMAND_NONE," "" \
+ " \"\"\"This is prefix-2 help string.\"\"\")" "" \
+ "gdb.Parameter('prefix-2 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.ParameterPrefix('prefix-3', gdb.COMMAND_NONE," "" \
+ " \"\"\"This is prefix-3 help string." "" \
+ " " "" \
+ " This help text spans multiple lines.\"\"\")" "" \
+ "gdb.Parameter('prefix-3 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ foreach mode { "set" "show" } {
+ gdb_test "help $mode prefix-1" \
+ [make_help_re $mode "prefix-1" \
+ "This command is not documented."]
+
+ gdb_test "help $mode prefix-2" \
+ [make_help_re $mode "prefix-2" \
+ "This is prefix-2 help string."]
+
+ gdb_test "help $mode prefix-3" \
+ [make_help_re $mode "prefix-3" \
+ [multi_line \
+ "This is prefix-3 help string." \
+ "" \
+ "This help text spans multiple lines."]]
+
+ foreach prefix { prefix-1 prefix-2 prefix-3 } {
+ gdb_test "$mode $prefix xxx" \
+ "^Undefined $mode $prefix command: \"xxx\"\\. Try \"help $mode $prefix\"\\."
+ }
+ }
+
+ foreach prefix { prefix-1 prefix-2 prefix-3 } {
+ gdb_test "set $prefix" \
+ [make_sub_cmd_help_re "set" $prefix]
+
+ gdb_test "show $prefix" \
+ [make_show_prefix_re $prefix]
+ }
+}
+
+# Create a sub-class of gdb.ParameterPrefix, but don't do anything
+# particularly interesting. Again test the with and without
+# documentation string cases.
+proc_with_prefix test_simple_sub_class {} {
+ gdb_test_multiline "some basic ParameterPrefix usage" \
+ "python" "" \
+ "class BasicParamPrefix(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefix('prefix-4')" "" \
+ "gdb.Parameter('prefix-4 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithSingleLineDoc(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is a single line doc string.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefixWithSingleLineDoc('prefix-5')" "" \
+ "gdb.Parameter('prefix-5 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithMultiLineDoc(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is a multi line doc string." "" \
+ " " "" \
+ " The rest of the doc string is here.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefixWithMultiLineDoc('prefix-6')" "" \
+ "gdb.Parameter('prefix-6 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithDocParameter(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is an unsused doc string.\"\"\"" "" \
+ " def __init__(self, name, doc):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE, doc)" "" \
+ "BasicParamPrefixWithDocParameter('prefix-7'," "" \
+ " \"\"\"The doc string text is here.\"\"\")" "" \
+ "gdb.Parameter('prefix-7 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ foreach mode { "set" "show" } {
+ gdb_test "help $mode prefix-4" \
+ [make_help_re $mode "prefix-4" \
+ "This command is not documented."]
+
+ gdb_test "help $mode prefix-5" \
+ [make_help_re $mode "prefix-5" \
+ "This is a single line doc string."]
+
+ gdb_test "help $mode prefix-6" \
+ [make_help_re $mode "prefix-6" \
+ [multi_line \
+ "This is a multi line doc string." \
+ "" \
+ "The rest of the doc string is here."]]
+
+ gdb_test "help $mode prefix-7" \
+ [make_help_re $mode "prefix-7" \
+ "The doc string text is here."]
+
+ foreach prefix { prefix-4 prefix-5 prefix-6 prefix-7 } {
+ gdb_test "$mode $prefix xxx" \
+ "^Undefined $mode $prefix command: \"xxx\"\\. Try \"help $mode $prefix\"\\."
+ }
+ }
+
+ foreach prefix { prefix-4 prefix-5 prefix-6 prefix-7 } {
+ gdb_test "set $prefix" \
+ [make_sub_cmd_help_re "set" $prefix]
+
+ gdb_test "show $prefix" \
+ [make_show_prefix_re $prefix]
+ }
+}
+
+# Create a sub-class of gdb.ParameterPrefix, and make use of
+# 'invoke_set' and 'invoke_show'. Test that the invoke method is
+# executed when expected, and that, by default, these invoke methods
+# repeat when the user issues an empty command.
+proc_with_prefix test_prefix_with_invoke {} {
+ gdb_test_multiline "ParameterPrefix with invoke_set" \
+ "python" "" \
+ "class PrefixWithInvokeSet(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set (a): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeSet('prefix-8')" "" \
+ "gdb.Parameter('prefix-8 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithInvokeShow(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show (b): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeShow('prefix-9')" "" \
+ "gdb.Parameter('prefix-9 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithBothInvoke(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set (c): \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show (d): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithBothInvoke('prefix-10')" "" \
+ "gdb.Parameter('prefix-10 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ gdb_test "set prefix-8 xxx yyy" \
+ "^invoke_set \\(a\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set \\(a\\): \"xxx yyy\" True" \
+ "repeat set prefix-8 xxx yyy"
+
+ gdb_test "show prefix-8 xxx yyy" \
+ "^Undefined show prefix-8 command: \"xxx yyy\"\\. Try \"help show prefix-8\"\\."
+
+ gdb_test "set prefix-9 xxx yyy" \
+ "^Undefined set prefix-9 command: \"xxx yyy\"\\. Try \"help set prefix-9\"\\."
+
+ gdb_test "show prefix-9 xxx yyy" \
+ "^invoke_show \\(b\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_show \\(b\\): \"xxx yyy\" True" \
+ "repeat show prefix-9 xxx yyy"
+
+ gdb_test "set prefix-10 xxx yyy" \
+ "^invoke_set \\(c\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set \\(c\\): \"xxx yyy\" True" \
+ "repeat set prefix-10 xxx yyy"
+
+ gdb_test "show prefix-10 xxx yyy" \
+ "^invoke_show \\(d\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_show \\(d\\): \"xxx yyy\" True" \
+ "repeat show prefix-10 xxx yyy"
+
+ gdb_test "set prefix-8" \
+ "^invoke_set \\(a\\): \"\" True"
+
+ gdb_test "show prefix-8" \
+ [make_show_prefix_re "prefix-8"]
+
+ gdb_test "set prefix-9" \
+ [make_sub_cmd_help_re "set" "prefix-9"]
+
+ gdb_test "show prefix-9" \
+ "^invoke_show \\(b\\): \"\" True"
+
+ gdb_test "set prefix-10" \
+ "^invoke_set \\(c\\): \"\" True"
+
+ gdb_test "show prefix-10" \
+ "^invoke_show \\(d\\): \"\" True"
+}
+
+# Create ParameterPrefix sub-classes that make use of the
+# dont_repeat() method. Check that the relevant set/show invoke
+# callback doesn't repeat when an empty command is used.
+proc_with_prefix test_dont_repeat {} {
+ gdb_test_multiline "ParameterPrefix with invoke_set and dont_repeat" \
+ "python" "" \
+ "class PrefixWithInvokeAndDoNotRepeatSet(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " self.dont_repeat()" "" \
+ " print(f\"invoke_set: \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show: \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeAndDoNotRepeatSet('prefix-11')" "" \
+ "gdb.Parameter('prefix-11 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithInvokeAndDoNotRepeatShow(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set: \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " self.dont_repeat()" "" \
+ " print(f\"invoke_show: \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeAndDoNotRepeatShow('prefix-12')" "" \
+ "gdb.Parameter('prefix-12 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ gdb_test "set prefix-11 xxx yyy" \
+ "^invoke_set: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^" \
+ "repeat set prefix-11 xxx yyy"
+
+ gdb_test "show prefix-11 xxx yyy" \
+ "^invoke_show: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "invoke_show: \"xxx yyy\" True" \
+ "repeat show prefix-11 xxx yyy"
+
+ gdb_test "set prefix-12 xxx yyy" \
+ "^invoke_set: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set: \"xxx yyy\" True" \
+ "repeat set prefix-12 xxx yyy"
+
+ gdb_test "show prefix-12 xxx yyy" \
+ "^invoke_show: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^" \
+ "repeat show prefix-12 xxx yyy"
+}
+
+# Create a parameter prefixm, and immediately add another prefix under
+# the first. The important thing here is that the second prefix is
+# created into an otherwise empty prefix as this triggered a bug at
+# one point.
+proc_with_prefix test_nested {} {
+ gdb_test_multiline "Create nested parameter prefixes" \
+ "python" "" \
+ "gdb.ParameterPrefix('prefix-13', gdb.COMMAND_NONE)" "" \
+ "gdb.ParameterPrefix('prefix-13 prefix-14', gdb.COMMAND_NONE)" "" \
+ "gdb.Parameter('prefix-13 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 param-2', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 prefix-14 param-3', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 prefix-14 param-4', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end" ""
+
+ gdb_test "show prefix-13 prefix-14" \
+ [multi_line \
+ "^prefix-13 prefix-14 param-3: The current value of 'prefix-13 prefix-14 param-3' is \"off\"\\." \
+ "prefix-13 prefix-14 param-4: The current value of 'prefix-13 prefix-14 param-4' is \"off\"\\."]
+
+ gdb_test "show prefix-13" \
+ [multi_line \
+ "^prefix-13 param-1: The current value of 'prefix-13 param-1' is \"off\"\\." \
+ "prefix-13 param-2: The current value of 'prefix-13 param-2' is \"off\"\\." \
+ "prefix-13 prefix-14 param-3: The current value of 'prefix-13 prefix-14 param-3' is \"off\"\\." \
+ "prefix-13 prefix-14 param-4: The current value of 'prefix-13 prefix-14 param-4' is \"off\"\\."]
+
+ gdb_test "set prefix-13 prefix-14" \
+ [multi_line \
+ "" \
+ "set prefix-13 prefix-14 param-3 -- Set the current value of 'prefix-13 prefix-14 param-3'\\." \
+ "set prefix-13 prefix-14 param-4 -- Set the current value of 'prefix-13 prefix-14 param-4'\\." \
+ "" \
+ ".*"]
+
+ gdb_test "set prefix-13" \
+ [multi_line \
+ "" \
+ "set prefix-13 param-1 -- Set the current value of 'prefix-13 param-1'\\." \
+ "set prefix-13 param-2 -- Set the current value of 'prefix-13 param-2'\\." \
+ "set prefix-13 prefix-14 -- This command is not documented\\." \
+ "" \
+ ".*"]
+}
+
+test_basic_usage
+test_simple_sub_class
+test_prefix_with_invoke
+test_dont_repeat
+test_nested
diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
index c15bef1..214c570 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -346,6 +346,91 @@ proc_with_prefix test_really_undocumented_parameter { } {
"test general help"
}
+# Test a parameter in which the __doc__ string is empty or None.
+proc_with_prefix test_empty_doc_parameter {} {
+ gdb_test_multiline "empty __doc__ parameter" \
+ "python" "" \
+ "class EmptyDocParam(gdb.Parameter):" "" \
+ " __doc__ = \"\"" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_empty_doc_param = EmptyDocParam('print test-empty-doc-param')" ""\
+ "end"
+
+ # Setting the __doc__ string to empty means GDB will completely
+ # elide it from the output.
+ gdb_test "help set print test-empty-doc-param" \
+ "^Set the current value of 'print test-empty-doc-param'\\."
+
+ gdb_test_multiline "None __doc__ parameter" \
+ "python" "" \
+ "class NoneDocParam(gdb.Parameter):" "" \
+ " __doc__ = None" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_none_doc_param = NoneDocParam('print test-none-doc-param')" ""\
+ "end"
+
+ # Setting the __doc__ string to None, or anything else that isn't
+ # a string, causes GDB to use a default string instead.
+ gdb_test "help set print test-none-doc-param" \
+ [multi_line \
+ "^Set the current value of 'print test-none-doc-param'\\." \
+ "This command is not documented\\."]
+}
+
+# Test a parameter in which the set_doc/show_doc strings are either
+# empty, or None.
+proc_with_prefix test_empty_set_show_doc_parameter {} {
+ gdb_test_multiline "empty set/show doc parameter" \
+ "python" "" \
+ "class EmptySetShowParam(gdb.Parameter):" "" \
+ " set_doc = \"\"" "" \
+ " show_doc = \"\"" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_empty_set_show_param = EmptySetShowParam('print test-empty-set-show-param')" ""\
+ "end"
+
+ # Setting the set_doc/show_doc string to empty means GDB will use
+ # a suitable default string.
+ gdb_test "help set print test-empty-set-show-param" \
+ [multi_line \
+ "^Set the current value of 'print test-empty-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test "help show print test-empty-set-show-param" \
+ [multi_line \
+ "^Show the current value of 'print test-empty-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test_multiline "None set/show doc parameter" \
+ "python" "" \
+ "class NoneSetShowParam(gdb.Parameter):" "" \
+ " set_doc = None" "" \
+ " show_doc = None" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_none_set_show_param = NoneSetShowParam('print test-none-set-show-param')" ""\
+ "end"
+
+ # Setting the set_doc/show_doc string to None (or any non-string
+ # value) means GDB will use a suitable default string.
+ gdb_test "help set print test-none-set-show-param" \
+ [multi_line \
+ "^Set the current value of 'print test-none-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test "help show print test-none-set-show-param" \
+ [multi_line \
+ "^Show the current value of 'print test-none-set-show-param'\\." \
+ "This command is not documented\\."]
+}
+
# Test deprecated API. Do not use in your own implementations.
proc_with_prefix test_deprecated_api_parameter { } {
clean_restart
@@ -669,6 +754,104 @@ proc_with_prefix test_ambiguous_parameter {} {
"Parameter .* is ambiguous.*Error occurred in Python.*"
gdb_test "python print(gdb.parameter('test-ambiguous-value-1a'))" \
"Could not find parameter.*Error occurred in Python.*"
+
+ # Create command prefixs 'set foo1' and 'show foo1'.
+ gdb_test_no_output "python gdb.Command('set foo1', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('show foo1', gdb.COMMAND_NONE, prefix=True)"
+
+ # Create a parameter under 'foo1', but use a truncated prefix. At
+ # this point though, the prefix is not ambiguous.
+ gdb_test_no_output "python gdb.Parameter('foo bar', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)"
+ gdb_test "python print(gdb.parameter('foo1 bar'))" "False"
+
+ # Create another prefix command, similar in name to the first.
+ gdb_test_no_output "python gdb.Command('set foo2', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('show foo2', gdb.COMMAND_NONE, prefix=True)"
+
+ # An attempt to create a parameter using an ambiguous prefix will give an error.
+ gdb_test "python gdb.Parameter('foo baz', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix foo\\." \
+ "Error occurred in Python: Could not find command prefix foo\\."]
+}
+
+# Check that creating a gdb.Parameter with an unknown command prefix results in an error.
+proc_with_prefix test_unknown_prefix {} {
+ gdb_test_multiline "create parameter" \
+ "python" "" \
+ "class UnknownPrefixParam(gdb.Parameter):" "" \
+ " def __init__ (self, name):" "" \
+ " super().__init__ (name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "end"
+
+ foreach prefix { "unknown-prefix" "style unknown-prefix" "style disassembler unknown-prefix"} {
+ gdb_test "python UnknownPrefixParam('$prefix new-param')" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+}
+
+# Test the default behaviour of a set/show parameter prefix command.
+proc_with_prefix test_set_show_parameters {} {
+ # This first set/show prefix command doesn't have an invoke
+ # method. As such, GDB installs the default invoke behaviour; set
+ # prints the full list of sub-commands, and show prints all the
+ # sub-command values.
+ gdb_test_multiline "Setup set/show parameter prefix with no invoke" \
+ "python" "" \
+ "class TestParamPrefix(gdb.Command):" "" \
+ " \"\"\"TestParamPrefix documentation string.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE, prefix = True)" "" \
+ "TestParamPrefix('set test-prefix')" "" \
+ "TestParamPrefix('show test-prefix')" "" \
+ "gdb.Parameter('test-prefix param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('test-prefix param-2', gdb.COMMAND_NONE, gdb.PARAM_INTEGER)" "" \
+ "gdb.Parameter('test-prefix param-3', gdb.COMMAND_NONE, gdb.PARAM_STRING)" "" \
+ "end"
+
+ gdb_test "set test-prefix" \
+ [multi_line \
+ "List of \"set test-prefix\" subcommands:" \
+ "" \
+ "set test-prefix param-1 -- Set the current value of 'test-prefix param-1'." \
+ "set test-prefix param-2 -- Set the current value of 'test-prefix param-2'." \
+ "set test-prefix param-3 -- Set the current value of 'test-prefix param-3'." \
+ "" \
+ "Type \"help set test-prefix\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."]
+
+ gdb_test "show test-prefix" \
+ [multi_line \
+ "test-prefix param-1: The current value of 'test-prefix param-1' is \"off\"\\." \
+ "test-prefix param-2: The current value of 'test-prefix param-2' is \"0\"\\." \
+ "test-prefix param-3: The current value of 'test-prefix param-3' is \"\"\\."]
+
+ # This next set/show prefix has an invoke method, which will be
+ # called instead of the default behaviour tested above.
+ gdb_test_multiline "Setup set/show parameter prefix with invoke" \
+ "python" "" \
+ "class TestParamPrefix(gdb.Command):" "" \
+ " \"\"\"TestParamPrefix documentation string.\"\"\"" "" \
+ " def __init__(self, name, mode):" "" \
+ " self._mode = mode" "" \
+ " super().__init__(self._mode + ' ' + name, gdb.COMMAND_NONE, prefix = True)" "" \
+ " def invoke(self, args, from_tty):" "" \
+ " print('invoke -- ' + self._mode)" "" \
+ "TestParamPrefix('test-prefix-2', 'set')" "" \
+ "TestParamPrefix('test-prefix-2', 'show')" "" \
+ "gdb.Parameter('test-prefix-2 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('test-prefix-2 param-2', gdb.COMMAND_NONE, gdb.PARAM_INTEGER)" "" \
+ "gdb.Parameter('test-prefix-2 param-3', gdb.COMMAND_NONE, gdb.PARAM_STRING)" "" \
+ "end"
+
+ gdb_test "set test-prefix-2" "^invoke -- set"
+
+ gdb_test "show test-prefix-2" "^invoke -- show"
}
test_directories
@@ -679,11 +862,15 @@ test_color_parameter
test_file_parameter
test_undocumented_parameter
test_really_undocumented_parameter
+test_empty_doc_parameter
+test_empty_set_show_doc_parameter
test_deprecated_api_parameter
test_gdb_parameter
test_integer_parameter
test_throwing_parameter
test_language
test_ambiguous_parameter
+test_unknown_prefix
+test_set_show_parameters
rename py_param_test_maybe_no_output ""
diff --git a/gdb/testsuite/gdb.python/py-source-styling-2.exp b/gdb/testsuite/gdb.python/py-source-styling-2.exp
index b13ee1f..ebf7f32 100644
--- a/gdb/testsuite/gdb.python/py-source-styling-2.exp
+++ b/gdb/testsuite/gdb.python/py-source-styling-2.exp
@@ -32,7 +32,9 @@ if { [build_executable "failed to build" $testfile $srcfile $opts] == -1 } {
return
}
-clean_restart
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_test_no_output "maint set gnu-source-highlight enabled off"
@@ -40,16 +42,14 @@ gdb_load $binfile
require {gdb_py_module_available pygments}
-with_ansi_styling_terminal {
- gdb_test_no_output "set style enabled on"
-
- gdb_test_multiple "list $line_number" "Styling of c++ keyword try" {
- -re -wrap " try\r\n.*" {
- # Unstyled.
- fail $gdb_test_name
- }
- -re -wrap "" {
- pass $gdb_test_name
- }
+gdb_test_no_output "set style enabled on"
+
+gdb_test_multiple "list $line_number" "Styling of c++ keyword try" {
+ -re -wrap " try\r\n.*" {
+ # Unstyled.
+ fail $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp
index 55cdebe..dfc435e 100644
--- a/gdb/testsuite/gdb.python/py-symbol.exp
+++ b/gdb/testsuite/gdb.python/py-symbol.exp
@@ -100,7 +100,6 @@ gdb_test_multiple $cmd "print value of rr" {
fail $gdb_test_name
}
}
-
gdb_test "python print (gdb.lookup_static_symbol ('rr').needs_frame)" \
"False" \
diff --git a/gdb/testsuite/gdb.python/py-warning.exp b/gdb/testsuite/gdb.python/py-warning.exp
new file mode 100644
index 0000000..6b26a4e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-warning.exp
@@ -0,0 +1,63 @@
+# Copyright (C) 2025 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.warning() function.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+clean_restart
+
+# Basic usage.
+gdb_test "python gdb.warning(\"some text\")" \
+ "warning: some text"
+
+# Basic usage with named argument.
+gdb_test "python gdb.warning(text=\"a warning message\")" \
+ "warning: a warning message"
+
+# Make sure GDB prints format specifiers correctly.
+gdb_test "python gdb.warning(\"%s %d %p\")" \
+ "warning: %s %d %p"
+
+# Empty string gives an error.
+gdb_test "python gdb.warning(\"\")" \
+ [multi_line \
+ "Python Exception <class 'ValueError'>: Empty text string passed to gdb\\.warning" \
+ "Error occurred in Python: Empty text string passed to gdb\\.warning"]
+
+# Missing argument gives an error.
+set re1 \
+ [multi_line \
+ [string_to_regexp \
+ [concat \
+ "Python Exception <class 'TypeError'>:" \
+ "function missing required argument 'text' (pos 1)"]] \
+ [string_to_regexp \
+ [concat \
+ "Error occurred in Python:" \
+ "function missing required argument 'text' (pos 1)"]]]
+set re2 \
+ [multi_line \
+ [string_to_regexp \
+ [concat \
+ "Python Exception <class 'TypeError'>:" \
+ "Required argument 'text' (pos 1) not found"]] \
+ [string_to_regexp \
+ [concat \
+ "Error occurred in Python:" \
+ "Required argument 'text' (pos 1) not found"]]]
+gdb_test "python gdb.warning()" $re1|$re2