defmodule DrainStopTest do use ExUnit.Case, async: false use Phoenix.ConnTest defmodule TestSupervisor do @drain_stop_timeout 100 def start_link do import Supervisor.Spec, warn: false children = [ # Start the endpoint when the application starts supervisor(DrainStopTest.TestEndpoint, []), worker( DrainStop, [[timeout: @drain_stop_timeout, endpoint: DrainStopTest.TestEndpoint]], [shutdown: @drain_stop_timeout * 2] ), ] opts = [strategy: :one_for_one] Supervisor.start_link(children, opts) end end defmodule TestPlug do def init(opts), do: opts def call(conn, _) do pid = Application.get_env(:drain_stop_test, :test_pid) conn = Plug.Conn.fetch_query_params(conn) send pid, :request_start {time, _} = Integer.parse(conn.params["sleep"]) :timer.sleep(time) send pid, :request_end conn end end defmodule TestEndpoint do use Phoenix.Endpoint, otp_app: :drain_stop_test plug DrainStopTest.TestPlug end @endpoint DrainStopTest.TestEndpoint setup do Application.put_env(:drain_stop_test, :test_pid, self) Application.put_env(:drain_stop_test, DrainStopTest.TestEndpoint, http: [port: "4807"], url: [host: "example.com"], server: true) {:ok, pid} = DrainStopTest.TestSupervisor.start_link Process.flag(:trap_exit, true) on_exit(fn -> if Process.whereis(DrainStopTest.TestEndpoint) do Supervisor.stop(DrainStopTest.TestEndpoint) end Process.exit(pid, :brutal_kill) end) {:ok, pid: pid} end test "waits for request to finish", %{pid: pid} do Task.async(fn -> HTTPoison.get("http://localhost:4807/?sleep=50") end) assert_receive :request_start, 1000 Supervisor.stop(pid, :shutdown) assert_received :request_end end test "truncates requests that don't finish in time", %{pid: pid} do Task.async(fn -> HTTPoison.get("http://localhost:4807/?sleep=500") end) assert_receive :request_start, 1000 Supervisor.stop(pid, :shutdown) refute_received :request_end end test "does not allow new requests" do # This is harder to test without reaching in to internals... DrainStop.stop_listening(DrainStopTest.TestEndpoint) assert_raise(HTTPoison.Error, fn -> HTTPoison.get!("http://localhost:4807/?sleep=500") end) end end