[MERGED] libosmocore[master]: VTY: implicit node exit by de-indenting, not parent lookup

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Tue Sep 19 01:35:30 UTC 2017


Neels Hofmeyr has submitted this change and it was merged.

Change subject: VTY: implicit node exit by de-indenting, not parent lookup
......................................................................


VTY: implicit node exit by de-indenting, not parent lookup

Note: This will break users' config files if they do not use consistent
indenting. (see below for a definition of "consistent".)

When reading VTY commands from a file, use indenting as means to implicitly
exit child nodes. Do not look for commands in the parent node implicitly.

The VTY so far implies 'exit' commands if a VTY line cannot be parsed on the
current node, but succeeds on the parent node. That is the mechanism by which
our VTY config files do not need 'exit' at the end of each child node.

We've hit problems with this in the following scenarios, which will show
improved user experience after this patch:

*) When both a parent and its child node have commands with identical names:

  cs7 instace 0
   point-code 1.2.3
   sccp-address osmo-msc
    point-code 0.0.1

If I put the parent's command below the child, it is still interpreted in the
context of the child node:

  cs7 instace 0
   sccp-address osmo-msc
    point-code 0.0.1
   point-code 1.2.3

Though the indenting lets me assume I am setting the cs7 instance's global PC
to 1.2.3, I'm actually overwriting osmo-msc's PC with 1.2.3 and discarding the
0.0.1.

*) When a software change moves a VTY command from a child to a parent. Say
'timezone' moved from 'bts' to 'network' level:

  network
   timezone 1 2

Say a user still has an old config file with 'timezone' on the child level:

  network
   bts 0
    timezone 1 2
    trx 0

The user would expect an error message that 'timezone' is invalid on the 'bts'
level. Instead, the VTY finds the parent node's 'timezone', steps out of 'bts'
to the 'network' level, and instead says that the 'trx' command does not exist.

Format:

Consistent means that two adjacent indenting lines have the exact
same indenting characters for the common length:

Weird mix if you ask me, but correct and consistent:

  ROOT
  <space>PARENT
  <space><tab><space>CHILD
  <space><tab><space><tab><tab>GRANDCHILD
  <space><tab><space><tab><tab>GRANDCHILD2
  <space>SIBLING

Inconsistent:

  ROOT
  <space>PARENT
  <tab><space>CHILD
  <space><space><tab>GRANDCHILD
  <space><tab><tab>GRANDCHILD2
  <tab>SIBLING

Also, when going back to a parent level, the exact same indenting must be used
as before in that node:

Incorrect:

  ROOT
  <tab>PARENT
  <tab><tab><tab>CHILD
  <tab><tab>SIBLING

As not really intended side effect, it is also permitted to indent the entire
file starting from the root level. We could guard against it but there's no
harm:

Correct and consistent:

  <tab>ROOT
  <tab><tab>PARENT
  <tab><tab><tab><tab>CHILD
  <tab><tab>SIBLING

Implementation:

Track parent nodes state: whenever a command enters a child node, push a parent
node onto an llist to remember the exact indentation characters used for that
level.

As soon as the first line on a child node is parsed, remember this new
indentation (which must have a longer strlen() than its parent level) to apply
to all remaining child siblings and grandchildren.

If the amount of spaces that indent a following VTY command are less than this
expected indentation, call vty_go_parent() until it matches up.

At any level, if the common length of indentation characters mismatch, abort
parsing in error.

Transitions to child node are spread across VTY implementations and are hard to
change. But transitions to the parent node are all handled by vty_go_parent().
By popping a parent from the list of parents in vty_go_parent(), we can also
detect that a command has changed the node without changing the parent, hence
it must have stepped into a child node, and we can push a parent frame.

The behavior on the interactive telnet VTY remains unchanged.

