diff --git a/Project.toml b/Project.toml index 0883891..eda0f06 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FMICore" uuid = "8af89139-c281-408e-bce2-3005eb87462f" authors = ["TT ", "LM ", "JK "] -version = "1.1.0" +version = "1.1.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/src/FMI2/cfunc.jl b/src/FMI2/cfunc.jl index eff4706..6a4c9ad 100644 --- a/src/FMI2/cfunc.jl +++ b/src/FMI2/cfunc.jl @@ -91,11 +91,22 @@ Source: FMISpec2.0.2[p.22]: 2.1.5 Creation, Destruction and Logging of FMU Insta The function controls debug logging that is output via the logger function callback. If loggingOn = fmi2True, debug logging is enabled, otherwise it is switched off. """ -function fmi2SetDebugLogging(cfunc::Ptr{Cvoid}, c::fmi2Component, loggingOn::fmi2Boolean, nCategories::Csize_t, categories::Union{Ptr{fmi2String}, AbstractArray{fmi2String}}) - status = ccall(cfunc, - fmi2Status, - (fmi2Component, fmi2Boolean, Csize_t, Ptr{fmi2String}), - c, loggingOn, nCategories, categories) +function fmi2SetDebugLogging( + cfunc::Ptr{Cvoid}, + c::fmi2Component, + loggingOn::fmi2Boolean, + nCategories::Csize_t, + categories::Union{Ptr{fmi2String},AbstractArray{fmi2String}}, +) + status = ccall( + cfunc, + fmi2Status, + (fmi2Component, fmi2Boolean, Csize_t, Ptr{fmi2String}), + c, + loggingOn, + nCategories, + categories, + ) @debug "fmi2SetDebugLogging(c: $(c), loggingOn: $(loggingOn), nCategories: $(nCategories), categories: $(categories)) → $(status)" return status end diff --git a/src/FMI3/cfunc.jl b/src/FMI3/cfunc.jl index 3f1b4b1..801a49c 100644 --- a/src/FMI3/cfunc.jl +++ b/src/FMI3/cfunc.jl @@ -1682,9 +1682,7 @@ function fmi3GetAdjointDerivative!( sensitivity::AbstractArray{fmi3Float64}, nSensitivity::Csize_t, )::fmi3Status - @assert fmi3ProvidesAdjointDerivatives(c.fmu) [ - "fmi3GetAdjointDerivative!(...): This FMU does not support build-in adjoint derivatives!", - ] + status = ccall( cfunc, fmi3Status, diff --git a/test/FMI2/CS.jl b/test/FMI2/CS.jl index 39a2979..b055b5e 100644 --- a/test/FMI2/CS.jl +++ b/test/FMI2/CS.jl @@ -5,45 +5,93 @@ using Libdl, Suppressor function test_CS(lib, cblibpath) - component = fmi2Instantiate(dlsym(lib, :fmi2Instantiate), pointer("test_cs"), fmi2TypeCoSimulation, pointer("{3c564ab6-a92a-48ca-ae7d-591f819b1d93}"), pointer("file:///"), Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), fmi2Boolean(false), fmi2Boolean(false)) - + component = fmi2Instantiate( + dlsym(lib, :fmi2Instantiate), + pointer("test_cs"), + fmi2TypeCoSimulation, + pointer("{3c564ab6-a92a-48ca-ae7d-591f819b1d93}"), + pointer("file:///"), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), + fmi2Boolean(false), + fmi2Boolean(false), + ) + startpoint = fmi2Real(0.0) - @test fmi2StatusOK == fmi2SetupExperiment(dlsym(lib, :fmi2SetupExperiment),component, fmi2Boolean(true), fmi2Real(0.01), startpoint, fmi2Boolean(false), fmi2Real(1.0)) + @test fmi2StatusOK == fmi2SetupExperiment( + dlsym(lib, :fmi2SetupExperiment), + component, + fmi2Boolean(true), + fmi2Real(0.01), + startpoint, + fmi2Boolean(false), + fmi2Real(1.0), + ) + - fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component) if Sys.WORD_SIZE == 64 - @test fmi2StatusOK == fmi2DoStep(dlsym(lib, :fmi2DoStep), component, fmi2Real(0.0), fmi2Real(0.01), fmi2False) + @test fmi2StatusOK == fmi2DoStep( + dlsym(lib, :fmi2DoStep), + component, + fmi2Real(0.0), + fmi2Real(0.01), + fmi2False, + ) end - + status = fmi2Real(0.0) statusptr = pointer([status]) - @test fmi2StatusOK == fmi2GetRealStatus!(dlsym(lib, :fmi2GetRealStatus), component, fmi2StatusKindLastSuccessfulTime, Ptr{fmi2Real}(statusptr)) + @test fmi2StatusOK == fmi2GetRealStatus!( + dlsym(lib, :fmi2GetRealStatus), + component, + fmi2StatusKindLastSuccessfulTime, + Ptr{fmi2Real}(statusptr), + ) @suppress begin - # Suppressing the IllegalFunctionCall Warnings, as they are expected here + # Suppressing the IllegalFunctionCall Warnings, as they are expected here # Async is not supported in this FMU, so the status should be fmi2StatusDiscard status = fmi2Status(fmi2StatusOK) statusptr = pointer([status]) - @test fmi2StatusDiscard == fmi2GetStatus!(dlsym(lib, :fmi2GetStatus), component, fmi2StatusKindDoStepStatus, Ptr{fmi2Status}(statusptr)) - - + @test fmi2StatusDiscard == fmi2GetStatus!( + dlsym(lib, :fmi2GetStatus), + component, + fmi2StatusKindDoStepStatus, + Ptr{fmi2Status}(statusptr), + ) + + status = fmi2Integer(0) statusptr = pointer([status]) # Async is not supported in this FMU, so the status should be fmi2StatusDiscard - @test fmi2StatusDiscard == fmi2GetIntegerStatus!(dlsym(lib, :fmi2GetIntegerStatus), component, Cuint(2), Ptr{fmi2Integer}(statusptr)) - + @test fmi2StatusDiscard == fmi2GetIntegerStatus!( + dlsym(lib, :fmi2GetIntegerStatus), + component, + Cuint(2), + Ptr{fmi2Integer}(statusptr), + ) + status = fmi2Boolean(false) statusptr = pointer([status]) # Async is not supported in this FMU, so the status should be fmi2StatusDiscard - @test fmi2StatusDiscard == fmi2GetBooleanStatus!(dlsym(lib, :fmi2GetBooleanStatus), component, Cuint(2), Ptr{fmi2Boolean}(statusptr)) + @test fmi2StatusDiscard == fmi2GetBooleanStatus!( + dlsym(lib, :fmi2GetBooleanStatus), + component, + Cuint(2), + Ptr{fmi2Boolean}(statusptr), + ) status = "test" statusptr = pointer(status) # Async is not supported in this FMU, so the status should be fmi2StatusDiscard - @test fmi2StatusDiscard == fmi2GetStringStatus!(dlsym(lib, :fmi2GetStringStatus), component, Cuint(2), Ptr{fmi2String}(statusptr)) + @test fmi2StatusDiscard == fmi2GetStringStatus!( + dlsym(lib, :fmi2GetStringStatus), + component, + Cuint(2), + Ptr{fmi2String}(statusptr), + ) end fmi2Terminate(dlsym(lib, :fmi2Terminate), component) @@ -51,22 +99,55 @@ function test_CS(lib, cblibpath) end function test_CS_IO(lib, cblibpath) - component = fmi2Instantiate(dlsym(lib, :fmi2Instantiate), pointer("test_generic_io"), fmi2TypeCoSimulation, pointer("{95a6399d-38c5-4504-b3f3-98319bd94ce6}"), pointer("file:///"), Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), fmi2Boolean(false), fmi2Boolean(false)) + component = fmi2Instantiate( + dlsym(lib, :fmi2Instantiate), + pointer("test_generic_io"), + fmi2TypeCoSimulation, + pointer("{95a6399d-38c5-4504-b3f3-98319bd94ce6}"), + pointer("file:///"), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), + fmi2Boolean(false), + fmi2Boolean(false), + ) @test component != C_NULL - @test fmi2StatusOK == fmi2SetupExperiment(dlsym(lib, :fmi2SetupExperiment),component, fmi2Boolean(false), fmi2Real(0.0), fmi2Real(0.0), fmi2Boolean(false), fmi2Real(1.0)) + @test fmi2StatusOK == fmi2SetupExperiment( + dlsym(lib, :fmi2SetupExperiment), + component, + fmi2Boolean(false), + fmi2Real(0.0), + fmi2Real(0.0), + fmi2Boolean(false), + fmi2Real(1.0), + ) - @test fmi2StatusOK == fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) - @test fmi2StatusOK == fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component) + @test fmi2StatusOK == + fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) + @test fmi2StatusOK == + fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component) fmireference = [fmi2ValueReference(352321536)] - @test fmi2StatusOK == fmi2SetRealInputDerivatives(dlsym(lib, :fmi2SetRealInputDerivatives), component, fmireference, Csize_t(1), [fmi2Integer(1)], fmi2Real.([1.0])) + @test fmi2StatusOK == fmi2SetRealInputDerivatives( + dlsym(lib, :fmi2SetRealInputDerivatives), + component, + fmireference, + Csize_t(1), + [fmi2Integer(1)], + fmi2Real.([1.0]), + ) fmireference = [fmi2ValueReference(335544320)] values = zeros(fmi2Real, 1) - @test fmi2StatusOK == fmi2GetRealOutputDerivatives!(dlsym(lib, :fmi2GetRealOutputDerivatives), component, fmireference, Csize_t(1), [fmi2Integer(1)], values) + @test fmi2StatusOK == fmi2GetRealOutputDerivatives!( + dlsym(lib, :fmi2GetRealOutputDerivatives), + component, + fmireference, + Csize_t(1), + [fmi2Integer(1)], + values, + ) + - - -end \ No newline at end of file + +end diff --git a/test/FMI2/ME.jl b/test/FMI2/ME.jl index dca2d9f..daea952 100644 --- a/test/FMI2/ME.jl +++ b/test/FMI2/ME.jl @@ -5,7 +5,16 @@ using Libdl function test_ME(lib, cblibpath) - component = fmi2Instantiate(dlsym(lib, :fmi2Instantiate), pointer("test_me"), fmi2TypeModelExchange, pointer("{3c564ab6-a92a-48ca-ae7d-591f819b1d93}"), pointer("file:///"), Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), fmi2Boolean(false), fmi2Boolean(false)) + component = fmi2Instantiate( + dlsym(lib, :fmi2Instantiate), + pointer("test_me"), + fmi2TypeModelExchange, + pointer("{3c564ab6-a92a-48ca-ae7d-591f819b1d93}"), + pointer("file:///"), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), + fmi2Boolean(false), + fmi2Boolean(false), + ) @test component != C_NULL fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) @@ -13,42 +22,76 @@ function test_ME(lib, cblibpath) @test fmi2StatusOK == fmi2EnterEventMode(dlsym(lib, :fmi2Instantiate), component) - eventInfo = fmi2EventInfo() + eventInfo = fmi2EventInfo() ptr = Ptr{fmi2EventInfo}(pointer_from_objref(eventInfo)) - @test fmi2StatusOK == fmi2NewDiscreteStates!(dlsym(lib, :fmi2NewDiscreteStates), component, ptr) - - @test fmi2StatusOK == fmi2EnterContinuousTimeMode(dlsym(lib, :fmi2EnterContinuousTimeMode), component) + @test fmi2StatusOK == + fmi2NewDiscreteStates!(dlsym(lib, :fmi2NewDiscreteStates), component, ptr) + + @test fmi2StatusOK == + fmi2EnterContinuousTimeMode(dlsym(lib, :fmi2EnterContinuousTimeMode), component) enterEventMode = fmi2Boolean(false) terminateSimulation = fmi2Boolean(false) - @test fmi2StatusOK == fmi2CompletedIntegratorStep!(dlsym(lib, :fmi2CompletedIntegratorStep), component, fmi2Boolean(false), pointer([enterEventMode]), pointer([terminateSimulation])) + @test fmi2StatusOK == fmi2CompletedIntegratorStep!( + dlsym(lib, :fmi2CompletedIntegratorStep), + component, + fmi2Boolean(false), + pointer([enterEventMode]), + pointer([terminateSimulation]), + ) @test fmi2StatusOK == fmi2SetTime(dlsym(lib, :fmi2SetTime), component, fmi2Real(0.0)) n_states = Csize_t(2) state_arr = zeros(fmi2Real, 2) - @test fmi2StatusOK == fmi2GetContinuousStates!(dlsym(lib, :fmi2GetContinuousStates), component,state_arr, n_states) + @test fmi2StatusOK == fmi2GetContinuousStates!( + dlsym(lib, :fmi2GetContinuousStates), + component, + state_arr, + n_states, + ) state_arr[2] = 2.0 - @test fmi2StatusOK == fmi2SetContinuousStates(dlsym(lib, :fmi2SetContinuousStates), component,state_arr, n_states) + @test fmi2StatusOK == fmi2SetContinuousStates( + dlsym(lib, :fmi2SetContinuousStates), + component, + state_arr, + n_states, + ) state_arr = zeros(fmi2Real, 2) - @test fmi2StatusOK == fmi2GetContinuousStates!(dlsym(lib, :fmi2GetContinuousStates), component,state_arr, n_states) + @test fmi2StatusOK == fmi2GetContinuousStates!( + dlsym(lib, :fmi2GetContinuousStates), + component, + state_arr, + n_states, + ) @test state_arr[2] == 2.0 n_indicators = Csize_t(2) indicator_arr = zeros(fmi2Real, 2) - @test fmi2StatusOK == fmi2GetEventIndicators!(dlsym(lib, :fmi2GetEventIndicators), component,indicator_arr, n_indicators) + @test fmi2StatusOK == fmi2GetEventIndicators!( + dlsym(lib, :fmi2GetEventIndicators), + component, + indicator_arr, + n_indicators, + ) nom_state_arr = zeros(fmi2Real, 2) - @test fmi2StatusOK == fmi2GetNominalsOfContinuousStates!(dlsym(lib, :fmi2GetNominalsOfContinuousStates), component, nom_state_arr, n_states) + @test fmi2StatusOK == fmi2GetNominalsOfContinuousStates!( + dlsym(lib, :fmi2GetNominalsOfContinuousStates), + component, + nom_state_arr, + n_states, + ) der_arr = zeros(fmi2Real, 2) - @test fmi2StatusOK == fmi2GetDerivatives!(dlsym(lib, :fmi2GetDerivatives), component,der_arr, n_states) + @test fmi2StatusOK == + fmi2GetDerivatives!(dlsym(lib, :fmi2GetDerivatives), component, der_arr, n_states) # Acceleration should be equal to Gravity in this FMU if Sys.WORD_SIZE == 64 - # on 32 Bit this returns 9.81 * 10^16 which is not equal to -9.81 + # on 32 Bit this returns 9.81 * 10^16 which is not equal to -9.81 @test der_arr[2] ≈ -9.81 end diff --git a/test/FMI2/cfunc.jl b/test/FMI2/cfunc.jl index 67f665e..281dd22 100644 --- a/test/FMI2/cfunc.jl +++ b/test/FMI2/cfunc.jl @@ -14,13 +14,27 @@ if binarypath != "" lib = dlopen(binarypath) libio = dlopen(iopath) # Missing Tests for fmi2 because the FMU we are testing with doesnt variables of these types - @testset "Generic Functions in ME Mode" begin test_generic(lib,cblibpath, fmi2TypeModelExchange) end - @testset "Generic Functions in ME Mode with IO FMU" begin test_generic_io(libio,iocblibpath, fmi2TypeModelExchange) end - @testset "Generic Functions in CS Mode with IO FMU" begin test_generic_io(libio,iocblibpath, fmi2TypeCoSimulation) end - @testset "Generic Functions in CS Mode" begin test_generic(lib,cblibpath, fmi2TypeCoSimulation) end - @testset "ME-specific Functions" begin test_ME(lib, cblibpath) end - @testset "CS-specific Functions" begin test_CS(lib, cblibpath) end - @testset "CS-specific Functions with IO FMU" begin test_CS_IO(libio, iocblibpath) end + @testset "Generic Functions in ME Mode" begin + test_generic(lib, cblibpath, fmi2TypeModelExchange) + end + @testset "Generic Functions in ME Mode with IO FMU" begin + test_generic_io(libio, iocblibpath, fmi2TypeModelExchange) + end + @testset "Generic Functions in CS Mode with IO FMU" begin + test_generic_io(libio, iocblibpath, fmi2TypeCoSimulation) + end + @testset "Generic Functions in CS Mode" begin + test_generic(lib, cblibpath, fmi2TypeCoSimulation) + end + @testset "ME-specific Functions" begin + test_ME(lib, cblibpath) + end + @testset "CS-specific Functions" begin + test_CS(lib, cblibpath) + end + @testset "CS-specific Functions with IO FMU" begin + test_CS_IO(libio, iocblibpath) + end else @warn "No valid FMU binaries found for this OS. Skipping tests." -end \ No newline at end of file +end diff --git a/test/FMI2/generic.jl b/test/FMI2/generic.jl index 28084e4..4f8da23 100644 --- a/test/FMI2/generic.jl +++ b/test/FMI2/generic.jl @@ -10,22 +10,51 @@ function test_generic(lib, cblibpath, type::fmi2Type) cGetTypesPlatform = dlsym(lib, :fmi2GetTypesPlatform) test = fmi2GetTypesPlatform(cGetTypesPlatform) @test unsafe_string(test) == "default" - + ## fmi2GetVersion TODO get Version from modelDescription.xml vers = fmi2GetVersion(dlsym(lib, :fmi2GetVersion)) @test unsafe_string(vers) == "2.0" # fmi2Instantiate - component = fmi2Instantiate(dlsym(lib, :fmi2Instantiate), pointer("test_generic"), type, pointer("{3c564ab6-a92a-48ca-ae7d-591f819b1d93}"), pointer("file:///"), Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), fmi2Boolean(false), fmi2Boolean(false)) + component = fmi2Instantiate( + dlsym(lib, :fmi2Instantiate), + pointer("test_generic"), + type, + pointer("{3c564ab6-a92a-48ca-ae7d-591f819b1d93}"), + pointer("file:///"), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), + fmi2Boolean(false), + fmi2Boolean(false), + ) @test component != C_NULL - @test fmi2StatusOK == fmi2SetDebugLogging(dlsym(lib, :fmi2SetDebugLogging), component, fmi2False, Unsigned(0), AbstractArray{fmi2String}([])) - @test fmi2StatusOK == fmi2SetDebugLogging(dlsym(lib, :fmi2SetDebugLogging), component, fmi2True, Unsigned(0), AbstractArray{fmi2String}([])) + @test fmi2StatusOK == fmi2SetDebugLogging( + dlsym(lib, :fmi2SetDebugLogging), + component, + fmi2False, + Unsigned(0), + AbstractArray{fmi2String}([]), + ) + @test fmi2StatusOK == fmi2SetDebugLogging( + dlsym(lib, :fmi2SetDebugLogging), + component, + fmi2True, + Unsigned(0), + AbstractArray{fmi2String}([]), + ) # fmi2SetupExperiment - @test fmi2StatusOK == fmi2SetupExperiment(dlsym(lib, :fmi2SetupExperiment),component, fmi2Boolean(false), fmi2Real(0.0), fmi2Real(0.0), fmi2Boolean(false), fmi2Real(1.0)) + @test fmi2StatusOK == fmi2SetupExperiment( + dlsym(lib, :fmi2SetupExperiment), + component, + fmi2Boolean(false), + fmi2Real(0.0), + fmi2Real(0.0), + fmi2Boolean(false), + fmi2Real(1.0), + ) @@ -33,67 +62,122 @@ function test_generic(lib, cblibpath, type::fmi2Type) state = fmi2FMUstate() stateRef = Ref(state) - @test fmi2StatusOK == fmi2GetFMUstate!(dlsym(lib, :fmi2GetFMUstate), component, stateRef) + @test fmi2StatusOK == + fmi2GetFMUstate!(dlsym(lib, :fmi2GetFMUstate), component, stateRef) state = stateRef[] @test typeof(state) == fmi2FMUstate - + @test fmi2StatusOK == fmi2SetFMUstate(dlsym(lib, :fmi2SetFMUstate), component, state) stateRef = Ref(state) size_ptr = Ref{Csize_t}(0) - @test fmi2StatusOK == fmi2SerializedFMUstateSize!(dlsym(lib, :fmi2SerializedFMUstateSize), component, state, size_ptr) + @test fmi2StatusOK == fmi2SerializedFMUstateSize!( + dlsym(lib, :fmi2SerializedFMUstateSize), + component, + state, + size_ptr, + ) size = size_ptr[] serializedState = Array{fmi2Byte}(zeros(size)) - @test fmi2StatusOK == fmi2SerializeFMUstate!(dlsym(lib,:fmi2SerializeFMUstate), component, state, serializedState, size) - - @test fmi2StatusOK == fmi2DeSerializeFMUstate!(dlsym(lib, :fmi2DeSerializeFMUstate), component, serializedState, size, stateRef) + @test fmi2StatusOK == fmi2SerializeFMUstate!( + dlsym(lib, :fmi2SerializeFMUstate), + component, + state, + serializedState, + size, + ) + + @test fmi2StatusOK == fmi2DeSerializeFMUstate!( + dlsym(lib, :fmi2DeSerializeFMUstate), + component, + serializedState, + size, + stateRef, + ) @test stateRef[] != C_NULL - @test fmi2StatusOK == fmi2FreeFMUstate(dlsym(lib,:fmi2FreeFMUstate), component, stateRef) + @test fmi2StatusOK == + fmi2FreeFMUstate(dlsym(lib, :fmi2FreeFMUstate), component, stateRef) @test stateRef[] == C_NULL - - + + # # Initialization Mode - - @test fmi2StatusOK == fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) + + @test fmi2StatusOK == + fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) fmireference = [fmi2ValueReference(16777220)] - @test fmi2StatusOK == fmi2SetReal(dlsym(lib, :fmi2SetReal), component, fmireference, Csize_t(1), fmi2Real.([0.8])) + @test fmi2StatusOK == fmi2SetReal( + dlsym(lib, :fmi2SetReal), + component, + fmireference, + Csize_t(1), + fmi2Real.([0.8]), + ) fmireference = [fmi2ValueReference(16777220)] value = zeros(fmi2Real, 1) - @test fmi2StatusOK == fmi2GetReal!(dlsym(lib, :fmi2GetReal), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == + fmi2GetReal!(dlsym(lib, :fmi2GetReal), component, fmireference, Csize_t(1), value) @test value == fmi2Real.([0.8]) fmireference = [fmi2ValueReference(637534208)] value = zeros(fmi2Integer, 1) - @test fmi2StatusOK == fmi2GetInteger!(dlsym(lib, :fmi2GetInteger), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == fmi2GetInteger!( + dlsym(lib, :fmi2GetInteger), + component, + fmireference, + Csize_t(1), + value, + ) fmireference = [fmi2ValueReference(637534208)] - @test fmi2StatusOK == fmi2SetInteger(dlsym(lib, :fmi2SetInteger), component, fmireference, Csize_t(1), fmi2Integer.([typemin(fmi2Integer)])) + @test fmi2StatusOK == fmi2SetInteger( + dlsym(lib, :fmi2SetInteger), + component, + fmireference, + Csize_t(1), + fmi2Integer.([typemin(fmi2Integer)]), + ) fmireference = [fmi2ValueReference(637534208)] value = zeros(fmi2Integer, 1) - @test fmi2StatusOK == fmi2GetInteger!(dlsym(lib, :fmi2GetInteger), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == fmi2GetInteger!( + dlsym(lib, :fmi2GetInteger), + component, + fmireference, + Csize_t(1), + value, + ) @test value == fmi2Integer.([typemin(fmi2Integer)]) # calculate ∂p/∂p (x) posreference = [fmi2ValueReference(33554432)] delta_x = fmi2Real.([randn()]) result = zeros(fmi2Real, 1) - @test fmi2StatusOK == fmi2GetDirectionalDerivative!(dlsym(lib,:fmi2GetDirectionalDerivative), component, posreference, Csize_t(1), posreference, Csize_t(1), delta_x, result) + @test fmi2StatusOK == fmi2GetDirectionalDerivative!( + dlsym(lib, :fmi2GetDirectionalDerivative), + component, + posreference, + Csize_t(1), + posreference, + Csize_t(1), + delta_x, + result, + ) # ∂p/∂p(x) should be just x for any x if Sys.WORD_SIZE == 64 # GetDirectionalDerivative behaves weirdly on 32 Bit @test result ≈ delta_x end - - @test fmi2StatusOK == fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component) + + @test fmi2StatusOK == + fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component) @suppress begin - # Suppressing the CVODE-Stats that are printed here in CS Mode + # Suppressing the CVODE-Stats that are printed here in CS Mode @test fmi2StatusOK == fmi2Reset(dlsym(lib, :fmi2Reset), component) end @@ -103,46 +187,113 @@ function test_generic(lib, cblibpath, type::fmi2Type) end function test_generic_io(lib, cblibpath, type::fmi2Type) - component = fmi2Instantiate(dlsym(lib, :fmi2Instantiate), pointer("test_generic_io"), type, pointer("{95a6399d-38c5-4504-b3f3-98319bd94ce6}"), pointer("file:///"), Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), fmi2Boolean(false), fmi2Boolean(false)) + component = fmi2Instantiate( + dlsym(lib, :fmi2Instantiate), + pointer("test_generic_io"), + type, + pointer("{95a6399d-38c5-4504-b3f3-98319bd94ce6}"), + pointer("file:///"), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(get_callbacks(cblibpath))), + fmi2Boolean(false), + fmi2Boolean(false), + ) @test component != C_NULL - @test fmi2StatusOK == fmi2SetupExperiment(dlsym(lib, :fmi2SetupExperiment),component, fmi2Boolean(false), fmi2Real(0.0), fmi2Real(0.0), fmi2Boolean(false), fmi2Real(1.0)) - - @test fmi2StatusOK == fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) + @test fmi2StatusOK == fmi2SetupExperiment( + dlsym(lib, :fmi2SetupExperiment), + component, + fmi2Boolean(false), + fmi2Real(0.0), + fmi2Real(0.0), + fmi2Boolean(false), + fmi2Real(1.0), + ) + + @test fmi2StatusOK == + fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component) fmireference = [fmi2ValueReference(16777216)] - @test fmi2StatusOK == fmi2SetReal(dlsym(lib, :fmi2SetReal), component, fmireference, Csize_t(1), fmi2Real.([0.8])) + @test fmi2StatusOK == fmi2SetReal( + dlsym(lib, :fmi2SetReal), + component, + fmireference, + Csize_t(1), + fmi2Real.([0.8]), + ) value = zeros(fmi2Real, 1) - @test fmi2StatusOK == fmi2GetReal!(dlsym(lib, :fmi2GetReal), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == + fmi2GetReal!(dlsym(lib, :fmi2GetReal), component, fmireference, Csize_t(1), value) @test value == fmi2Real.([0.8]) fmireference = [fmi2ValueReference(16777217)] value = zeros(fmi2Integer, 1) - @test fmi2StatusOK == fmi2GetInteger!(dlsym(lib, :fmi2GetInteger), component, fmireference, Csize_t(1), value) - - @test fmi2StatusOK == fmi2SetInteger(dlsym(lib, :fmi2SetInteger), component, fmireference, Csize_t(1), fmi2Integer.([typemin(fmi2Integer)])) + @test fmi2StatusOK == fmi2GetInteger!( + dlsym(lib, :fmi2GetInteger), + component, + fmireference, + Csize_t(1), + value, + ) + + @test fmi2StatusOK == fmi2SetInteger( + dlsym(lib, :fmi2SetInteger), + component, + fmireference, + Csize_t(1), + fmi2Integer.([typemin(fmi2Integer)]), + ) value = zeros(fmi2Integer, 1) - @test fmi2StatusOK == fmi2GetInteger!(dlsym(lib, :fmi2GetInteger), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == fmi2GetInteger!( + dlsym(lib, :fmi2GetInteger), + component, + fmireference, + Csize_t(1), + value, + ) @test value == fmi2Integer.([typemin(fmi2Integer)]) fmireference = [fmi2ValueReference(16777218)] - @test fmi2StatusOK == fmi2SetBoolean(dlsym(lib, :fmi2SetBoolean), component, fmireference, Csize_t(1), fmi2Boolean.([false])) + @test fmi2StatusOK == fmi2SetBoolean( + dlsym(lib, :fmi2SetBoolean), + component, + fmireference, + Csize_t(1), + fmi2Boolean.([false]), + ) value = zeros(fmi2Boolean, 1) - @test fmi2StatusOK == fmi2GetBoolean!(dlsym(lib, :fmi2GetBoolean), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == fmi2GetBoolean!( + dlsym(lib, :fmi2GetBoolean), + component, + fmireference, + Csize_t(1), + value, + ) @test value == fmi2Boolean.([false]) fmireference = [fmi2ValueReference(134217728)] - + value = ["anything"] valueptr = pointer.(value) - @test fmi2StatusOK == fmi2SetString(dlsym(lib, :fmi2SetString), component, fmireference, Csize_t(1), valueptr) + @test fmi2StatusOK == fmi2SetString( + dlsym(lib, :fmi2SetString), + component, + fmireference, + Csize_t(1), + valueptr, + ) value = Vector{fmi2String}(undef, 1) values = string.(zeros(1)) - @test fmi2StatusOK == fmi2GetString!(dlsym(lib, :fmi2GetString), component, fmireference, Csize_t(1), value) + @test fmi2StatusOK == fmi2GetString!( + dlsym(lib, :fmi2GetString), + component, + fmireference, + Csize_t(1), + value, + ) values[:] = unsafe_string.(value) @test values == ["anything"] -end \ No newline at end of file +end diff --git a/test/FMI2/utils.jl b/test/FMI2/utils.jl index 7caae0b..e60cf1e 100644 --- a/test/FMI2/utils.jl +++ b/test/FMI2/utils.jl @@ -5,7 +5,7 @@ using ZipFile -function getFMU(fmuname::String="BouncingBallGravitySwitch1D") +function getFMU(fmuname::String = "BouncingBallGravitySwitch1D") if fmuname == "IO" dlurl = "https://github.com/ThummeTo/FMIZoo.jl/raw/main/models/bin/Dymola/2023x/2.0/IO.fmu" else @@ -13,7 +13,7 @@ function getFMU(fmuname::String="BouncingBallGravitySwitch1D") fmuname = "BouncingBallGravitySwitch1D" end dlpath = Downloads.download(dlurl) - unpackPath = mktempdir(; prefix="fmijl_", cleanup=true) + unpackPath = mktempdir(; prefix = "fmijl_", cleanup = true) unzippedPath = joinpath(unpackPath, fmuname) unzippedAbsPath = isabspath(unzippedPath) ? unzippedPath : joinpath(pwd(), unzippedPath) numFiles = 0 @@ -23,9 +23,11 @@ function getFMU(fmuname::String="BouncingBallGravitySwitch1D") zarchive = ZipFile.Reader(dlpath) for f in zarchive.files fileAbsPath = normpath(joinpath(unzippedAbsPath, f.name)) - if endswith(f.name,"/") || endswith(f.name,"\\") + if endswith(f.name, "/") || endswith(f.name, "\\") mkpath(fileAbsPath) # mkdir(fileAbsPath) - @assert isdir(fileAbsPath) ["fmi2Unzip(...): Can't create directory `$(f.name)` at `$(fileAbsPath)`."] + @assert isdir(fileAbsPath) [ + "fmi2Unzip(...): Can't create directory `$(f.name)` at `$(fileAbsPath)`.", + ] else # create directory if not forced by zip file folder mkpath(dirname(fileAbsPath)) @@ -36,7 +38,9 @@ function getFMU(fmuname::String="BouncingBallGravitySwitch1D") @debug "fmi2Unzip(...): Written file `$(f.name)`, but file is empty." end - @assert isfile(fileAbsPath) ["fmi2Unzip(...): Can't unzip file `$(f.name)` at `$(fileAbsPath)`."] + @assert isfile(fileAbsPath) [ + "fmi2Unzip(...): Can't unzip file `$(f.name)` at `$(fileAbsPath)`.", + ] numFiles += 1 end end @@ -46,29 +50,37 @@ function getFMU(fmuname::String="BouncingBallGravitySwitch1D") end -function get_os_binaries(fmuname::String="BouncingBallGravitySwitch1D") +function get_os_binaries(fmuname::String = "BouncingBallGravitySwitch1D") path = getFMU(fmuname) binarypath = joinpath(path, "binaries") if Sys.WORD_SIZE == 64 if Sys.islinux() binarypath = joinpath(binarypath, "linux64") - cblibpath = Downloads.download("https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/linux64/libcallbackFunctions.so") + cblibpath = Downloads.download( + "https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/linux64/libcallbackFunctions.so", + ) os_supported = true elseif Sys.iswindows() binarypath = joinpath(binarypath, "win64") - cblibpath = Downloads.download("https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/win64/callbackFunctions.dll") + cblibpath = Downloads.download( + "https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/win64/callbackFunctions.dll", + ) cblibpath = cblibpath * "." os_supported = true elseif Sys.isapple() binarypath = joinpath(binarypath, "darwin64") - cblibpath = Downloads.download("https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/darwin64/libcallbackFunctions.dylib") + cblibpath = Downloads.download( + "https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/darwin64/libcallbackFunctions.dylib", + ) os_supported = false # the FMU we are testing with only contains Binaries for win<32,64> and linux64 else os_supported = false end elseif Sys.iswindows() binarypath = joinpath(binarypath, "win32") - cblibpath = Downloads.download("https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/win32/callbackFunctions.dll") + cblibpath = Downloads.download( + "https://github.com/ThummeTo/FMIImport.jl/raw/main/src/FMI2/callbackFunctions/binaries/win32/callbackFunctions.dll", + ) cblibpath = cblibpath * "." os_supported = true else @@ -83,7 +95,7 @@ function get_os_binaries(fmuname::String="BouncingBallGravitySwitch1D") perm = filemode(cblibpath) permRWX = 16895 if perm != permRWX - chmod(cblibpath, permRWX; recursive=true) + chmod(cblibpath, permRWX; recursive = true) end end (binarypath, path, cblibpath) @@ -114,11 +126,12 @@ function get_callbacks(cblibpath) ptrComponentEnvironment = Ptr{FMU2ComponentEnvironment}(pointer_from_objref(compEnv)) callbacklib = dlopen(cblibpath) ptrLogger = dlsym(callbacklib, :logger) - callbackFunctions = fmi2CallbackFunctions(ptrLogger, C_NULL, C_NULL, C_NULL, ptrComponentEnvironment) + callbackFunctions = + fmi2CallbackFunctions(ptrLogger, C_NULL, C_NULL, C_NULL, ptrComponentEnvironment) callbackFunctions end -function fmi2StatusToString(status::Union{fmi2Status, Integer}) +function fmi2StatusToString(status::Union{fmi2Status,Integer}) if status == fmi2StatusOK return "OK" elseif status == fmi2StatusWarning @@ -137,11 +150,13 @@ function fmi2StatusToString(status::Union{fmi2Status, Integer}) end export fmi2StatusToString -function fmi2CallbackLogger(_componentEnvironment::Ptr{FMU2ComponentEnvironment}, - _instanceName::Ptr{Cchar}, - _status::Cuint, - _category::Ptr{Cchar}, - _message::Ptr{Cchar}) +function fmi2CallbackLogger( + _componentEnvironment::Ptr{FMU2ComponentEnvironment}, + _instanceName::Ptr{Cchar}, + _status::Cuint, + _category::Ptr{Cchar}, + _message::Ptr{Cchar}, +) message = unsafe_string(_message) category = unsafe_string(_category) @@ -150,14 +165,14 @@ function fmi2CallbackLogger(_componentEnvironment::Ptr{FMU2ComponentEnvironment} componentEnvironment = unsafe_load(_componentEnvironment) if status == fmi2StatusOK && componentEnvironment.logStatusOK - @info "[$status][$category][$instanceName]: $message" + @info "[$status][$category][$instanceName]: $message" elseif (status == fmi2StatusWarning && componentEnvironment.logStatusWarning) || - (status == fmi2StatusPending && componentEnvironment.logStatusPending) - @warn "[$status][$category][$instanceName]: $message" + (status == fmi2StatusPending && componentEnvironment.logStatusPending) + @warn "[$status][$category][$instanceName]: $message" elseif (status == fmi2StatusDiscard && componentEnvironment.logStatusDiscard) || - (status == fmi2StatusError && componentEnvironment.logStatusError) || - (status == fmi2StatusFatal && componentEnvironment.logStatusFatal) - @error "[$status][$category][$instanceName]: $message" + (status == fmi2StatusError && componentEnvironment.logStatusError) || + (status == fmi2StatusFatal && componentEnvironment.logStatusFatal) + @error "[$status][$category][$instanceName]: $message" end return nothing diff --git a/test/FMI3/cfunc.jl b/test/FMI3/cfunc.jl index 466d8d8..e83d334 100644 --- a/test/FMI3/cfunc.jl +++ b/test/FMI3/cfunc.jl @@ -3,4 +3,4 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # -# [ToDo] tests for FMI3 \ No newline at end of file +# [ToDo] tests for FMI3