]>
Commit | Line | Data |
---|---|---|
58e6ac70 | 1 | /* Self tests for GDB command definitions for GDB, the GNU debugger. |
d2834edc | 2 | |
b811d2c2 | 3 | Copyright (C) 2019-2020 Free Software Foundation, Inc. |
d2834edc PW |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "cli/cli-cmds.h" | |
22 | #include "cli/cli-decode.h" | |
23 | #include "gdbsupport/selftest.h" | |
24 | ||
58e6ac70 PW |
25 | #include <map> |
26 | ||
d2834edc | 27 | namespace selftests { |
58e6ac70 PW |
28 | |
29 | /* Verify some invariants of GDB commands documentation. */ | |
30 | ||
d2834edc PW |
31 | namespace help_doc_tests { |
32 | ||
33 | static unsigned int nr_failed_invariants; | |
34 | ||
35 | /* Report a broken invariant and increments nr_failed_invariants. */ | |
36 | ||
37 | static void | |
38 | broken_doc_invariant (const char *prefix, const char *name, const char *msg) | |
39 | { | |
40 | fprintf_filtered (gdb_stdout, | |
41 | "help doc broken invariant: command '%s%s' help doc %s\n", | |
42 | prefix, name, msg); | |
43 | nr_failed_invariants++; | |
44 | } | |
45 | ||
46 | /* Recursively walk the commandlist structures, and check doc invariants: | |
47 | - The first line of the doc must end with a '.'. | |
48 | - the doc must not end with a new line. | |
49 | If an invariant is not respected, produce a message and increment | |
50 | nr_failed_invariants. | |
51 | Note that we do not call SELF_CHECK in this function, as we want | |
52 | all commands to be checked before making the test fail. */ | |
53 | ||
54 | static void | |
55 | check_doc (struct cmd_list_element *commandlist, const char *prefix) | |
56 | { | |
57 | struct cmd_list_element *c; | |
58 | ||
59 | /* Walk through the commands. */ | |
60 | for (c = commandlist; c; c = c->next) | |
61 | { | |
62 | /* Checks the doc has a first line terminated with a '.'. */ | |
63 | const char *p = c->doc; | |
64 | ||
65 | /* Position p on the first LF, or on terminating null byte. */ | |
66 | while (*p && *p != '\n') | |
67 | p++; | |
68 | if (p == c->doc) | |
69 | broken_doc_invariant | |
70 | (prefix, c->name, | |
71 | "is missing the first line terminated with a '.' character"); | |
72 | else if (*(p-1) != '.') | |
73 | broken_doc_invariant | |
74 | (prefix, c->name, | |
75 | "first line is not terminated with a '.' character"); | |
76 | ||
77 | /* Checks the doc is not terminated with a new line. */ | |
78 | if (c->doc[strlen (c->doc) - 1] == '\n') | |
79 | broken_doc_invariant | |
80 | (prefix, c->name, | |
81 | "has a superfluous trailing end of line"); | |
82 | ||
83 | /* Check if this command has subcommands and is not an | |
84 | abbreviation. We skip checking subcommands of abbreviations | |
85 | in order to avoid duplicates in the output. */ | |
86 | if (c->prefixlist != NULL && !c->abbrev_flag) | |
87 | { | |
88 | /* Recursively call ourselves on the subcommand list, | |
89 | passing the right prefix in. */ | |
90 | check_doc (*c->prefixlist, c->prefixname); | |
91 | } | |
92 | } | |
93 | } | |
94 | ||
95 | static void | |
96 | help_doc_invariants_tests () | |
97 | { | |
98 | nr_failed_invariants = 0; | |
99 | check_doc (cmdlist, ""); | |
100 | SELF_CHECK (nr_failed_invariants == 0); | |
101 | } | |
102 | ||
103 | } /* namespace help_doc_tests */ | |
58e6ac70 PW |
104 | |
105 | /* Verify some invariants of GDB command structure. */ | |
106 | ||
107 | namespace command_structure_tests { | |
108 | ||
109 | unsigned int nr_duplicates = 0; | |
110 | ||
111 | /* A map associating a list with the prefix leading to it. */ | |
112 | ||
113 | std::map<cmd_list_element **, const char *> lists; | |
114 | ||
115 | /* Store each command list in lists, associated with the prefix to reach it. A | |
116 | list must only be found once. */ | |
117 | ||
118 | static void | |
119 | traverse_command_structure (struct cmd_list_element **list, | |
120 | const char *prefix) | |
121 | { | |
122 | struct cmd_list_element *c; | |
123 | ||
124 | auto dupl = lists.find (list); | |
125 | if (dupl != lists.end ()) | |
126 | { | |
127 | fprintf_filtered (gdb_stdout, | |
128 | "list %p duplicated," | |
129 | " reachable via prefix '%s' and '%s'." | |
130 | " Duplicated list first command is '%s'\n", | |
131 | list, | |
132 | prefix, dupl->second, | |
133 | (*list)->name); | |
134 | nr_duplicates++; | |
135 | return; | |
136 | } | |
137 | ||
138 | lists.insert ({list, prefix}); | |
139 | ||
140 | /* Walk through the commands. */ | |
141 | for (c = *list; c; c = c->next) | |
142 | { | |
143 | /* If this command has subcommands and is not an alias, | |
144 | traverse the subcommands. */ | |
145 | if (c->prefixlist != NULL && c->cmd_pointer == nullptr) | |
146 | { | |
147 | /* Recursively call ourselves on the subcommand list, | |
148 | passing the right prefix in. */ | |
149 | traverse_command_structure (c->prefixlist, c->prefixname); | |
150 | } | |
151 | } | |
152 | } | |
153 | ||
154 | /* Verify that a list of commands is present in the tree only once. */ | |
155 | ||
156 | static void | |
157 | command_structure_invariants_tests () | |
158 | { | |
159 | nr_duplicates = 0; | |
160 | traverse_command_structure (&cmdlist, ""); | |
161 | ||
162 | /* Release memory, be ready to be re-run. */ | |
163 | lists.clear (); | |
164 | ||
165 | SELF_CHECK (nr_duplicates == 0); | |
166 | } | |
167 | ||
168 | } | |
169 | ||
d2834edc PW |
170 | } /* namespace selftests */ |
171 | ||
58e6ac70 | 172 | void _initialize_command_def_selftests (); |
d2834edc | 173 | void |
58e6ac70 | 174 | _initialize_command_def_selftests () |
d2834edc PW |
175 | { |
176 | selftests::register_test | |
177 | ("help_doc_invariants", | |
178 | selftests::help_doc_tests::help_doc_invariants_tests); | |
58e6ac70 PW |
179 | |
180 | selftests::register_test | |
181 | ("command_structure_invariants", | |
182 | selftests::command_structure_tests::command_structure_invariants_tests); | |
d2834edc | 183 | } |