Skip to content
This repository has been archived by the owner on Oct 5, 2018. It is now read-only.

Commit

Permalink
Test reorg, fixed esc's in @define_singleton, added tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
tpapp committed Mar 31, 2017
1 parent 6522b17 commit 4a83d3b
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 116 deletions.
6 changes: 3 additions & 3 deletions src/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ uppercase.
macro define_singleton(name_and_supertype, constant = nothing)
@capture name_and_supertype name_ <: supertype_
if constant == nothing
constant = esc(Symbol(uppercase(string(name))))
constant = Symbol(uppercase(string(name)))
end
quote
Core.@__doc__ immutable $name <: $supertype end
Core.@__doc__ const $(constant) = $name()
Core.@__doc__ immutable $(esc(name)) <: $(esc(supertype)) end
Core.@__doc__ const $(esc(constant)) = $(esc(name))()
end
end
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ using ArgCheck
using Base.Test
import Compat:

include("test-utilities.jl")
include("utilities.jl")

include("test-utilities.jl")
include("test-intervals.jl")
include("test-transformations-basic.jl")
include("test-transformations-composed.jl")
Expand Down
120 changes: 8 additions & 112 deletions test/test-utilities.jl
Original file line number Diff line number Diff line change
@@ -1,115 +1,11 @@
import ForwardDiff: derivative
import Base: rand
"Test singleton type."
@define_singleton TestSingleton <: Real

"""
Return a random float in an interval (for testing). Do not use
directly when testing extrema, as these may happen with `0`
probability.
"""
rand(::RealLine, ::Type{Val{true}}) = randn()
rand(ray::PositiveRay, ::Type{Val{true}}) = ray.left + abs(randn())
rand(ray::NegativeRay, ::Type{Val{true}}) = ray.right + abs(randn())
rand(seg::Segment, ::Type{Val{true}}) = seg.left + width(seg) * rand()
@testset "define singleton" begin

@test TestSingleton <: Real
@test isa(TESTSINGLETON, TestSingleton)
@test repr(@doc(TESTSINGLETON)) == repr(@doc(TestSingleton)) ==
repr(doc"Test singleton type.")

function rand(x::AbstractInterval; left_prob = 0.1, right_prob = 0.1)
@argcheck left_prob + right_prob 1
z = rand()
left, right = extrema(x)
if z < left_prob
left
elseif z > 1-right_prob
right
else
rand(x, Val{true})
end
end


"""
Return a function that generates random intervals in the given
interval (for testing).
"""
function random_interval(x::AbstractInterval)
a = rand(x; right_prob = 0)
b = rand(x; left_prob = 0)
if a > b
a, b = b, a
end
Interval(a, b)
end

"""
Return a vector of values outside the interval (for testing).
"""
scalars_outside_interval(::RealLine) = []
scalars_outside_interval(ray::PositiveRay) = ray.left - [0.1, 1.0, 2.0, Inf]
scalars_outside_interval(ray::NegativeRay) = ray.right + [0.1, 1.0, 2.0, Inf]
function scalars_outside_interval(seg::Segment)
vcat(scalars_outside_interval(PositiveRay(seg.left)),
scalars_outside_interval(NegativeRay(seg.right)))
end

"""
Test univariate transformation `f` with `x`. Tests for:
1. type of the transformed value,
2. whether it is in the range,
3. inverse,
4. jacobian determinant and its log using automatic differentiation.
`forwarddiff_exceptions` is a dictionary handling exceptions that ForwardDiff
cannot cope with at the moment. See eg
## workaround for https://github.com/JuliaDiff/ForwardDiff.jl/issues/209
"""
function test_univariate_scalar{T}(f::UnivariateTransformation, x::T;
AD_exceptions = Dict())
y = f(x)
@test y image(f)
@test inv(f)(y) x
(y2, jac) = f(x, JAC)
@test y == y2
expected_jac = get(AD_exceptions, x, abs(derivative(f, x)))
@test jac expected_jac
(y3, logjac) = f(x, LOGJAC)
@test y == y3
@test logjac log(expected_jac)
end

# some exceptions below
logit_exceptions(t=Multiply(1.0)) = Dict(t(1.0) => Inf)

logistic_exceptions() = Dict(-Inf => 0.0)

