Skip to content

Commit

Permalink
Avoid overwrite warning using more specific method
Browse files Browse the repository at this point in the history
  • Loading branch information
omus committed Jul 12, 2024
1 parent f0adf5d commit c10e68f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 31 deletions.
48 changes: 22 additions & 26 deletions src/Mocking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,42 @@ include("patch.jl")
include("mock.jl")
include("deprecated.jl")

# Create the initial definition of `activated` which defaults Mocking to be disabled
activated() = false
# Create the initial definition of `activated` which defaults having Mocking be deactivated.
# We utilize method invalidation as a feature here to allow functions using `@mock` to be
# automatically re-compiled after Mocking was activated.
#
# We slightly abuse multiple-dispatch here so that we avoid having a "method definition
# overwritten" for the first call to `Mocking.activate`. By defining a more specific method
# we avoid the warning but can still trigger invalidation.
_activated(::Integer) = false

"""
Mocking.activate([func])
Mocking.activated() -> Bool
Enable `@mock` call sites to allow for calling patches instead of the original function.
Indicates if Mocking has been activated or not via `Mocking.activate`.
"""
function activate()
# Avoid redefining `activated` when it's already set appropriately
!Base.invokelatest(activated) && @eval activated() = true
return nothing
end

function activate(f)
started_deactivated = !activated()
try
activate()
Base.invokelatest(f)
finally
started_deactivated && deactivate()
end
end
activated() = _activated(0)

"""
Mocking.deactivate()
Mocking.activate() -> Nothing
Activates `@mock` call sites to allow for calling patches instead of the original function.
Intended to be called within a packages `test/runtests.jl` file.
Disable `@mock` call sites to only call the original function.
!!! note
Calling this causes functions which use `@mock` to become invalidated and re-compiled
the next time they are called.
"""
function deactivate()
# Avoid redefining `activated` when it's already set appropriately
Base.invokelatest(activated) && @eval activated() = false
function activate()
# Avoid redefining `_activated` when it's already set appropriately
!activated() && @eval _activated(::Int) = true
return nothing
end


const NULLIFIED = Ref{Bool}(false)

"""
Mocking.nullify()
Mocking.nullify() -> Nothing
Force any packages loaded after this point to treat the `@mock` macro as a no-op. Doing so
will maximize performance by eliminating any runtime checks taking place at the `@mock` call
Expand Down
27 changes: 25 additions & 2 deletions src/deprecated.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
using Base: @deprecate, depwarn
using Base: depwarn

function ismocked(pe::PatchEnv, func_name::Symbol, args::Tuple)
m = @__MODULE__
depwarn("`$m.ismocked` is no longer used and can be safely removed.", :ismocked)
return false
end

# Note: Very similar to using `@deprecate` but displays fully qualified function names
# Note: The `depwarn` call here is similar to using `@deprecate` but instead shows a fully
# qualified function name.
function enable(; force=false)
m = @__MODULE__
depwarn("`$m.enable(; force=$force)` is deprecated, use `$m.activate()` instead.", :enable)
activate()
end

function activate(f)
m = @__MODULE__
depwarn("`$m.activate(f)` is deprecated and will be removed in the future.", :activate)

started_deactivated = !activated()
try
activate()
Base.invokelatest(f)
finally
started_deactivated && deactivate()
end
end

function deactivate()
m = @__MODULE__
depwarn("`$m.deactivate()` is deprecated and will be removed in the future.", :deactivate)

# Avoid redefining `_activated` when it's already set appropriately
Base.invokelatest(activated) && @eval _activated(::Int) = false
return nothing
end
6 changes: 3 additions & 3 deletions test/activate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Starting with Mocking enabled.
Mocking.activate()
@test Mocking.activated()
Mocking.activate() do
@test_deprecated Mocking.activate() do
apply(patch) do
@test (@mock add1(2)) == 44
end
Expand All @@ -15,9 +15,9 @@
# Starting with Mocking disabled.
# Make sure to leave it enabled for the rest of the tests.
try
Mocking.deactivate()
@test_deprecated Mocking.deactivate()
@test !Mocking.activated()
Mocking.activate() do
@test_deprecated Mocking.activate() do
apply(patch) do
@test (@mock add1(2)) == 44
end
Expand Down

0 comments on commit c10e68f

Please sign in to comment.