Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.0'
- 'lts'
- '1'
- 'nightly'
os:
Expand Down
10 changes: 8 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ version = "0.4.0"

[deps]
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"

[weakdeps]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[extensions]
DensityInterfaceTestExt = "Test"

[compat]
InverseFunctions = "0.1"
julia = "1"
julia = "1.10"

[extras]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Documenter", "LinearAlgebra"]
test = ["Documenter", "LinearAlgebra", "Test"]
26 changes: 7 additions & 19 deletions src/interface_test.jl → ext/DensityInterfaceTestExt.jl
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
# This file is a part of DensityInterface.jl, licensed under the MIT License (MIT).

"""
DensityInterface.test_density_interface(object, x, ref_logd_at_x; kwargs...)
module DensityInterfaceTestExt

Test that `object` is compatible with `DensityInterface`.
using Test: @test, @testset
using DensityInterface: DensityInterface, DensityKind, IsDensity, IsOrHasDensity,
logdensityof, densityof, logfuncdensity, funcdensity

Tests that either `DensityKind(object) isa IsOrHasDensity`.

Also tests that [`logdensityof(object, x)`](@ref) equals `ref_logd_at_x` and
that the behavior of [`logdensityof(object)`](@ref),
[`densityof(object, x)`](@ref) and [`densityof(object)`](@ref) is consistent.

The results of `logdensityof(object, x)` and `densityof(object, x)` are compared to
`ref_logd_at_x` and `exp(ref_logd_at_x)` using `isapprox`. `kwargs...` are
forwarded to `isapprox`.

Also tests that `d = logfuncdensity(logdensityof(object))` returns a density
(`DensityKind(d) == IsDensity()`) that is equivalent to `object` in respect to
`logdensityof` and `densityof`, and that `funcdensity(densityof(object))`
behaves the same way.
"""
function test_density_interface(object, x, ref_logd_at_x; kwargs...)
function DensityInterface.test_density_interface(object, x, ref_logd_at_x; kwargs...)
@testset "test_density_interface: $object with input $x" begin
ref_d_at_x = exp(ref_logd_at_x)

Expand All @@ -43,3 +29,5 @@ function test_density_interface(object, x, ref_logd_at_x; kwargs...)
end
end
end

end # module
37 changes: 35 additions & 2 deletions src/DensityInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,42 @@ associated with a density.
module DensityInterface

using InverseFunctions
using Test

include("interface.jl")
include("interface_test.jl")

"""
DensityInterface.test_density_interface(object, x, ref_logd_at_x; kwargs...)

Test that `object` is compatible with `DensityInterface`.

Tests that either `DensityKind(object) isa IsOrHasDensity`.

Also tests that [`logdensityof(object, x)`](@ref) equals `ref_logd_at_x` and
that the behavior of [`logdensityof(object)`](@ref),
[`densityof(object, x)`](@ref) and [`densityof(object)`](@ref) is consistent.

The results of `logdensityof(object, x)` and `densityof(object, x)` are compared to
`ref_logd_at_x` and `exp(ref_logd_at_x)` using `isapprox`. `kwargs...` are
forwarded to `isapprox`.

Also tests that `d = logfuncdensity(logdensityof(object))` returns a density
(`DensityKind(d) == IsDensity()`) that is equivalent to `object` in respect to
`logdensityof` and `densityof`, and that `funcdensity(densityof(object))`
behaves the same way.

!!! note
This function is available only after the `Test` standard library has been
loaded.
"""
function test_density_interface end

function __init__()
Base.Experimental.register_error_hint(MethodError) do io, exc, _, _
if exc.f === test_density_interface &&
Base.get_extension(DensityInterface, :DensityInterfaceTestExt) === nothing
print(io, "\n`test_density_interface` requires the Test standard library; run `using Test` first.")
end
end
end

end # module
12 changes: 12 additions & 0 deletions test/test_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,16 @@ DensityInterface.logdensityof(::MyMeasure, x::Any) = -norm(x)^2
@test DensityKind(object3) === IsDensity()
DensityInterface.test_density_interface(object3, x, -norm(x)^2)
end

# Needs a process that has not loaded Test
code = """
using DensityInterface
try
DensityInterface.test_density_interface(1, 1, 1)
catch e
showerror(stdout, e)
end
"""
cmd = `$(Base.julia_cmd()) --startup-file=no --project=$(Base.active_project()) -e $code`
@test occursin("run `using Test` first", read(cmd, String))
end
Loading