85 lines
2.2 KiB
Elixir
85 lines
2.2 KiB
Elixir
defmodule Parrhesia.IntegrationCase do
|
|
@moduledoc false
|
|
|
|
use ExUnit.CaseTemplate
|
|
|
|
alias Ecto.Adapters.SQL.Sandbox
|
|
alias ExUnit.Case
|
|
alias Parrhesia.Repo
|
|
alias Parrhesia.TestSupport.Runtime
|
|
|
|
using opts do
|
|
quote bind_quoted: [opts: opts] do
|
|
use Case, async: Keyword.get(opts, :async, false)
|
|
|
|
alias Ecto.Adapters.SQL.Sandbox
|
|
alias Parrhesia.Repo
|
|
|
|
@moduletag parrhesia_sandbox: Keyword.get(opts, :sandbox, false)
|
|
end
|
|
end
|
|
|
|
setup tags do
|
|
Runtime.ensure_started!()
|
|
|
|
case tags[:parrhesia_sandbox] do
|
|
false ->
|
|
:ok
|
|
|
|
true ->
|
|
:ok = Sandbox.checkout(Repo)
|
|
|
|
:shared ->
|
|
# Delegate sandbox ownership to a dedicated process that outlives
|
|
# the test process. ExUnit terminates start_supervised! children
|
|
# (in reverse start order) before running on_exit callbacks. With
|
|
# the test process as sandbox owner, the connection dies the
|
|
# moment the test process exits — supervised children that make
|
|
# DB calls during their shutdown sequence would hit a dead
|
|
# connection. The separate owner stays alive through the entire
|
|
# supervised-child shutdown, and is only stopped in on_exit
|
|
# (which runs afterwards).
|
|
test_pid = self()
|
|
|
|
owner =
|
|
spawn(fn ->
|
|
:ok = Sandbox.checkout(Repo)
|
|
send(test_pid, {:sandbox_ready, self()})
|
|
|
|
receive do
|
|
:stop ->
|
|
Sandbox.checkin(Repo)
|
|
|
|
# Allow the pool to process the checkin before this process
|
|
# exits, so Postgrex does not see a dead client and log a
|
|
# spurious disconnect error.
|
|
Process.sleep(50)
|
|
end
|
|
end)
|
|
|
|
receive do
|
|
{:sandbox_ready, ^owner} -> :ok
|
|
after
|
|
5_000 -> raise "Sandbox owner checkout timed out"
|
|
end
|
|
|
|
Sandbox.mode(Repo, {:shared, owner})
|
|
|
|
on_exit(fn ->
|
|
ref = Process.monitor(owner)
|
|
send(owner, :stop)
|
|
|
|
receive do
|
|
{:DOWN, ^ref, :process, ^owner, _reason} -> :ok
|
|
after
|
|
5_000 -> :ok
|
|
end
|
|
|
|
Sandbox.mode(Repo, :manual)
|
|
end)
|
|
end
|
|
|
|
:ok
|
|
end
|
|
end
|