"""
Test that univariate transformations map an interval the correct way.
"""
function test_univariate_interval(f::UnivariateTransformation, x::AbstractInterval)
y = f(x)
left, right = extrema(x)
f_left, f_right = f(left), f(right)
if f_right < f_left
f_right, f_left = f_left, f_right
end
y_left, y_right = extrema(y)
@test y_left f_left
@test y_right f_right
end

"""
Test univariate transformation `f`, called with random numbers and
intervals generated by `randform`, which should return numbers in the
domain.
"""
function test_univariate(f; N=500, AD_exceptions = Dict())
dom = domain(f)
for i in 1:500
test_univariate_scalar(f, rand(dom), AD_exceptions = AD_exceptions)
end
for i in 1:500
test_univariate_interval(f, random_interval(dom))
end
for x in scalars_outside_interval(dom)
@test_throws DomainError f(x)
end
end

114 changes: 114 additions & 0 deletions test/utilities.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import ForwardDiff: derivative
import Base: rand

"""
Return a random float in an interval (for testing). Do not use
directly when testing extrema, as these may happen with `0`
probability.
"""
rand(::RealLine, ::Type{Val{true}}) = randn()
rand(ray::PositiveRay, ::Type{Val{true}}) = ray.left + abs(randn())
rand(ray::NegativeRay, ::Type{Val{true}}) = ray.right + abs(randn())
rand(seg::Segment, ::Type{Val{true}}) = seg.left + width(seg) * rand()

function rand(x::AbstractInterval; left_prob = 0.1, right_prob = 0.1)
@argcheck left_prob + right_prob 1
z = rand()
left, right = extrema(x)
if z < left_prob
left
elseif z > 1-right_prob
right
else
rand(x, Val{true})
end
end


"""
Return a function that generates random intervals in the given
interval (for testing).
"""
function random_interval(x::AbstractInterval)
a = rand(x; right_prob = 0)
b = rand(x; left_prob = 0)
if a > b
a, b = b, a
end
Interval(a, b)
end

"""
Return a vector of values outside the interval (for testing).
"""
scalars_outside_interval(::RealLine) = []
scalars_outside_interval(ray::PositiveRay) = ray.left - [0.1, 1.0, 2.0, Inf]
scalars_outside_interval(ray::NegativeRay) = ray.right + [0.1, 1.0, 2.0, Inf]
function scalars_outside_interval(seg::Segment)
vcat(scalars_outside_interval(PositiveRay(seg.left)),
scalars_outside_interval(NegativeRay(seg.right)))
end

"""
Test univariate transformation `f` with `x`. Tests for:
1. type of the transformed value,
2. whether it is in the range,
3. inverse,
4. jacobian determinant and its log using automatic differentiation.
`forwarddiff_exceptions` is a dictionary handling exceptions that ForwardDiff
cannot cope with at the moment. See eg
## workaround for https://github.com/JuliaDiff/ForwardDiff.jl/issues/209
"""
function test_univariate_scalar{T}(f::UnivariateTransformation, x::T;
AD_exceptions = Dict())
y = f(x)
@test y image(f)
@test inv(f)(y) x
(y2, jac) = f(x, JAC)
@test y == y2
expected_jac = get(AD_exceptions, x, abs(derivative(f, x)))
@test jac expected_jac
(y3, logjac) = f(x, LOGJAC)
@test y == y3
@test logjac log(expected_jac)
end

# some exceptions below
logit_exceptions(t=Multiply(1.0)) = Dict(t(1.0) => Inf)

logistic_exceptions() = Dict(-Inf => 0.0)

"""
Test that univariate transformations map an interval the correct way.
"""
function test_univariate_interval(f::UnivariateTransformation, x::AbstractInterval)
y = f(x)
left, right = extrema(x)
f_left, f_right = f(left), f(right)
if f_right < f_left
f_right, f_left = f_left, f_right
end
y_left, y_right = extrema(y)
@test y_left f_left
@test y_right f_right
end

"""
Test univariate transformation `f`, called with random numbers and
intervals generated by `randform`, which should return numbers in the
domain.
"""
function test_univariate(f; N=500, AD_exceptions = Dict())
dom = domain(f)
for i in 1:500
test_univariate_scalar(f, rand(dom), AD_exceptions = AD_exceptions)
end
for i in 1:500
test_univariate_interval(f, random_interval(dom))
end
for x in scalars_outside_interval(dom)
@test_throws DomainError f(x)
end
end

0 comments on commit 4a83d3b

Please sign in to comment.