[gdb/testsuite] Reimplement gdb.gdb/python-interrupts.exp as unittest

The test-case gdb.gdb/python-interrupts.exp:
- runs to captured_command_loop
- sets a breakpoint at set_active_ext_lang
- calls a python command
- verifies the command triggers the breakpoint
- sends a signal and verifies the result

The test-case is fragile, because (f.i. with -flto) it cannot be guaranteed
that captured_command_loop and set_active_ext_lang are available for setting
breakpoints.

Reimplement the test-case as unittest, using:
- execute_command_to_string to capture the output
- try/catch to catch the "Error while executing Python code" exception
- a new hook selftests::hook_set_active_ext_lang to raise the signal

Tested on x86_64-linux.
This commit is contained in:
Tom de Vries 2021-10-19 23:50:50 +02:00
parent 5a8edb756a
commit c82f680a94
4 changed files with 57 additions and 50 deletions

View file

@ -682,6 +682,12 @@ install_gdb_sigint_handler (struct signal_handler *previous)
previous->handler_saved = 0; previous->handler_saved = 0;
} }
#if GDB_SELF_TEST
namespace selftests {
void (*hook_set_active_ext_lang) () = nullptr;
}
#endif
/* Set the currently active extension language to NOW_ACTIVE. /* Set the currently active extension language to NOW_ACTIVE.
The result is a pointer to a malloc'd block of memory to pass to The result is a pointer to a malloc'd block of memory to pass to
restore_active_ext_lang. restore_active_ext_lang.
@ -708,6 +714,11 @@ install_gdb_sigint_handler (struct signal_handler *previous)
struct active_ext_lang_state * struct active_ext_lang_state *
set_active_ext_lang (const struct extension_language_defn *now_active) set_active_ext_lang (const struct extension_language_defn *now_active)
{ {
#if GDB_SELF_TEST
if (selftests::hook_set_active_ext_lang)
selftests::hook_set_active_ext_lang ();
#endif
struct active_ext_lang_state *previous struct active_ext_lang_state *previous
= XCNEW (struct active_ext_lang_state); = XCNEW (struct active_ext_lang_state);

View file

@ -319,4 +319,10 @@ extern void get_matching_xmethod_workers
extern gdb::optional<std::string> ext_lang_colorize extern gdb::optional<std::string> ext_lang_colorize
(const std::string &filename, const std::string &contents); (const std::string &filename, const std::string &contents);
#if GDB_SELF_TEST
namespace selftests {
extern void (*hook_set_active_ext_lang) ();
}
#endif
#endif /* EXTENSION_H */ #endif /* EXTENSION_H */

View file

@ -1933,21 +1933,46 @@ test_python ()
output.clear (); output.clear ();
bool saw_exception = false; bool saw_exception = false;
scoped_restore reset_gdb_python_initialized {
= make_scoped_restore (&gdb_python_initialized, 0); scoped_restore reset_gdb_python_initialized
try = make_scoped_restore (&gdb_python_initialized, 0);
{ try
CMD (output); {
} CMD (output);
catch (const gdb_exception &e) }
{ catch (const gdb_exception &e)
saw_exception = true; {
SELF_CHECK (e.reason == RETURN_ERROR); saw_exception = true;
SELF_CHECK (e.error == GENERIC_ERROR); SELF_CHECK (e.reason == RETURN_ERROR);
SELF_CHECK (*e.message == "Python not initialized"); SELF_CHECK (e.error == GENERIC_ERROR);
} SELF_CHECK (*e.message == "Python not initialized");
SELF_CHECK (saw_exception); }
SELF_CHECK (output.empty ()); SELF_CHECK (saw_exception);
SELF_CHECK (output.empty ());
}
saw_exception = false;
{
scoped_restore save_hook
= make_scoped_restore (&hook_set_active_ext_lang,
[]() { raise (SIGINT); });
try
{
CMD (output);
}
catch (const gdb_exception &e)
{
saw_exception = true;
SELF_CHECK (e.reason == RETURN_ERROR);
SELF_CHECK (e.error == GENERIC_ERROR);
SELF_CHECK (*e.message == "Error while executing Python code.");
}
SELF_CHECK (saw_exception);
std::string ref_output("Traceback (most recent call last):\n"
" File \"<string>\", line 1, in <module>\n"
"KeyboardInterrupt\n");
SELF_CHECK (output == ref_output);
}
#undef CMD #undef CMD
} }

View file

@ -1,35 +0,0 @@
# Copyright 2014-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 Python SIGINT handling.
# This is easiest if we can send SIGINT when gdb is at particular points.
load_lib selftest-support.exp
load_lib gdb-python.exp
proc test_python_interrupts {} {
if {[skip_python_tests]} {
return -1
}
gdb_breakpoint set_active_ext_lang temporary
gdb_test "call catch_command_errors(execute_command, \"python print(5)\", 0, true)" \
"Temporary breakpoint.*silently stop."
gdb_test "signal SIGINT" \
"KeyboardInterrupt.*Error while executing Python code."
return 0
}
do_self_tests captured_command_loop test_python_interrupts