Change-Id: I24cbb3f6de111f2d31110c3c484c066f1153aac9
---
M include/osmocom/vty/command.h
M include/osmocom/vty/vty.h
M src/vty/command.c
M src/vty/vty.c
M tests/Makefile.am
M tests/testsuite.at
A tests/vty/fail_not_de-indented.cfg
A tests/vty/fail_tabs_and_spaces.cfg
A tests/vty/fail_too_much_indent.cfg
A tests/vty/ok.cfg
A tests/vty/ok_ignore_blank.cfg
A tests/vty/ok_ignore_comment.cfg
A tests/vty/ok_indented_root.cfg
A tests/vty/ok_more_spaces.cfg
A tests/vty/ok_tabs.cfg
A tests/vty/ok_tabs_and_spaces.cfg
M tests/vty/vty_test.c
M tests/vty/vty_test.ok
18 files changed, 321 insertions(+), 26 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h
index 0fa5175..cb2edaa 100644
--- a/include/osmocom/vty/command.h
+++ b/include/osmocom/vty/command.h
@@ -161,6 +161,7 @@
 #define CMD_COMPLETE_MATCH       8
 #define CMD_COMPLETE_LIST_MATCH  9
 #define CMD_SUCCESS_DAEMON      10
+#define CMD_ERR_INVALID_INDENT  11
 
 /* Argc max counts. */
 #define CMD_ARGC_MAX   256
@@ -368,6 +369,7 @@
 char *argv_concat(const char **argv, int argc, int shift);
 
 vector cmd_make_strvec(const char *);
+int cmd_make_strvec2(const char *string, char **indent, vector *strvec_p);
 void cmd_free_strvec(vector);
 vector cmd_describe_command();
 char **cmd_complete_command();
diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h
index 544e1fa..02ba03e 100644
--- a/include/osmocom/vty/vty.h
+++ b/include/osmocom/vty/vty.h
@@ -3,6 +3,8 @@
 #include <stdio.h>
 #include <stdarg.h>
 
+#include <osmocom/core/linuxlist.h>
+
 /*! \defgroup vty VTY (Virtual TTY) interface
  *  @{
  * \file vty.h */
@@ -43,6 +45,20 @@
 	VTY_FILE,
 	VTY_SHELL,
 	VTY_SHELL_SERV
+};
+
+struct vty_parent_node {
+	struct llist_head entry;
+
+	/*! private data, specified by creator */
+	void *priv;
+
+	/*! Node status of this vty */
+	int node;
+
+	/*! When reading from a config file, these are the indenting characters expected for children of
+	 * this VTY node. */
+	char *indent;
 };
 
 /*! Internal representation of a single VTY */
@@ -134,6 +150,13 @@
 
 	/*! In configure mode. */
 	int config;
+
+	/*! List of parent nodes, last item is the outermost parent. */
+	struct llist_head parent_nodes;
+
+	/*! When reading from a config file, these are the indenting characters expected for children of
+	 * the current VTY node. */
+	char *indent;
 };
 
 /* Small macro to determine newline is newline only or linefeed needed. */
diff --git a/src/vty/command.c b/src/vty/command.c
index 52c7191..a65b4de 100644
--- a/src/vty/command.c
+++ b/src/vty/command.c
@@ -190,31 +190,56 @@
 		}
 }
 
-/*! Breaking up string into each command piece. I assume given
-   character is separated by a space character. Return value is a
-   vector which includes char ** data element. */
-vector cmd_make_strvec(const char *string)
+/*! Break up string in command tokens. Return leading indents.
+ * \param[in] string  String to split.
+ * \param[out] indent  If not NULL, return a talloc_strdup of indent characters.
+ * \param[out] strvec_p  Returns vector of split tokens, must not be NULL.
+ * \returns CMD_SUCCESS or CMD_ERR_INVALID_INDENT
+ *
+ * If \a indent is passed non-NULL, only simple space ' ' indents are allowed,
+ * so that \a indent can simply return the count of leading spaces.
+ * Otherwise any isspace() characters are allowed for indenting (backwards compat).
+ */
+int cmd_make_strvec2(const char *string, char **indent, vector *strvec_p)
 {
 	const char *cp, *start;
 	char *token;
 	int strlen;
 	vector strvec;
 
+	*strvec_p = NULL;
+	if (indent)
+		*indent = 0;
+
 	if (string == NULL)
-		return NULL;
+		return CMD_SUCCESS;
 
 	cp = string;
 
 	/* Skip white spaces. */
-	while (isspace((int)*cp) && *cp != '\0')
+	while (isspace((int)*cp) && *cp != '\0') {
+		/* if we're counting indents, we need to be strict about them */
+		if (indent && (*cp != ' ') && (*cp != '\t')) {
+			/* Ignore blank lines, they appear as leading whitespace with line breaks. */
+			if (*cp == '\n' || *cp == '\r') {
+				cp++;
+				string = cp;
+				continue;
+			}
+			return CMD_ERR_INVALID_INDENT;
+		}
 		cp++;
+	}
+
+	if (indent)
+		*indent = talloc_strndup(tall_vty_cmd_ctx, string, cp - string);
 
 	/* Return if there is only white spaces */
 	if (*cp == '\0')
-		return NULL;
+		return CMD_SUCCESS;
 
 	if (*cp == '!' || *cp == '#')
-		return NULL;
+		return CMD_SUCCESS;
 
 	/* Prepare return vector. */
 	strvec = vector_init(VECTOR_MIN_SIZE);
@@ -236,8 +261,21 @@
 			cp++;
 
 		if (*cp == '\0')
-			return strvec;
+			break;
 	}
