FMI Library: part of JModelica.org
fmi1_xml_parsing_test.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <fmilib.h>
3 #include <stdio.h>
4 #include "config_test.h"
5 
6 static const int NO_LOG_EXPECTED_MSG = 0;
7 static const int DO_LOG_EXPECTED_MSG = 1;
8 
10 static char *expected_message = "Invalid structured ScalarVariable name";
12 
13 char *concat(char *s1, char *s2)
14 {
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));
19  if (result == NULL) {
20  exit(CTEST_RETURN_FAIL);
21  }
22  memcpy(result, s1, len1);
23  memcpy(result + len1, s2, len2 + 1); /* +1 to copy the null-terminator */
24  return result;
25 }
26 
28  jm_log_level_enu_t log_level, jm_string message)
29 {
30  printf("module = %s, log level = %d: %s\n", module, log_level, message);
31  if (!strncmp(expected_message, message, strlen(expected_message))) {
33  }
34 }
35 
38  free(cb);
39 }
40 
42  jm_callbacks *cb;
43 
44  cb = (jm_callbacks *) malloc(sizeof(jm_callbacks));
45  cb->malloc = malloc;
46  cb->calloc = calloc;
47  cb->realloc = realloc;
48  cb->free = free;
49  cb->logger = importlogger;
52 
53  return cb;
54 }
55 
56 fmi1_import_t* test_parser(jm_callbacks *cb, char *xml_dir, int should_log_expected_msg, int configuration)
57 {
59  char *full_path;
60 
61  if (configuration != 0) {
63  }
64 
66  full_path = concat(name_check_test_directory, xml_dir);
67  fmu = fmi1_import_parse_xml((fmi_import_context_t *)cb->context, full_path);
68 
69  free(full_path);
70  if (fmu == NULL) {
71  exit(CTEST_RETURN_FAIL);
72  }
73  if (should_log_expected_msg != did_log_expected_msg) {
74  exit(CTEST_RETURN_FAIL);
75  }
76 
77  return fmu;
78 }
79 
80 void test_parser_with_cleanup(char *xml_dir, int should_log_expected_msg, int configuration) {
82 
83  fmi1_import_t* fmu = test_parser(cb, xml_dir, should_log_expected_msg, configuration);
84  fmi1_import_free(fmu);
86 }
87 
88 void fail_name_check(char *xml_dir)
89 {
92 }
93 
94 void pass_name_check(char *xml_dir)
95 {
97 }
98 
99 void parser_log_expected_message(char *xml_dir)
100 {
102 }
103 
105 {
107 }
108 
109 typedef int (*fmu_test_f)(fmi1_import_t* fmu);
110 
111 void test_parsing_and_fmu(char *xml_dir, fmu_test_f fmu_test, int should_log_expected_msg)
112 {
114 
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);
118  }
119  fmi1_import_free(fmu);
120 
122 }
123 
124 void test_parsing_fail_and_fmu(char *xml_dir, fmu_test_f fmu_test)
125 {
126  test_parsing_and_fmu(xml_dir, fmu_test, DO_LOG_EXPECTED_MSG);
127 }
128 
129 void test_parsing_pass_and_fmu(char *xml_dir, fmu_test_f fmu_test)
130 {
131  test_parsing_and_fmu(xml_dir, fmu_test, NO_LOG_EXPECTED_MSG);
132 }
133 
135  /* Test scalar variable names
136  *
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
140  * modelDescriptions.
141  */
142 
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");
147 
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");
154 
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");
162 
163  /* q-name tests */
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 */
170 
171  /* der() tests */
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");
181 
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");
197 
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");
203 
204  /* flat hierarchy test */
205  fail_name_check("naming_conventions_xmls/flat/acad");
206  pass_name_check("naming_conventions_xmls/flat/q-char-nonescaped");
207 }
208 
211 
212  vars = fmi1_import_get_variable_list(fmu);
213  return fmi1_import_get_variable_list_size(vars) == 0;
214 }
215 
219 
220  vars = fmi1_import_get_variable_list(fmu);
221  if (fmi1_import_get_variable_list_size(vars) != 1) {
222  return 0;
223  }
224 
225  var = fmi1_import_get_variable(vars, 0);
227 }
228 
232 
233  vars = fmi1_import_get_variable_list(fmu);
234 
235  if (fmi1_import_get_variable_list_size(vars) != 2) {
236  return 0;
237  }
238 
239  var = fmi1_import_get_variable(vars, 0);
241  return 0;
242  }
243 
244  var = fmi1_import_get_variable(vars, 1);
246 }
247 
251 
252  vars = fmi1_import_get_variable_list(fmu);
253 
254  if (fmi1_import_get_variable_list_size(vars) != 2) {
255  return 0;
256  }
257 
258  var = fmi1_import_get_variable(vars, 0);
260  return 0;
261  }
262 
263  var = fmi1_import_get_variable(vars, 1);
265 }
266 
270 
271  vars = fmi1_import_get_variable_list(fmu);
272 
273  if (fmi1_import_get_variable_list_size(vars) != 3) {
274  return 0;
275  }
276 
277  var = fmi1_import_get_variable(vars, 0);
279  return 0;
280  }
281 
282  var = fmi1_import_get_variable(vars, 1);
284  return 0;
285  }
286 
287  var = fmi1_import_get_variable(vars, 2);
289 }
290 
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 */
295 
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);
300 
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);
305 
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);
310 
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);
313 
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);
316 
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);
319 
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);
324 
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);
327 
328  expected_message = "Inconsistent start values in alias set";
329  parser_no_log_expected_message("alias_validation/consistent_real_start_values");
330 
331  expected_message = "Inconsistent start values in alias set";
332  parser_no_log_expected_message("alias_validation/consistent_int_start_values");
333 
334  expected_message = "Inconsistent start values in alias set";
335  parser_no_log_expected_message("alias_validation/consistent_enum_start_values");
336 
337  expected_message = "Inconsistent start values in alias set";
338  parser_no_log_expected_message("alias_validation/consistent_bool_start_values");
339 
340  expected_message = "Inconsistent start values in alias set";
341  parser_no_log_expected_message("alias_validation/consistent_str_start_values");
342 
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",
347 
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",
353 
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",
359 
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",
365 
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",
371 
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",
376 
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",
382 
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",
388 
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",
394 
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",
400 
401  expected_message = "Inconsistent start values in alias set";
402  parser_no_log_expected_message("alias_validation/consistent_real_start_values2");
403 
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");
408 
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);
411 }
412 
414  /* Test that we give errors for deprecated behviour
415  *
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
419  * modelDescriptions.
420  */
421 
422  expected_message = "Found capability flag canSignalEvents which have been "
423  "deprecated as it fills no function";
424  parser_log_expected_message("deprecated/canSignalEvents");
425 }
426 
427 int main(int argc, char *argv[])
428 {
429  if (argc == 2) {
430  name_check_test_directory = argv[1];
431  } else {
432  printf("Usage: %s <path to folder naming_conventions_xmls>\n", argv[0]);
433  exit(CTEST_RETURN_FAIL);
434  }
435 
439 
440  return 0;
441 }
int jm_diff char
Definition: jm_vector.h:369
jm_calloc_f calloc
Allocate zero initialized memory.
Definition: jm_callbacks.h:77
void test_parser_with_cleanup(char *xml_dir, int should_log_expected_msg, int configuration)
static char * name_check_test_directory
static const int DO_LOG_EXPECTED_MSG
size_t jm_callbacks * c
int should_have_size_3_alias_group(fmi1_import_t *fmu)
struct fmi1_import_variable_list_t fmi1_import_variable_list_t
List of variables.
int main(int argc, char *argv[])
char * concat(char *s1, char *s2)
void test_parsing_pass_and_fmu(char *xml_dir, fmu_test_f fmu_test)
void importlogger(jm_callbacks *c, jm_string module, jm_log_level_enu_t log_level, jm_string message)
jm_log_level_enu_t
Log levels supported via the logger functions in jm_callbacks.
Definition: jm_types.h:51
void parser_log_expected_message(char *xml_dir)
Debug messages. Only enabled if library is configured with FMILIB_ENABLE_LOG_LEVEL_DEBUG.
Definition: jm_types.h:59
struct fmi1_xml_variable_t fmi1_import_variable_t
General variable type.
int should_have_size_2_no_alis(fmi1_import_t *fmu)
FMILIB_EXPORT fmi1_variable_alias_kind_enu_t fmi1_import_get_variable_alias_kind(fmi1_import_variable_t *)
Get the variable alias kind.
void parser_no_log_expected_message(char *xml_dir)
jm_log_level_enu_t log_level
Logging level.
Definition: jm_callbacks.h:85
FMILIB_EXPORT fmi1_import_variable_list_t * fmi1_import_get_variable_list(fmi1_import_t *fmu)
Get the list of all the variables in the model.
fmi1_capi_t * fmu
fmi1_import_t * test_parser(jm_callbacks *cb, char *xml_dir, int should_log_expected_msg, int configuration)
void pass_name_check(char *xml_dir)
static const int NO_LOG_EXPECTED_MSG
void test_parsing_fail_and_fmu(char *xml_dir, fmu_test_f fmu_test)
FMILIB_EXPORT fmi1_import_t * fmi1_import_parse_xml(fmi_import_context_t *c, const char *dirName)
Parse FMI 1.0 XML file found in the directory dirName.
Include file to be used in client applications of the FMI Library.
static char * expected_message
jm_malloc_f malloc
Allocate non-initialized memory.
Definition: jm_callbacks.h:75
jm_voidp context
Arbitrary context pointer passed to the logger function.
Definition: jm_callbacks.h:87
int should_have_1_no_alias_var(fmi1_import_t *fmu)
const char * jm_string
A constant string.
Definition: jm_types.h:33
void test_alias_set_error_handling(void)
FMILIB_EXPORT void fmi_import_set_configuration(fmi_import_context_t *c, int conf)
Sets advanced configuration, if zero is passed default configuration is set. Currently only one non d...
The callbacks struct is sent to all the modules in the library.
Definition: jm_callbacks.h:73
int should_have_size_2_alias_group(fmi1_import_t *fmu)
struct fmi_xml_context_t fmi_import_context_t
FMI version independent library context. Opaque struct returned from fmi_import_allocate_context() ...
FMILIB_EXPORT fmi_import_context_t * fmi_import_allocate_context(jm_callbacks *callbacks)
Create fmi_import_context_t structure.
void test_variable_naming_conventions(void)
int should_have_no_vars(fmi1_import_t *fmu)
struct fmi1_import_t fmi1_import_t
FMU version 1.0 object.
FMILIB_EXPORT size_t fmi1_import_get_variable_list_size(fmi1_import_variable_list_t *vl)
Get number of variables in a list.
jm_callbacks * create_parse_test_callbacks(void)
static int did_log_expected_msg
void test_parsing_and_fmu(char *xml_dir, fmu_test_f fmu_test, int should_log_expected_msg)
FMILIB_EXPORT void fmi_import_free_context(fmi_import_context_t *c)
Free memory allocated for the library context.
jm_realloc_f realloc
Re-allocate memory.
Definition: jm_callbacks.h:79
int(* fmu_test_f)(fmi1_import_t *fmu)
FMILIB_EXPORT fmi1_import_variable_t * fmi1_import_get_variable(fmi1_import_variable_list_t *vl, unsigned int index)
Get a single variable from the list.
#define FMI_IMPORT_NAME_CHECK
If this configuration option is set, the model description will be checked to follow the variable nam...
FMILIB_EXPORT void fmi1_import_free(fmi1_import_t *fmu)
Release the memory allocated.
void destroy_parse_test_callbacks(jm_callbacks *cb)
void test_deprecation_errors(void)
jm_free_f free
Free-allocated memory.
Definition: jm_callbacks.h:81
jm_logger_f logger
Logging callback.
Definition: jm_callbacks.h:83
void fail_name_check(char *xml_dir)