diff --git a/Project.toml b/Project.toml index cd76b32..8537834 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SciMLTesting" uuid = "09d9d899-5365-40a9-917a-5f67fddea283" authors = ["SciML"] -version = "2.9.0" +version = "2.10.0" [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" diff --git a/src/SciMLTesting.jl b/src/SciMLTesting.jl index 5b13944..ba345af 100644 --- a/src/SciMLTesting.jl +++ b/src/SciMLTesting.jl @@ -729,7 +729,7 @@ end aqua = Aqua !== nothing, jet = JET !== nothing, explicit_imports = true, api_docs = true, check_reexports = true, clean_sources = true, - aqua_kwargs = (;), jet_kwargs = (; target_modules = (pkg,), mode = :typo), + aqua_kwargs = (;), jet_kwargs = (;), ei_kwargs = (;), api_docs_kwargs = (;), reexports_allow = (), aqua_broken = (), jet_broken = false, ei_broken = (), testset = "Quality Assurance") @@ -747,7 +747,11 @@ module; `run_qa` then picks it up. The typical call collapses to just Each tool runs if it is both available and enabled: * `Aqua` + `aqua` ⇒ `Aqua.test_all(pkg; aqua_kwargs...)`, - * `JET` + `jet` ⇒ `JET.test_package(pkg; jet_kwargs...)`, + * `JET` + `jet` ⇒ `JET.test_package(pkg; jet_kwargs...)`, where `jet_kwargs` is merged + over the standard `(; target_modules = (pkg,), mode = :typo)` rather than replacing + it, so a partial override keeps the standard setting for every key it omits. Passing + JET's deprecated `target_defined_modules` suppresses the `target_modules` default, + since the two configure the same thing. * `ExplicitImports` + `explicit_imports` ⇒ ExplicitImports' standard + public-API checks (see [`run_explicit_imports`](@ref)). * `api_docs` ⇒ the public-API documentation check (see [`run_api_docs`](@ref)): every @@ -882,7 +886,7 @@ function run_qa( reexports_allow = (), clean_sources::Bool = true, aqua_kwargs = (;), - jet_kwargs = (; target_modules = (pkg,), mode = :typo), + jet_kwargs = (;), ei_kwargs = (;), api_docs_kwargs = (;), aqua_broken = (), @@ -923,11 +927,12 @@ function run_qa( run_aqua_with_dependencies() end if jet + effective_jet_kwargs = _standard_jet_kwargs(pkg, jet_kwargs) if jet_broken - rep = JET.report_package(pkg; _jet_report_kwargs(jet_kwargs)...) + rep = JET.report_package(pkg; _jet_report_kwargs(effective_jet_kwargs)...) @test_broken isempty(JET.get_reports(rep)) else - JET.test_package(pkg; jet_kwargs...) + JET.test_package(pkg; effective_jet_kwargs...) end end explicit_imports && run_explicit_imports(pkg, ExplicitImports; ei_kwargs, ei_broken) @@ -989,6 +994,18 @@ function _standard_aqua_kwargs(aqua_kwargs, extension_functions = _solver_extens return merge(kwargs, (; piracies = merge(piracies, (; treat_as_own = unique(treat_as_own))))) end +# Fill in the standard JET configuration for every key the caller did not mention. This +# must merge rather than replace: as a whole-NamedTuple default, any `jet_kwargs` at all +# dropped `mode = :typo` and silently reverted JET to its far more expensive `BasicPass`. +# `target_defined_modules` is JET's deprecated spelling of `target_modules`, so a caller +# passing it already owns that slot and must not also receive `target_modules`. +function _standard_jet_kwargs(pkg::Module, jet_kwargs) + nt = NamedTuple(jet_kwargs) + defaults = haskey(nt, :target_defined_modules) ? (; mode = :typo) : + (; target_modules = (pkg,), mode = :typo) + return merge(defaults, nt) +end + # `JET.report_package` is report-only and takes JET config keys via `jetconfigs...` # (target_modules / target_defined_modules / ignored_modules / ...). It does NOT have # a pass/fail `mode`, which is a `JET.test_package`-only config; drop it for the diff --git a/test/runtests.jl b/test/runtests.jl index 3d2c419..6b6ef79 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -26,9 +26,13 @@ end module FakeJET using Test: @test import ..SciMLTesting + # Records what test_package actually received so a test can assert that a partial + # `jet_kwargs` override still carries the standard configuration for the keys it omits. + const LAST_TEST_KWARGS = Ref{Any}(nothing) function test_package(pkg; target_modules = nothing, mode = nothing, kwargs...) @test pkg === SciMLTesting @test mode === :typo + LAST_TEST_KWARGS[] = (; target_modules, mode, kwargs...) return true end # report_package variant for jet_broken. Returns a fake "result" carrying a list of @@ -538,6 +542,36 @@ end api_docs = false, ) + # A partial `jet_kwargs` override merges over the standard configuration instead + # of replacing it. Regression: `jet_kwargs` used to be a whole-NamedTuple default, + # so passing any entry dropped `mode = :typo` and silently reverted JET to its far + # more expensive `BasicPass`. + FakeJET.LAST_TEST_KWARGS[] = nothing + run_qa( + SciMLTesting; Aqua = nothing, JET = FakeJET, ExplicitImports = nothing, + explicit_imports = false, api_docs = false, + jet_kwargs = (; ignore_throws = false), + ) + @test FakeJET.LAST_TEST_KWARGS[].mode === :typo + @test FakeJET.LAST_TEST_KWARGS[].target_modules == (SciMLTesting,) + @test FakeJET.LAST_TEST_KWARGS[].ignore_throws === false + + # An explicit entry still wins over the default it collides with. + @test SciMLTesting._standard_jet_kwargs(SciMLTesting, (; mode = :sound)).mode === + :sound + @test SciMLTesting._standard_jet_kwargs( + SciMLTesting, (; target_modules = (Base,)) + ).target_modules == (Base,) + + # `target_defined_modules` is JET's deprecated spelling of `target_modules`, so it + # owns that slot: the default must not also inject `target_modules` alongside it. + deprecated = SciMLTesting._standard_jet_kwargs( + SciMLTesting, (; target_defined_modules = true) + ) + @test deprecated.mode === :typo + @test deprecated.target_defined_modules === true + @test !haskey(deprecated, :target_modules) + # Helpful errors when an enable flag is forced on but the module is unavailable. @test_throws ArgumentError run_qa( SciMLTesting; Aqua = nothing, aqua = true,