+
+	*strvec_p = strvec;
+	return CMD_SUCCESS;
+}
+
+/*! Breaking up string into each command piece. I assume given
+   character is separated by a space character. Return value is a
+   vector which includes char ** data element. */
+vector cmd_make_strvec(const char *string)
+{
+	vector strvec;
+	cmd_make_strvec2(string, NULL, &strvec);
+	return strvec;
 }
 
 /*! Free allocated string vector. */
@@ -1947,6 +1985,33 @@
 	return cmd_complete_command_real(vline, vty, status);
 }
 
+static struct vty_parent_node *vty_parent(struct vty *vty)
+{
+	return llist_first_entry_or_null(&vty->parent_nodes,
+					 struct vty_parent_node,
+					 entry);
+}
+
+static bool vty_pop_parent(struct vty *vty)
+{
+	struct vty_parent_node *parent = vty_parent(vty);
+	if (!parent)
+		return false;
+	llist_del(&parent->entry);
+	vty->node = parent->node;
+	vty->priv = parent->priv;
+	if (vty->indent)
+		talloc_free(vty->indent);
+	vty->indent = parent->indent;
+	talloc_free(parent);
+	return true;
+}
+
+static void vty_clear_parents(struct vty *vty)
+{
+	while (vty_pop_parent(vty));
+}
+
 /* return parent node */
 /*
  * This function MUST eventually converge on a node when called repeatedly,
@@ -1969,24 +2034,33 @@
 		case VIEW_NODE:
 		case ENABLE_NODE:
 		case CONFIG_NODE:
+			vty_clear_parents(vty);
 			break;
 
 		case AUTH_ENABLE_NODE:
 			vty->node = VIEW_NODE;
+			vty_clear_parents(vty);
 			break;
 
 		case CFG_LOG_NODE:
 		case VTY_NODE:
 			vty->node = CONFIG_NODE;
+			vty_clear_parents(vty);
 			break;
 
 		default:
-			if (host.app_info->go_parent_cb)
+			if (host.app_info->go_parent_cb) {
 				host.app_info->go_parent_cb(vty);
-			else if (is_config_child(vty))
+				vty_pop_parent(vty);
+			}
+			else if (is_config_child(vty)) {
 				vty->node = CONFIG_NODE;
-			else
+				vty_clear_parents(vty);
+			}
+			else {
 				vty->node = VIEW_NODE;
+				vty_clear_parents(vty);
+			}
 			break;
 	}
 
@@ -2252,36 +2326,130 @@
 	return (*matched_element->func) (matched_element, vty, argc, argv);
 }
 
+static inline size_t len(const char *str)
+{
+	return str? strlen(str) : 0;
+}
+
+static int indent_cmp(const char *a, const char *b)
+{
+	size_t al, bl;
+	al = len(a);
+	bl = len(b);
+	if (al > bl) {
+		if (bl && strncmp(a, b, bl) != 0)
+			return EINVAL;
+		return 1;
+	}
+	/* al <= bl */
+	if (al && strncmp(a, b, al) != 0)
+		return EINVAL;
+	return (al < bl)? -1 : 0;
+}
+
 /* Configration make from file. */
 int config_from_file(struct vty *vty, FILE * fp)
 {
 	int ret;
 	vector vline;
+	char *indent;
+	int cmp;
+	struct vty_parent_node this_node;
+	struct vty_parent_node *parent;
 
 	while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
-		vline = cmd_make_strvec(vty->buf);
+		indent = NULL;
+		vline = NULL;
+		ret = cmd_make_strvec2(vty->buf, &indent, &vline);
 
-		/* In case of comment line */
-		if (vline == NULL)
+		if (ret != CMD_SUCCESS)
+			goto return_invalid_indent;
+
+		/* In case of comment or empty line */
+		if (vline == NULL) {
+			if (indent) {
+				talloc_free(indent);
+				indent = NULL;
+			}
 			continue;
-		/* Execute configuration command : this is strict match */
-		ret = cmd_execute_command_strict(vline, vty, NULL);
-
-		/* Try again with setting node to CONFIG_NODE */
-		while (ret != CMD_SUCCESS && ret != CMD_WARNING
-		       && ret != CMD_ERR_NOTHING_TODO
-		       && is_config_child(vty)) {
-			vty_go_parent(vty);
-			ret = cmd_execute_command_strict(vline, vty, NULL);
 		}
 
+		/* We have a nonempty line. This might be the first on a deeper indenting level, so let's
+		 * remember this indent if we don't have one yet. */
+		if (!vty->indent)
+			vty->indent = talloc_strdup(vty, indent);
+
+		cmp = indent_cmp(indent, vty->indent);
+		if (cmp == EINVAL)
+			goto return_invalid_indent;
+
+		/* Less indent: go up the parent nodes to find matching amount of less indent. When this
+		 * loop exits, we want to have found an exact match, i.e. cmp == 0. */
+		while (cmp < 0) {
+			vty_go_parent(vty);
+			cmp = indent_cmp(indent, vty->indent);
+			if (cmp == EINVAL)
+				goto return_invalid_indent;
+		}
+
+		/* More indent without having entered a child node level? Either the parent node's indent
+		 * wasn't hit exactly (e.g. there's a space more than the parent level had further above)
+		 * or the indentation increased even though the vty command didn't enter a child. */
+		if (cmp > 0)
+			goto return_invalid_indent;
+
+		/* Remember the current node before the command possibly changes it. */
+		this_node = (struct vty_parent_node){
+				.node = vty->node,
+				.priv = vty->priv,
+				.indent = vty->indent,
+			};
+
+		parent = vty_parent(vty);
+		ret = cmd_execute_command_strict(vline, vty, NULL);
 		cmd_free_strvec(vline);
 
 		if (ret != CMD_SUCCESS && ret != CMD_WARNING
-		    && ret != CMD_ERR_NOTHING_TODO)
+		    && ret != CMD_ERR_NOTHING_TODO) {
+			if (indent) {
+				talloc_free(indent);
+				indent = NULL;
+			}
 			return ret;
+		}
+
+		/* If we have stepped down into a child node, push a parent frame.
+		 * The causality is such: we don't expect every single node entry implementation to push
+		 * a parent node entry onto vty->parent_nodes. Instead we expect vty_go_parent() to *pop*
+		 * a parent node. Hence if the node changed without the parent node changing, we must
+		 * have stepped into a child node (and now expect a deeper indent). */
+		if (vty->node != this_node.node && parent == vty_parent(vty)) {
+			/* Push the parent node. */
+			parent = talloc_zero(vty, struct vty_parent_node);
+			*parent = this_node;
+			llist_add(&parent->entry, &vty->parent_nodes);
+
+			/* The current talloc'ed vty->indent string will now be owned by this parent
+			 * struct. Indicate that we don't know what deeper indent characters the user
+			 * will choose. */
+			vty->indent = NULL;
+		}
+
+		if (indent) {
+			talloc_free(indent);
+			indent = NULL;
+		}
 	}
 	return CMD_SUCCESS;
