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

test_unbound_args: add a functionality to ignore specific methods #316

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
22 changes: 20 additions & 2 deletions src/unbound_args.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
"""
test_unbound_args(module::Module)
test_unbound_args(unbounds)

Test that all methods in `module` and its submodules do not have
unbound type parameters. An unbound type parameter is a type parameter
with a `where`, that does not occur in the signature of some dispatch
of the method.
of the method. If unbounds methods are already known, they can be
passed directly to the function instead of the module.
lgoettgens marked this conversation as resolved.
Show resolved Hide resolved

# Keyword Arguments
- `broken::Bool = false`: If true, it uses `@test_broken` instead of
`@test` and shortens the error message.
- `ignore::Vector{Tuple{Function, DataType...}}`: A list of functions and their
lgoettgens marked this conversation as resolved.
Show resolved Hide resolved
signatures to ignore. The signatures are given as tuples, where the
first element is the function and the rest are the types of the
arguments. For example, to ignore `foo(x::Int, y::Float64)`, pass
`(foo, Int, Float64)`.
"""
function test_unbound_args(m::Module; broken::Bool = false)
function test_unbound_args(m::Module; broken::Bool = false, ignore = ())
unbounds = detect_unbound_args_recursively(m)
for i in ignore
# i[2:end] is empty if length(i) == 1
ignore_signature = Tuple{typeof(i[1]),i[2:end]...}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach unfortunately does not work for callable objects.

Please make sure that this also works for cases like

struct S{U}
  s::U
end

(::S{U})(::NTuple{N,T}) where {N,T,U} = (N,T,U)
(::S{U})(::Tuple{}) where {U} = (0,Any,U)

and include such an example in the tests

filter!(unbounds) do method
method.sig != ignore_signature
end
end
test_unbound_args(unbounds; broken = broken)
end

function test_unbound_args(unbounds; broken::Bool = false)
if broken
if !isempty(unbounds)
printstyled(
Expand Down
5 changes: 5 additions & 0 deletions test/pkgs/PkgUnboundArgs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ end
# `_totuple` is taken from
# https://github.com/JuliaLang/julia/blob/48634f9f8669e1dc1be0a1589cd5be880c04055a/test/ambiguous.jl#L257-L259

# taken from https://github.com/JuliaTesting/Aqua.jl/issues/86
module Issue86
f(::NTuple{N,T}) where {N,T} = (N, T)
f(::Tuple{}) = (0, Any)
end
end # module
8 changes: 8 additions & 0 deletions test/test_unbound_args.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ using PkgUnboundArgs
@test length(results) == 1
@test results[1] isa Test.Fail

Aqua.test_unbound_args(
PkgUnboundArgs,
ignore = [
(PkgUnboundArgs.M25341._totuple, Type{Tuple{Vararg{E}}} where {E}, Any, Vararg),
(PkgUnboundArgs.Issue86.f, NTuple),
],
)

# It works with other tests:
Aqua.test_ambiguities(PkgUnboundArgs)
Aqua.test_undefined_exports(PkgUnboundArgs)
Expand Down
Loading