Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests #66

Merged
merged 53 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5f65962
Add devcontainer and Dependencies
halentin May 28, 2024
33a91bc
template for FMI2/3 tests
ThummeTo May 31, 2024
1d938fd
s
halentin May 31, 2024
678ca14
Merge branch 'tests2' into tests
halentin May 31, 2024
29122e1
Unzip and Load
halentin May 31, 2024
0ce617b
switch container to 22.04
halentin May 31, 2024
b05f4bf
add os and architecture distinction and check
halentin May 31, 2024
84439e3
add passing test to os change
halentin May 31, 2024
007b340
Working Tests for Instantiate, Free, GetVersion and GetTypesPlatform
halentin Jun 4, 2024
0ebc1d5
create utils.jl
halentin Jun 5, 2024
e0f2852
os check in utils
halentin Jun 5, 2024
f270aaf
Get/SetStatus Tests, type checking
halentin Jun 5, 2024
7861259
typo
halentin Jun 5, 2024
4e6b259
SetDebugLogging
halentin Jun 5, 2024
4682b90
Reset + Terminate
halentin Jun 5, 2024
f41cab2
FreeState
halentin Jun 5, 2024
5c047fe
serializedsize
halentin Jun 5, 2024
3c94fce
typo
halentin Jun 6, 2024
95af3a1
Getter and Setter
halentin Jun 6, 2024
65cdff1
get/set and directionalderivative
halentin Jun 6, 2024
a4cfbd1
ME-specific Functions
halentin Jun 7, 2024
cfba806
move type check to utils
halentin Jun 7, 2024
e5df48d
Testsets
halentin Jun 7, 2024
ac3330b
some CS Tests
halentin Jun 7, 2024
af3f925
logging?
halentin Jun 10, 2024
acc1e90
ähh
halentin Jun 10, 2024
6edc1b7
working generic and ME-specific functions
halentin Jun 10, 2024
00090d3
remove component typecast
halentin Jun 10, 2024
778127a
try internal callback
halentin Jun 10, 2024
353a20e
fix terminate test with logger
halentin Jun 12, 2024
47e0e3c
add os distinction to cblibpath
halentin Jun 12, 2024
6064af1
add binaries for linux and mac
halentin Jun 12, 2024
45d2e71
add function to create callbacks
halentin Jun 12, 2024
6e4dbfd
stop logging
halentin Jun 12, 2024
3d454e3
CS Get/Set Tests
halentin Jun 13, 2024
58023c3
Get and Set Real Input and Output Derivatives CS
halentin Jun 13, 2024
72f7443
split files
halentin Jun 13, 2024
0b51fbf
remove todo
halentin Jun 13, 2024
a98e01f
remove devcontainer
halentin Jun 13, 2024
ed54c2a
add download for callbacks
halentin Jun 13, 2024
0b9bd0f
fix download dll on windows
halentin Jun 13, 2024
c9a7bbd
replace OS-Check Test with warning and skip
halentin Jun 17, 2024
04726b4
add begin and end to testsets for 1.6 compatibility
halentin Jun 17, 2024
b04f824
remove Type Checks and "fix" 32 Bit Tests
halentin Jun 18, 2024
0683f94
Add Testing with IO FMU and Tests for fmi2String and fmi2Boolean
halentin Jun 20, 2024
d4c09dc
move CS Get/Set OutputDerivatives to IO-FMU
halentin Jun 20, 2024
0361bc1
Supress expected Warnings and CVODE Stats
halentin Jun 20, 2024
a967276
point to right 32 bit binaries
halentin Jun 20, 2024
23dbff5
remove unnecessary DoStep that Errors on 32 Bit for some reason
halentin Jun 20, 2024
fe7822b
decrease dostep size
halentin Jun 20, 2024
c5f981c
change stepsize back
halentin Jun 20, 2024
d43cb4a
only Test DoStep on x64
halentin Jun 20, 2024
dea4428
Merge branch 'main' into tests
ThummeTo Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 6 additions & 17 deletions src/FMI2/cfunc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,12 @@ 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,
logginOn::fmi2Boolean,
nCategories::Csize_t,
categories::Union{Ptr{fmi2String},AbstractArray{fmi2String}},
)::fmi2Status
status = ccall(
cfunc,
fmi2Status,
(fmi2Component, fmi2Boolean, Csize_t, Ptr{fmi2String}),
c,
logginOn,
nCategories,
categories,
)
@debug "fmi2SetDebugLogging(c: $(c), logginOn: $(loggingOn), nCategories: $(nCategories), categories: $(categories)) → $(status)"
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
export fmi2SetDebugLogging
Expand Down
72 changes: 72 additions & 0 deletions test/FMI2/CS.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher
# Licensed under the MIT license. See LICENSE file in the project root for details.
#

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))