+
+return_invalid_indent:
+	if (vline)
+		cmd_free_strvec(vline);
+	if (indent) {
+		talloc_free(indent);
+		indent = NULL;
+	}
+	return CMD_ERR_INVALID_INDENT;
 }
 
 /* Configration from terminal */
diff --git a/src/vty/vty.c b/src/vty/vty.c
index 113a781..bd0d2c3 100644
--- a/src/vty/vty.c
+++ b/src/vty/vty.c
@@ -110,6 +110,8 @@
 	if (!new)
 		goto out;
 
+	INIT_LLIST_HEAD(&new->parent_nodes);
+
 	new->obuf = buffer_new(new, 0);	/* Use default buffer size. */
 	if (!new->obuf)
 		goto out_new;
@@ -1480,6 +1482,12 @@
 		case CMD_ERR_NO_MATCH:
 			fprintf(stderr, "There is no such command.\n");
 			break;
+		case CMD_ERR_INVALID_INDENT:
+			fprintf(stderr,
+				"Inconsistent indentation -- leading whitespace must match adjacent lines, and\n"
+				"indentation must reflect child node levels. A mix of tabs and spaces is\n"
+				"allowed, but their sequence must not change within a child block.\n");
+			break;
 		}
 		fprintf(stderr, "Error occurred during reading the below "
 			"line:\n%s\n", vty->buf);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 37378fb..8935bf7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -217,7 +217,18 @@
              logging/logging_test.ok logging/logging_test.err		\
              fr/fr_test.ok loggingrb/logging_test.ok			\
              loggingrb/logging_test.err	strrb/strrb_test.ok		\
