4 #include "config_test.h"
6 static const int NO_LOG_EXPECTED_MSG = 0;
7 static const int DO_LOG_EXPECTED_MSG = 1;
9 static int did_log_expected_msg;
10 static char *expected_message = "Invalid structured ScalarVariable name";
11 static char *name_check_test_directory;
13 char *concat(char *s1, char *s2)
15 size_t len1 = strlen(s1);
16 size_t len2 = strlen(s2);
17 /* +1 for the zero-terminator */
18 char *result = (char *) malloc((len1 + len2 + 1) * sizeof(char));
20 exit(CTEST_RETURN_FAIL);
22 memcpy(result, s1, len1);
23 memcpy(result + len1, s2, len2 + 1); /* +1 to copy the null-terminator */
27 void importlogger(jm_callbacks* c, jm_string module,
\r
28 jm_log_level_enu_t log_level, jm_string message)
\r
30 printf("module = %s, log level = %d: %s\n", module, log_level, message);
\r
31 if (!strncmp(expected_message, message, strlen(expected_message))) {
\r
32 did_log_expected_msg = 1;
\r
36 void destroy_parse_test_callbacks(jm_callbacks *cb) {
37 fmi_import_free_context((fmi_import_context_t *)cb->context);
41 jm_callbacks* create_parse_test_callbacks(void) {
44 cb = (jm_callbacks *) malloc(sizeof(jm_callbacks));
\r
45 cb->malloc = malloc;
\r
46 cb->calloc = calloc;
\r
47 cb->realloc = realloc;
\r
49 cb->logger = importlogger;
\r
50 cb->log_level = jm_log_level_all;
\r
51 cb->context = fmi_import_allocate_context(cb);
56 fmi1_import_t* test_parser(jm_callbacks *cb, char *xml_dir, int should_log_expected_msg, int configuration)
61 if (configuration != 0) {
62 fmi_import_set_configuration((fmi_import_context_t *)cb->context, configuration);
65 did_log_expected_msg = 0;
66 full_path = concat(name_check_test_directory, xml_dir);
67 fmu = fmi1_import_parse_xml((fmi_import_context_t *)cb->context, full_path);
71 exit(CTEST_RETURN_FAIL);
73 if (should_log_expected_msg != did_log_expected_msg) {
74 exit(CTEST_RETURN_FAIL);
80 void test_parser_with_cleanup(char *xml_dir, int should_log_expected_msg, int configuration) {
81 jm_callbacks* cb = create_parse_test_callbacks();
83 fmi1_import_t* fmu = test_parser(cb, xml_dir, should_log_expected_msg, configuration);
84 fmi1_import_free(fmu);
85 destroy_parse_test_callbacks(cb);
88 void fail_name_check(char *xml_dir)
90 test_parser_with_cleanup(xml_dir, DO_LOG_EXPECTED_MSG, FMI_IMPORT_NAME_CHECK);
91 test_parser_with_cleanup(xml_dir, NO_LOG_EXPECTED_MSG, 0);
94 void pass_name_check(char *xml_dir)
96 test_parser_with_cleanup(xml_dir, NO_LOG_EXPECTED_MSG, FMI_IMPORT_NAME_CHECK);
99 void parser_log_expected_message(char *xml_dir)
101 test_parser_with_cleanup(xml_dir, DO_LOG_EXPECTED_MSG, 0);
104 void parser_no_log_expected_message(char *xml_dir)
106 test_parser_with_cleanup(xml_dir, NO_LOG_EXPECTED_MSG, 0);
109 typedef int (*fmu_test_f)(fmi1_import_t* fmu);
111 void test_parsing_and_fmu(char *xml_dir, fmu_test_f fmu_test, int should_log_expected_msg)
113 jm_callbacks* cb = create_parse_test_callbacks();
115 fmi1_import_t* fmu = test_parser(cb, xml_dir, should_log_expected_msg, 0);
116 if (!fmu_test(fmu)) {
117 exit(CTEST_RETURN_FAIL);
119 fmi1_import_free(fmu);
121 destroy_parse_test_callbacks(cb);
124 void test_parsing_fail_and_fmu(char *xml_dir, fmu_test_f fmu_test)
126 test_parsing_and_fmu(xml_dir, fmu_test, DO_LOG_EXPECTED_MSG);
129 void test_parsing_pass_and_fmu(char *xml_dir, fmu_test_f fmu_test)
131 test_parsing_and_fmu(xml_dir, fmu_test, NO_LOG_EXPECTED_MSG);
134 void test_variable_naming_conventions(void) {
135 /* Test scalar variable names
137 * Every test below has a corresponding modelDescription in
138 * Test/FMI1/parser_test_xmls/naming_conventions_xmls/
139 * What is passed to these macros are names of directories containing
143 /* Test examples mentioned */
144 fail_name_check("naming_conventions_xmls/examples/foo");
145 fail_name_check("naming_conventions_xmls/examples/derderx");
146 pass_name_check("naming_conventions_xmls/examples/derx2");
148 /* FMI 1.0 standard examples from the documentaiton */
149 pass_name_check("naming_conventions_xmls/standard/vehicle.engine.speed");
150 pass_name_check("naming_conventions_xmls/standard/resistor12.u");
151 pass_name_check("naming_conventions_xmls/standard/v_min");
152 pass_name_check("naming_conventions_xmls/standard/robot.axis.motor234");
153 pass_name_check("naming_conventions_xmls/standard/derpipe34.T142");
155 /* Implementation test examples */
156 fail_name_check("naming_conventions_xmls/implementation/empty");
157 fail_name_check("naming_conventions_xmls/implementation/-0");
158 pass_name_check("naming_conventions_xmls/implementation/_0");
159 pass_name_check("naming_conventions_xmls/implementation/a0");
160 fail_name_check("naming_conventions_xmls/implementation/0a");
161 fail_name_check("naming_conventions_xmls/implementation/0");
164 fail_name_check("naming_conventions_xmls/q-name/empty");
165 pass_name_check("naming_conventions_xmls/q-name/space");
166 fail_name_check("naming_conventions_xmls/q-name/backslash");
167 pass_name_check("naming_conventions_xmls/q-name/q-char");
168 pass_name_check("naming_conventions_xmls/q-name/escape");
169 pass_name_check("naming_conventions_xmls/q-name/chinese"); /* this should fail in FMI 2.0 */
172 pass_name_check("naming_conventions_xmls/der/dera32"); /* this should fail in FMI 2.0 */
173 fail_name_check("naming_conventions_xmls/der/dera12");
174 pass_name_check("naming_conventions_xmls/der/dera32-no-space");
175 pass_name_check("naming_conventions_xmls/der/dera");
176 fail_name_check("naming_conventions_xmls/der/dera-no-closing-parenthesis");
177 pass_name_check("naming_conventions_xmls/der/somederthing");
178 pass_name_check("naming_conventions_xmls/der/der0");
179 fail_name_check("naming_conventions_xmls/der/der2");
180 fail_name_check("naming_conventions_xmls/der/adera");
182 /* array and hierarchy tests */
183 pass_name_check("naming_conventions_xmls/array/n0");
184 fail_name_check("naming_conventions_xmls/array/a1comma");
185 pass_name_check("naming_conventions_xmls/array/a12345678");
186 pass_name_check("naming_conventions_xmls/array/a12345678space"); /* this should fail in FMI 2.0 */
187 pass_name_check("naming_conventions_xmls/array/a1.a3");
188 pass_name_check("naming_conventions_xmls/array/a.a123");
189 fail_name_check("naming_conventions_xmls/array/aspace1");
190 fail_name_check("naming_conventions_xmls/array/a1space");
191 pass_name_check("naming_conventions_xmls/array/a1space1"); /* this should fail in FMI 2.0 */
192 fail_name_check("naming_conventions_xmls/array/aspacebracket1");
193 fail_name_check("naming_conventions_xmls/array/a-1");
194 pass_name_check("naming_conventions_xmls/array/a1");
195 pass_name_check("naming_conventions_xmls/array/a.a");
196 pass_name_check("naming_conventions_xmls/array/a");
198 /* list of variables */
199 fail_name_check("naming_conventions_xmls/list/aemptyc");
200 expected_message = "Two variables with the same name";
201 pass_name_check("naming_conventions_xmls/list/cba");
202 fail_name_check("naming_conventions_xmls/list/acad");
204 /* flat hierarchy test */
205 fail_name_check("naming_conventions_xmls/flat/acad");
206 pass_name_check("naming_conventions_xmls/flat/q-char-nonescaped");
209 int should_have_no_vars(fmi1_import_t* fmu) {
210 fmi1_import_variable_list_t* vars;
212 vars = fmi1_import_get_variable_list(fmu);
213 return fmi1_import_get_variable_list_size(vars) == 0;
216 int should_have_1_no_alias_var(fmi1_import_t* fmu) {
217 fmi1_import_variable_list_t* vars;
218 fmi1_import_variable_t* var;
220 vars = fmi1_import_get_variable_list(fmu);
221 if (fmi1_import_get_variable_list_size(vars) != 1) {
225 var = fmi1_import_get_variable(vars, 0);
226 return (fmi1_import_get_variable_alias_kind(var) == fmi1_variable_is_not_alias);
229 int should_have_size_2_alias_group(fmi1_import_t* fmu) {
230 fmi1_import_variable_list_t* vars;
231 fmi1_import_variable_t* var;
233 vars = fmi1_import_get_variable_list(fmu);
235 if (fmi1_import_get_variable_list_size(vars) != 2) {
239 var = fmi1_import_get_variable(vars, 0);
240 if (fmi1_import_get_variable_alias_kind(var) != fmi1_variable_is_not_alias) {
244 var = fmi1_import_get_variable(vars, 1);
245 return (fmi1_import_get_variable_alias_kind(var) == fmi1_variable_is_alias);
248 int should_have_size_2_no_alis(fmi1_import_t* fmu) {
249 fmi1_import_variable_list_t* vars;
250 fmi1_import_variable_t* var;
252 vars = fmi1_import_get_variable_list(fmu);
254 if (fmi1_import_get_variable_list_size(vars) != 2) {
258 var = fmi1_import_get_variable(vars, 0);
259 if (fmi1_import_get_variable_alias_kind(var) != fmi1_variable_is_not_alias) {
263 var = fmi1_import_get_variable(vars, 1);
264 return (fmi1_import_get_variable_alias_kind(var) == fmi1_variable_is_not_alias);
267 int should_have_size_3_alias_group(fmi1_import_t* fmu) {
268 fmi1_import_variable_list_t* vars;
269 fmi1_import_variable_t* var;
271 vars = fmi1_import_get_variable_list(fmu);
273 if (fmi1_import_get_variable_list_size(vars) != 3) {
277 var = fmi1_import_get_variable(vars, 0);
278 if (fmi1_import_get_variable_alias_kind(var) != fmi1_variable_is_not_alias) {
282 var = fmi1_import_get_variable(vars, 1);
283 if (fmi1_import_get_variable_alias_kind(var) != fmi1_variable_is_alias) {
287 var = fmi1_import_get_variable(vars, 2);
288 return (fmi1_import_get_variable_alias_kind(var) == fmi1_variable_is_negated_alias);
291 void test_alias_set_error_handling(void) {
292 /* Test that we log errors for incorrect alias set and
293 * that incorrect alias variables are removed or that
294 * variable that should be alias variables becomes alias */
296 expected_message = "Alias set with vr=0 (type=Real) do not have a 'noAlias' variable.";
297 parser_log_expected_message("alias_validation/all_alias");
298 expected_message = "Removing incorrect alias variable 'v2'";
299 test_parsing_fail_and_fmu("alias_validation/all_alias", should_have_no_vars);
301 expected_message = "Alias set with vr=0 (type=Real) do not have a 'noAlias' variable.";
302 parser_log_expected_message("alias_validation/all_alias_mixed");
303 expected_message = "Removing incorrect alias variable 'v2'";
304 test_parsing_fail_and_fmu("alias_validation/all_alias_mixed", should_have_no_vars);
306 expected_message = "Alias set with vr=0 (type=Real) do not have a 'noAlias' variable.";
307 parser_log_expected_message("alias_validation/all_negated_alias");
308 expected_message = "Removing incorrect alias variable 'v2'";
309 test_parsing_fail_and_fmu("alias_validation/all_negated_alias", should_have_no_vars);
311 expected_message = "Variables v1 and v2 reference the same vr 0. Marking 'v2' as alias.";
312 test_parsing_fail_and_fmu("alias_validation/all_no_alias", should_have_size_2_alias_group);
314 expected_message = "Variables v1 and v2 reference the same vr 0. Marking 'v2' as alias.";
315 test_parsing_pass_and_fmu("alias_validation/small_valid_alias_set", should_have_size_2_alias_group);
317 expected_message = "Variables v1 and v2 reference the same vr 0. Marking 'v2' as alias.";
318 test_parsing_pass_and_fmu("alias_validation/medium_valid_alias_set", should_have_size_3_alias_group);
320 expected_message = "Alias set with vr=0 (type=Real) do not have a 'noAlias' variable.";
321 parser_log_expected_message("alias_validation/all_alias_two_sets");
322 expected_message = "Alias set with vr=1 (type=Real) do not have a 'noAlias' variable.";
323 test_parsing_fail_and_fmu("alias_validation/all_alias_two_sets", should_have_no_vars);
325 expected_message = "Variables v1 and v2 reference the same vr 0. Marking 'v2' as alias.";
326 test_parsing_pass_and_fmu("alias_validation/all_no_alias_two_sets", should_have_size_2_no_alis);
328 expected_message = "Inconsistent start values in alias set";
329 parser_no_log_expected_message("alias_validation/consistent_real_start_values");
331 expected_message = "Inconsistent start values in alias set";
332 parser_no_log_expected_message("alias_validation/consistent_int_start_values");
334 expected_message = "Inconsistent start values in alias set";
335 parser_no_log_expected_message("alias_validation/consistent_enum_start_values");
337 expected_message = "Inconsistent start values in alias set";
338 parser_no_log_expected_message("alias_validation/consistent_bool_start_values");
340 expected_message = "Inconsistent start values in alias set";
341 parser_no_log_expected_message("alias_validation/consistent_str_start_values");
343 expected_message = "Inconsistent start values in alias set, "
344 "start value '1.0"; /* Cannot check more of message due to potential roundings */
345 test_parsing_fail_and_fmu("alias_validation/inconsistent_real_start_values",
346 should_have_1_no_alias_var);
348 expected_message = "Inconsistent start values in alias set, "
349 "start value '1' of 'v1' does not match "
350 "start value '3' of 'v2'.";
351 test_parsing_fail_and_fmu("alias_validation/inconsistent_int_start_values",
352 should_have_1_no_alias_var);
354 expected_message = "Inconsistent start values in alias set, "
355 "start value '1' of 'v1' does not match "
356 "start value '2' of 'v2'.";
357 test_parsing_fail_and_fmu("alias_validation/inconsistent_enum_start_values",
358 should_have_1_no_alias_var);
360 expected_message = "Inconsistent start values in alias set, "
361 "start value 'true' of 'v1' does not match "
362 "start value 'false' of 'v2'.";
363 test_parsing_fail_and_fmu("alias_validation/inconsistent_bool_start_values",
364 should_have_1_no_alias_var);
366 expected_message = "Inconsistent start values in alias set, "
367 "start value 'a' of 'v1' does not match "
368 "start value 'b' of 'v2'.";
369 test_parsing_fail_and_fmu("alias_validation/inconsistent_str_start_values",
370 should_have_1_no_alias_var);
372 expected_message = "Inconsistent start values in alias set, "
373 "start value '1.0"; /* Cannot check more of message due to potential roundings */
374 test_parsing_fail_and_fmu("alias_validation/inconsistent_neg_real_start_values",
375 should_have_1_no_alias_var);
377 expected_message = "Inconsistent start values in alias set, "
378 "start value '1' of 'v1' does not match "
379 "start value '1' of 'v2'(negated alias).";
380 test_parsing_fail_and_fmu("alias_validation/inconsistent_neg_int_start_values",
381 should_have_1_no_alias_var);
383 expected_message = "Inconsistent start values in alias set, "
384 "start value '1' of 'v1' does not match "
385 "start value '1' of 'v2'(negated alias).";
386 test_parsing_fail_and_fmu("alias_validation/inconsistent_neg_enum_start_values",
387 should_have_1_no_alias_var);
389 expected_message = "Inconsistent start values in alias set, "
390 "start value 'true' of 'v1' does not match "
391 "start value 'true' of 'v2'(negated alias).";
392 test_parsing_fail_and_fmu("alias_validation/inconsistent_neg_bool_start_values",
393 should_have_1_no_alias_var);
395 expected_message = "Inconsistent start values in alias set, "
396 "start value 'a' of 'v1' does not match "
397 "start value 'a' of 'v2'(negated alias).";
398 test_parsing_fail_and_fmu("alias_validation/inconsistent_neg_str_start_values",
399 should_have_1_no_alias_var);
401 expected_message = "Inconsistent start values in alias set";
402 parser_no_log_expected_message("alias_validation/consistent_real_start_values2");
404 expected_message = "Inconsistent start values in alias set, "
405 "start value '1' of 'v2' does not match "
406 "start value '3' of 'v3'.";
407 parser_log_expected_message("alias_validation/inconsistent_int_start_values2");
409 expected_message = "Inconsistent start values in alias set";
410 test_parsing_pass_and_fmu("alias_validation/consistent_real_zero_start_values", should_have_size_2_alias_group);
413 void test_deprecation_errors(void) {
414 /* Test that we give errors for deprecated behviour
416 * Every test below has a corresponding modelDescription in
417 * Test/FMI1/parser_test_xmls/deprecated/
418 * What is passed to these macros are names of directories containing
422 expected_message = "Found capability flag canSignalEvents which have been "
423 "deprecated as it fills no function";
424 parser_log_expected_message("deprecated/canSignalEvents");
427 int main(int argc, char *argv[])
430 name_check_test_directory = argv[1];
\r
432 printf("Usage: %s <path to folder naming_conventions_xmls>\n", argv[0]);
\r
433 exit(CTEST_RETURN_FAIL);
436 test_variable_naming_conventions();
437 test_deprecation_errors();
438 test_alias_set_error_handling();