blob: 1db0d5ce4dfd6a57894edbf81c8ec20269a77630 [file] [log] [blame]
Harald Weltee08da972017-11-13 01:00:26 +09001/* (C) 2013 by sysmocom - s.f.m.c. GmbH, Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +02002 * All Rights Reserved
3 *
Harald Weltee08da972017-11-13 01:00:26 +09004 * SPDX-License-Identifier: GPL-2.0+
5 *
6 * This program is free software; you can redistribute it and/or modify
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +02007 * it under the terms of the GNU General Public License as published by
Harald Weltee08da972017-11-13 01:00:26 +09008 * the Free Software Foundation; either version 2 of the License, or
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +02009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22#include <stdio.h>
23#include <string.h>
Neels Hofmeyr4a31ffa2017-09-07 03:08:06 +020024#include <errno.h>
Pau Espin Pedrold92be9a2020-07-30 14:55:49 +020025#include <limits.h>
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020026
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020027#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/un.h>
30
Holger Hans Peter Freyther6ef71b02013-09-10 11:17:46 +020031#include <osmocom/core/application.h>
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020032#include <osmocom/core/talloc.h>
Vadim Yanitskiy4abda9e2019-11-21 00:19:36 +070033#include <osmocom/core/logging_internal.h>
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020034#include <osmocom/core/logging.h>
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +010035#include <osmocom/core/stats.h>
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020036#include <osmocom/core/utils.h>
Holger Hans Peter Freyther2c9168c2013-10-10 20:21:33 +020037#include <osmocom/core/signal.h>
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020038#include <osmocom/vty/misc.h>
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020039#include <osmocom/vty/vty.h>
40#include <osmocom/vty/command.h>
41#include <osmocom/vty/buffer.h>
Holger Hans Peter Freyther6ef71b02013-09-10 11:17:46 +020042#include <osmocom/vty/logging.h>
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +010043#include <osmocom/vty/stats.h>
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020044
45static enum event last_vty_connection_event = -1;
Neels Hofmeyra829b452018-04-05 03:02:35 +020046void *ctx = NULL;
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020047
48static void test_cmd_string_from_valstr(void)
49{
50 char *cmd;
51 const struct value_string printf_seq_vs[] = {
52 { .value = 42, .str = "[foo%s%s%s%s%s]"},
53 { .value = 43, .str = "[bar%s%s%s%s%s]"},
54 { .value = 0, .str = NULL}
55 };
56
57 printf("Going to test vty_cmd_string_from_valstr()\n");
58
59 /* check against character strings that could break printf */
60
Neels Hofmeyra829b452018-04-05 03:02:35 +020061 cmd = vty_cmd_string_from_valstr (ctx, printf_seq_vs, "[prefix%s%s%s%s%s]", "[sep%s%s%s%s%s]", "[end%s%s%s%s%s]", 1);
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +020062 printf ("Tested with %%s-strings, resulting cmd = '%s'\n", cmd);
63 talloc_free (cmd);
64}
65
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020066static int do_vty_command(struct vty *vty, const char *cmd)
67{
68 vector vline;
69 int ret;
70
71 printf("Going to execute '%s'\n", cmd);
72 vline = cmd_make_strvec(cmd);
73 ret = cmd_execute_command(vline, vty, NULL, 0);
74 cmd_free_strvec(vline);
75 printf("Returned: %d, Current node: %d '%s'\n", ret, vty->node, cmd_prompt(vty->node));
76 return ret;
77}
78
Holger Hans Peter Freyther2c9168c2013-10-10 20:21:33 +020079/* Handle the events from telnet_interface.c */
80static int vty_event_cb(unsigned int subsys, unsigned int signal,
81 void *handler_data, void *_signal_data)
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020082{
Holger Hans Peter Freyther2c9168c2013-10-10 20:21:33 +020083 struct vty_signal_data *signal_data;
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020084
Holger Hans Peter Freyther2c9168c2013-10-10 20:21:33 +020085 if (subsys != SS_L_VTY)
86 return 0;
87 if (signal != S_VTY_EVENT)
88 return 0;
89
90 signal_data = _signal_data;
91 last_vty_connection_event = signal_data->event;
92
93 fprintf(stderr, "Got VTY event: %d\n", signal_data->event);
94 return 0;
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +020095}
96
Jacob Erlbeckca6602f2015-11-03 13:47:11 +010097struct vty_test {
98 int sock[2];
99};
100
101static struct vty* create_test_vty(struct vty_test *data)
102{
103 struct vty *vty;
104 /* Fake connection. */
105 socketpair(AF_UNIX, SOCK_STREAM, 0, data->sock);
106
107 vty = vty_create(data->sock[0], NULL);
108 OSMO_ASSERT(vty != NULL);
109 OSMO_ASSERT(vty->status != VTY_CLOSE);
110
111 return vty;
112}
113
114static void destroy_test_vty(struct vty_test *data, struct vty *vty)
115{
116 vty_close(vty);
117 OSMO_ASSERT(last_vty_connection_event == VTY_CLOSED);
118}
119
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200120static void test_node_tree_structure(void)
121{
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100122 struct vty_test test;
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200123 struct vty *vty;
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200124
125 printf("Going to test VTY node tree structure\n");
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100126 vty = create_test_vty(&test);
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200127
128 OSMO_ASSERT(do_vty_command(vty, "enable") == CMD_SUCCESS);
129 OSMO_ASSERT(vty->node == ENABLE_NODE);
130
131 OSMO_ASSERT(do_vty_command(vty, "configure terminal") == CMD_SUCCESS);
132 OSMO_ASSERT(vty->node == CONFIG_NODE);
133 OSMO_ASSERT(do_vty_command(vty, "exit") == CMD_SUCCESS);
134 OSMO_ASSERT(vty->node == ENABLE_NODE);
135
136 OSMO_ASSERT(do_vty_command(vty, "configure terminal") == CMD_SUCCESS);
137 OSMO_ASSERT(vty->node == CONFIG_NODE);
138 OSMO_ASSERT(do_vty_command(vty, "end") == CMD_SUCCESS);
139 OSMO_ASSERT(vty->node == ENABLE_NODE);
140
141 OSMO_ASSERT(do_vty_command(vty, "configure terminal") == CMD_SUCCESS);
142 OSMO_ASSERT(vty->node == CONFIG_NODE);
143 OSMO_ASSERT(do_vty_command(vty, "log stderr") == CMD_SUCCESS);
144 OSMO_ASSERT(vty->node == CFG_LOG_NODE);
145 OSMO_ASSERT(do_vty_command(vty, "exit") == CMD_SUCCESS);
146 OSMO_ASSERT(vty->node == CONFIG_NODE);
147 OSMO_ASSERT(do_vty_command(vty, "log stderr") == CMD_SUCCESS);
148 OSMO_ASSERT(vty->node == CFG_LOG_NODE);
149 OSMO_ASSERT(do_vty_command(vty, "end") == CMD_SUCCESS);
150 OSMO_ASSERT(vty->node == ENABLE_NODE);
151
152 OSMO_ASSERT(do_vty_command(vty, "configure terminal") == CMD_SUCCESS);
153 OSMO_ASSERT(vty->node == CONFIG_NODE);
154 OSMO_ASSERT(do_vty_command(vty, "line vty") == CMD_SUCCESS);
155 OSMO_ASSERT(vty->node == VTY_NODE);
156 OSMO_ASSERT(do_vty_command(vty, "exit") == CMD_SUCCESS);
157 OSMO_ASSERT(vty->node == CONFIG_NODE);
158 OSMO_ASSERT(do_vty_command(vty, "line vty") == CMD_SUCCESS);
159 OSMO_ASSERT(vty->node == VTY_NODE);
160 OSMO_ASSERT(do_vty_command(vty, "end") == CMD_SUCCESS);
161 OSMO_ASSERT(vty->node == ENABLE_NODE);
162
163
Neels Hofmeyrd64b6ae2017-09-07 04:52:05 +0200164 /* Check for not searching the parent node for matching commands. */
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200165 OSMO_ASSERT(do_vty_command(vty, "configure terminal") == CMD_SUCCESS);
166 OSMO_ASSERT(vty->node == CONFIG_NODE);
167 OSMO_ASSERT(do_vty_command(vty, "log stderr") == CMD_SUCCESS);
168 OSMO_ASSERT(vty->node == CFG_LOG_NODE);
Neels Hofmeyrd64b6ae2017-09-07 04:52:05 +0200169 OSMO_ASSERT(do_vty_command(vty, "line vty") == CMD_ERR_NO_MATCH);
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200170 OSMO_ASSERT(vty->node == CFG_LOG_NODE);
171 OSMO_ASSERT(do_vty_command(vty, "end") == CMD_SUCCESS);
172 OSMO_ASSERT(vty->node == ENABLE_NODE);
173
174 /* Check for final 'exit' (connection close). */
175 OSMO_ASSERT(do_vty_command(vty, "exit") == CMD_SUCCESS);
176 OSMO_ASSERT(vty->node == ENABLE_NODE);
177 OSMO_ASSERT(vty->status == VTY_CLOSE);
178
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100179 destroy_test_vty(&test, vty);
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200180}
181
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100182static void check_srep_vty_config(struct vty* vty,
183 struct osmo_stats_reporter *srep)
184{
185 OSMO_ASSERT(srep->enabled == 0);
186
187 OSMO_ASSERT(do_vty_command(vty, "prefix myprefix") == CMD_SUCCESS);
188 OSMO_ASSERT(srep->name_prefix != NULL);
189 OSMO_ASSERT(strcmp(srep->name_prefix, "myprefix") == 0);
190 OSMO_ASSERT(do_vty_command(vty, "no prefix") == CMD_SUCCESS);
191 OSMO_ASSERT(srep->name_prefix == NULL || strlen(srep->name_prefix) == 0);
192
193 OSMO_ASSERT(srep->max_class == OSMO_STATS_CLASS_GLOBAL);
194 OSMO_ASSERT(do_vty_command(vty, "level peer") == CMD_SUCCESS);
195 OSMO_ASSERT(srep->max_class == OSMO_STATS_CLASS_PEER);
196 OSMO_ASSERT(do_vty_command(vty, "level subscriber") == CMD_SUCCESS);
197 OSMO_ASSERT(srep->max_class == OSMO_STATS_CLASS_SUBSCRIBER);
198 OSMO_ASSERT(do_vty_command(vty, "level global") == CMD_SUCCESS);
199 OSMO_ASSERT(srep->max_class == OSMO_STATS_CLASS_GLOBAL);
200 OSMO_ASSERT(do_vty_command(vty, "level foobar") == CMD_ERR_NO_MATCH);
201
202 if (srep->have_net_config) {
203 OSMO_ASSERT(do_vty_command(vty, "remote-ip 127.0.0.99") ==
204 CMD_SUCCESS);
205 OSMO_ASSERT(srep->dest_addr_str &&
206 strcmp(srep->dest_addr_str, "127.0.0.99") == 0);
207 OSMO_ASSERT(do_vty_command(vty, "remote-ip 678.0.0.99") ==
208 CMD_WARNING);
209 OSMO_ASSERT(srep->dest_addr_str &&
210 strcmp(srep->dest_addr_str, "127.0.0.99") == 0);
211
212 OSMO_ASSERT(do_vty_command(vty, "remote-port 12321") ==
213 CMD_SUCCESS);
214 OSMO_ASSERT(srep->dest_port == 12321);
215
216 OSMO_ASSERT(srep->bind_addr_str == NULL);
217 OSMO_ASSERT(do_vty_command(vty, "local-ip 127.0.0.98") ==
218 CMD_SUCCESS);
219 OSMO_ASSERT(srep->bind_addr_str &&
220 strcmp(srep->bind_addr_str, "127.0.0.98") == 0);
221 OSMO_ASSERT(do_vty_command(vty, "no local-ip") == CMD_SUCCESS);
222 OSMO_ASSERT(srep->bind_addr_str == NULL);
223
224 OSMO_ASSERT(srep->mtu == 0);
225 OSMO_ASSERT(do_vty_command(vty, "mtu 987") == CMD_SUCCESS);
226 OSMO_ASSERT(srep->mtu == 987);
227 OSMO_ASSERT(do_vty_command(vty, "no mtu") == CMD_SUCCESS);
228 OSMO_ASSERT(srep->mtu == 0);
229 };
230
231 OSMO_ASSERT(do_vty_command(vty, "enable") == CMD_SUCCESS);
232 OSMO_ASSERT(srep->enabled != 0);
233 OSMO_ASSERT(do_vty_command(vty, "disable") == CMD_SUCCESS);
234 OSMO_ASSERT(srep->enabled == 0);
235}
236
237static void test_stats_vty(void)
238{
239 struct osmo_stats_reporter *srep;
240 struct vty_test test;
241 struct vty *vty;
242
243 printf("Going to test VTY configuration of the stats subsystem\n");
244 vty = create_test_vty(&test);
245
246 /* Go to config node */
247 OSMO_ASSERT(do_vty_command(vty, "enable") == CMD_SUCCESS);
248 OSMO_ASSERT(vty->node == ENABLE_NODE);
249 OSMO_ASSERT(do_vty_command(vty, "configure terminal") == CMD_SUCCESS);
250 OSMO_ASSERT(vty->node == CONFIG_NODE);
251
252 /* Try to create invalid reporter */
253 OSMO_ASSERT(do_vty_command(vty, "stats reporter foobar") ==
254 CMD_ERR_NO_MATCH);
255
256 /* Set reporting interval */
257 OSMO_ASSERT(do_vty_command(vty, "stats interval 42") == CMD_SUCCESS);
258 OSMO_ASSERT(osmo_stats_config->interval == 42);
259
260 /* Create log reporter */
261 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL);
262 OSMO_ASSERT(srep == NULL);
263 OSMO_ASSERT(do_vty_command(vty, "stats reporter log") == CMD_SUCCESS);
264 OSMO_ASSERT(vty->node == CFG_STATS_NODE);
265 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL);
266 OSMO_ASSERT(srep != NULL);
267 OSMO_ASSERT(srep->type == OSMO_STATS_REPORTER_LOG);
268 check_srep_vty_config(vty, srep);
269 OSMO_ASSERT(do_vty_command(vty, "exit") == CMD_SUCCESS);
270 OSMO_ASSERT(vty->node == CONFIG_NODE);
271
272 /* Create statsd reporter */
273 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL);
274 OSMO_ASSERT(srep == NULL);
275 OSMO_ASSERT(do_vty_command(vty, "stats reporter statsd") == CMD_SUCCESS);
276 OSMO_ASSERT(vty->node == CFG_STATS_NODE);
277 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL);
278 OSMO_ASSERT(srep != NULL);
279 OSMO_ASSERT(srep->type == OSMO_STATS_REPORTER_STATSD);
280 check_srep_vty_config(vty, srep);
281 OSMO_ASSERT(do_vty_command(vty, "exit") == CMD_SUCCESS);
282 OSMO_ASSERT(vty->node == CONFIG_NODE);
283
284 /* Destroy log reporter */
285 OSMO_ASSERT(osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL));
286 OSMO_ASSERT(do_vty_command(vty, "no stats reporter log") == CMD_SUCCESS);
287 OSMO_ASSERT(!osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL));
288
289 /* Destroy statsd reporter */
290 OSMO_ASSERT(osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL));
291 OSMO_ASSERT(do_vty_command(vty, "no stats reporter statsd") == CMD_SUCCESS);
292 OSMO_ASSERT(!osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL));
293
294 destroy_test_vty(&test, vty);
295}
296
Neels Hofmeyr4a31ffa2017-09-07 03:08:06 +0200297void test_exit_by_indent(const char *fname, int expect_rc)
298{
299 int rc;
300 printf("reading file %s, expecting rc=%d\n", fname, expect_rc);
301 rc = vty_read_config_file(fname, NULL);
302 printf("got rc=%d\n", rc);
303 OSMO_ASSERT(rc == expect_rc);
304}
305
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200306enum test_nodes {
307 LEVEL1_NODE = _LAST_OSMOVTY_NODE + 1,
308 LEVEL2_NODE,
309 LEVEL3_NODE,
310};
311
312struct cmd_node level1_node = {
313 LEVEL1_NODE,
314 "%s(config-level1)# ",
315 1
316};
317
318struct cmd_node level2_node = {
319 LEVEL2_NODE,
320 "%s(config-level1-level2)# ",
321 1
322};
323
324struct cmd_node level3_node = {
325 LEVEL3_NODE,
326 "%s(config-level1-level2-level3)# ",
327 1
328};
329
330DEFUN(cfg_level1, cfg_level1_cmd,
331 "level1 [MARKER]",
332 "Level 1 node for VTY testing purposes\n"
333 "optional string to mark the line for test debugging\n")
334{
335 vty->index = NULL;
336 vty->node = LEVEL1_NODE;
337 printf("called level1 node %s\n", argc? argv[0] : "");
338 return CMD_SUCCESS;
339}
340
341DEFUN(cfg_level1_child, cfg_level1_child_cmd,
342 "child1 [MARKER]",
343 "Level 1 child cmd for VTY testing purposes\n"
344 "optional string to mark the line for test debugging\n")
345{
346 printf("called level1 child cmd %s\n", argc? argv[0] : "");
347 return CMD_SUCCESS;
348}
349
350DEFUN(cfg_level2, cfg_level2_cmd,
351 "level2 [MARKER]",
352 "Level 2 node for VTY testing purposes\n"
353 "optional string to mark the line for test debugging\n")
354{
355 vty->index = NULL;
356 vty->node = LEVEL2_NODE;
357 printf("called level2 node %s\n", argc? argv[0] : "");
358 return CMD_SUCCESS;
359}
360
361DEFUN(cfg_level2_child, cfg_level2_child_cmd,
362 "child2 [MARKER]",
363 "Level 2 child cmd for VTY testing purposes\n"
364 "optional string to mark the line for test debugging\n")
365{
366 printf("called level2 child cmd %s\n", argc? argv[0] : "");
367 return CMD_SUCCESS;
368}
369
370DEFUN(cfg_level3, cfg_level3_cmd,
371 "level3 [MARKER]",
372 "Level 3 node for VTY testing purposes\n"
373 "optional string to mark the line for test debugging\n")
374{
375 vty->index = NULL;
376 vty->node = LEVEL3_NODE;
377 printf("called level3 node %s\n", argc? argv[0] : "");
378 return CMD_SUCCESS;
379}
380
381DEFUN(cfg_level3_child, cfg_level3_child_cmd,
382 "child3 [MARKER]",
383 "Level 3 child cmd for VTY testing purposes\n"
384 "optional string to mark the line for test debugging\n")
385{
386 printf("called level3 child cmd %s\n", argc? argv[0] : "");
387 return CMD_SUCCESS;
388}
389
Neels Hofmeyr5314c512018-07-09 23:22:21 +0200390DEFUN(cfg_ambiguous_nr_1, cfg_ambiguous_nr_1_cmd,
391 "ambiguous_nr [<0-23>]",
392 "testing is_cmd_ambiguous()\n"
393 "optional number arg\n")
394{
395 printf("Called: 'ambiguous_nr [<0-23>]' (argc=%d)\n", argc);
396 return CMD_SUCCESS;
397}
398
399DEFUN(cfg_ambiguous_nr_2, cfg_ambiguous_nr_2_cmd,
400 "ambiguous_nr <0-23> keyword",
401 "testing is_cmd_ambiguous()\n"
402 "optional number arg\n")
403{
404 printf("Called: 'ambiguous_nr <0-23> keyword'\n");
405 return CMD_SUCCESS;
406}
407
408DEFUN(cfg_ambiguous_str_1, cfg_ambiguous_str_1_cmd,
409 "ambiguous_str [ARG]",
410 "testing is_cmd_ambiguous()\n"
411 "optional string arg\n")
412{
413 printf("Called: 'ambiguous_str [ARG]' (argc=%d)\n", argc);
414 return CMD_SUCCESS;
415}
416
417DEFUN(cfg_ambiguous_str_2, cfg_ambiguous_str_2_cmd,
418 "ambiguous_str ARG keyword",
419 "testing is_cmd_ambiguous()\n"
420 "optional string arg\n")
421{
422 printf("Called: 'ambiguous_str ARG keyword'\n");
423 return CMD_SUCCESS;
424}
425
Pau Espin Pedrola0c81952019-10-22 18:38:01 +0200426DEFUN(cfg_ret_success, cfg_ret_success_cmd,
427 "return-success",
428 "testing return success\n")
429{
430 printf("Called: 'return-success'\n");
431 return CMD_SUCCESS;
432}
433
434DEFUN(cfg_ret_warning, cfg_ret_warning_cmd,
435 "return-warning",
436 "testing return warning\n")
437{
438 printf("Called: 'return-warning'\n");
439 return CMD_WARNING;
440}
441
Pau Espin Pedrold92be9a2020-07-30 14:55:49 +0200442DEFUN(cfg_numeric_range, cfg_numeric_range_cmd,
443#if ULONG_MAX == 18446744073709551615UL
444 "numeric-range <0-18446744073709551615>",
445#else
446 "numeric-range <0-4294967295>",
447#endif
448 "testing numeric range\n"
449 "the numeric range\n")
450{
451 printf("Called: 'return-success'\n");
452 return CMD_SUCCESS;
453}
454
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200455void test_vty_add_cmds()
456{
Pau Espin Pedrola0c81952019-10-22 18:38:01 +0200457 install_element(CONFIG_NODE, &cfg_ret_warning_cmd);
458 install_element(CONFIG_NODE, &cfg_ret_success_cmd);
459
Vadim Yanitskiy4abda9e2019-11-21 00:19:36 +0700460 logging_vty_add_deprecated_subsys(tall_log_ctx, "depr");
461
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200462 install_element(CONFIG_NODE, &cfg_level1_cmd);
463 install_node(&level1_node, NULL);
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200464 install_element(LEVEL1_NODE, &cfg_level1_child_cmd);
465 install_element(LEVEL1_NODE, &cfg_level2_cmd);
466
467 install_node(&level2_node, NULL);
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200468 install_element(LEVEL2_NODE, &cfg_level2_child_cmd);
469 install_element(LEVEL2_NODE, &cfg_level3_cmd);
470
471 install_node(&level3_node, NULL);
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200472 install_element(LEVEL3_NODE, &cfg_level3_child_cmd);
Neels Hofmeyr5314c512018-07-09 23:22:21 +0200473
474 install_element_ve(&cfg_ambiguous_nr_1_cmd);
475 install_element_ve(&cfg_ambiguous_nr_2_cmd);
476 install_element_ve(&cfg_ambiguous_str_1_cmd);
477 install_element_ve(&cfg_ambiguous_str_2_cmd);
Pau Espin Pedrold92be9a2020-07-30 14:55:49 +0200478
479 install_element_ve(&cfg_numeric_range_cmd);
Neels Hofmeyr5314c512018-07-09 23:22:21 +0200480}
481
482void test_is_cmd_ambiguous()
483{
484 struct vty *vty;
485 struct vty_test test;
486
487 printf("Going to test is_cmd_ambiguous()\n");
488 vty = create_test_vty(&test);
489
490 OSMO_ASSERT(do_vty_command(vty, "ambiguous_nr") == CMD_SUCCESS);
491 OSMO_ASSERT(do_vty_command(vty, "ambiguous_nr 23") == CMD_SUCCESS);
492 OSMO_ASSERT(do_vty_command(vty, "ambiguous_nr 23 keyword") == CMD_SUCCESS);
493
494 OSMO_ASSERT(do_vty_command(vty, "ambiguous_str") == CMD_SUCCESS);
495 OSMO_ASSERT(do_vty_command(vty, "ambiguous_str arg") == CMD_SUCCESS);
496 OSMO_ASSERT(do_vty_command(vty, "ambiguous_str arg keyword") == CMD_SUCCESS);
497
498 destroy_test_vty(&test, vty);
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200499}
500
Pau Espin Pedrold92be9a2020-07-30 14:55:49 +0200501void test_numeric_range()
502{
503 struct vty *vty;
504 struct vty_test test;
505
506 printf("Going to test test_numeric_range()\n");
507 vty = create_test_vty(&test);
508
Pau Espin Pedrol9fdc8712020-07-30 14:56:38 +0200509 OSMO_ASSERT(do_vty_command(vty, "numeric-range 0") == CMD_SUCCESS);
510 OSMO_ASSERT(do_vty_command(vty, "numeric-range 40000") == CMD_SUCCESS);
Pau Espin Pedrola1847012020-07-28 17:44:48 +0200511 OSMO_ASSERT(do_vty_command(vty, "numeric-range -400000") == CMD_ERR_NO_MATCH);
Pau Espin Pedrold92be9a2020-07-30 14:55:49 +0200512
513 destroy_test_vty(&test, vty);
514}
515
Vadim Yanitskiy024e1952020-10-02 18:23:38 +0700516/* Application specific attributes */
517enum vty_test_attr {
518 VTY_TEST_ATTR_FOO = 0,
519 VTY_TEST_ATTR_BAR,
520 VTY_TEST_ATTR_ZOO,
521 VTY_TEST_ATTR_FOO_DUP,
522 VTY_TEST_ATTR_ZOO_DUP,
Vadim Yanitskiyf94355d2020-10-03 17:43:37 +0700523 VTY_TEST_ATTR_UPPER,
Vadim Yanitskiyef4c5972020-10-07 13:44:31 +0700524 VTY_TEST_ATTR_RAFC_DOT,
525 VTY_TEST_ATTR_RAFC_EXCL,
526 VTY_TEST_ATTR_RAFC_AT,
Vadim Yanitskiy024e1952020-10-02 18:23:38 +0700527};
528
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +0200529int main(int argc, char **argv)
530{
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100531 struct vty_app_info vty_info = {
532 .name = "VtyTest",
533 .version = 0,
Vadim Yanitskiy024e1952020-10-02 18:23:38 +0700534 .usr_attr_letters = {
535 [VTY_TEST_ATTR_FOO] = 'f',
536 [VTY_TEST_ATTR_BAR] = 'b',
537 [VTY_TEST_ATTR_ZOO] = 'z',
538
539 /* Duplicate detection check */
540 [VTY_TEST_ATTR_FOO_DUP] = 'f',
541 [VTY_TEST_ATTR_ZOO_DUP] = 'z',
Vadim Yanitskiyf94355d2020-10-03 17:43:37 +0700542 /* Reserved for libraries */
543 [VTY_TEST_ATTR_UPPER] = 'X',
Vadim Yanitskiyef4c5972020-10-07 13:44:31 +0700544 /* Reserved for global attribues */
545 [VTY_TEST_ATTR_RAFC_DOT] '.',
546 [VTY_TEST_ATTR_RAFC_EXCL] '!',
547 [VTY_TEST_ATTR_RAFC_AT] '@',
Vadim Yanitskiy024e1952020-10-02 18:23:38 +0700548 },
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100549 };
550
551 const struct log_info_cat default_categories[] = {};
552
553 const struct log_info log_info = {
554 .cat = default_categories,
555 .num_cat = ARRAY_SIZE(default_categories),
556 };
Neels Hofmeyra829b452018-04-05 03:02:35 +0200557 void *stats_ctx;
558
559 ctx = talloc_named_const(NULL, 0, "stats test context");
560 stats_ctx = talloc_named_const(ctx, 1, "stats test context");
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100561
Holger Hans Peter Freyther2c9168c2013-10-10 20:21:33 +0200562 osmo_signal_register_handler(SS_L_VTY, vty_event_cb, NULL);
563
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100564 /* Fake logging. */
Neels Hofmeyra829b452018-04-05 03:02:35 +0200565 osmo_init_logging2(ctx, &log_info);
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100566
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100567 /* Init stats */
568 osmo_stats_init(stats_ctx);
569
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100570 vty_init(&vty_info);
571
572 /* Setup VTY commands */
Maxc65c5b42017-03-15 13:20:23 +0100573 logging_vty_add_cmds();
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100574 osmo_stats_vty_add_cmds();
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100575
Neels Hofmeyrb022c862017-09-20 01:49:11 +0200576 test_vty_add_cmds();
577
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +0200578 test_cmd_string_from_valstr();
Jacob Erlbeck0c987bd2013-09-06 16:52:00 +0200579 test_node_tree_structure();
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100580 test_stats_vty();
Neels Hofmeyr4a31ffa2017-09-07 03:08:06 +0200581 test_exit_by_indent("ok.cfg", 0);
582 test_exit_by_indent("ok_more_spaces.cfg", 0);
583 test_exit_by_indent("ok_tabs.cfg", 0);
584 test_exit_by_indent("ok_tabs_and_spaces.cfg", 0);
585 test_exit_by_indent("ok_ignore_comment.cfg", 0);
586 test_exit_by_indent("ok_ignore_blank.cfg", 0);
587 test_exit_by_indent("fail_not_de-indented.cfg", -EINVAL);
588 test_exit_by_indent("fail_too_much_indent.cfg", -EINVAL);
589 test_exit_by_indent("fail_tabs_and_spaces.cfg", -EINVAL);
590 test_exit_by_indent("ok_indented_root.cfg", 0);
Neels Hofmeyr43063632017-09-19 23:54:01 +0200591 test_exit_by_indent("ok_empty_parent.cfg", 0);
Pau Espin Pedrola0c81952019-10-22 18:38:01 +0200592 test_exit_by_indent("fail_cmd_ret_warning.cfg", -EINVAL);
Vadim Yanitskiy4abda9e2019-11-21 00:19:36 +0700593 test_exit_by_indent("ok_deprecated_logging.cfg", 0);
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100594
Neels Hofmeyr5314c512018-07-09 23:22:21 +0200595 test_is_cmd_ambiguous();
596
Pau Espin Pedrold92be9a2020-07-30 14:55:49 +0200597 test_numeric_range();
598
Jacob Erlbeckbe37fb72015-11-03 15:21:34 +0100599 /* Leak check */
600 OSMO_ASSERT(talloc_total_blocks(stats_ctx) == 1);
Jacob Erlbeckca6602f2015-11-03 13:47:11 +0100601
Jacob Erlbeckae15a2c2013-08-06 14:29:14 +0200602 printf("All tests passed\n");
603
604 return 0;
605}