2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 FMILIB_License.txt file for more details.
12 You should have received a copy of the FMILIB_License.txt file
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
23 #include "config_test.h"
24 /*#include <JM/jm_types.h>
25 #include <JM/jm_portability.h>
26 #include <FMI1/fmi1_types.h>
27 #include <FMI1/fmi1_functions.h>
28 #include <FMI1/fmi1_capi.h>
29 #include <JM/jm_callbacks.h> */
30 #include <FMI1/fmi1_capi.h>
31 #include <fmu_dummy/fmu1_model_defines.h>
34 #define MODEL_IDENTIFIER FMU_DUMMY_ME_MODEL_IDENTIFIER
36 /* #define PRINT_VERBOSE */
37 #define INSTANCE_NAME "Test Model"
39 fmi1_capi_t* fmu; /* Pointer to the C-API struct that is used in all tests */
41 /* Logger function used by the C-API */
42 void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message)
44 printf("module = %s, log level = %d: %s\n", module, log_level, message);
47 /* Logger function used by the FMU internally */
48 void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...)
53 va_start(argp, message);
54 len = jm_vsnprintf(msg, BUFFER, message, argp);
55 printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg);
57 printf("Warning: Message was truncated");
61 /* Pause and exit function. Useally called when an error occured */
62 void do_exit(int code)
64 printf("Press any key to exit\n");
69 jm_callbacks* callbacks;
72 * \brief Tests fmi1_capi_create_dllfmu
75 int test_create_dllfmu()
77 fmi1_callback_functions_t callBackFunctions;
78 fmi1_fmu_kind_enu_t standard = fmi1_fmu_kind_enu_me;
80 callbacks = calloc(1, sizeof(jm_callbacks));
82 callbacks->malloc = malloc;
83 callbacks->calloc = calloc;
84 callbacks->realloc = realloc;
85 callbacks->free = free;
86 callbacks->logger = importlogger;
87 callbacks->context = 0;
89 callBackFunctions.logger = fmilogger;
90 callBackFunctions.allocateMemory = calloc;
91 callBackFunctions.freeMemory = free;
93 printf("fmi1_capi_create_dllfmu: ");
94 fmu = fmi1_capi_create_dllfmu(callbacks, FMU1_DLL_ME_PATH, MODEL_IDENTIFIER_STR, callBackFunctions, standard);
96 printf("An error occured while fmi1_capi_create_dllfmu was called, an error message should been printed.\n");
97 do_exit(CTEST_RETURN_FAIL);;
105 * \brief Tests fmi1_capi_load_dll
110 jm_status_enu_t status;
112 printf("fmi1_capi_load_dll: ");
113 status = fmi1_capi_load_dll(fmu);
114 if (status == jm_status_error) {
115 printf("Error in fmi1_capi_load_dll: %s\n", "fmi1_capi_get_last_error(fmu)");
116 do_exit(CTEST_RETURN_FAIL);;
124 * \brief Tests fmi1_capi_load_fcn
127 int test_load_dll_fcn()
129 jm_status_enu_t status;
131 printf("fmi1_capi_load_fcn: ");
132 status = fmi1_capi_load_fcn(fmu);
133 if (status == jm_status_error) {
135 printf("Error in fmi1_capi_load_fcn: %s\n", "fmi1_capi_get_last_error(fmu)");
136 do_exit(CTEST_RETURN_FAIL);;
144 * \brief Tests fmi1_capi_get_version
147 int test_fmi_get_version()
149 const char* version = fmi1_capi_get_version(fmu);
151 printf("fmi1_capi_get_version: ");
152 if (strcmp(FMI_VERSION, version) != 0) {
153 printf("Expected \"%s\" but returned \"%s\"", FMI_VERSION, version);
154 do_exit(CTEST_RETURN_FAIL);;
162 * \brief Tests fmi1_capi_get_model_types_platform
165 int test_fmi_get_model_types_platform()
167 const char* platformtype = fmi1_capi_get_model_types_platform(fmu);
169 printf("fmi1_capi_get_model_types_platform: ");
170 if (strcmp(FMI_PLATFORM_TYPE, platformtype) != 0) {
171 printf("Expected \"%s\" but returned \"%s\"", FMI_PLATFORM_TYPE, platformtype);
172 do_exit(CTEST_RETURN_FAIL);;
180 * \brief Tests fmi1_capi_instantiate_model
183 int test_instantiate_model()
185 fmi1_boolean_t loggingOn = fmi1_true;
187 if (fmi1_capi_instantiate_model(fmu, INSTANCE_NAME, FMI_GUID, loggingOn) == NULL) {
188 printf("fmi1_capi_instantiate_model: Failed\n");
189 do_exit(CTEST_RETURN_FAIL);;
191 printf("fmi1_capi_instantiate_model: Success\n");
197 * \brief Tests fmi1_capi_set_time
200 int test_fmi_set_time()
202 fmi1_status_t status;
203 status = fmi1_capi_set_time(fmu, 0.1);
204 if (status == fmi1_status_error || status == fmi1_status_fatal) {
205 printf("fmi1_capi_set_time: Failed\n");
206 do_exit(CTEST_RETURN_FAIL);;
208 printf("fmi1_capi_set_time: Success\n");
214 * \brief Tests fmi1_capi_set_continuous_states
217 int test_set_continuous_states()
219 fmi1_status_t status;
221 fmi1_real_t states[N_STATES];
223 for (k = 0; k < N_STATES; k++) {
224 states[k] = (fmi1_real_t)(k + 1) * 12;
227 status = fmi1_capi_set_continuous_states(fmu, states, N_STATES);
228 if (status == fmi1_status_error || status == fmi1_status_fatal) {
229 printf("fmi1_capi_set_continuous_states: Failed\n");
230 do_exit(CTEST_RETURN_FAIL);;
232 printf("fmi1_capi_set_continuous_states: Success\n");
234 for (k=0; k < N_STATES; k++) {
235 printf("\t x[%d] = %f\n",k, states[k]);
243 * \brief Tests fmi1_capi_initialize
246 int test_initialize()
248 fmi1_status_t status;
249 fmi1_boolean_t toleranceControlled;
250 fmi1_real_t relativeTolerance;
251 fmi1_event_info_t eventInfo;
253 relativeTolerance = 1e-5;
254 toleranceControlled = fmi1_true;
255 status = fmi1_capi_initialize(fmu, toleranceControlled, relativeTolerance, &eventInfo);
256 if (status == fmi1_status_error || status == fmi1_status_fatal) {
257 printf("fmi1_capi_initialize: Failed\n");
258 do_exit(CTEST_RETURN_FAIL);;
260 printf("fmi1_capi_initialize: Success\n");
262 printf("\t fmiEventInfo.iterationConverged = %s\n", eventInfo.iterationConverged ? "True" : "False");
263 printf("\t fmiEventInfo.stateValueReferencesChanged = %s\n", eventInfo.stateValueReferencesChanged ? "True" : "False");
264 printf("\t fmiEventInfo.stateValuesChanged = %s\n", eventInfo.stateValuesChanged ? "True" : "False");
265 printf("\t fmiEventInfo.terminateSimulation = %s\n", eventInfo.terminateSimulation ? "True" : "False");
266 printf("\t fmiEventInfo.upcomingTimeEvent = %s\n", eventInfo.upcomingTimeEvent ? "True" : "False");
267 printf("\t fmiEventInfo.nextEventTime = %f\n", eventInfo.nextEventTime);
274 * \brief Tests fmi1_capi_completed_integrator_step
277 int test_completed_integrator_step()
279 fmi1_status_t status;
280 fmi1_boolean_t callEventUpdate;
282 status = fmi1_capi_completed_integrator_step(fmu, &callEventUpdate);
283 if (status == fmi1_status_error || status == fmi1_status_fatal) {
284 printf("fmi1_capi_completed_integrator_step: Failed\n");
285 do_exit(CTEST_RETURN_FAIL);;
287 printf("fmi1_capi_completed_integrator_step: Success\n");
289 printf("\t callEventUpdate = %s\n", callEventUpdate ? "True" : "False");
296 * \brief Tests fmi1_capi_get_derivatives
299 int test_get_derivatives()
301 fmi1_status_t status;
303 fmi1_real_t dstates[N_STATES];
305 status = fmi1_capi_get_derivatives(fmu, dstates, N_STATES);
306 if (status == fmi1_status_error || status == fmi1_status_fatal) {
307 printf("fmi1_capi_get_derivatives: Failed\n");
308 do_exit(CTEST_RETURN_FAIL);;
310 printf("fmi1_capi_get_derivatives: Success\n");
312 for (k=0; k < N_STATES; k++) {
313 printf("\t dx[%d] = %f\n", k, dstates[k]);
320 int test_get_event_indicators()
322 fmi1_status_t status;
324 fmi1_real_t zerocrossing[N_EVENT_INDICATORS];
326 status = fmi1_capi_get_event_indicators(fmu, zerocrossing, N_EVENT_INDICATORS);
327 if (status == fmi1_status_error || status == fmi1_status_fatal) {
328 printf("fmi1_capi_get_event_indicators: Failed\n");
329 do_exit(CTEST_RETURN_FAIL);;
331 printf("fmi1_capi_get_event_indicators: Success\n");
333 for (k=0; k < N_EVENT_INDICATORS; k++) {
334 printf("\t nz[%d] = %f\n",k, zerocrossing[k]);
342 * \brief Tests fmi1_capi_eventUpdate
345 int test_event_update()
347 fmi1_status_t status;
348 fmi1_boolean_t intermediateResults = fmi1_false;
349 fmi1_event_info_t eventInfo;
351 status = fmi1_capi_eventUpdate(fmu, intermediateResults, &eventInfo);
352 if (status == fmi1_status_error || status == fmi1_status_fatal) {
353 printf("fmi1_capi_eventUpdate: Failed\n");
354 do_exit(CTEST_RETURN_FAIL);;
356 printf("fmi1_capi_eventUpdate: Success\n");
358 printf("\t fmiEventInfo.iterationConverged = %s\n", eventInfo.iterationConverged ? "True" : "False");
359 printf("\t fmiEventInfo.stateValueReferencesChanged = %s\n", eventInfo.stateValueReferencesChanged ? "True" : "False");
360 printf("\t fmiEventInfo.stateValuesChanged = %s\n", eventInfo.stateValuesChanged ? "True" : "False");
361 printf("\t fmiEventInfo.terminateSimulation = %s\n", eventInfo.terminateSimulation ? "True" : "False");
362 printf("\t fmiEventInfo.upcomingTimeEvent = %s\n", eventInfo.upcomingTimeEvent ? "True" : "False");
363 printf("\t fmiEventInfo.nextEventTime = %f\n", eventInfo.nextEventTime);
370 * \brief Tests fmi1_capi_get_continuous_states
373 int test_get_continuous_states()
375 fmi1_status_t status;
376 fmi1_real_t states[N_STATES];
379 status = fmi1_capi_get_continuous_states(fmu, states, N_STATES);
380 if (status == fmi1_status_error || status == fmi1_status_fatal) {
381 printf("fmi1_capi_get_continuous_states: Failed\n");
382 do_exit(CTEST_RETURN_FAIL);;
384 printf("fmi1_capi_get_continuous_states: Success\n");
386 for (k = 0; k < N_STATES; k++) {
387 printf("\t x[%d] = %f\n",k, states[k]);
395 * \brief Tests fmi1_capi_get_nominal_continuous_states
398 int test_get_nominal_continuous_states()
400 fmi1_status_t status;
402 fmi1_real_t states[N_STATES];
404 status = fmi1_capi_get_nominal_continuous_states(fmu, states, N_STATES);
405 if (status == fmi1_status_error || status == fmi1_status_fatal) {
406 printf("fmi1_capi_get_nominal_continuous_states: Failed\n");
407 do_exit(CTEST_RETURN_FAIL);;
409 printf("fmi1_capi_get_nominal_continuous_states: Success\n");
411 for (k = 0; k < N_STATES; k++) {
412 printf("\t x[%d] = %f\n",k, states[k]);
420 * \brief Tests fmi1_capi_get_state_value_references
423 int test_get_state_value_references()
425 fmi1_status_t status;
427 fmi1_value_reference_t vrs[N_STATES];
429 status = fmi1_capi_get_state_value_references(fmu, vrs, N_STATES);
430 if (status == fmi1_status_error || status == fmi1_status_fatal) {
431 printf("fmi1_capi_get_state_value_references: Failed\n");
432 do_exit(CTEST_RETURN_FAIL);;
434 printf("fmi1_capi_get_state_value_references: Success\n");
436 for (k=0; k < N_STATES; k++) {
437 printf("\t vrs[%u] = %u\n", k, vrs[k]);
445 * \brief Tests fmi1_capi_set_debug_logging
448 int test_set_debug_logging()
450 fmi1_status_t status;
451 status = fmi1_capi_set_debug_logging(fmu, fmi1_true);
452 if (status == fmi1_status_error || status == fmi1_status_fatal) {
453 printf("fmi1_capi_set_debug_logging: Failed\n");
454 do_exit(CTEST_RETURN_FAIL);;
456 printf("fmi1_capi_set_debug_logging: Success\n");
462 * \brief Tests fmi1_capi_set_string and fmi1_capi_get_string
463 * Some values are set with fmi1_capi_set_string. The same values are retrived with fmi1_capi_get_string and tested to be the same as thoughs that were set.
465 int test_set_get_string()
467 fmi1_status_t status;
468 fmi1_value_reference_t vrs[N_STRING];
469 fmi1_string_t values[N_STRING];
470 fmi1_string_t values_ref[N_STRING];
473 for (k = 0; k < N_STRING; k++) {
474 vrs[k] = (fmi1_value_reference_t)k;
476 values_ref[k] = values[k];
479 /* Test fmi1_capi_set_string */
480 status = fmi1_capi_set_string(fmu, vrs, N_STRING, values);
481 if (status == fmi1_status_error || status == fmi1_status_fatal) {
482 printf("fmi1_capi_set_string: Failed\n");
483 do_exit(CTEST_RETURN_FAIL);;
485 printf("fmi1_capi_set_string: Success\n");
488 /* Test fmi1_capi_get_string */
489 status = fmi1_capi_get_string(fmu, vrs, N_STRING, values);
490 if (status == fmi1_status_error || status == fmi1_status_fatal) {
491 printf("fmi1_capi_get_string: Failed\n");
492 do_exit(CTEST_RETURN_FAIL);;
494 for (k = 0; k < N_STRING; k++) {
495 if (strcmp(values_ref[k], values[k]) != 0) {
496 printf("fmi1_capi_get_string returned values[%u] = \"%s\" expected \"%s\"\n", (unsigned)k, values[k], values_ref[k]);
497 do_exit(CTEST_RETURN_FAIL);;
500 printf("fmi1_capi_get_string: Success\n");
507 * \brief Tests fmi1_capi_set_integer and fmi1_capi_get_integer
508 * Some values are set with fmi1_capi_set_integer. The same values are retrived with fmi1_capi_get_integer and tested to be the same as thoughs that were set.
510 int test_set_get_integer()
512 fmi1_status_t status;
513 fmi1_value_reference_t vrs[N_INTEGER];
514 fmi1_integer_t values[N_INTEGER];
515 fmi1_integer_t values_ref[N_INTEGER];
518 for (k = 0; k < N_INTEGER; k++) {
519 vrs[k] = (fmi1_value_reference_t)k;
520 values[k] = (k + 1) * 12;
521 values_ref[k] = values[k];
524 /* Test fmi1_capi_set_integer */
525 status = fmi1_capi_set_integer(fmu, vrs, N_INTEGER, values);
526 if (status == fmi1_status_error || status == fmi1_status_fatal) {
527 printf("fmi1_capi_set_integer: Failed\n");
528 do_exit(CTEST_RETURN_FAIL);;
530 printf("fmi1_capi_set_integer: Success\n");
533 /* Test fmi1_capi_get_integer */
534 status = fmi1_capi_get_integer(fmu, vrs, N_INTEGER, values);
535 if (status == fmi1_status_error || status == fmi1_status_fatal) {
536 printf("fmi1_capi_get_integer: Failed\n");
537 do_exit(CTEST_RETURN_FAIL);;
539 for (k = 0; k < N_INTEGER; k++) {
540 if (values_ref[k] != values[k]) {
541 printf("fmi1_capi_get_integer returned values[%d] = \"%d\" expected \"%d\"\n", k, values[k], values_ref[k]);
542 do_exit(CTEST_RETURN_FAIL);;
545 printf("fmi1_capi_get_integer: Success\n");
552 * \brief Tests fmi1_capi_set_boolean and fmi1_capi_get_boolean
553 * Some values are set with fmi1_capi_set_boolean. The same values are retrived with fmi1_capi_get_boolean and tested to be the same as thoughs that were set.
555 int test_set_get_boolean()
557 fmi1_status_t status;
558 fmi1_value_reference_t vrs[N_BOOLEAN];
559 fmi1_boolean_t values[N_BOOLEAN];
560 fmi1_boolean_t values_ref[N_BOOLEAN];
563 for (k = 0; k < N_INTEGER; k++) {
564 vrs[k] = (fmi1_value_reference_t)k;
565 values[k] = fmi1_true;
566 values_ref[k] = values[k];
569 /* Test fmi1_capi_set_boolean */
570 status = fmi1_capi_set_boolean(fmu, vrs, N_BOOLEAN, values);
571 if (status == fmi1_status_error || status == fmi1_status_fatal) {
572 printf("fmi1_capi_set_boolean: Failed\n");
573 do_exit(CTEST_RETURN_FAIL);;
575 printf("fmi1_capi_set_boolean: Success\n");
578 /* Test fmi1_capi_get_boolean */
579 status = fmi1_capi_get_boolean(fmu, vrs, N_BOOLEAN, values);
580 if (status == fmi1_status_error || status == fmi1_status_fatal) {
581 printf("fmi1_capi_get_boolean: Failed\n");
582 do_exit(CTEST_RETURN_FAIL);;
584 for (k = 0; k < N_BOOLEAN; k++) {
585 if (values_ref[k] != values[k]) {
586 printf("fmi1_capi_get_boolean returned values[%u] = \"%s\" expected \"%s\"\n", (unsigned)k, values[k] ? "fmiTrue" : "fmiFalse", values_ref[k] ? "fmiTrue" : "fmiFalse");
587 do_exit(CTEST_RETURN_FAIL);;
590 printf("fmi1_capi_get_boolean: Success\n");
597 * \brief Tests fmi1_capi_set_real and fmi1_capi_get_real
598 * Some values are set with fmi1_capi_set_real. The same values are retrived with fmi1_capi_get_real and tested to be the same as thoughs that were set.
600 int test_set_get_real()
602 fmi1_status_t status;
603 fmi1_value_reference_t vrs[N_REAL];
604 fmi1_real_t values[N_REAL];
605 fmi1_real_t values_ref[N_REAL];
608 for (k = 0; k < N_REAL; k++) {
609 vrs[k] = (fmi1_value_reference_t)(N_STATES + k);
610 values[k] = (fmi1_real_t)(k + 1) * 12;
611 values_ref[k] = values[k];
614 /* Test fmi1_capi_set_real */
615 status = fmi1_capi_set_real(fmu, vrs, N_REAL, values);
616 if (status == fmi1_status_error || status == fmi1_status_fatal) {
617 printf("fmi1_capi_set_real: Failed\n");
618 do_exit(CTEST_RETURN_FAIL);;
620 printf("fmi1_capi_set_real: Success\n");
623 /* Test fmi1_capi_get_real */
624 status = fmi1_capi_get_real(fmu, vrs, N_REAL, values);
625 if (status == fmi1_status_error || status == fmi1_status_fatal) {
626 printf("fmi1_capi_get_real: Failed\n");
627 do_exit(CTEST_RETURN_FAIL);;
629 for (k = 0; k < N_REAL; k++) {
630 if (values_ref[k] != values[k]) {
632 printf("fmi1_capi_get_real returned values[%u] = \"%f\" expected \"%f\"\n", (unsigned)k, (double)values[k], (double)values_ref[k]);
633 do_exit(CTEST_RETURN_FAIL);;
636 printf("fmi1_capi_get_real: Success\n");
643 * \brief Tests fmi1_capi_terminate
648 fmi1_status_t status;
650 status = fmi1_capi_terminate(fmu);
651 if (status == fmi1_status_error || status == fmi1_status_fatal) {
652 printf("fmi1_capi_terminate: Failed\n");
653 do_exit(CTEST_RETURN_FAIL);;
655 printf("fmi1_capi_terminate: Success\n");
661 * \brief Tests fmi1_capi_free_model_instance
664 int test_free_model_instance()
666 fmi1_capi_free_model_instance(fmu);
667 printf("fmi1_capi_instantiate_model: Success\n");
672 * \brief Tests fmi1_capi_free_dll
677 fmi1_capi_free_dll(fmu);
678 printf("fmi1_capi_free_dll: Success\n");
683 * \brief Tests fmi1_capi_destroy_dllfmu
686 int test_destroy_dllfmu()
688 fmi1_capi_destroy_dllfmu(fmu);
689 printf("fmi1_capi_destroy_dllfmu: Success\n");
694 * \brief Tests the C-API for FMI 1.0 Model Exchange.
695 * The tests are performed using a test-dll. The functions are called and the values are set or returned are validated either in the test function(output functions) or inside the dll(input functions). If any error occures, the program exits.
698 int main(int argc, char *argv[])
700 /* Test CAPI constructor functions */
701 test_create_dllfmu();
705 /* FMI ME 1.0 functions */
706 test_fmi_get_model_types_platform();
707 test_instantiate_model();
709 test_set_continuous_states();
711 test_completed_integrator_step();
712 test_get_derivatives();
713 test_get_event_indicators();
715 test_get_continuous_states();
716 test_get_nominal_continuous_states();
717 test_get_state_value_references();
719 test_fmi_get_version();
720 test_set_get_string();
721 test_set_get_boolean();
722 test_set_get_integer();
724 test_set_debug_logging();
727 test_free_model_instance();
729 /* Test CAPI destructor functions */
731 test_destroy_dllfmu();
734 printf("Everything seems to be ok!\n");
736 do_exit(CTEST_RETURN_SUCCESS);