PSPDFKit-labs/bypass

Bypass hangs in Bypass.do_verify_expectations/2 when using hackney inside a task with a timeout

Aperta

#75 aperta il 15 gen 2019

 (1 commento) (0 reazioni) (0 assegnatari)Elixir (89 fork)batch import
help wanted

Metriche repository

Star
 (847 stelle)
Metriche merge PR
 (Nessuna PR mergiata in 30 g)

Descrizione

I want to test that I'm able to abort a request that takes too long for any reason. I decided to use a task to wrap my request, the task is shut down after a timeout. I use bypass in my test to simulate a request that takes longer than the timeout value.

When using httpc to make the request the test succeeds. When using hackney to make the request, the test hangs in Bypass.do_verify_expectations/2.

I use {:hackney, "~> 1.15"} and {:bypass, "~> 1.0.0", only: :test}. Below is the test runner output and the code for the two tests.

1) test bypass with hackney (HackneyBypassTest)
     test/peertube_index/hackney_bypass_test.exs:5
     ** (ExUnit.TimeoutError) on_exit callback timed out after 2000ms. You can change the timeout:
     
       1. per test by setting "@tag timeout: x"
       2. per case by setting "@moduletag timeout: x"
       3. globally via "ExUnit.start(timeout: x)" configuration
       4. or set it to infinity per run by calling "mix test --trace"
          (useful when using IEx.pry)
     
     Timeouts are given as integers in milliseconds.
     
     stacktrace:
       (stdlib) gen.erl:169: :gen.do_call/4
       (elixir) lib/gen_server.ex:921: GenServer.call/3
       (bypass) lib/bypass.ex:71: Bypass.do_verify_expectations/2
       (ex_unit) lib/ex_unit/on_exit_handler.ex:140: ExUnit.OnExitHandler.exec_callback/1
       (ex_unit) lib/ex_unit/on_exit_handler.ex:126: ExUnit.OnExitHandler.on_exit_runner_loop/0
defmodule HackneyBypassTest do
  use ExUnit.Case

  @tag timeout: 2000
  test "bypass with hackney" do
    bypass = Bypass.open
    reponse_delay = 600
    timeout = reponse_delay - 100

    Bypass.expect(bypass, "GET", "/", fn conn ->
      Process.sleep(reponse_delay)
      Plug.Conn.resp(conn, 200, "response data")
    end)

    request = Task.async(fn ->
      :hackney.get("http://localhost:#{bypass.port}", [], "", [follow_redirect: true, with_body: true])
    end)
    result =
    case Task.yield(request, timeout) || Task.shutdown(request) do
      {:ok, result} ->
        {:ok, result}
      nil ->
        {:error, :timeout}
    end

    assert result == {:error, :timeout}
    IO.puts "DEBUG: End of test reached"
  end

  test "bypass with httpc" do
    bypass = Bypass.open
    reponse_delay = 600
    timeout = reponse_delay - 100

    Bypass.expect(bypass, "GET", "/", fn conn ->
      Process.sleep(reponse_delay)
      Plug.Conn.resp(conn, 200, "response data")
    end)

    request = Task.async(fn ->
      :httpc.request(:get, {String.to_charlist("http://localhost:#{bypass.port}"), []}, [], body_format: :binary)
    end)
    result =
    case Task.yield(request, timeout) || Task.shutdown(request) do
      {:ok, result} ->
        {:ok, result}
      nil ->
        {:error, :timeout}
    end

    assert result == {:error, :timeout}
    IO.puts "DEBUG: End of test reached"
  end
end

Guida contributor