-	     vty/vty_test.ok comp128/comp128_test.ok			\
+	     vty/vty_test.ok \
+	     vty/fail_not_de-indented.cfg \
+	     vty/fail_tabs_and_spaces.cfg \
+	     vty/fail_too_much_indent.cfg \
+	     vty/ok.cfg \
+	     vty/ok_ignore_blank.cfg \
+	     vty/ok_ignore_comment.cfg \
+	     vty/ok_indented_root.cfg \
+	     vty/ok_more_spaces.cfg \
+	     vty/ok_tabs_and_spaces.cfg \
+	     vty/ok_tabs.cfg \
+	     comp128/comp128_test.ok					\
 	     utils/utils_test.ok stats/stats_test.ok			\
 	     bitvec/bitvec_test.ok msgb/msgb_test.ok bits/bitcomp_test.ok \
 	     sim/sim_test.ok tlv/tlv_test.ok abis/abis_test.ok		\
diff --git a/tests/testsuite.at b/tests/testsuite.at
index f148cf5..1954e66 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -174,6 +174,7 @@
 AT_SETUP([vty])
 AT_KEYWORDS([vty])
 cat $abs_srcdir/vty/vty_test.ok > expout
+cp $abs_srcdir/vty/*.cfg .
 AT_CHECK([$abs_top_builddir/tests/vty/vty_test], [0], [expout], [ignore])
 AT_CLEANUP
 
diff --git a/tests/vty/fail_not_de-indented.cfg b/tests/vty/fail_not_de-indented.cfg
new file mode 100644
index 0000000..5af833d
--- /dev/null
+++ b/tests/vty/fail_not_de-indented.cfg
@@ -0,0 +1,3 @@
+line vty
+ no login
+ log stderr
diff --git a/tests/vty/fail_tabs_and_spaces.cfg b/tests/vty/fail_tabs_and_spaces.cfg
new file mode 100644
index 0000000..fa6ce05
--- /dev/null
+++ b/tests/vty/fail_tabs_and_spaces.cfg
@@ -0,0 +1,4 @@
+line vty
+ 		no login
+	 	no login
+log stderr
diff --git a/tests/vty/fail_too_much_indent.cfg b/tests/vty/fail_too_much_indent.cfg
new file mode 100644
index 0000000..bacb3e1
--- /dev/null
+++ b/tests/vty/fail_too_much_indent.cfg
@@ -0,0 +1,3 @@
+line vty
+  no login
+ log stderr
diff --git a/tests/vty/ok.cfg b/tests/vty/ok.cfg
new file mode 100644
index 0000000..d5ef23e
--- /dev/null
+++ b/tests/vty/ok.cfg
@@ -0,0 +1,3 @@
+line vty
+ no login
+log stderr
diff --git a/tests/vty/ok_ignore_blank.cfg b/tests/vty/ok_ignore_blank.cfg
new file mode 100644
index 0000000..d16ff64
--- /dev/null
+++ b/tests/vty/ok_ignore_blank.cfg
@@ -0,0 +1,7 @@
+line vty
+
+  no login
+
+  no login
+
+log stderr
diff --git a/tests/vty/ok_ignore_comment.cfg b/tests/vty/ok_ignore_comment.cfg
new file mode 100644
index 0000000..5813fc7
--- /dev/null
+++ b/tests/vty/ok_ignore_comment.cfg
@@ -0,0 +1,7 @@
+line vty
+  ! comment
+  no login
+! comment
+  no login
+     ! comment
+log stderr
diff --git a/tests/vty/ok_indented_root.cfg b/tests/vty/ok_indented_root.cfg
new file mode 100644
index 0000000..313c674
--- /dev/null
+++ b/tests/vty/ok_indented_root.cfg
@@ -0,0 +1,3 @@
+	line vty
+	 no login
+	log stderr
diff --git a/tests/vty/ok_more_spaces.cfg b/tests/vty/ok_more_spaces.cfg
new file mode 100644
index 0000000..b66a9c2
--- /dev/null
+++ b/tests/vty/ok_more_spaces.cfg
@@ -0,0 +1,4 @@
+line vty
+  no login
+  no login
+log stderr
diff --git a/tests/vty/ok_tabs.cfg b/tests/vty/ok_tabs.cfg
new file mode 100644
index 0000000..e94609b
--- /dev/null
+++ b/tests/vty/ok_tabs.cfg
@@ -0,0 +1,4 @@
+line vty
+	no login
+	no login
+log stderr
diff --git a/tests/vty/ok_tabs_and_spaces.cfg b/tests/vty/ok_tabs_and_spaces.cfg
new file mode 100644
index 0000000..2049b73
--- /dev/null
+++ b/tests/vty/ok_tabs_and_spaces.cfg
@@ -0,0 +1,4 @@
+line vty
+	  no login
+	  no login
+log stderr
diff --git a/tests/vty/vty_test.c b/tests/vty/vty_test.c
index d84bf41..eba9995 100644
--- a/tests/vty/vty_test.c
+++ b/tests/vty/vty_test.c
@@ -19,6 +19,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -288,6 +289,15 @@
 	destroy_test_vty(&test, vty);
 }
 
+void test_exit_by_indent(const char *fname, int expect_rc)
+{
+	int rc;
+	printf("reading file %s, expecting rc=%d\n", fname, expect_rc);
+	rc = vty_read_config_file(fname, NULL);
+	printf("got rc=%d\n", rc);
+	OSMO_ASSERT(rc == expect_rc);
+}
+
 int main(int argc, char **argv)
 {
 	struct vty_app_info vty_info = {
@@ -322,6 +332,16 @@
 	test_cmd_string_from_valstr();
 	test_node_tree_structure();
 	test_stats_vty();
+	test_exit_by_indent("ok.cfg", 0);
+	test_exit_by_indent("ok_more_spaces.cfg", 0);
+	test_exit_by_indent("ok_tabs.cfg", 0);
+	test_exit_by_indent("ok_tabs_and_spaces.cfg", 0);
+	test_exit_by_indent("ok_ignore_comment.cfg", 0);
+	test_exit_by_indent("ok_ignore_blank.cfg", 0);
+	test_exit_by_indent("fail_not_de-indented.cfg", -EINVAL);
+	test_exit_by_indent("fail_too_much_indent.cfg", -EINVAL);
+	test_exit_by_indent("fail_tabs_and_spaces.cfg", -EINVAL);
+	test_exit_by_indent("ok_indented_root.cfg", 0);
 
 	/* Leak check */
 	OSMO_ASSERT(talloc_total_blocks(stats_ctx) == 1);
