command-def-selftests.c: detect missing or wrong prefix cmd in subcommands.

This test revealed a number of problems that are fixed in the previous commit.

2020-05-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* unittests/command-def-selftests.c (traverse_command_structure):
	Verify all commands of a list have the same prefix command and
	that only the top cmdlist commands have a null prefix.
This commit is contained in:
Philippe Waroquiers 2020-05-09 16:17:45 +02:00
parent 3f4d92ebdf
commit 89bcba74f8
2 changed files with 41 additions and 2 deletions

View File

@ -1,3 +1,9 @@
2020-05-15 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* unittests/command-def-selftests.c (traverse_command_structure):
Verify all commands of a list have the same prefix command and
that only the top cmdlist commands have a null prefix.
2020-05-15 Philippe Waroquiers <philippe.waroquiers@skynet.be> 2020-05-15 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* cli/cli-decode.c (lookup_cmd_for_prefix): Return the aliased command * cli/cli-decode.c (lookup_cmd_for_prefix): Return the aliased command

View File

@ -106,20 +106,26 @@ help_doc_invariants_tests ()
namespace command_structure_tests { namespace command_structure_tests {
/* Nr of commands in which a duplicated list is found. */
unsigned int nr_duplicates = 0; unsigned int nr_duplicates = 0;
/* Nr of commands in a list having no valid prefix cmd. */
unsigned int nr_invalid_prefixcmd = 0;
/* A map associating a list with the prefix leading to it. */ /* A map associating a list with the prefix leading to it. */
std::map<cmd_list_element **, const char *> lists; std::map<cmd_list_element **, const char *> lists;
/* Store each command list in lists, associated with the prefix to reach it. A /* Store each command list in lists, associated with the prefix to reach it. A
list must only be found once. */ list must only be found once.
Verifies that all elements of the list have the same non-null prefix
command. */
static void static void
traverse_command_structure (struct cmd_list_element **list, traverse_command_structure (struct cmd_list_element **list,
const char *prefix) const char *prefix)
{ {
struct cmd_list_element *c; struct cmd_list_element *c, *prefixcmd;
auto dupl = lists.find (list); auto dupl = lists.find (list);
if (dupl != lists.end ()) if (dupl != lists.end ())
@ -137,6 +143,13 @@ traverse_command_structure (struct cmd_list_element **list,
lists.insert ({list, prefix}); lists.insert ({list, prefix});
/* All commands of *list must have a prefix command equal to PREFIXCMD,
the prefix command of the first command. */
if (*list == nullptr)
prefixcmd = nullptr; /* A prefix command with an empty subcommand list. */
else
prefixcmd = (*list)->prefix;
/* Walk through the commands. */ /* Walk through the commands. */
for (c = *list; c; c = c->next) for (c = *list; c; c = c->next)
{ {
@ -148,6 +161,23 @@ traverse_command_structure (struct cmd_list_element **list,
passing the right prefix in. */ passing the right prefix in. */
traverse_command_structure (c->prefixlist, c->prefixname); traverse_command_structure (c->prefixlist, c->prefixname);
} }
if (prefixcmd != c->prefix
|| (prefixcmd == nullptr && *list != cmdlist))
{
if (c->prefix == nullptr)
fprintf_filtered (gdb_stdout,
"list %p reachable via prefix '%s'."
" command '%s' has null prefixcmd\n",
list,
prefix, c->name);
else
fprintf_filtered (gdb_stdout,
"list %p reachable via prefix '%s'."
" command '%s' has a different prefixcmd\n",
list,
prefix, c->name);
nr_invalid_prefixcmd++;
}
} }
} }
@ -157,12 +187,15 @@ static void
command_structure_invariants_tests () command_structure_invariants_tests ()
{ {
nr_duplicates = 0; nr_duplicates = 0;
nr_invalid_prefixcmd = 0;
traverse_command_structure (&cmdlist, ""); traverse_command_structure (&cmdlist, "");
/* Release memory, be ready to be re-run. */ /* Release memory, be ready to be re-run. */
lists.clear (); lists.clear ();
SELF_CHECK (nr_duplicates == 0); SELF_CHECK (nr_duplicates == 0);
SELF_CHECK (nr_invalid_prefixcmd == 0);
} }
} }