blob: 62bcf9e27c05e430452364c72fd62c22bef3a9aa [file] [log] [blame]
Radek Iša59bf3272021-03-10 11:22:52 +01001/**
2 * @file test_error.c
3 * @author Radek Iša <isa@cesnet.cz>
4 * @brief test for int8 values
5 *
6 * Copyright (c) 2021 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/* INCLUDE UTEST HEADER */
16#define _UTEST_MAIN_
17#include "../utests.h"
18
19/* GLOBAL INCLUDE HEADERS */
20#include <ctype.h>
21
22/* LOCAL INCLUDE HEADERS */
23#include "libyang.h"
24#include "path.h"
25
26#define MODULE_CREATE_YIN(MOD_NAME, NODES) \
27 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
28 "<module name=\"" MOD_NAME "\"\n" \
29 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" \
30 " xmlns:pref=\"urn:tests:" MOD_NAME "\">\n" \
31 " <yang-version value=\"1.1\"/>\n" \
32 " <namespace uri=\"urn:tests:" MOD_NAME "\"/>\n" \
33 " <prefix value=\"pref\"/>\n" \
34 NODES \
35 "</module>\n"
36
37#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
38 "module " MOD_NAME " {\n" \
39 " yang-version 1.1;\n" \
40 " namespace \"urn:tests:" MOD_NAME "\";\n" \
41 " prefix pref;\n" \
42 NODES \
43 "}\n"
44
45#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
46 { \
47 struct lyd_node *tree; \
48 const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
49 CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
50 CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
51 CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
52 lyd_free_all(tree); \
53 }
54
55#define TEST_SUCCESS_JSON(MOD_NAME, DATA, TYPE, ...) \
56 { \
57 struct lyd_node *tree; \
58 const char *data = "{\"" MOD_NAME ":port\":" DATA "}"; \
59 CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
60 CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
61 CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
62 lyd_free_all(tree); \
63 }
64
65#define TEST_ERROR_XML(MOD_NAME, DATA) \
66 {\
67 struct lyd_node *tree; \
68 const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
69 CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
70 assert_null(tree); \
71 }
72
73#define TEST_ERROR_JSON(MOD_NAME, DATA) \
74 { \
75 struct lyd_node *tree; \
76 const char *data = "{\"" MOD_NAME ":port\":" DATA "}"; \
77 CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
78 assert_null(tree); \
79 }
80
81static void
82test_schema_yang(void **state)
83{
84 const char *schema;
85 const struct lys_module *mod;
86 struct lysc_node_leaf *lysc_leaf;
87 struct lysp_node_leaf *lysp_leaf;
88 struct lysc_pattern *pattern;
89 struct lysc_range *range;
90
91 schema = MODULE_CREATE_YANG("T0", "leaf port {type string {"
92 "pattern \"[A-Za-z]*\"{"
93 "description \"pattern description\";"
94 "error-app-tag \"pattern err-apt-tag\";"
95 "error-message \"pattern error message\";}}}");
96 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
97 assert_non_null(mod);
98 lysc_leaf = (void *) mod->compiled->data;
99 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
100 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
101 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
102 CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
103 "pattern error message", "[A-Za-z]*", 0, 0, NULL);
104 lysp_leaf = (void *) mod->parsed->data;
105 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
106 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 1, 1, 0, 0, 0);
107 CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Za-z]*", "pattern description",
108 "pattern err-apt-tag", "pattern error message", 0, NULL);
109
110 /* heredity */
111 schema = MODULE_CREATE_YANG("T1", "typedef my_type {type string {"
112 "pattern \"[A-Za-z]*\"{"
113 "description \"pattern description\";"
114 "error-app-tag \"pattern err-apt-tag\";"
115 "error-message \"pattern error message\";}}}"
116 "leaf port {type my_type;}");
117 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
118 assert_non_null(mod);
119 lysc_leaf = (void *) mod->compiled->data;
120 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
121 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
122 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
123 CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
124 "pattern error message", "[A-Za-z]*", 0, 0, NULL);
125 lysp_leaf = (void *) mod->parsed->data;
126 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
127 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
128
129 /* heredity new pattern */
130 schema = MODULE_CREATE_YANG("T2", "typedef my_type {type string {"
131 "pattern \"[A-Za-z]*\"{"
132 "description \"pattern description\";"
133 "error-app-tag \"pattern err-apt-tag\";"
134 "error-message \"pattern error message\";}}}"
135 "leaf port {type my_type{pattern \"[A-Z]*\";}}");
136 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
137 assert_non_null(mod);
138 lysc_leaf = (void *) mod->compiled->data;
139 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
140 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
141 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
142 CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
143 "pattern error message", "[A-Za-z]*", 0, 0, NULL);
144 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
145 CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[A-Z]*", 0, 0, NULL);
146 lysp_leaf = (void *) mod->parsed->data;
147 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
148 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
149 CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", NULL, NULL, NULL, 0, NULL);
150
151 /* heredity new pattern */
152 schema = MODULE_CREATE_YANG("T3", "typedef my_type {type string {"
153 "pattern \"[A-Za-z]*\"{"
154 " description \"pattern 0 description\";"
155 " error-app-tag \"pattern 0 err-apt-tag\";"
156 " error-message \"pattern 0 error message\";}}}"
157 "leaf port {type my_type{pattern \"[A-Z]*\"{"
158 " description \"pattern 1 description\";"
159 " error-app-tag \"pattern 1 err-apt-tag\";"
160 " error-message \"pattern 1 error message\";"
161 "}}}");
162 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
163 assert_non_null(mod);
164 lysc_leaf = (void *) mod->compiled->data;
165 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
166 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
167 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
168 CHECK_LYSC_PATTERN(pattern, "pattern 0 description", "pattern 0 err-apt-tag",
169 "pattern 0 error message", "[A-Za-z]*", 0, 0, NULL);
170 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
171 CHECK_LYSC_PATTERN(pattern, "pattern 1 description", "pattern 1 err-apt-tag",
172 "pattern 1 error message", "[A-Z]*", 0, 0, NULL);
173 lysp_leaf = (void *) mod->parsed->data;
174 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
175 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
176 CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", "pattern 1 description",
177 "pattern 1 err-apt-tag", "pattern 1 error message", 0, NULL);
178}
179
Radek Iša59bf3272021-03-10 11:22:52 +0100180static void
181test_schema_yin(void **state)
182{
183 const char *schema;
184 const struct lys_module *mod;
185 struct lysc_node_leaf *lysc_leaf;
186 struct lysp_node_leaf *lysp_leaf;
187 struct lysc_pattern *pattern;
188 struct lysc_range *range;
189
190 schema = MODULE_CREATE_YIN("T0", "<leaf name=\"port\"> <type name=\"string\">"
191 "<pattern value=\"[A-Za-z]*\">"
192 " <description><text>pattern description</text></description>"
193 " <error-app-tag value=\"pattern err-apt-tag\"/>"
194 " <error-message> <value>pattern error message</value></error-message>"
195 "</pattern></type></leaf>");
196 UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
197 assert_non_null(mod);
198 lysc_leaf = (void *) mod->compiled->data;
199 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
200 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
201 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
202 CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
203 "pattern error message", "[A-Za-z]*", 0, 0, NULL);
204 lysp_leaf = (void *) mod->parsed->data;
205 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
206 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 1, 1, 0, 0, 0);
207 CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Za-z]*", "pattern description",
208 "pattern err-apt-tag", "pattern error message", 0, NULL);
209
210 /* heredity */
211 schema = MODULE_CREATE_YIN("T1", "<typedef name=\"my_type\"> <type name=\"string\">"
212 "<pattern value=\"[A-Za-z]*\">"
213 " <description><text>pattern description</text></description>"
214 " <error-app-tag value=\"pattern err-apt-tag\"/>"
215 " <error-message><value>pattern error message</value></error-message>"
216 "</pattern></type></typedef>"
217 "<leaf name=\"port\"><type name=\"my_type\"/></leaf>");
218 UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
219 assert_non_null(mod);
220 lysc_leaf = (void *) mod->compiled->data;
221 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
222 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
223 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
224 CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
225 "pattern error message", "[A-Za-z]*", 0, 0, NULL);
226 lysp_leaf = (void *) mod->parsed->data;
227 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
228 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
229
230 /* heredity new pattern */
231 schema = MODULE_CREATE_YIN("T2", "<typedef name=\"my_type\"> <type name=\"string\">"
232 "<pattern value=\"[A-Za-z]*\">"
233 " <description><text>pattern description</text></description>"
234 " <error-app-tag value=\"pattern err-apt-tag\"/>"
235 " <error-message><value>pattern error message</value></error-message>"
236 "</pattern></type></typedef>"
237 "<leaf name=\"port\"> <type name=\"my_type\"><pattern value=\"[A-Z]*\"/>"
238 "</type></leaf>");
239 UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
240 assert_non_null(mod);
241 lysc_leaf = (void *) mod->compiled->data;
242 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
243 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
244 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
245 CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
246 "pattern error message", "[A-Za-z]*", 0, 0, NULL);
247 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
248 CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[A-Z]*", 0, 0, NULL);
249 lysp_leaf = (void *) mod->parsed->data;
250 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
251 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
252 CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", NULL, NULL, NULL, 0, NULL);
253
254 /* heredity new pattern */
255 schema = MODULE_CREATE_YIN("T3", "<typedef name=\"my_type\"> <type name=\"string\">"
256 "<pattern value=\"[A-Za-z]*\">"
257 " <description> <text>pattern 0 description</text></description>"
258 " <error-app-tag value=\"pattern 0 err-apt-tag\"/>"
259 " <error-message> <value>pattern 0 error message</value></error-message>"
260 "</pattern></type></typedef>"
261 "<leaf name=\"port\"> <type name=\"my_type\">"
262 "<pattern value=\"[A-Z]*\">"
263 " <description><text>pattern 1 description</text></description>"
264 " <error-app-tag value=\"pattern 1 err-apt-tag\"/>"
265 " <error-message><value>pattern 1 error message</value></error-message>"
266 "</pattern></type></leaf>");
267
268 UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
269 assert_non_null(mod);
270 lysc_leaf = (void *) mod->compiled->data;
271 CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
272 CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
273 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
274 CHECK_LYSC_PATTERN(pattern, "pattern 0 description", "pattern 0 err-apt-tag",
275 "pattern 0 error message", "[A-Za-z]*", 0, 0, NULL);
276 pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
277 CHECK_LYSC_PATTERN(pattern, "pattern 1 description", "pattern 1 err-apt-tag",
278 "pattern 1 error message", "[A-Z]*", 0, 0, NULL);
279 lysp_leaf = (void *) mod->parsed->data;
280 CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
281 CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
282 CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", "pattern 1 description",
283 "pattern 1 err-apt-tag", "pattern 1 error message", 0, NULL);
284}
285
286static void
287test_schema_print(void **state)
288{
289 const char *schema_yang, *schema_yin;
290 char *printed;
291 const struct lys_module *mod;
292
293 /* test print yang to yin */
294 schema_yang = MODULE_CREATE_YANG("PRINT0", "leaf port {type string {"
295 "pattern \"[A-Z]*\"{"
296 "description \"desc < \";"
297 "error-app-tag \"err-apt-tag <\";"
298 "error-message \"error message <\";}}}");
299
300 schema_yin = MODULE_CREATE_YIN("PRINT0",
301 " <leaf name=\"port\">\n"
302 " <type name=\"string\">\n"
303 " <pattern value=\"[A-Z]*\">\n"
304 " <error-message>\n"
305 " <value>error message &lt;</value>\n"
306 " </error-message>\n"
307 " <error-app-tag value=\"err-apt-tag &lt;\"/>\n"
308 " <description>\n"
309 " <text>desc &lt; </text>\n"
310 " </description>\n"
311 " </pattern>\n"
312 " </type>\n"
313 " </leaf>\n");
314
315 UTEST_ADD_MODULE(schema_yang, LYS_IN_YANG, NULL, &mod);
316 assert_non_null(mod);
317 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
318 assert_string_equal(printed, schema_yin);
319 free(printed);
320
321 /* test print yin to yang */
322 schema_yang = MODULE_CREATE_YANG("PRINT1",
323 " leaf port {\n"
324 " type string {\n"
325 " pattern \"[A-Z]*\" {\n"
326 " error-message\n"
327 " \"error message <\";\n"
328 " error-app-tag \"err-apt-tag <\";\n"
329 " description\n"
330 " \"desc < \";\n"
331 " }\n"
332 " }\n"
333 " }\n");
334
335 schema_yin = MODULE_CREATE_YIN("PRINT1",
336 " <leaf name=\"port\">\n"
337 " <type name=\"string\">\n"
338 " <pattern value=\"[A-Z]*\">\n"
339 " <error-message>\n"
340 " <value>error message &lt;</value>\n"
341 " </error-message>\n"
342 " <error-app-tag value=\"err-apt-tag &lt;\"/>\n"
343 " <description>\n"
344 " <text>desc &lt; </text>\n"
345 " </description>\n"
346 " </pattern>\n"
347 " </type>\n"
348 " </leaf>\n");
349
350 UTEST_ADD_MODULE(schema_yin, LYS_IN_YIN, NULL, &mod);
351 assert_non_null(mod);
352 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
353 assert_string_equal(printed, schema_yang);
354 free(printed);
355}
356
357static void
358test_data_xml(void **state)
359{
360 const char *schema;
361
362 /* xml test */
363 schema = MODULE_CREATE_YANG("TPATTERN_0", "typedef my_type {type string {"
364 "pattern \"[A-Za-z]*\"{"
365 " description \"pattern 0 description\";"
366 " error-app-tag \"pattern 0 err-apt-tag\";"
367 " error-message \"pattern 0 error message\";}}}"
368 "leaf port {type my_type{pattern \"[A-Z]*\"{"
369 " description \"pattern 1 description\";"
370 " error-app-tag \"pattern 1 err-apt-tag\";"
371 " error-message \"pattern 1 error message\";"
372 "}}}");
373 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
374
375 /* test success */
376 TEST_SUCCESS_XML("TPATTERN_0", "AHOJ", STRING, "AHOJ");
377 /* test print error */
378 TEST_ERROR_XML("TPATTERN_0", "T128");
379 CHECK_LOG_CTX("pattern 0 error message",
380 "Schema location /TPATTERN_0:port, line number 1.");
381 TEST_ERROR_XML("TPATTERN_0", "ahoj");
382 CHECK_LOG_CTX("pattern 1 error message",
383 "Schema location /TPATTERN_0:port, line number 1.");
384
385}
386
387int
388main(void)
389{
390 const struct CMUnitTest tests[] = {
391 UTEST(test_schema_yang),
392 UTEST(test_schema_yin),
393 UTEST(test_schema_print),
394 UTEST(test_data_xml),
395 };
396
397 return cmocka_run_group_tests(tests, NULL, NULL);
398}