diff --git a/tests/vty/vty_test.ok b/tests/vty/vty_test.ok
index 2b6d5a6..b2df1a1 100644
--- a/tests/vty/vty_test.ok
+++ b/tests/vty/vty_test.ok
@@ -108,4 +108,24 @@
 Returned: 0, Current node: 4 '%s(config)# '
 Going to execute 'no stats reporter statsd'
 Returned: 0, Current node: 4 '%s(config)# '
+reading file ok.cfg, expecting rc=0
+got rc=0
+reading file ok_more_spaces.cfg, expecting rc=0
+got rc=0
+reading file ok_tabs.cfg, expecting rc=0
+got rc=0
+reading file ok_tabs_and_spaces.cfg, expecting rc=0
+got rc=0
+reading file ok_ignore_comment.cfg, expecting rc=0
+got rc=0
+reading file ok_ignore_blank.cfg, expecting rc=0
+got rc=0
+reading file fail_not_de-indented.cfg, expecting rc=-22
+got rc=-22
+reading file fail_too_much_indent.cfg, expecting rc=-22
+got rc=-22
+reading file fail_tabs_and_spaces.cfg, expecting rc=-22
+got rc=-22
+reading file ok_indented_root.cfg, expecting rc=0
+got rc=0
 All tests passed

-- 
To view, visit https://gerrit.osmocom.org/3880
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I24cbb3f6de111f2d31110c3c484c066f1153aac9
Gerrit-PatchSet: 5
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>



More information about the gerrit-log mailing list