We already have some gdb_argv tests, but these only test the
gdb_argv::as_array_view member function.
This commit creates a new unittests/gdb_argv-selftests.c file and adds
a wider range of gdb_argv tests, this includes covering the existing
as_array_view tests, so the existing tests have been deleted from
gdb/utils.c.
I've also added an additional test to gdb.python/py-cmd.exp which
tests calling gdb.string_to_argv with an empty string. The
gdb.string_to_argv function is a wrapper around gdb_argv, and I
thought the empty string case was worth covering.
---
gdb/Makefile.in | 1 +
gdb/testsuite/gdb.python/py-cmd.exp | 4 +
gdb/unittests/gdb_argv-selftests.c | 131 ++++++++++++++++++++++++++++
gdb/utils.c | 26 ------
4 files changed, 136 insertions(+), 26 deletions(-)
create mode 100644 gdb/unittests/gdb_argv-selftests.c
@@ -462,6 +462,7 @@ SELFTESTS_SRCS = \
unittests/format_pieces-selftests.c \
unittests/frame_info_ptr-selftests.c \
unittests/function-view-selftests.c \
+ unittests/gdb_argv-selftests.c \
unittests/gdb_tilde_expand-selftests.c \
unittests/gmp-utils-selftests.c \
unittests/intrusive_list-selftests.c \
@@ -142,6 +142,10 @@ gdb_test "python print (gdb.string_to_argv ('1\\ 2 3'))" \
{\['1 2', '3'\]} \
"string_to_argv ('1\\ 2 3')"
+gdb_test "python print (gdb.string_to_argv (''))" \
+ {\[\]} \
+ "string_to_argv ('')"
+
# Test user-defined python commands.
gdb_test_multiline "input simple user-defined command" \
"python" "" \
new file mode 100644
@@ -0,0 +1,131 @@
+/* Self tests for the gdb_argv class from gdbsupport.
+
+ Copyright (C) 2024 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#include "defs.h"
+#include "gdbsupport/selftest.h"
+#include "gdbsupport/buildargv.h"
+
+namespace selftests {
+namespace gdb_argv_tests {
+
+static extract_string_ctrl shell_extract_string_ctrl
+ (nullptr, "", "\"$`\\", "\n", "", "\n");
+
+struct test_def
+{
+ /* INPUT is the string to pass to the gdb_argv constructor. OUTPUT is
+ the vector of arguments that gdb_argv should split INPUT into. */
+
+ test_def (const char *input,
+ std::vector<const char *> output)
+ : m_input (input),
+ m_output (output)
+ { /* Nothing. */ }
+
+ /* Run this test and check the results. Throws an exception if the test
+ fails. */
+
+ void run () const
+ {
+ gdb_argv argv (m_input);
+ int count = argv.count ();
+
+ if (run_verbose ())
+ {
+ debug_printf ("Input: %s\n", m_input);
+ debug_printf ("Output [Count]: %d\n", count);
+ }
+
+ SELF_CHECK (count == m_output.size ());
+
+ gdb::array_view<char *> view = argv.as_array_view ();
+ SELF_CHECK (view.size () == count);
+
+ const char *const *data = argv.get ();
+ for (int i = 0; i < count; ++i)
+ {
+ const char *a = argv[i];
+ SELF_CHECK (view[i] == a);
+ SELF_CHECK (strcmp (a, m_output[i]) == 0);
+ SELF_CHECK (a == *data);
+ ++data;
+ }
+
+ SELF_CHECK (*data == nullptr);
+ }
+
+private:
+ /* What to pass to gdb_argv constructor. */
+
+ const char *m_input;
+
+ /* The expected contents of gdb_argv after construction. */
+
+ std::vector<const char *> m_output;
+};
+
+/* The array of all tests. */
+
+test_def tests[] = {
+ { "abc def", {"abc", "def"} },
+ { "one two 3", {"one", "two", "3"} },
+ { "one two\\ three", {"one", "two three"} },
+ { "one\\ two three", {"one two", "three"} },
+ { "'one two' three", {"one two", "three"} },
+ { "one \"two three\"", {"one", "two three"} },
+ { "'\"' \"''\"", {"\"", "''"} },
+};
+
+/* Test the creation of an empty gdb_argv object. */
+
+static void
+empty_argv_tests ()
+{
+ {
+ gdb_argv argv;
+
+ SELF_CHECK (argv.get () == nullptr);
+ SELF_CHECK (argv.count () == 0);
+
+ gdb::array_view<char *> view = argv.as_array_view ();
+
+ SELF_CHECK (view.data () == nullptr);
+ SELF_CHECK (view.size () == 0);
+ }
+}
+
+static void
+run_tests ()
+{
+ empty_argv_tests ();
+
+ for (const auto &test : tests)
+ test.run ();
+}
+
+} /* namespace gdb_argv_tests */
+} /* namespace selftests */
+
+void _initialize_gdb_argv_selftest ();
+void
+_initialize_gdb_argv_selftest ()
+{
+ selftests::register_test ("gdb_argv",
+ selftests::gdb_argv_tests::run_tests);
+}
@@ -3294,31 +3294,6 @@ gdb_realpath_tests ()
gdb_realpath_check_trailer ("", "");
}
-/* Test the gdb_argv::as_array_view method. */
-
-static void
-gdb_argv_as_array_view_test ()
-{
- {
- gdb_argv argv;
-
- gdb::array_view<char *> view = argv.as_array_view ();
-
- SELF_CHECK (view.data () == nullptr);
- SELF_CHECK (view.size () == 0);
- }
- {
- gdb_argv argv ("une bonne 50");
-
- gdb::array_view<char *> view = argv.as_array_view ();
-
- SELF_CHECK (view.size () == 3);
- SELF_CHECK (strcmp (view[0], "une") == 0);
- SELF_CHECK (strcmp (view[1], "bonne") == 0);
- SELF_CHECK (strcmp (view[2], "50") == 0);
- }
-}
-
#endif /* GDB_SELF_TEST */
/* Simple, portable version of dirname that does not modify its
@@ -3794,7 +3769,6 @@ When set, debugging messages will be marked with seconds and microseconds."),
#if GDB_SELF_TEST
selftests::register_test ("gdb_realpath", gdb_realpath_tests);
- selftests::register_test ("gdb_argv_array_view", gdb_argv_as_array_view_test);
selftests::register_test ("strncmp_iw_with_mode",
strncmp_iw_with_mode_tests);
selftests::register_test ("pager", test_pager);