Asynchronous tasks can accidentally call patched functions
In a scenario where an background asynchronous task is calling a function using @mock and a patch is applied during that time the async task can call the patched function instead of the original:
julia> using Mocking
julia> Mocking.activate()
julia> f() = 1
f (generic function with 1 method)
julia> function g(name, n)
for i in 1:n
x = @mock f()
println(name, ": ", x)
sleep(1)
end
end
g (generic function with 1 method)
julia> p = @patch f() = 2
Patch{typeof(f)}(f, var"##f_patch#259")
julia> @async g("async", 5)
async: Task (runnable) @0x000000012f5973101
julia> apply(p) do
g("apply", 1)
end
apply: 2
async: 2
julia> async: 1
async: 1
async: 1
julia>
We might want to push the variable that says if we are mocking or not into a dynamically scoped context from ContextVariablesX.jl I think that supports tasks and threads. We use it in Checkpoints.jl as of https://github.com/invenia/Checkpoints.jl/pull/15
I've confirmed that ContextVariablesX.jl does fix the issue as demonstrated above. I'll work on a PR for this.
@oxinabox I appreciate you bringing that package to my attention ❤️
Unfortunately using ContextVariablesX.jl doesn't play nice with @test_logs or @test_deprecated so using that had to be reverted.
@tkf any ideas?
omus already figured it out. But, linking the discussion for the record: https://github.com/tkf/ContextVariablesX.jl/issues/16#issuecomment-943494351
Issue was fixed in https://github.com/JuliaTesting/Mocking.jl/pull/112 but requires Julia 1.11