public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>,
	Michael Weghorn <m.weghorn@posteo.de>
Subject: [PATCH 10/16] gdb: add remote argument passing self tests
Date: Tue,  9 Jan 2024 14:26:33 +0000	[thread overview]
Message-ID: <b1f5c55a19e4370dfbf03bd3c5cd628df91ca287.1704809585.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1704809585.git.aburgess@redhat.com>

This commit adds some remote argument passing self-tests.  There are
not many tests right now -- there are known bugs in the remote
argument passing mechanism (see PR gdb/28392) -- but some simple cases
are covered here, and I plan to add additional tests once I've fixed
some of the problems with the existing code.

The tests take an inferior argument string, this is the string that
GDB would carry around as inferior::m_args.  This string is then split
using gdb::remote_args::split, this gives a vector of strings, these
are the strings that are passed over the remote protocol.  These split
strings are validated as part of the test.

The split strings are then combined using gdb::remote_args::join which
gives the inferior argument string that gdbserver will use, this is
held in server.cc, program_args, this joined string is then checked as
part of the test.

There are no changes to GDB's behaviour as part of this commit, other
than adding the new tests.
---
 gdb/Makefile.in                      |   1 +
 gdb/unittests/remote-arg-selftests.c | 189 +++++++++++++++++++++++++++
 2 files changed, 190 insertions(+)
 create mode 100644 gdb/unittests/remote-arg-selftests.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 195f3a2e2d1..cc2e62b6f3c 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -476,6 +476,7 @@ SELFTESTS_SRCS = \
 	unittests/ptid-selftests.c \
 	unittests/main-thread-selftests.c \
 	unittests/mkdir-recursive-selftests.c \
+	unittests/remote-arg-selftests.c \
 	unittests/rsp-low-selftests.c \
 	unittests/scoped_fd-selftests.c \
 	unittests/scoped_ignore_signal-selftests.c \
