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>.
22 #include <JM/jm_types.h>
23 #include <JM/jm_portability.h>
24 #include <FMI1/fmi1_types.h>
25 #include <FMI1/fmi1_functions.h>
26 #include <FMI1/fmi1_capi.h>
27 #include <JM/jm_callbacks.h>
28 #include <fmu_dummy/fmu1_model_defines.h>
29 #include "config_test.h" /* Defines path to the DLL file */
32 #define MODEL_IDENTIFIER FMU_DUMMY_CS_MODEL_IDENTIFIER
34 /* #define PRINT_VERBOSE */
35 #define INSTANCE_NAME "Test Model"
37 fmi1_capi_t* fmu; /* Pointer to the C-API struct that is used in all tests */
39 /* Logger function used by the C-API */
40 void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message)
42 printf("module = %s, log level = %d: %s\n", module, log_level, message);
45 /* Logger function used by the FMU internally */
46 void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...)
51 va_start(argp, message);
52 len=jm_vsnprintf(msg, BUFFER, message, argp);
53 printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg);
55 printf("Warning: message was trancated");
59 /* Pause and exit function. Useally called when an error occured */
60 void do_exit(int code)
62 printf("Press any key to exit\n");
67 jm_callbacks* callbacks = 0;
70 * \brief Tests fmi1_capi_create_dllfmu
73 int test_create_dllfmu()
75 fmi1_callback_functions_t callBackFunctions;
76 fmi1_fmu_kind_enu_t standard = fmi1_fmu_kind_enu_cs_standalone;
78 callbacks = calloc(1, sizeof(jm_callbacks));
80 callbacks->malloc = malloc;
81 callbacks->calloc = calloc;
82 callbacks->realloc = realloc;
83 callbacks->free = free;
84 callbacks->logger = importlogger;
85 callbacks->log_level = jm_log_level_debug;
86 callbacks->context = 0;
88 callBackFunctions.logger = fmilogger;
89 callBackFunctions.allocateMemory = calloc;
90 callBackFunctions.freeMemory = free;
92 printf("fmi1_capi_create_dllfmu: ");
93 fmu = fmi1_capi_create_dllfmu(callbacks, FMU1_DLL_CS_PATH, MODEL_IDENTIFIER_STR, callBackFunctions, standard);
95 printf("An error occured while fmi1_capi_create_dllfmu was called, an error message should been printed.\n");
96 do_exit(CTEST_RETURN_FAIL);;
104 * \brief Tests fmi1_capi_load_dll
109 jm_status_enu_t status;
111 printf("fmi1_capi_load_dll: ");
112 status = fmi1_capi_load_dll(fmu);
113 if (status == jm_status_error) {
114 printf("Error in fmi1_capi_load_dll: %s\n", jm_get_last_error(callbacks));
115 do_exit(CTEST_RETURN_FAIL);;
123 * \brief Tests fmi1_capi_load_fcn
126 int test_load_dll_fcn()
128 jm_status_enu_t status;
130 printf("fmi1_capi_load_fcn: ");
131 status = fmi1_capi_load_fcn(fmu);
132 if (status == jm_status_error) {
134 printf("Error in fmi1_capi_load_fcn: %s\n", "fmi1_capi_get_last_error(fmu)");
135 do_exit(CTEST_RETURN_FAIL);;
143 * \brief Tests fmi1_capi_get_version
146 int test_fmi_get_version()
148 const char* version = fmi1_capi_get_version(fmu);
150 printf("fmi1_capi_get_version: ");
151 if (strcmp(FMI_VERSION, version) != 0) {
152 printf("Expected \"%s\" but returned \"%s\"", FMI_VERSION, version);
153 do_exit(CTEST_RETURN_FAIL);;
161 * \brief Tests fmi1_capi_get_types_platform
164 int test_get_types_platform()
166 const char* platformtype = fmi1_capi_get_types_platform(fmu);
168 printf("fmi1_capi_get_types_platform: ");
169 if (strcmp(FMI_PLATFORM_TYPE, platformtype) != 0) {
170 printf("Expected \"%s\" but returned \"%s\"", FMI_PLATFORM_TYPE, platformtype);
171 do_exit(CTEST_RETURN_FAIL);;
179 * \brief Tests fmi1_capi_instantiate_slave
182 int test_instantiate_slave()
184 fmi1_string_t fmuLocation;
185 fmi1_string_t mimeType;
187 fmi1_boolean_t visible;
188 fmi1_boolean_t interactive;
189 fmi1_boolean_t loggingOn;
194 visible = fmi1_false;
195 interactive = fmi1_false;
196 loggingOn = fmi1_true;
198 if (fmi1_capi_instantiate_slave(fmu, INSTANCE_NAME, FMI_GUID, fmuLocation, mimeType, timeout, visible, interactive, loggingOn) == NULL) {
199 printf("fmi1_capi_instantiate_slave: Failed\n");
200 do_exit(CTEST_RETURN_FAIL);;
202 printf("fmi1_capi_instantiate_slave: Success\n");
208 * \brief Tests fmi1_capi_initialize_slave
211 int test_initialize_slave()
213 fmi1_status_t status;
216 fmi1_boolean_t StopTimeDefined;
220 StopTimeDefined = fmi1_false;
222 status = fmi1_capi_initialize_slave(fmu, tStart, StopTimeDefined, tStop);
223 if (status == fmi1_status_error || status == fmi1_status_fatal) {
224 printf("fmi1_capi_initialize_slave: Failed\n");
225 do_exit(CTEST_RETURN_FAIL);;
227 printf("fmi1_capi_initialize_slave: Success\n");
233 * \brief Tests fmi1_capi_set_debug_logging
236 int test_set_debug_logging()
238 fmi1_status_t status;
239 status = fmi1_capi_set_debug_logging(fmu, fmi1_true);
240 if (status == fmi1_status_error || status == fmi1_status_fatal) {
241 printf("fmi1_capi_set_debug_logging: Failed\n");
242 do_exit(CTEST_RETURN_FAIL);;
244 printf("fmi1_capi_set_debug_logging: Success\n");
250 * \brief Tests fmi1_capi_cancel_step
253 int test_cancel_step()
255 fmi1_status_t status;
256 status = fmi1_capi_cancel_step(fmu);
257 if (status == fmi1_status_error || status == fmi1_status_fatal) {
258 printf("fmi1_capi_cancel_step: Failed\n");
259 do_exit(CTEST_RETURN_FAIL);;
261 printf("fmi1_capi_cancel_step: Success\n");
267 * \brief Tests fmi1_capi_do_step
272 fmi1_status_t status;
273 fmi1_real_t currentCommunicationPoint;
274 fmi1_real_t communicationStepSize;
275 fmi1_boolean_t newStep;
277 currentCommunicationPoint = 0;
278 communicationStepSize = 0.1;
280 status = fmi1_capi_do_step(fmu, currentCommunicationPoint, communicationStepSize, newStep);
281 if (status == fmi1_status_error || status == fmi1_status_fatal) {
282 printf("fmi1_capi_do_step: Failed\n");
283 do_exit(CTEST_RETURN_FAIL);;
285 printf("fmi1_capi_do_step: Success\n");
291 * \brief Tests fmi1_capi_get_status
294 int test_get_status()
296 fmi1_status_t status;
297 fmi1_status_kind_t statuskind;
298 fmi1_status_t statusvalue;
300 statuskind = fmi1_do_step_status;
301 status = fmi1_capi_get_status(fmu, statuskind, &statusvalue);
302 if (status == fmi1_status_error || status == fmi1_status_fatal) {
303 printf("fmi1_capi_get_status: Failed\n");
304 do_exit(CTEST_RETURN_FAIL);;
306 printf("fmi1_capi_get_status: Success\n");
312 * \brief Tests fmi1_capi_get_real_status
315 int test_get_real_status()
317 fmi1_status_t status;
318 fmi1_status_kind_t statuskind = fmi1_last_successful_time;
321 status = fmi1_capi_get_real_status(fmu, statuskind, &real);
322 if (status == fmi1_status_error || status == fmi1_status_fatal) {
323 printf("fmi1_capi_get_real_status: Failed\n");
324 do_exit(CTEST_RETURN_FAIL);;
326 printf("fmi1_capi_get_real_status: Success\n");
332 * \brief Tests fmi1_capi_get_integer_status
335 int test_get_integer_status()
337 fmi1_status_t status;
338 fmi1_status_kind_t statuskind = fmi1_last_successful_time;
339 fmi1_integer_t integer;
341 status = fmi1_capi_get_integer_status(fmu, statuskind, &integer);
342 if (status != fmi1_status_discard) {
343 printf("fmi1_capi_get_integer_status: Failed\n");
344 do_exit(CTEST_RETURN_FAIL);;
346 printf("fmi1_capi_get_integer_status: Success\n");
352 * \brief Tests fmi1_capi_get_boolean_status
355 int test_get_boolean_status()
357 fmi1_status_t status;
358 fmi1_status_kind_t statuskind = fmi1_last_successful_time;
359 fmi1_boolean_t boolean;
361 status = fmi1_capi_get_boolean_status(fmu, statuskind, &boolean);
362 if (status != fmi1_status_discard) {
363 printf("fmi1_capi_get_boolean_status: Failed\n");
364 do_exit(CTEST_RETURN_FAIL);;
366 printf("fmi1_capi_get_boolean_status: Success\n");
372 * \brief Tests fmi1_capi_get_string_status
375 int test_get_string_status()
377 fmi1_status_t status;
378 fmi1_status_kind_t statuskind = fmi1_pending_status;
379 fmi1_string_t string;
381 status = fmi1_capi_get_string_status(fmu, statuskind, &string);
382 if (status != fmi1_status_discard) {
383 printf("fmi1_capi_get_string_status: Failed\n");
384 do_exit(CTEST_RETURN_FAIL);;
386 printf("fmi1_capi_get_string_status: Success\n");
392 * \brief Tests fmi1_capi_set_string and fmi1_capi_get_string
393 * 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.
395 int test_set_get_string()
397 fmi1_status_t status;
398 fmi1_value_reference_t vrs[N_STRING];
399 fmi1_string_t values[N_STRING];
400 fmi1_string_t values_ref[N_STRING];
403 for (k = 0; k < N_STRING; k++) {
404 vrs[k] = (fmi1_value_reference_t)k;
406 values_ref[k] = values[k];
409 /* Test fmi1_capi_set_string */
410 status = fmi1_capi_set_string(fmu, vrs, N_STRING, values);
411 if (status == fmi1_status_error || status == fmi1_status_fatal) {
412 printf("fmi1_capi_set_string: Failed\n");
413 do_exit(CTEST_RETURN_FAIL);;
415 printf("fmi1_capi_set_string: Success\n");
418 /* Test fmi1_capi_get_string */
419 status = fmi1_capi_get_string(fmu, vrs, N_STRING, values);
420 if (status == fmi1_status_error || status == fmi1_status_fatal) {
421 printf("fmi1_capi_get_string: Failed\n");
422 do_exit(CTEST_RETURN_FAIL);;
424 for (k = 0; k < N_STRING; k++) {
425 if (strcmp(values_ref[k], values[k]) != 0) {
426 printf("fmi1_capi_get_string returned values[%u] = \"%s\" expected \"%s\"\n", (unsigned)k, values[k], values_ref[k]);
427 do_exit(CTEST_RETURN_FAIL);;
430 printf("fmi1_capi_get_string: Success\n");
437 * \brief Tests fmi1_capi_set_integer and fmi1_capi_get_integer
438 * 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.
440 int test_set_get_integer()
442 fmi1_status_t status;
443 fmi1_value_reference_t vrs[N_INTEGER];
444 fmi1_integer_t values[N_INTEGER];
445 fmi1_integer_t values_ref[N_INTEGER];
448 for (k = 0; k < N_INTEGER; k++) {
449 vrs[k] = (fmi1_value_reference_t)k;
450 values[k] = (k + 1) * 12;
451 values_ref[k] = values[k];
454 /* Test fmi1_capi_set_integer */
455 status = fmi1_capi_set_integer(fmu, vrs, N_INTEGER, values);
456 if (status == fmi1_status_error || status == fmi1_status_fatal) {
457 printf("fmi1_capi_set_integer: Failed\n");
458 do_exit(CTEST_RETURN_FAIL);;
460 printf("fmi1_capi_set_integer: Success\n");
463 /* Test fmi1_capi_get_integer */
464 status = fmi1_capi_get_integer(fmu, vrs, N_INTEGER, values);
465 if (status == fmi1_status_error || status == fmi1_status_fatal) {
466 printf("fmi1_capi_get_integer: Failed\n");
467 do_exit(CTEST_RETURN_FAIL);
469 for (k = 0; k < N_INTEGER; k++) {
470 if (values_ref[k] != values[k]) {
471 printf("fmi1_capi_get_integer returned values[%d] = \"%d\" expected \"%d\"\n", k, values[k], values_ref[k]);
472 do_exit(CTEST_RETURN_FAIL);
475 printf("fmi1_capi_get_integer: Success\n");
482 * \brief Tests fmi1_capi_set_boolean and fmi1_capi_get_boolean
483 * 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.
485 int test_set_get_boolean()
487 fmi1_status_t status;
488 fmi1_value_reference_t vrs[N_BOOLEAN];
489 fmi1_boolean_t values[N_BOOLEAN];
490 fmi1_boolean_t values_ref[N_BOOLEAN];
493 for (k = 0; k < N_INTEGER; k++) {
494 vrs[k] = (fmi1_value_reference_t)k;
495 values[k] = fmi1_true;
496 values_ref[k] = values[k];
499 /* Test fmi1_capi_set_boolean */
500 status = fmi1_capi_set_boolean(fmu, vrs, N_BOOLEAN, values);
501 if (status == fmi1_status_error || status == fmi1_status_fatal) {
502 printf("fmi1_capi_set_boolean: Failed\n");
503 do_exit(CTEST_RETURN_FAIL);
505 printf("fmi1_capi_set_boolean: Success\n");
508 /* Test fmi1_capi_get_boolean */
509 status = fmi1_capi_get_boolean(fmu, vrs, N_BOOLEAN, values);
510 if (status == fmi1_status_error || status == fmi1_status_fatal) {
511 printf("fmi1_capi_get_boolean: Failed\n");
512 do_exit(CTEST_RETURN_FAIL);
514 for (k = 0; k < N_BOOLEAN; k++) {
515 if (values_ref[k] != values[k]) {
516 printf("fmi1_capi_get_boolean returned values[%u] = \"%s\" expected \"%s\"\n", (unsigned)k, values[k] ? "fmiTrue" : "fmiFalse", values_ref[k] ? "fmiTrue" : "fmiFalse");
517 do_exit(CTEST_RETURN_FAIL);
520 printf("fmi1_capi_get_boolean: Success\n");
527 * \brief Tests fmi1_capi_set_real and fmi1_capi_get_real
528 * 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.
530 int test_set_get_real()
532 fmi1_status_t status;
533 fmi1_value_reference_t vrs[N_REAL];
534 fmi1_real_t values[N_REAL];
535 fmi1_real_t values_ref[N_REAL];
538 for (k = 0; k < N_REAL; k++) {
539 vrs[k] = (fmi1_value_reference_t)(N_STATES + k);
540 values[k] = (fmi1_real_t)(k + 1) * 12;
541 values_ref[k] = values[k];
544 /* Test fmi1_capi_set_real */
545 status = fmi1_capi_set_real(fmu, vrs, N_REAL, values);
546 if (status == fmi1_status_error || status == fmi1_status_fatal) {
547 printf("fmi1_capi_set_real: Failed\n");
548 do_exit(CTEST_RETURN_FAIL);
550 printf("fmi1_capi_set_real: Success\n");
553 /* Test fmi1_capi_get_real */
554 status = fmi1_capi_get_real(fmu, vrs, N_REAL, values);
555 if (status == fmi1_status_error || status == fmi1_status_fatal) {
556 printf("fmi1_capi_get_real: Failed\n");
557 do_exit(CTEST_RETURN_FAIL);
559 for (k = 0; k < N_REAL; k++) {
560 if (values_ref[k] != values[k]) {
561 printf("fmi1_capi_get_real returned values[%u] = \"%f\" expected \"%f\"\n", (unsigned)k, values[k], values_ref[k]);
562 do_exit(CTEST_RETURN_FAIL);
565 printf("fmi1_capi_get_real: Success\n");
572 * \brief Tests fmi1_capi_reset_slave
575 int test_reset_slave()
577 fmi1_status_t status;
578 status = fmi1_capi_reset_slave(fmu);
579 if (status == fmi1_status_error || status == fmi1_status_fatal) {
580 printf("fmi1_capi_reset_slave: Failed\n");
581 do_exit(CTEST_RETURN_FAIL);
583 printf("fmi1_capi_reset_slave: Success\n");
589 * \brief Tests fmi1_capi_set_real_input_derivatives
590 * fmi1_capi_set_real_input_derivatives returns fmiError if wrong values are set. The values that are set are tested inside the DLL.
592 int test_set_real_input_derivatives()
594 fmi1_status_t status;
595 fmi1_value_reference_t vrs [N_INPUT_REAL * N_INPUT_REAL_MAX_ORDER];
596 fmi1_real_t values [N_INPUT_REAL * N_INPUT_REAL_MAX_ORDER];
597 fmi1_integer_t order [N_INPUT_REAL * N_INPUT_REAL_MAX_ORDER];
600 for (k = 0; k < N_INPUT_REAL_MAX_ORDER; k++) {
601 for (p = 0; p < N_INPUT_REAL; p++)
603 vrs [p + k * N_INPUT_REAL] = (fmi1_value_reference_t)p;
604 values [p + k * N_INPUT_REAL] = MAGIC_TEST_VALUE; /* This value is tested in the DLL to be exakt MAGIC_TEST_VALUE */
605 order [p + k * N_INPUT_REAL] = k + 1;
609 status = fmi1_capi_set_real_input_derivatives(fmu, vrs, N_INPUT_REAL * N_INPUT_REAL_MAX_ORDER, order, values);
610 if (status == fmi1_status_error || status == fmi1_status_fatal) {
611 printf("fmi1_capi_set_real_input_derivatives: Failed\n");
612 do_exit(CTEST_RETURN_FAIL);
614 printf("fmi1_capi_set_real_input_derivatives: Success\n");
620 * \brief Tests fmi1_capi_get_real_output_derivatives
621 * The output values from fmi1_capi_get_real_output_derivatives is expected to have a special value that is coded in the DLL.
623 int test_get_real_output_derivatives()
625 fmi1_status_t status;
626 fmi1_value_reference_t vrs [N_OUTPUT_REAL * N_OUTPUT_REAL_MAX_ORDER];
627 fmi1_real_t values [N_OUTPUT_REAL * N_OUTPUT_REAL_MAX_ORDER];
628 fmi1_integer_t order [N_OUTPUT_REAL * N_OUTPUT_REAL_MAX_ORDER];
631 for (k = 0; k < N_OUTPUT_REAL_MAX_ORDER; k++) {
632 for (p = 0; p < N_OUTPUT_REAL; p++)
634 vrs [p + k * N_OUTPUT_REAL] = (fmi1_value_reference_t)p;
635 values [p + k * N_OUTPUT_REAL] = -1;
636 order [p + k * N_OUTPUT_REAL] = (fmi1_integer_t)k + 1;
640 status = fmi1_capi_get_real_output_derivatives(fmu, vrs, N_INPUT_REAL * N_INPUT_REAL_MAX_ORDER, order, values);
641 if (status == fmi1_status_error || status == fmi1_status_fatal) {
642 printf("fmi1_capi_get_real_output_derivatives: Failed\n");
643 do_exit(CTEST_RETURN_FAIL);
645 printf("fmi1_capi_get_real_output_derivatives: Success\n");
647 for (k = 0; k < N_OUTPUT_REAL_MAX_ORDER; k++) {
648 for (p = 0; p < N_OUTPUT_REAL; p++)
650 fmi1_real_t value = values[p + k * N_OUTPUT_REAL];
651 if (value != MAGIC_TEST_VALUE) { /* This value is set in DLL to be exakt MAGIC_TEST_VALUE */
652 printf("fmi1_capi_get_real_output_derivatives: Failed\n");
653 do_exit(CTEST_RETURN_FAIL);
657 fmi1_integer_t ord = k + 1;
658 printf("value[%d][%d] = %f \n", p, ord, value);
667 * \brief Tests fmi1_capi_terminate_slave
670 int test_terminate_slave()
672 fmi1_status_t status;
673 status = fmi1_capi_terminate_slave(fmu);
674 if (status == fmi1_status_error || status == fmi1_status_fatal) {
675 printf("fmi1_capi_terminate_slave: Failed\n");
676 do_exit(CTEST_RETURN_FAIL);
678 printf("fmi1_capi_terminate_slave: Success\n");
684 * \brief Tests fmi1_capi_free_slave_instance
687 int test_free_slave_instance()
689 fmi1_capi_free_slave_instance(fmu);
690 printf("fmi1_capi_free_slave_instance: Success\n");
695 * \brief Tests fmi1_capi_free_dll
700 fmi1_capi_free_dll(fmu);
701 printf("fmi1_capi_free_dll: Success\n");
706 * \brief Tests fmi1_capi_destroy_dllfmu
709 int test_destroy_dllfmu()
711 fmi1_capi_destroy_dllfmu(fmu);
712 printf("fmi1_capi_destroy_dllfmu: Success\n");
717 * \brief Tests the C-API for FMI 1.0 Co-Simulation.
718 * 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.
721 int main(int argc, char *argv[])
723 /* Test CAPI constructor functions */
724 test_create_dllfmu();
728 /* FMI CS 1.0 functions */
729 test_instantiate_slave();
730 test_get_types_platform();
731 test_initialize_slave();
735 test_get_real_status();
736 test_get_integer_status();
737 test_get_boolean_status();
738 test_get_string_status();
740 test_set_real_input_derivatives();
741 test_get_real_output_derivatives();
743 test_fmi_get_version();
744 test_set_get_string();
745 test_set_get_boolean();
746 test_set_get_integer();
748 test_set_debug_logging();
750 test_terminate_slave();
751 test_free_slave_instance();
753 /* Test CAPI destructor functions */
755 test_destroy_dllfmu();
758 printf("Everything seems to be ok!\n");
760 do_exit(CTEST_RETURN_SUCCESS);