blob: ea69343d2bb6400cf7a6ee6f66fac9d57056a303 [file] [log] [blame]
Radek Krejci80dd33e2018-09-26 15:57:18 +02001/*
2 * @file test_parser_yang.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for functions from parser_yang.c
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _BSD_SOURCE
16#define _DEFAULT_SOURCE
17#include <stdarg.h>
18#include <stddef.h>
19#include <setjmp.h>
20#include <cmocka.h>
21
22#include <stdio.h>
23#include <string.h>
24
25#include "libyang.h"
26#include "../../src/parser_yang.c"
27
28#define BUFSIZE 1024
29char logbuf[BUFSIZE] = {0};
30
31/* set to 0 to printing error messages to stderr instead of checking them in code */
32#define ENABLE_LOGGER_CHECKING 1
33
34static void
35logger(LY_LOG_LEVEL level, const char *msg, const char *path)
36{
37 (void) level; /* unused */
38
39 if (path) {
40 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
41 } else {
42 strncpy(logbuf, msg, BUFSIZE - 1);
43 }
44}
45
46static int
47logger_setup(void **state)
48{
49 (void) state; /* unused */
50#if ENABLE_LOGGER_CHECKING
51 ly_set_log_clb(logger, 1);
52#endif
53 return 0;
54}
55
56void
57logbuf_clean(void)
58{
59 logbuf[0] = '\0';
60}
61
62#if ENABLE_LOGGER_CHECKING
63# define logbuf_assert(str) assert_string_equal(logbuf, str)
64#else
65# define logbuf_assert(str)
66#endif
67
Radek Krejci44ceedc2018-10-02 15:54:31 +020068static void
69test_helpers(void **state)
70{
71 (void) state; /* unused */
72
73 const char *str;
Radek Krejci404251e2018-10-09 12:06:44 +020074 char *buf, *p;
Radek Krejci44ceedc2018-10-02 15:54:31 +020075 size_t len, size;
76 int prefix;
77 struct ly_parser_ctx ctx;
78 ctx.ctx = NULL;
79 ctx.line = 1;
80
81 /* storing into buffer */
82 str = "abcd";
83 buf = NULL;
84 size = len = 0;
85 assert_int_equal(LY_SUCCESS, buf_add_char(NULL, &str, 2, &buf, &size, &len));
86 assert_int_not_equal(0, size);
87 assert_int_equal(2, len);
88 assert_string_equal("cd", str);
89 assert_false(strncmp("ab", buf, 2));
90 free(buf);
Radek Krejci404251e2018-10-09 12:06:44 +020091 buf = NULL;
92
93 /* invalid first characters */
94 len = 0;
95 str = "2invalid";
96 assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1));
97 str = ".invalid";
98 assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1));
99 str = "-invalid";
100 assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1));
101 /* invalid following characters */
102 len = 3; /* number of characters read before the str content */
103 str = "!";
104 assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1));
105 str = ":";
106 assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1));
107 /* valid colon for prefixed identifiers */
108 len = size = 0;
109 p = NULL;
110 str = "x:id";
111 assert_int_equal(LY_SUCCESS, buf_store_char(&ctx, &str, Y_PREF_IDENTIF_ARG, &p, &len, &buf, &size, 0));
112 assert_int_equal(1, len);
113 assert_null(buf);
114 assert_string_equal(":id", str);
115 assert_int_equal('x', p[len - 1]);
116 assert_int_equal(LY_SUCCESS, buf_store_char(&ctx, &str, Y_PREF_IDENTIF_ARG, &p, &len, &buf, &size, 1));
117 assert_int_equal(2, len);
118 assert_string_equal("id", str);
119 assert_int_equal(':', p[len - 1]);
120 free(buf);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200121
122 /* checking identifiers */
123 assert_int_equal(LY_EVALID, check_identifierchar(&ctx, ':', 0, NULL));
124 logbuf_assert("Invalid identifier character ':'. Line number 1.");
125 assert_int_equal(LY_EVALID, check_identifierchar(&ctx, '#', 1, NULL));
126 logbuf_assert("Invalid identifier first character '#'. Line number 1.");
127
128 assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, 'a', 1, &prefix));
129 assert_int_equal(0, prefix);
130 assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, ':', 0, &prefix));
131 assert_int_equal(1, prefix);
132 assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, 'b', 0, &prefix));
133 assert_int_equal(2, prefix);
134}
Radek Krejci80dd33e2018-09-26 15:57:18 +0200135
136static void
137test_comments(void **state)
138{
139 (void) state; /* unused */
140
Radek Krejci44ceedc2018-10-02 15:54:31 +0200141 struct ly_parser_ctx ctx;
Radek Krejci80dd33e2018-09-26 15:57:18 +0200142 const char *str, *p;
Radek Krejciefd22f62018-09-27 11:47:58 +0200143 char *word, *buf;
144 size_t len;
Radek Krejci80dd33e2018-09-26 15:57:18 +0200145
Radek Krejci44ceedc2018-10-02 15:54:31 +0200146 ctx.ctx = NULL;
147 ctx.line = 1;
148
Radek Krejciefd22f62018-09-27 11:47:58 +0200149 str = " // this is a text of / one * line */ comment\nargument";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200150 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200151 assert_string_equal("argument", word);
152 assert_null(buf);
153 assert_int_equal(8, len);
Radek Krejci80dd33e2018-09-26 15:57:18 +0200154
Radek Krejciefd22f62018-09-27 11:47:58 +0200155 str = "/* this is a \n * text // of / block * comment */\"arg\" + \"ume\" \n + \n \"nt\"";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200156 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200157 assert_string_equal("argument", word);
158 assert_ptr_equal(buf, word);
159 assert_int_equal(8, len);
160 free(word);
Radek Krejci80dd33e2018-09-26 15:57:18 +0200161
162 str = p = " this is one line comment on last line";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200163 assert_int_equal(LY_SUCCESS, skip_comment(&ctx, &str, 1));
Radek Krejci80dd33e2018-09-26 15:57:18 +0200164 assert_true(str[0] == '\0');
165
166 str = p = " this is a not terminated comment x";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200167 assert_int_equal(LY_EVALID, skip_comment(&ctx, &str, 2));
168 logbuf_assert("Unexpected end-of-file, non-terminated comment. Line number 5.");
Radek Krejci80dd33e2018-09-26 15:57:18 +0200169 assert_true(str[0] == '\0');
170}
171
Radek Krejciefd22f62018-09-27 11:47:58 +0200172static void
173test_arg(void **state)
174{
175 (void) state; /* unused */
176
Radek Krejci44ceedc2018-10-02 15:54:31 +0200177 struct ly_parser_ctx ctx;
Radek Krejciefd22f62018-09-27 11:47:58 +0200178 const char *str;
179 char *word, *buf;
180 size_t len;
181
Radek Krejci44ceedc2018-10-02 15:54:31 +0200182 ctx.ctx = NULL;
183 ctx.line = 1;
184
Radek Krejciefd22f62018-09-27 11:47:58 +0200185 /* missing argument */
186 str = ";";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200187 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_MAYBE_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200188 assert_null(word);
189
Radek Krejci44ceedc2018-10-02 15:54:31 +0200190 assert_int_equal(LY_EVALID, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
191 logbuf_assert("Invalid character sequence \";\", expected an argument. Line number 1.");
Radek Krejciefd22f62018-09-27 11:47:58 +0200192
193 /* different quoting */
194 str = "hello";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200195 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200196 assert_null(buf);
197 assert_string_equal("hello", word);
198
199 str = "\"hello\"";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200200 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200201 assert_null(buf);
202 assert_int_equal(5, len);
203 assert_false(strncmp("hello", word, 5));
204
205 str = "\'hello\'";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200206 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200207 assert_null(buf);
208 assert_int_equal(5, len);
209 assert_false(strncmp("hello", word, 5));
210
211 str = "\"hel\" +\t\n\"lo\"";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200212 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200213 assert_ptr_equal(word, buf);
214 assert_int_equal(5, len);
215 assert_string_equal("hello", word);
216 free(buf);
217
218 str = "\'he\'\t\n+ \"llo\"";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200219 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200220 assert_ptr_equal(word, buf);
221 assert_int_equal(5, len);
222 assert_string_equal("hello", word);
223 free(buf);
224
225 str = "\"he\"+\'llo\'";
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 assert_int_equal(LY_SUCCESS, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
Radek Krejciefd22f62018-09-27 11:47:58 +0200227 assert_ptr_equal(word, buf);
228 assert_int_equal(5, len);
229 assert_string_equal("hello", word);
230 free(buf);
231
Radek Krejci44ceedc2018-10-02 15:54:31 +0200232 /* missing argument */
233 str = ";";
234 assert_int_equal(LY_EVALID, get_string(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
235 logbuf_assert("Invalid character sequence \";\", expected an argument. Line number 3.");
236
Radek Krejciefd22f62018-09-27 11:47:58 +0200237}
238
Radek Krejci80dd33e2018-09-26 15:57:18 +0200239int main(void)
240{
241 const struct CMUnitTest tests[] = {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200242 cmocka_unit_test_setup(test_helpers, logger_setup),
Radek Krejci80dd33e2018-09-26 15:57:18 +0200243 cmocka_unit_test_setup(test_comments, logger_setup),
Radek Krejciefd22f62018-09-27 11:47:58 +0200244 cmocka_unit_test_setup(test_arg, logger_setup),
Radek Krejci80dd33e2018-09-26 15:57:18 +0200245 };
246
247 return cmocka_run_group_tests(tests, NULL, NULL);
248}