diff --git a/gdb/unittests/remote-arg-selftests.c b/gdb/unittests/remote-arg-selftests.c
new file mode 100644
index 00000000000..3240ab9aeea
--- /dev/null
+++ b/gdb/unittests/remote-arg-selftests.c
@@ -0,0 +1,189 @@
+/* Self tests for GDB's argument splitting and merging.
+
+   Copyright (C) 2023 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"
+#include "gdbsupport/common-inferior.h"
+#include "gdbsupport/remote-args.h"
+
+namespace selftests {
+namespace remote_args_tests {
+
+/* The data needed to perform a single remote argument test.  */
+struct arg_test_desc
+{
+  /* The original inferior argument string.  */
+  std::string input;
+
+  /* The individual arguments once they have been split.  */
+  std::vector<std::string> split;
+
+  /* The new inferior argument string, created by joining SPLIT.  */
+  std::string joined;
+};
+
+/* The list of tests.  */
+arg_test_desc desc[] = {
+  { "abc", { "abc" }, "abc" },
+  { "a b c", { "a", "b", "c" }, "a b c" },
+  { "\"a b\" 'c d'", { "a b", "c d" }, "a\\ b c\\ d" },
+  { "\\' \\\"", { "'", "\"" }, "\\' \\\"" },
+  { "'\\'", { "\\" }, "\\\\" },
+  { "\"\\\\\" \"\\\\\\\"\"", { "\\", "\\\"" }, "\\\\ \\\\\\\"" },
+  { "\\  \" \" ' '", { " ", " ", " "}, "\\  \\  \\ " },
+  { "\"'\"", { "'" }, "\\'" },
+  { "'\"' '\\\"'", { "\"", "\\\"" } , "\\\" \\\\\\\""},
+  { "\"first arg\" \"\" \"third-arg\" \"'\" \"\\\"\" \"\\\\\\\"\" \" \" \"\"",
+    { "first arg", "", "third-arg", "'", "\"", "\\\""," ", "" },
+    "first\\ arg '' third-arg \\' \\\" \\\\\\\" \\  ''"},
+  { "\"\\a\" \"\\&\" \"\\#\" \"\\<\" \"\\^\"",
+    { "\\a", "\\&", "\\#" , "\\<" , "\\^"},
+    "\\\\a \\\\\\& \\\\\\# \\\\\\< \\\\\\^" },
+  { "1 '\n' 3", { "1", "\n", "3" }, "1 '\n' 3" },
+};
+
+/* Convert a std::vector<std::string> into std::vector<char *>.  This
+   requires copying all of the string content.  This class takes care of
+   freeing the memory once we are done with it.  */
+
+struct args_as_c_strings
+{
+  args_as_c_strings (std::vector<std::string> args)
+  {
+    for (const auto & a : args)
+      m_data.push_back (xstrdup (a.c_str ()));
+  }
+
+  ~args_as_c_strings ()
+  {
+    free_vector_argv (m_data);
+  }
+
+  std::vector<char *> &get ()
+  {
+    return m_data;
+  }
+
+private:
+  std::vector<char *> m_data;
+};
+
+/* Run the remote argument passing self tests.  */
+
+static void
+self_test ()
+{
+  int failure_count = 0;
+  for (const auto &d : desc)
+    {
+      if (run_verbose ())
+	{
+	  if (&d != &desc[0])
+	    debug_printf ("------------------------------\n");
+	  debug_printf ("Input (%s)\n", d.input.c_str ());
+	}
+
+      /* Split argument string into individual arguments.  */
+      std::vector<std::string> split_args = gdb::remote_args::split (d.input);
+
+      if (run_verbose ())
+	{
+	  debug_printf ("Split:\n");
+
+	  size_t len = std::max (split_args.size (), d.split.size ());
+	  for (size_t i = 0; i < len; ++i)
+	    {
+	      const char *got = "N/A";
+	      const char *expected = got;
+
+	      if (i < split_args.size ())
+		got = split_args[i].c_str ();
+
+	      if (i < d.split.size ())
+		expected = d.split[i].c_str ();
+
+	      debug_printf ("  got (%s), expected (%s)\n", got, expected);
+	    }
+	}
+
+      if (split_args != d.split)
+	{
+	  ++failure_count;
+	  if (run_verbose ())
+	    debug_printf ("FAIL\n");
+	  continue;
+	}
+
+      /* Now join the arguments.  */
+      args_as_c_strings split_args_c_str (split_args);
+      std::string joined_args
+	= gdb::remote_args::join (split_args_c_str.get ());
+
+      if (run_verbose ())
+	debug_printf ("Joined (%s), expected (%s)\n",
+		      joined_args.c_str (), d.joined.c_str ());
+
+      if (joined_args != d.joined)
+	{
+	  ++failure_count;
+	  if (run_verbose ())
+	    debug_printf ("FAIL\n");
+	  continue;
+	}
+
+      /* The contents of JOINED_ARGS will not be identical to D.INPUT.
+	 There are multiple ways that an argument can be escaped, and out
+	 join function just picks one.  However, if we split JOINED_ARGS
+	 again then each individual argument should be the same as those in
+	 SPLIT_ARGS.  So lets test that next.  */
+      std::vector<std::string> split_args_v2
+	= gdb::remote_args::split (joined_args);
+
+      if (split_args_v2 != split_args)
+	{
+	  ++failure_count;
+	  if (run_verbose ())
+	    {
+	      debug_printf ("Re-split:\n");
+	      for (const auto &a : split_args_v2)
+		debug_printf ("  got (%s)\n", a.c_str ());
+	      debug_printf ("FAIL\n");
+	    }
+	  continue;
+	}
+
+      if (run_verbose ())
+	debug_printf ("PASS\n");
+    }
+
+  SELF_CHECK (failure_count == 0);
+}
+
+} /* namespace remote_args_tests */
+} /* namespace selftests */
+
+void _initialize_remote_arg_selftests ();
+
+void
+_initialize_remote_arg_selftests ()
+{
+  selftests::register_test ("remote-args",
+			    selftests::remote_args_tests::self_test);
+}
-- 
2.25.4


  parent reply	other threads:[~2024-01-09 14:27 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-09 14:26 [PATCH 00/16] Inferior argument (inc for remote targets) changes Andrew Burgess
2024-01-09 14:26 ` [PATCH 01/16] libiberty/buildargv: POSIX behaviour for backslash handling Andrew Burgess
2024-01-09 14:26 ` [PATCH 02/16] gdb/testsuite: add some xfail in gdb.base/startup-with-shell.exp Andrew Burgess
2024-01-09 14:26 ` [PATCH 03/16] gdb: Support some escaping of args with startup-with-shell being off Andrew Burgess
2024-01-09 14:26 ` [PATCH 04/16] gdb: remove the !startup_with_shell path from construct_inferior_arguments Andrew Burgess
2024-01-21  3:56   ` Keith Seitz
2024-01-09 14:26 ` [PATCH 05/16] gdbserver: convert program_args to a single string Andrew Burgess
2024-01-09 14:26 ` [PATCH 06/16] gdbsupport: have construct_inferior_arguments take an escape function Andrew Burgess
2024-01-09 14:26 ` [PATCH 07/16] gdbsupport: split escape_shell_characters in two Andrew Burgess
2024-01-09 14:26 ` [PATCH 08/16] gdb: move remote arg splitting and joining into gdbsupport/ Andrew Burgess
2024-01-21  3:57   ` Keith Seitz
2024-01-09 14:26 ` [PATCH 09/16] gdb/python: change escaping rules when setting arguments Andrew Burgess
2024-01-09 16:30   ` Eli Zaretskii
2024-01-09 14:26 ` Andrew Burgess [this message]
2024-01-21  3:57   ` [PATCH 10/16] gdb: add remote argument passing self tests Keith Seitz
2024-01-09 14:26 ` [PATCH 11/16] gdb/gdbserver: pass inferior arguments as a single string Andrew Burgess
2024-01-09 16:34   ` Eli Zaretskii
2024-01-09 16:35   ` Eli Zaretskii
2024-01-09 14:26 ` [PATCH 12/16] gdb/gdbserver: add a '--no-escape-args' command line option Andrew Burgess
2024-01-09 16:43   ` Eli Zaretskii
2024-01-21  3:57   ` Keith Seitz
2024-01-09 14:26 ` [PATCH 13/16] gdb: allow 'set args' and run commands to contain newlines Andrew Burgess
2024-01-09 16:44   ` Eli Zaretskii
2024-01-21  3:57   ` Keith Seitz
2024-01-09 14:26 ` [PATCH 14/16] gdb/gdbserver: remove some uses of free_vector_argv Andrew Burgess
2024-01-09 14:26 ` [PATCH 15/16] gdb: new maintenance command to help debug remote argument issues Andrew Burgess
2024-01-09 16:32   ` Eli Zaretskii
2024-01-21  3:57   ` Keith Seitz
2024-01-09 14:26 ` [PATCH 16/16] gdb/gdbserver: rework argument splitting and joining Andrew Burgess
2024-01-09 16:37   ` Eli Zaretskii
2024-01-21  3:57   ` Keith Seitz
2024-01-09 16:58 ` [PATCH 00/16] Inferior argument (inc for remote targets) changes Eli Zaretskii
2024-01-20 22:46   ` Andrew Burgess
2024-01-21 10:22     ` Eli Zaretskii
2024-01-22 10:29       ` Andrew Burgess
2024-01-10  8:28 ` Michael Weghorn
2024-01-21  3:56 ` Keith Seitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b1f5c55a19e4370dfbf03bd3c5cd628df91ca287.1704809585.git.aburgess@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=m.weghorn@posteo.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).