]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/Test/FMI1/fmi_import_cs_test.c
Add FMILibrary-2.0.3 to org.simantics.fmil.core\native.
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / Test / FMI1 / fmi_import_cs_test.c
1 /*\r
2     Copyright (C) 2012 Modelon AB\r
3 \r
4     This program is free software: you can redistribute it and/or modify\r
5     it under the terms of the BSD style license.\r
6 \r
7     This program is distributed in the hope that it will be useful,\r
8     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
10     FMILIB_License.txt file for more details.\r
11 \r
12     You should have received a copy of the FMILIB_License.txt file\r
13     along with this program. If not, contact Modelon AB <http://www.modelon.com>.\r
14 */\r
15 \r
16 #include <stdio.h>\r
17 #include <stdlib.h>\r
18 #include <stdarg.h>\r
19 #include <string.h>\r
20 \r
21 #include "config_test.h"\r
22 \r
23 #include <fmilib.h>\r
24 \r
25 \r
26 #define BUFFER 1000\r
27 \r
28 void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message)\r
29 {\r
30         printf("module = %s, log level = %s: %s\n", module, jm_log_level_to_string(log_level), message);\r
31 }\r
32 \r
33 /* Logger function used by the FMU internally */\r
34 \r
35 void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...)\r
36 {\r
37         /* char msg[BUFFER];*/\r
38         va_list argp;\r
39         va_start(argp, message);\r
40         /* vsnprintf(msg, BUFFER, message, argp); */\r
41         fmi1_log_forwarding_v(c, instanceName, status, category, message, argp);\r
42         va_end(argp);\r
43 }\r
44 \r
45 void do_exit(int code)\r
46 {\r
47         printf("Press 'Enter' to exit\n");\r
48         /* getchar(); */\r
49         exit(code);\r
50 }\r
51 \r
52 /* Testing "...Test\FMI1\fmu_dummy\modelDescription_cs_tc.xml" */\r
53 void test_xml_modelDescription_cs_tc(const char* xmlFileName, fmi1_import_t* fmu)\r
54 {\r
55     fmi1_import_variable_t* v;\r
56 \r
57     { /* Test variable "INTEGER" */\r
58         fmi1_import_integer_variable_t* vi;\r
59         const char* name = "INTEGER";\r
60         printf("Testing ScalarVariable %s\n", name);\r
61         v = fmi1_import_get_variable_by_name(fmu, name);\r
62         vi = fmi1_import_get_variable_as_integer(v);\r
63 \r
64         /* Test min attr */\r
65         if (1 != fmi1_import_get_integer_variable_min(vi)) {\r
66             printf("Test of XML file \"%s\" failed. min attribute value missmatch.\n", xmlFileName);\r
67             do_exit(CTEST_RETURN_FAIL);\r
68         }\r
69 \r
70         /* Test max attr */\r
71         if (11 != fmi1_import_get_integer_variable_max(vi)) {\r
72             printf("Test of XML file \"%s\" failed. max attribute value missmatch.\n", xmlFileName);\r
73             do_exit(CTEST_RETURN_FAIL);\r
74         }\r
75     }\r
76 \r
77     { /* Test variable "INTEGER_DECLAREDTYPE" */\r
78         fmi1_import_integer_variable_t* vi;\r
79         const char* name = "INTEGER_DECLAREDTYPE";\r
80         printf("Testing ScalarVariable %s\n", name);\r
81         v = fmi1_import_get_variable_by_name(fmu, name);\r
82         vi = fmi1_import_get_variable_as_integer(v);\r
83 \r
84         /* Test min attr */\r
85         if (2 != fmi1_import_get_integer_variable_min(vi)) {\r
86             printf("Test of XML file \"%s\" failed. min attribute value missmatch.\n", xmlFileName);\r
87             do_exit(CTEST_RETURN_FAIL);\r
88         }\r
89 \r
90         /* Test max attr */\r
91         if (22 != fmi1_import_get_integer_variable_max(vi)) {\r
92             printf("Test of XML file \"%s\" failed. max attribute value missmatch.\n", xmlFileName);\r
93             do_exit(CTEST_RETURN_FAIL);\r
94         }\r
95     }\r
96 \r
97     { /* Test variable "INTEGER_DECLAREDTYPE_OVERWRITE" */\r
98         fmi1_import_integer_variable_t* vi;\r
99         const char* name = "INTEGER_DECLAREDTYPE_OVERWRITE";\r
100         printf("Testing ScalarVariable %s\n", name);\r
101         v = fmi1_import_get_variable_by_name(fmu, name);\r
102         vi = fmi1_import_get_variable_as_integer(v);\r
103 \r
104         /* Test min attr */\r
105         if (1 != fmi1_import_get_integer_variable_min(vi)) {\r
106             printf("Test of XML file \"%s\" failed. min attribute value missmatch.\n", xmlFileName);\r
107             do_exit(CTEST_RETURN_FAIL);\r
108         }\r
109 \r
110         /* Test max attr */\r
111         if (11 != fmi1_import_get_integer_variable_max(vi)) {\r
112             printf("Test of XML file \"%s\" failed. max attribute value missmatch.\n", xmlFileName);\r
113             do_exit(CTEST_RETURN_FAIL);\r
114         }\r
115     }\r
116 \r
117     { /* Test variable "ENUMERATION_DECLAREDTYPE" */\r
118         fmi1_import_enum_variable_t* vi;\r
119         const char* name = "ENUMERATION_DECLAREDTYPE";\r
120         printf("Testing ScalarVariable %s\n", name);\r
121         v = fmi1_import_get_variable_by_name(fmu, name);\r
122         vi = fmi1_import_get_variable_as_enum(v);\r
123 \r
124         /* Test min attr */\r
125         if (1 != fmi1_import_get_enum_variable_min(vi)) {\r
126             printf("Test of XML file \"%s\" failed. min attribute value missmatch.\n", xmlFileName);\r
127             do_exit(CTEST_RETURN_FAIL);\r
128         }\r
129 \r
130         /* Test max attr */\r
131         if (5 != fmi1_import_get_enum_variable_max(vi)) {\r
132             printf("Test of XML file \"%s\" failed. max attribute value missmatch.\n", xmlFileName);\r
133             do_exit(CTEST_RETURN_FAIL);\r
134         }\r
135     }\r
136 \r
137     { /* Test variable "ENUMERATION_DECLAREDTYPE_OVERWRITE" */\r
138         fmi1_import_enum_variable_t* vi;\r
139         const char* name = "ENUMERATION_DECLAREDTYPE_OVERWRITE";\r
140         printf("Testing ScalarVariable %s\n", name);\r
141         v = fmi1_import_get_variable_by_name(fmu, name);\r
142         vi = fmi1_import_get_variable_as_enum(v);\r
143 \r
144         /* Test min attr */\r
145         if (2 != fmi1_import_get_enum_variable_min(vi)) {\r
146             printf("Test of XML file \"%s\" failed. min attribute value missmatch.\n", xmlFileName);\r
147             do_exit(CTEST_RETURN_FAIL);\r
148         }\r
149 \r
150         /* Test max attr */\r
151         if (3 != fmi1_import_get_enum_variable_max(vi)) {\r
152             printf("Test of XML file \"%s\" failed. max attribute value missmatch.\n", xmlFileName);\r
153             do_exit(CTEST_RETURN_FAIL);\r
154         }\r
155     }\r
156 }\r
157 \r
158 typedef struct {\r
159         const char* filename;\r
160         int performTest;\r
161         void (*fcn)(const char* xmlFileName, fmi1_import_t* fmu);\r
162 } xml_test_files_t;\r
163 \r
164 xml_test_files_t xml_test_files[] = {\r
165         {"modelDescription_cs_tc.xml", 1, test_xml_modelDescription_cs_tc},\r
166         {"modelDescription_cs.xml", 0, NULL}\r
167 };\r
168 \r
169 void test_xml(const char* xmlFileName, fmi1_import_t* fmu)\r
170 {\r
171     int k;\r
172     int foundxml = 0;\r
173 \r
174     for (k = 0; k < sizeof(xml_test_files)/sizeof(*xml_test_files); k++) {\r
175         foundxml = strcmp(xmlFileName, xml_test_files[k].filename) == 0 ? 1 : 0;\r
176         if (foundxml) {\r
177             if (xml_test_files[k].performTest) {\r
178                 xml_test_files[k].fcn(xmlFileName, fmu); /* Run specific file XML file test */\r
179             }\r
180             return;\r
181         }\r
182     }\r
183 \r
184     if (!foundxml) {\r
185         printf("XML file test is not properly implemented in " __FILE__ " . Could not find the XML \"%s\" in the list of expected XML-files", xmlFileName);\r
186         do_exit(CTEST_RETURN_FAIL);\r
187     }\r
188 }\r
189 \r
190 \r
191 int test_simulate_cs(fmi1_import_t* fmu)\r
192 {\r
193         fmi1_status_t fmistatus;\r
194         jm_status_enu_t jmstatus;\r
195 \r
196         fmi1_string_t instanceName = "Test CS model instance";\r
197         fmi1_string_t fmuGUID;\r
198         fmi1_string_t fmuLocation = "";\r
199         fmi1_string_t mimeType = "";\r
200         fmi1_real_t timeout = 0.0;\r
201         fmi1_boolean_t visible = fmi1_false;\r
202         fmi1_boolean_t interactive = fmi1_false;\r
203 /*      fmi1_boolean_t loggingOn = fmi1_true; */\r
204 \r
205         /* fmi1_real_t simulation_results[] = {-0.001878, -1.722275}; */\r
206         fmi1_real_t simulation_results[] = {0.0143633,   -1.62417};\r
207         fmi1_value_reference_t compare_real_variables_vr[] = {0, 1};\r
208         size_t k;\r
209 \r
210         fmi1_real_t tstart = 0.0;\r
211         fmi1_real_t tcur = tstart;\r
212         fmi1_real_t hstep = 0.1;\r
213         fmi1_real_t tend = 2.0;\r
214         fmi1_boolean_t StopTimeDefined = fmi1_false;\r
215 \r
216         if (sizeof(compare_real_variables_vr)/sizeof(fmi1_value_reference_t) != sizeof(simulation_results)/sizeof(fmi1_real_t)) {\r
217                 printf("Number of simulation values and reference values are different\n");\r
218                 do_exit(CTEST_RETURN_FAIL);\r
219         }\r
220 \r
221         printf("Version returned from FMU:   %s\n", fmi1_import_get_version(fmu));\r
222         printf("Platform type returned:      %s\n", fmi1_import_get_types_platform(fmu));\r
223 \r
224         fmuGUID = fmi1_import_get_GUID(fmu);\r
225     printf("GUID:      %s\n", fmuGUID);\r
226 \r
227 \r
228         jmstatus = fmi1_import_instantiate_slave(fmu, instanceName, fmuLocation, mimeType, timeout, visible, interactive);\r
229         if (jmstatus == jm_status_error) {\r
230                 printf("fmi1_import_instantiate_model failed\n");\r
231                 do_exit(CTEST_RETURN_FAIL);\r
232         }\r
233 \r
234         fmistatus = fmi1_import_initialize_slave(fmu, tstart, StopTimeDefined, tend);\r
235     if(fmistatus != fmi1_status_ok) {\r
236         printf("fmi1_import_initialize_slave failed\n");\r
237                 do_exit(CTEST_RETURN_FAIL);\r
238     }\r
239 \r
240         tcur = tstart;\r
241         printf("%10s %10s\n", "Ball height", "Ball speed");\r
242         while (tcur < tend) {\r
243                 fmi1_boolean_t newStep = fmi1_true;\r
244 #if 0 /* Prints a real value.. */\r
245                 fmi1_real_t rvalue;\r
246                 fmi1_value_reference_t vr = 0;\r
247 \r
248                 fmistatus = fmi1_import_get_real(fmu, &vr, 1, &rvalue);\r
249                 printf("rvalue = %f\n", rvalue);\r
250 #endif\r
251                 fmistatus = fmi1_import_do_step(fmu, tcur, hstep, newStep);\r
252 \r
253                 for (k = 0; k < sizeof(compare_real_variables_vr)/sizeof(fmi1_value_reference_t); k++) {\r
254                         fmi1_value_reference_t vr = compare_real_variables_vr[k];\r
255                         fmi1_real_t rvalue;\r
256                         fmistatus = fmi1_import_get_real(fmu, &vr, 1, &rvalue);\r
257                 }\r
258                 {\r
259                         fmi1_real_t val[2];\r
260                         fmi1_import_get_real(fmu, compare_real_variables_vr, 2, val);\r
261                         printf("%10g %10g\n", val[0],val[1]);\r
262                 }\r
263 \r
264                 tcur += hstep;\r
265         }\r
266 \r
267         printf("Simulation finished. Checking results\n");\r
268 \r
269         /* Validate result */\r
270         for (k = 0; k < sizeof(compare_real_variables_vr)/sizeof(fmi1_value_reference_t); k++) {\r
271                 fmi1_value_reference_t vr = compare_real_variables_vr[k];\r
272                 fmi1_real_t rvalue;\r
273                 fmi1_real_t res;\r
274                 fmistatus = fmi1_import_get_real(fmu, &vr, 1, &rvalue);\r
275                 res = rvalue - simulation_results[k];\r
276                 res = res > 0 ? res: -res; /* Take abs */\r
277                 if (res > 3e-3) {\r
278                         printf("Simulation results is wrong!\n");\r
279                         printf("State [%u]  %g != %g, |res| = %g\n", (unsigned)k, rvalue, simulation_results[k], res);\r
280                         printf("\n");\r
281                         do_exit(CTEST_RETURN_FAIL);\r
282                 }\r
283         }\r
284 \r
285         fmistatus = fmi1_import_terminate_slave(fmu);\r
286 \r
287         fmi1_import_free_slave_instance(fmu);\r
288 \r
289         return 0;\r
290 }\r
291 \r
292 int main(int argc, char *argv[])\r
293 {\r
294         fmi1_callback_functions_t callBackFunctions;\r
295         const char* FMUPath;\r
296         const char* tmpPath;\r
297         const char* xmlFileName;\r
298         jm_callbacks callbacks;\r
299         fmi_import_context_t* context;\r
300         fmi_version_enu_t version;\r
301         jm_status_enu_t status;\r
302         int k;\r
303 \r
304         fmi1_import_t* fmu;\r
305 \r
306         if(argc < 4) {\r
307                 printf("Usage: %s <fmu_file> <temporary_dir> <modelDescription_file>\n", argv[0]);\r
308                 do_exit(CTEST_RETURN_FAIL);\r
309         }\r
310         for (k = 0; k < argc; k ++)\r
311                 printf("argv[%d] = %s\n", k, argv[k]);\r
312 \r
313         FMUPath = argv[1];\r
314         tmpPath = argv[2];\r
315         xmlFileName = argv[3];\r
316 \r
317         callbacks.malloc = malloc;\r
318     callbacks.calloc = calloc;\r
319     callbacks.realloc = realloc;\r
320     callbacks.free = free;\r
321     callbacks.logger = importlogger;\r
322         callbacks.log_level = jm_log_level_debug;\r
323     callbacks.context = 0;\r
324 \r
325         callBackFunctions.logger = fmi1_log_forwarding;\r
326         callBackFunctions.allocateMemory = calloc;\r
327         callBackFunctions.freeMemory = free;\r
328 \r
329 #ifdef FMILIB_GENERATE_BUILD_STAMP\r
330         printf("Library build stamp:\n%s\n", fmilib_get_build_stamp());\r
331 #endif\r
332 \r
333         context = fmi_import_allocate_context(&callbacks);\r
334 \r
335         version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);\r
336 \r
337         if(version != fmi_version_1_enu) {\r
338                 printf("Only version 1.0 is supported so far\n");\r
339                 do_exit(CTEST_RETURN_FAIL);\r
340         }\r
341 \r
342         fmu = fmi1_import_parse_xml(context, tmpPath);\r
343 \r
344         if(!fmu) {\r
345                 printf("Error parsing XML, exiting\n");\r
346                 do_exit(CTEST_RETURN_FAIL);\r
347         }\r
348 \r
349 \r
350         status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 1);\r
351         if (status == jm_status_error) {\r
352                 printf("Could not create the DLL loading mechanism(C-API) (error: %s).\n", fmi1_import_get_last_error(fmu));\r
353                 do_exit(CTEST_RETURN_FAIL);\r
354         }\r
355 \r
356         test_simulate_cs(fmu);\r
357         test_xml(xmlFileName, fmu);\r
358 \r
359         fmi1_import_destroy_dllfmu(fmu);\r
360 \r
361         fmi1_import_free(fmu);\r
362         fmi_import_free_context(context);\r
363 \r
364         printf("Everything seems to be OK since you got this far=)!\n");\r
365 \r
366         do_exit(CTEST_RETURN_SUCCESS);\r
367 \r
368         return 0;\r
369 }\r
370 \r
371 \r