/* Copyright (C) 2012 Modelon AB This program is free software: you can redistribute it and/or modify it under the terms of the BSD style license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the FMILIB_License.txt file for more details. You should have received a copy of the FMILIB_License.txt file along with this program. If not, contact Modelon AB . */ #include #include #include #include #include "config_test.h" #include #include #include FILE* logFile; void logger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message) { char buf[10000]; const char* loadingstr = "Loading '"; /* need to replace platform specific message with a standard one */ if( (log_level == jm_log_level_info) && (strcmp(module, "FMILIB") == 0) && (strncmp(message, "Loading '", strlen(loadingstr)) == 0) ) { jm_snprintf(buf, 10000, "[INFO][FMILIB] Loading '-----' binary with '------' platform types\n"); } else jm_snprintf(buf, 10000, "[%s][%s] %s\n", jm_log_level_to_string(log_level), module, message); printf("%s", buf); fprintf(logFile, "%s", buf); } void do_exit(int code) { /* getchar();*/ exit(code); } int test_logger(fmi1_import_t* fmu) { fmi1_status_t fmistatus; jm_status_enu_t jmstatus; jmstatus = fmi1_import_instantiate_model(fmu, "LoggerTesting"); if (jmstatus == jm_status_error) { printf("fmi1_import_instantiate_model failed\n"); do_exit(CTEST_RETURN_FAIL); } /* Logger message to print: */ { fmi1_value_reference_t* vr; size_t n; size_t k; const char* str[] = { "###### Reals ######", "OK HIGHT = #r0#", /* HIGHT */ "OK HIGHT_SPEED = #r1#", /* HIGHT_SPEED */ "OK GRAVITY = #r2#", /* GRAVITY */ "OK BOUNCE_COF = #r3#", /* BOUNCE_COF */ "Bad reference #r0", "Bad reference #r-0", "Bad reference #r-1", "Bad reference #r100#", "###### Integers ######", "OK LOGGER_TEST_INTEGER = #i0#", /* LOGGER_TEST_INTEGER */ "Bad reference #i0", "Bad reference #i-0", "Bad reference #i-1", "Bad reference #i100#", "###### Booleans ######", "OK LOGGER_TEST_BOOLEAN = #b0#", /* LOGGER_TEST_BOOLEAN */ "Bad reference #b0", "Bad reference #b-0", "Bad reference #b-1", "Bad reference #b100#", "###### Strings ######", "OK LOGGER_TEST = #s0#", /* LOGGER_TEST */ "Bad reference #s0", "Bad reference #s-0", "Bad reference #s-1", "Bad reference #s100#" }; n = sizeof(str)/sizeof(*str); vr = calloc(n, sizeof(fmi1_value_reference_t)); for (k = 0; k < n; k++) { vr[k] = VAR_S_LOGGER_TEST; } fmistatus = fmi1_import_set_string(fmu, vr, n, str); if(fmistatus != fmi1_status_ok) { abort(); } { /* Print a really big message */ #define MESSAGE_SIZE_TO_EXPAND_AND_PRINT 3000 /* Using fixed size since the log message is printed to a file and compared */ #if JM_MAX_ERROR_MESSAGE_SIZE + 200 > MESSAGE_SIZE_TO_EXPAND_AND_PRINT #error This test triggers the logger function to allocate more memory than the default size JM_MAX_ERROR_MESSAGE_SIZE. If you change JM_MAX_ERROR_MESSAGE_SIZE, please update this test. #endif char longmessage[MESSAGE_SIZE_TO_EXPAND_AND_PRINT]; const char* str[1]; str[0] = (const char*)&longmessage; { fmi1_value_reference_t vr = VAR_S_LOGGER_TEST; int k; char repmsg[] = "#r0# "; /* HIGHT */ for (k = 0; k < sizeof(longmessage)/sizeof(*longmessage) - 1; k++) { longmessage[k] = repmsg[k%(sizeof(repmsg)/sizeof(*repmsg) - 1)]; } longmessage[k] = '\0'; fmistatus = fmi1_import_set_string(fmu, &vr, 1, str); if(fmistatus != fmi1_status_ok) { abort(); } } } free(vr); } fmi1_import_free_model_instance(fmu); return 0; } int main(int argc, char *argv[]) { fmi1_callback_functions_t callBackFunctions; const char* FMUPath; const char* tmpPath; jm_callbacks callbacks; fmi_import_context_t* context; fmi_version_enu_t version; jm_status_enu_t status; int register_active_fmu; fmi1_import_t* fmu; char* outfile; if(argc < 4) { printf("Usage: %s \n", argv[0]); do_exit(CTEST_RETURN_FAIL); } FMUPath = argv[1]; tmpPath = argv[2]; outfile = argv[3]; logFile = fopen(outfile, "wb"); if(!logFile) { printf("Could not open output file %s\n", outfile); do_exit(CTEST_RETURN_FAIL); } callbacks.malloc = malloc; callbacks.calloc = calloc; callbacks.realloc = realloc; callbacks.free = free; callbacks.logger = logger; callbacks.log_level = jm_log_level_info; callbacks.context = 0; callBackFunctions.logger = fmi1_log_forwarding; callBackFunctions.allocateMemory = calloc; callBackFunctions.freeMemory = free; #ifdef FMILIB_GENERATE_BUILD_STAMP printf("Library build stamp:\n%s\n", fmilib_get_build_stamp()); #endif context = fmi_import_allocate_context(&callbacks); version = fmi_import_get_fmi_version(context, FMUPath, tmpPath); if(version != fmi_version_1_enu) { printf("Only version 1.0 is supported so far\n"); do_exit(CTEST_RETURN_FAIL); } fmu = fmi1_import_parse_xml(context, tmpPath); if(!fmu) { printf("Error parsing XML, exiting\n"); do_exit(CTEST_RETURN_FAIL); } register_active_fmu = 1; /* Must be used to use our logger. (jm standard prints to strerr which does not generate out put test file) */ status = fmi1_import_create_dllfmu(fmu, callBackFunctions, register_active_fmu); if (status == jm_status_error) { printf("Could not create the DLL loading mechanism(C-API test).\n"); do_exit(CTEST_RETURN_FAIL); } test_logger(fmu); fmi1_import_destroy_dllfmu(fmu); fmi1_import_free(fmu); fmi_import_free_context(context); fclose(logFile); return 0; }