Skip to content

Commit

Permalink
Refactor test_deps_compat
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens committed Sep 21, 2023
1 parent 3d5ed9f commit f679bdb
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 105 deletions.
101 changes: 42 additions & 59 deletions src/deps_compat.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Aqua.test_deps_compat(package; [ignore])
Aqua.test_deps_compat(package)
Test that `Project.toml` of `package` list all `compat` for `deps`.
Test that the `Project.toml` of `package` lists a `compat` entry for each `deps`.
# Arguments
- `packages`: a top-level `Module`, a `Base.PkgId`, or a collection of
Expand All @@ -10,75 +10,58 @@ Test that `Project.toml` of `package` list all `compat` for `deps`.
# Keyword Arguments
- `ignore::Vector{Symbol}`: names of dependent packages to be ignored.
"""
function test_deps_compat(packages; kwargs...)
@testset "$(result.label)" for result in analyze_deps_compat(packages; kwargs...)
@debug result.label result
@test result true
function test_deps_compat(pkg::PkgId; kwargs...)
result = find_missing_deps_compat(pkg; kwargs...)
@test result == []
end

# Remove with next breaking version
function test_deps_compat(packages::Vector{<:Union{Module,PkgId}}; kwargs...)
@testset "$pkg" for pkg in packages
test_deps_compat(pkg; kwargs...)

Check warning on line 21 in src/deps_compat.jl

View check run for this annotation

Codecov / codecov/patch

src/deps_compat.jl#L19-L21

Added lines #L19 - L21 were not covered by tests
end
end

function analyze_deps_compat(packages; kwargs...)
result = [_analyze_deps_compat_1(pkg; kwargs...) for pkg in aspkgids(packages)]
return result
function test_deps_compat(mod::Module; kwargs...)
test_deps_compat(aspkgid(mod); kwargs...)
end

function _analyze_deps_compat_1(pkg::PkgId; kwargs...)
function find_missing_deps_compat(pkg::PkgId, deps_type::String = "deps"; kwargs...)
result = root_project_or_failed_lazytest(pkg)
result isa LazyTestResult && return result
result isa LazyTestResult && error("Unable to locate Project.toml")
root_project_path = result
return _analyze_deps_compat_2(
pkg,
root_project_path,
TOML.parsefile(root_project_path);
kwargs...,
)
missing_compat =
find_missing_deps_compat(TOML.parsefile(root_project_path), deps_type; kwargs...)

if !isempty(missing_compat)
printstyled(

Check warning on line 37 in src/deps_compat.jl

View check run for this annotation

Codecov / codecov/patch

src/deps_compat.jl#L37

Added line #L37 was not covered by tests
stderr,
"$pkg does not declare a compat entry for the following $deps_type:\n";
bold = true,
color = Base.error_color(),
)
show(stderr, MIME"text/plain"(), missing_compat)
println(stderr)

Check warning on line 44 in src/deps_compat.jl

View check run for this annotation

Codecov / codecov/patch

src/deps_compat.jl#L43-L44

Added lines #L43 - L44 were not covered by tests
end

return missing_compat
end

# For supporting Julia 1.8-DEV and above which give us a tuple instead of a string
_unwrap_name(x::Tuple) = first(x)
_unwrap_name(x::String) = x
_unwrap_name(x::Nothing) = x
function _analyze_deps_compat_2(
pkg::PkgId,
root_project_path,
prj;
function find_missing_deps_compat(
prj::Dict{String,Any},
deps_type::String;
ignore::AbstractVector{Symbol} = Symbol[],
)
label = "$pkg"
deps = get(prj, deps_type, Dict{String,Any}())
compat = get(prj, "compat", Dict{String,Any}())

deps = get(prj, "deps", nothing)
if deps === nothing
return LazyTestResult(label, "`$root_project_path` does not have `deps`", true)
end
compat = get(prj, "compat", nothing)
if compat === nothing
return LazyTestResult(label, "`$root_project_path` does not have `compat`", false)
end

stdlib_name_from_uuid = stdlibs()
stdlib_deps = filter!(
!isnothing,
stdlibs = get_stdlib_list()
missing_compat = sort!(
[
_unwrap_name(get(stdlib_name_from_uuid, UUID(uuid), nothing)) for
(_, uuid) in deps
],
)
missing_compat =
setdiff(setdiff(setdiff(keys(deps), keys(compat)), stdlib_deps), String.(ignore))
if !isempty(missing_compat)
msg = join(
[
"`$root_project_path` does not specify `compat` for:"
sort!(collect(missing_compat))
],
"\n",
)
return LazyTestResult(label, msg, false)
end

return LazyTestResult(
label,
"`$root_project_path` specifies `compat` for all `deps`",
true,
d for d in map(d -> PkgId(UUID(last(d)), first(d)), collect(deps)) if
!(d.name in keys(compat)) && !(d in stdlibs) && !(d.name in String.(ignore))
];
by = (pkg -> pkg.name),

Check warning on line 64 in src/deps_compat.jl

View check run for this annotation

Codecov / codecov/patch

src/deps_compat.jl#L64

Added line #L64 was not covered by tests
)
return missing_compat
end
27 changes: 18 additions & 9 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,25 @@ function checked_repr(obj)
return code
end

const stdlibs = try
Pkg.Types.stdlibs
catch
try
# https://github.com/JuliaLang/Pkg.jl/pull/1559
Pkg.Types.stdlib # julia < 1.4
catch
# https://github.com/JuliaLang/Pkg.jl/pull/696
Pkg.Types.gather_stdlib_uuids # julia < 1.1


function get_stdlib_list()
@static if VERSION >= v"1.5.0-DEV.200"

Check warning on line 90 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L90

Added line #L90 was not covered by tests
result = Pkg.Types.stdlibs()
elseif VERSION >= v"1.1.0-DEV.800"
result = Pkg.Types.stdlib()
else
result = Pkg.Types.gather_stdlib_uuids()
end

@static if VERSION >= v"1.7.0-DEV.1261"

Check warning on line 98 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L98

Added line #L98 was not covered by tests
# format: Dict{Base.UUID, Tuple{String, Union{Nothing, VersionNumber}}}
libs = [PkgId(first(entry), first(last(entry))) for entry in result]
else
# format Dict{Base.UUID, String}
libs = [PkgId(first(entry), last(entry)) for entry in result]
end
return libs
end

const _project_key_order = [
Expand Down
65 changes: 28 additions & 37 deletions test/test_deps_compat.jl
Original file line number Diff line number Diff line change
@@ -1,82 +1,73 @@
module TestDepsCompat

include("preamble.jl")
using Aqua: PkgId, UUID, _analyze_deps_compat_2,
using Aqua: find_missing_deps_compat

const DictSA = Dict{String,Any}

@testset "_analyze_deps_compat_2" begin
pkg = PkgId(UUID(42), "TargetPkg")
root_project_path = "DUMMY_PATH"
@testset "find_missing_deps_compat" begin
@testset "pass" begin
@test _analyze_deps_compat_2(
pkg,
root_project_path,
result = find_missing_deps_compat(
DictSA("deps" => DictSA(), "compat" => DictSA("julia" => "1")),
) true
@test _analyze_deps_compat_2(
pkg,
root_project_path,
"deps",
)
@test result == []
result = find_missing_deps_compat(
DictSA(
"deps" => DictSA("SHA" => "ea8e919c-243c-51af-8825-aaa63cd721ce"),
"compat" => DictSA("julia" => "1"),
),
) true
@test _analyze_deps_compat_2(
pkg,
root_project_path,
"deps",
)
@test result == []
result = find_missing_deps_compat(
DictSA(
"deps" => DictSA("PkgA" => "229717a1-0d13-4dfb-ba8f-049672e31205"),
"compat" => DictSA("julia" => "1", "PkgA" => "1.0"),
),
) true
"deps",
)
@test result == []
@testset "does not have `deps`" begin
# Not sure if it should fail or passs:
t = _analyze_deps_compat_2(pkg, root_project_path, DictSA())
@test t true
@test occursin("does not have `deps`", string(t))
result = find_missing_deps_compat(DictSA(), "deps")
@test result == []
end
end
@testset "failure" begin
@testset "does not have `compat`" begin
t = _analyze_deps_compat_2(
pkg,
root_project_path,
result = find_missing_deps_compat(
DictSA("deps" => DictSA("PkgA" => "229717a1-0d13-4dfb-ba8f-049672e31205")),
"deps",
)
@test t false
@test occursin("does not have `compat`", string(t))
@test length(result) == 1
@test [pkg.name for pkg in result] == ["PkgA"]
end

@testset "does not specify `compat` for PkgA" begin
t = _analyze_deps_compat_2(
pkg,
root_project_path,
result = find_missing_deps_compat(
DictSA(
"deps" => DictSA("PkgA" => "229717a1-0d13-4dfb-ba8f-049672e31205"),
"compat" => DictSA("julia" => "1"),
),
"deps",
)
@test t false
@test occursin("does not specify `compat` for", string(t))
@test occursin("PkgA", string(t))
@test length(result) == 1
@test [pkg.name for pkg in result] == ["PkgA"]
end

@testset "does not specify `compat` for PkgB" begin
t = _analyze_deps_compat_2(
pkg,
root_project_path,
result = find_missing_deps_compat(
DictSA(
"deps" => DictSA(
"PkgA" => "229717a1-0d13-4dfb-ba8f-049672e31205",
"PkgB" => "3d97d89c-7c41-49ae-981c-14fe13cc7943",
),
"compat" => DictSA("julia" => "1", "PkgA" => "1.0"),
),
"deps",
)
@test t false
@test occursin("does not specify `compat` for", string(t))
@test occursin("PkgB", string(t))
@test length(result) == 1
@test [pkg.name for pkg in result] == ["PkgB"]
end
end
end
Expand Down

0 comments on commit f679bdb

Please sign in to comment.