startpoint = fmi2Real(0.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)
end


status = fmi2Real(0.0)
statusptr = pointer([status])
@test fmi2StatusOK == fmi2GetRealStatus!(dlsym(lib, :fmi2GetRealStatus), component, fmi2StatusKindLastSuccessfulTime, Ptr{fmi2Real}(statusptr))

@suppress begin
# 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))


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))

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))

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))
end

fmi2Terminate(dlsym(lib, :fmi2Terminate), component)

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))
@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 == fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component)


fmireference = [fmi2ValueReference(352321536)]
@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)




end
56 changes: 56 additions & 0 deletions test/FMI2/ME.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher
# Licensed under the MIT license. See LICENSE file in the project root for details.
#

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))
@test component != C_NULL

fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component)
fmi2ExitInitializationMode(dlsym(lib, :fmi2ExitInitializationMode), component)

@test fmi2StatusOK == fmi2EnterEventMode(dlsym(lib, :fmi2Instantiate), component)

eventInfo = fmi2EventInfo()
ptr = Ptr{fmi2EventInfo}(pointer_from_objref(eventInfo))

@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 == 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)

state_arr[2] = 2.0
@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 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)

nom_state_arr = zeros(fmi2Real, 2)
@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)
# 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
@test der_arr[2] ≈ -9.81
end

@test fmi2StatusOK == fmi2Terminate(dlsym(lib, :fmi2Terminate), component)
end
22 changes: 21 additions & 1 deletion test/FMI2/cfunc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,24 @@
# Licensed under the MIT license. See LICENSE file in the project root for details.
#

# [ToDo] tests for FMI2
using Libdl

include.(["utils.jl", "ME.jl", "CS.jl", "generic.jl"])


binarypath, fmu_path, cblibpath = get_os_binaries()
iopath, io_fmu_path, iocblibpath = get_os_binaries("IO")
if binarypath != ""
lib = dlopen(binarypath)
libio = dlopen(iopath)
# Missing Tests for fmi2<Set, Get><Boolean, String> 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
else
@warn "No valid FMU binaries found for this OS. Skipping tests."
end
148 changes: 148 additions & 0 deletions test/FMI2/generic.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher
# Licensed under the MIT license. See LICENSE file in the project root for details.
#

using Libdl, Suppressor

function test_generic(lib, cblibpath, type::fmi2Type)
# Tests missing for fmi2<Set, Get><Boolean, String> because the FMU we are testing with doesnt have such variables

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))
@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}([]))

# fmi2SetupExperiment

@test fmi2StatusOK == fmi2SetupExperiment(dlsym(lib, :fmi2SetupExperiment),component, fmi2Boolean(false), fmi2Real(0.0), fmi2Real(0.0), fmi2Boolean(false), fmi2Real(1.0))



# get, set and free State
state = fmi2FMUstate()
stateRef = Ref(state)

@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)
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 stateRef[] != C_NULL
@test fmi2StatusOK == fmi2FreeFMUstate(dlsym(lib,:fmi2FreeFMUstate), component, stateRef)
@test stateRef[] == C_NULL



# # Initialization Mode

@test fmi2StatusOK == fmi2EnterInitializationMode(dlsym(lib, :fmi2EnterInitializationMode), component)

fmireference = [fmi2ValueReference(16777220)]
@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 value == fmi2Real.([0.8])

fmireference = [fmi2ValueReference(637534208)]
value = zeros(fmi2Integer, 1)
@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)]))

fmireference = [fmi2ValueReference(637534208)]
value = zeros(fmi2Integer, 1)
@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)
# ∂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)
@suppress begin
# Suppressing the CVODE-Stats that are printed here in CS Mode
@test fmi2StatusOK == fmi2Reset(dlsym(lib, :fmi2Reset), component)
end

# # # fmi2FreeInstance
@test isnothing(fmi2FreeInstance(dlsym(lib, :fmi2FreeInstance), component))

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))
@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)

fmireference = [fmi2ValueReference(16777216)]
@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 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)]))

value = zeros(fmi2Integer, 1)
@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]))

value = zeros(fmi2Boolean, 1)
@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)

value = Vector{fmi2String}(undef, 1)
values = string.(zeros(1))
@test fmi2StatusOK == fmi2GetString!(dlsym(lib, :fmi2GetString), component, fmireference, Csize_t(1), value)
values[:] = unsafe_string.(value)
@test values == ["anything"]

end
Loading
Loading