PSPDFKit-labs/bypass

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

Ouverte

#75 ouverte le 15 janv. 2019

 (1 commentaire) (0 réaction) (0 personne assignée)Elixir (89 forks)batch import
help wanted

Métriques du dépôt

Stars
 (847 étoiles)
Métriques de merge PR
 (Aucune PR mergée en 30 j)

Description

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

Guide contributeur