tests CHANGE cover get_keyword in YANG parser
diff --git a/src/parser_yang.c b/src/parser_yang.c
index ec5200a..77c7084 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -145,7 +145,11 @@
* @param[in] ctx yang parser context for logging.
* @param[in] c UTF8 code point of a character to check.
* @param[in] first Flag to check the first character of an identifier, which is more restricted.
- * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers.
+ * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
+ * 0 - colon not yet found (no prefix)
+ * 1 - \p c is the colon character
+ * 2 - prefix already processed, now processing the identifier
+ *
* If the identifier cannot be prefixed, NULL is expected.
* @return LY_ERR values.
*/
@@ -653,8 +657,6 @@
LY_ERR ret;
int prefix;
const char *word_start;
- /* slash: 0 - nothing, 1 - last character was '/' */
- int slash = 0;
unsigned int c;
size_t len;
@@ -665,32 +667,27 @@
/* first skip "optsep", comments */
while (**data) {
- if (slash) {
- if (**data == '/') {
+ switch (**data) {
+ case '/':
+ if ((*data)[1] == '/') {
/* one-line comment */
- MOVE_INPUT(ctx, data, 1);
+ MOVE_INPUT(ctx, data, 2);
ret = skip_comment(ctx, data, 1);
if (ret) {
return ret;
}
- } else if (**data == '*') {
+ } else if ((*data)[1] == '*') {
/* block comment */
- MOVE_INPUT(ctx, data, 1);
+ MOVE_INPUT(ctx, data, 2);
ret = skip_comment(ctx, data, 2);
if (ret) {
return ret;
}
} else {
- /* not a comment after all */
- goto keyword_start;
+ /* error - not a comment after all, keyword cannot start with slash */
+ LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
+ return LY_EVALID;
}
- slash = 0;
- }
-
- switch (**data) {
- case '/':
- slash = 1;
- ++ctx->indent;
break;
case '\n':
/* skip whitespaces (optsep) */
@@ -910,6 +907,12 @@
case '\t':
/* mandatory "sep" */
break;
+ case '{':
+ /* allowed only for input and output statements which can be without arguments */
+ if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
+ break;
+ }
+ /* fallthrough */
default:
MOVE_INPUT(ctx, data, 1);
LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
@@ -932,7 +935,7 @@
}
/* prefix is mandatory for extension instances */
- if (prefix != 1) {
+ if (prefix != 2) {
LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
return LY_EVALID;
}
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index 87b847c..60ba4ad 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -131,8 +131,13 @@
assert_int_equal(0, prefix);
assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, ':', 0, &prefix));
assert_int_equal(1, prefix);
+ assert_int_equal(LY_EVALID, check_identifierchar(&ctx, ':', 0, &prefix));
+ assert_int_equal(1, prefix);
assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, 'b', 0, &prefix));
assert_int_equal(2, prefix);
+ /* second colon is invalid */
+ assert_int_equal(LY_EVALID, check_identifierchar(&ctx, ':', 0, &prefix));
+ logbuf_assert("Invalid identifier character ':'. Line number 1.");
}
static void
@@ -293,6 +298,327 @@
str = ";";
assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
logbuf_assert("Invalid character sequence \";\", expected an argument. Line number 7.");
+}
+
+static void
+test_stmts(void **state)
+{
+ (void) state; /* unused */
+
+ struct ly_parser_ctx ctx;
+ const char *str, *p;
+ enum yang_keyword kw;
+ char *word;
+ size_t len;
+
+ ctx.ctx = NULL;
+ ctx.line = 1;
+
+ str = "\n// comment\n\tinput\t{";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_INPUT, kw);
+ assert_int_equal(5, len);
+ assert_string_equal("input\t{", word);
+ assert_string_equal("\t{", str);
+
+ str = "\t /* comment */\t output\n\t{";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_OUTPUT, kw);
+ assert_int_equal(6, len);
+ assert_string_equal("output\n\t{", word);
+ assert_string_equal("\n\t{", str);
+
+ str = "/input { "; /* invalid slash */
+ assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+ logbuf_assert("Invalid identifier first character '/'. Line number 4.");
+
+ str = "not-a-statement-nor-extension { "; /* invalid identifier */
+ assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+ logbuf_assert("Invalid character sequence \"not-a-statement-nor-extension\", expected a keyword. Line number 4.");
+
+ str = "path;"; /* missing sep after the keyword */
+ assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+ logbuf_assert("Invalid character sequence \"path;\", expected a keyword followed by a separator. Line number 4.");
+
+ str = "action ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ACTION, kw);
+ assert_int_equal(6, len);
+ str = "anydata ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ANYDATA, kw);
+ assert_int_equal(7, len);
+ str = "anyxml ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ANYXML, kw);
+ assert_int_equal(6, len);
+ str = "argument ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ARGUMENT, kw);
+ assert_int_equal(8, len);
+ str = "augment ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_AUGMENT, kw);
+ assert_int_equal(7, len);
+ str = "base ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_BASE, kw);
+ assert_int_equal(4, len);
+ str = "belongs-to ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_BELONGS_TO, kw);
+ assert_int_equal(10, len);
+ str = "bit ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_BIT, kw);
+ assert_int_equal(3, len);
+ str = "case ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_CASE, kw);
+ assert_int_equal(4, len);
+ str = "choice ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_CHOICE, kw);
+ assert_int_equal(6, len);
+ str = "config ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_CONFIG, kw);
+ assert_int_equal(6, len);
+ str = "contact ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_CONTACT, kw);
+ assert_int_equal(7, len);
+ str = "container ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_CONTAINER, kw);
+ assert_int_equal(9, len);
+ str = "default ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_DEFAULT, kw);
+ assert_int_equal(7, len);
+ str = "description ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_DESCRIPTION, kw);
+ assert_int_equal(11, len);
+ str = "deviate ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_DEVIATE, kw);
+ assert_int_equal(7, len);
+ str = "deviation ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_DEVIATION, kw);
+ assert_int_equal(9, len);
+ str = "enum ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ENUM, kw);
+ assert_int_equal(4, len);
+ str = "error-app-tag ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ERROR_APP_TAG, kw);
+ assert_int_equal(13, len);
+ str = "error-message ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ERROR_MESSAGE, kw);
+ assert_int_equal(13, len);
+ str = "extension ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_EXTENSION, kw);
+ assert_int_equal(9, len);
+ str = "feature ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_FEATURE, kw);
+ assert_int_equal(7, len);
+ str = "fraction-digits ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_FRACTION_DIGITS, kw);
+ assert_int_equal(15, len);
+ str = "grouping ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_GROUPING, kw);
+ assert_int_equal(8, len);
+ str = "identity ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_IDENTITY, kw);
+ assert_int_equal(8, len);
+ str = "if-feature ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_IF_FEATURE, kw);
+ assert_int_equal(10, len);
+ str = "import ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_IMPORT, kw);
+ assert_int_equal(6, len);
+ str = "include ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_INCLUDE, kw);
+ assert_int_equal(7, len);
+ str = "input{";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_INPUT, kw);
+ assert_int_equal(5, len);
+ str = "key ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_KEY, kw);
+ assert_int_equal(3, len);
+ str = "leaf ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_LEAF, kw);
+ assert_int_equal(4, len);
+ str = "leaf-list ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_LEAF_LIST, kw);
+ assert_int_equal(9, len);
+ str = "length ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_LENGTH, kw);
+ assert_int_equal(6, len);
+ str = "list ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_LIST, kw);
+ assert_int_equal(4, len);
+ str = "mandatory ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_MANDATORY, kw);
+ assert_int_equal(9, len);
+ str = "max-elements ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_MAX_ELEMENTS, kw);
+ assert_int_equal(12, len);
+ str = "min-elements ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_MIN_ELEMENTS, kw);
+ assert_int_equal(12, len);
+ str = "modifier ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_MODIFIER, kw);
+ assert_int_equal(8, len);
+ str = "module ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_MODULE, kw);
+ assert_int_equal(6, len);
+ str = "must ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_MUST, kw);
+ assert_int_equal(4, len);
+ str = "namespace ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_NAMESPACE, kw);
+ assert_int_equal(9, len);
+ str = "notification ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_NOTIFICATION, kw);
+ assert_int_equal(12, len);
+ str = "ordered-by ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ORDERED_BY, kw);
+ assert_int_equal(10, len);
+ str = "organization ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_ORGANIZATION, kw);
+ assert_int_equal(12, len);
+ str = "output ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_OUTPUT, kw);
+ assert_int_equal(6, len);
+ str = "path ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_PATH, kw);
+ assert_int_equal(4, len);
+ str = "pattern ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_PATTERN, kw);
+ assert_int_equal(7, len);
+ str = "position ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_POSITION, kw);
+ assert_int_equal(8, len);
+ str = "prefix ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_PREFIX, kw);
+ assert_int_equal(6, len);
+ str = "presence ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_PRESENCE, kw);
+ assert_int_equal(8, len);
+ str = "range ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_RANGE, kw);
+ assert_int_equal(5, len);
+ str = "reference ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_REFERENCE, kw);
+ assert_int_equal(9, len);
+ str = "refine ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_REFINE, kw);
+ assert_int_equal(6, len);
+ str = "require-instance ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_REQUIRE_INSTANCE, kw);
+ assert_int_equal(16, len);
+ str = "revision ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_REVISION, kw);
+ assert_int_equal(8, len);
+ str = "revision-date ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_REVISION_DATE, kw);
+ assert_int_equal(13, len);
+ str = "rpc ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_RPC, kw);
+ assert_int_equal(3, len);
+ str = "status ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_STATUS, kw);
+ assert_int_equal(6, len);
+ str = "submodule ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_SUBMODULE, kw);
+ assert_int_equal(9, len);
+ str = "type ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_TYPE, kw);
+ assert_int_equal(4, len);
+ str = "typedef ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_TYPEDEF, kw);
+ assert_int_equal(7, len);
+ str = "unique ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_UNIQUE, kw);
+ assert_int_equal(6, len);
+ str = "units ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_UNITS, kw);
+ assert_int_equal(5, len);
+ str = "uses ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_USES, kw);
+ assert_int_equal(4, len);
+ str = "value ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_VALUE, kw);
+ assert_int_equal(5, len);
+ str = "when ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_WHEN, kw);
+ assert_int_equal(4, len);
+ str = "yang-version ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_YANG_VERSION, kw);
+ assert_int_equal(12, len);
+ str = "yin-element ";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_YIN_ELEMENT, kw);
+ assert_int_equal(11, len);
+
+ /* geenric extension */
+ str = p = "nacm:default-deny-write;";
+ assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+ assert_int_equal(YANG_CUSTOM, kw);
+ assert_int_equal(23, len);
+ assert_ptr_equal(p, word);
}
@@ -302,6 +628,7 @@
cmocka_unit_test_setup(test_helpers, logger_setup),
cmocka_unit_test_setup(test_comments, logger_setup),
cmocka_unit_test_setup(test_arg, logger_setup),
+ cmocka_unit_test_setup(test_stmts, logger_setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);