diff --git a/src/implements.jl b/src/implements.jl index fc6e4b7..813445f 100644 --- a/src/implements.jl +++ b/src/implements.jl @@ -18,6 +18,33 @@ function implements end implements(T::Type{<:Interface}, obj) = implements(T, typeof(obj)) implements(::Type{<:Interface}, obj::Type) = false +function test_objects(::Type{T}) where T<:Interface + methodlist = methods(Interfaces.test_objects, Tuple{Type{T},Any}) + objects = Dict{Type,Any}() + # Check that all found methods are either unrequired, or pass their tests + for m in (methodlist) + (m.module == Interfaces) && continue + # We define this signature in the @interface macro so we know it is this consistent. + # There may be some methods to help with these things? + + # Handle either Type or UnionAll for the method signature parameters + b = m.sig isa UnionAll ? m.sig.body : m.sig + + # Skip the fallback methods + b.parameters[2] == Type{<:Interface} && continue + + # Skip the Type versions of implements and keep the UnionAll + t = b.parameters[2].var.ub + t isa UnionAll || return nothing, true + + interface = t.body.name.wrapper + implementation = b.parameters[3].var.ub + implementation == Any && return continue + objects[implementation] = test_objects(interface, implementation) + end + return objects +end + """ @implements(interface, objtype, test_objects) diff --git a/test/basic.jl b/test/basic.jl index 58310d3..ea29653 100644 --- a/test/basic.jl +++ b/test/basic.jl @@ -105,6 +105,7 @@ using Test #src @test Interfaces.test(Animals.AnimalInterface) == true # Test all implemented types for AnimalInterface # TODO wrap errors somehow, or just let Invariants.jl handle that. #src @test_throws Interfaces.InterfaceError Interfaces.test(Animals.AnimalInterface{:dig}, Duck) #src + @test Interfaces.test_objects(Animals.AnimalInterface) == Dict(Duck => ducks) end #src @testset "Chicken" begin #src