2019-08-13 07:37:19 -04:00
|
|
|
# Pleroma: A lightweight social networking server
|
|
|
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
defmodule Gun.ConnectionsTest do
|
2019-08-14 06:37:27 -04:00
|
|
|
use ExUnit.Case
|
2019-08-13 07:37:19 -04:00
|
|
|
alias Pleroma.Gun.{Connections, Conn, API}
|
|
|
|
|
2019-08-19 08:40:06 -04:00
|
|
|
setup_all do
|
|
|
|
{:ok, _} = Registry.start_link(keys: :unique, name: API.Mock)
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-08-13 07:37:19 -04:00
|
|
|
setup do
|
|
|
|
name = :test_gun_connections
|
2019-08-14 06:37:27 -04:00
|
|
|
adapter = Application.get_env(:tesla, :adapter)
|
|
|
|
Application.put_env(:tesla, :adapter, Tesla.Adapter.Gun)
|
|
|
|
on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end)
|
2019-08-19 08:40:06 -04:00
|
|
|
{:ok, pid} = Connections.start_link({name, [max_connections: 2, timeout: 10]})
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
{:ok, name: name, pid: pid}
|
|
|
|
end
|
|
|
|
|
2019-08-14 06:37:27 -04:00
|
|
|
describe "alive?/2" do
|
|
|
|
test "is alive", %{name: name} do
|
|
|
|
assert Connections.alive?(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "returns false if not started" do
|
|
|
|
refute Connections.alive?(:some_random_name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
test "try_to_get_gun_conn/1 returns conn", %{name: name, pid: pid} do
|
|
|
|
conn = Connections.try_to_get_gun_conn("http://some-domain.com", [genserver_pid: pid], name)
|
|
|
|
assert is_pid(conn)
|
|
|
|
assert Process.alive?(conn)
|
|
|
|
|
|
|
|
reused_conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name)
|
|
|
|
|
|
|
|
assert conn == reused_conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:some-domain.com:80" => %Conn{
|
2019-08-14 06:37:27 -04:00
|
|
|
conn: ^conn,
|
|
|
|
state: :up,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: [],
|
|
|
|
used: 2
|
2019-08-14 06:37:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
|
|
|
|
2019-08-13 07:37:19 -04:00
|
|
|
test "opens connection and reuse it on next request", %{name: name, pid: pid} do
|
2019-08-14 06:37:27 -04:00
|
|
|
conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
assert is_pid(conn)
|
|
|
|
assert Process.alive?(conn)
|
|
|
|
|
2019-08-14 06:37:27 -04:00
|
|
|
reused_conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
assert conn == reused_conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:some-domain.com:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: ^conn,
|
|
|
|
state: :up,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: [],
|
|
|
|
used: 2
|
2019-08-13 07:37:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "reuses connection based on protocol", %{name: name, pid: pid} do
|
2019-08-14 06:37:27 -04:00
|
|
|
conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
assert is_pid(conn)
|
|
|
|
assert Process.alive?(conn)
|
|
|
|
|
2019-08-14 06:37:27 -04:00
|
|
|
https_conn = Connections.get_conn("https://some-domain.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
refute conn == https_conn
|
|
|
|
|
2019-08-14 06:37:27 -04:00
|
|
|
reused_https = Connections.get_conn("https://some-domain.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
refute conn == reused_https
|
|
|
|
|
|
|
|
assert reused_https == https_conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:some-domain.com:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: ^conn,
|
|
|
|
state: :up,
|
|
|
|
waiting_pids: []
|
|
|
|
},
|
2019-08-19 08:40:06 -04:00
|
|
|
"https:some-domain.com:443" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: ^https_conn,
|
|
|
|
state: :up,
|
|
|
|
waiting_pids: []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "process gun_down message", %{name: name, pid: pid} do
|
2019-08-14 06:37:27 -04:00
|
|
|
conn = Connections.get_conn("http://gun_down.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
refute conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:gun_down.com:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: _,
|
|
|
|
state: :down,
|
|
|
|
waiting_pids: _
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "process gun_down message and then gun_up", %{name: name, pid: pid} do
|
2019-08-14 06:37:27 -04:00
|
|
|
conn = Connections.get_conn("http://gun_down_and_up.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
refute conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:gun_down_and_up.com:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: _,
|
|
|
|
state: :down,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: _,
|
|
|
|
used: 0
|
2019-08-13 07:37:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
|
2019-08-14 06:37:27 -04:00
|
|
|
conn = Connections.get_conn("http://gun_down_and_up.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
assert is_pid(conn)
|
|
|
|
assert Process.alive?(conn)
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:gun_down_and_up.com:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: _,
|
|
|
|
state: :up,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: [],
|
|
|
|
used: 2
|
2019-08-13 07:37:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "async processes get same conn for same domain", %{name: name, pid: pid} do
|
|
|
|
tasks =
|
|
|
|
for _ <- 1..5 do
|
|
|
|
Task.async(fn ->
|
2019-08-14 06:37:27 -04:00
|
|
|
Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
tasks_with_results = Task.yield_many(tasks)
|
|
|
|
|
|
|
|
results =
|
|
|
|
Enum.map(tasks_with_results, fn {task, res} ->
|
|
|
|
res || Task.shutdown(task, :brutal_kill)
|
|
|
|
end)
|
|
|
|
|
|
|
|
conns = for {:ok, value} <- results, do: value
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:some-domain.com:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: conn,
|
|
|
|
state: :up,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: [],
|
|
|
|
used: 5
|
2019-08-13 07:37:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
|
|
|
|
assert Enum.all?(conns, fn res -> res == conn end)
|
|
|
|
end
|
|
|
|
|
2019-08-19 08:40:06 -04:00
|
|
|
test "remove frequently used", %{name: name, pid: pid} do
|
|
|
|
Connections.get_conn("https://some-domain.com", [genserver_pid: pid], name)
|
|
|
|
|
|
|
|
for _ <- 1..4 do
|
|
|
|
Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name)
|
|
|
|
end
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
|
|
|
"http:some-domain.com:80" => %Conn{
|
|
|
|
conn: _,
|
|
|
|
state: :up,
|
|
|
|
waiting_pids: [],
|
|
|
|
used: 4
|
|
|
|
},
|
|
|
|
"https:some-domain.com:443" => %Conn{
|
|
|
|
conn: _,
|
|
|
|
state: :up,
|
|
|
|
waiting_pids: [],
|
|
|
|
used: 1
|
|
|
|
}
|
|
|
|
},
|
|
|
|
opts: [max_connections: 2, timeout: 10]
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
|
|
|
|
conn = Connections.get_conn("http://another-domain.com", [genserver_pid: pid], name)
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
|
|
|
"http:another-domain.com:80" => %Conn{
|
|
|
|
conn: ^conn,
|
|
|
|
state: :up,
|
|
|
|
waiting_pids: [],
|
|
|
|
used: 1
|
|
|
|
},
|
|
|
|
"http:some-domain.com:80" => %Conn{
|
|
|
|
conn: _,
|
|
|
|
state: :up,
|
|
|
|
waiting_pids: [],
|
|
|
|
used: 4
|
|
|
|
}
|
|
|
|
},
|
|
|
|
opts: [max_connections: 2, timeout: 10]
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
|
|
|
|
2019-08-13 07:37:19 -04:00
|
|
|
describe "integration test" do
|
|
|
|
@describetag :integration
|
|
|
|
|
|
|
|
test "opens connection and reuse it on next request", %{name: name} do
|
|
|
|
api = Pleroma.Config.get([API])
|
2019-08-16 09:45:50 -04:00
|
|
|
Pleroma.Config.put([API], API.Gun)
|
2019-08-13 07:37:19 -04:00
|
|
|
on_exit(fn -> Pleroma.Config.put([API], api) end)
|
2019-08-14 06:37:27 -04:00
|
|
|
conn = Connections.get_conn("http://httpbin.org", [], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
assert is_pid(conn)
|
|
|
|
assert Process.alive?(conn)
|
|
|
|
|
2019-08-14 06:37:27 -04:00
|
|
|
reused_conn = Connections.get_conn("http://httpbin.org", [], name)
|
2019-08-13 07:37:19 -04:00
|
|
|
|
|
|
|
assert conn == reused_conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"http:httpbin.org:80" => %Conn{
|
2019-08-13 07:37:19 -04:00
|
|
|
conn: ^conn,
|
|
|
|
state: :up,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: [],
|
|
|
|
used: 2
|
2019-08-13 07:37:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
2019-08-14 07:27:55 -04:00
|
|
|
|
|
|
|
test "opens ssl connection and reuse it on next request", %{name: name} do
|
|
|
|
api = Pleroma.Config.get([API])
|
2019-08-16 09:45:50 -04:00
|
|
|
Pleroma.Config.put([API], API.Gun)
|
2019-08-14 07:27:55 -04:00
|
|
|
on_exit(fn -> Pleroma.Config.put([API], api) end)
|
|
|
|
conn = Connections.get_conn("https://httpbin.org", [], name)
|
|
|
|
|
|
|
|
assert is_pid(conn)
|
|
|
|
assert Process.alive?(conn)
|
|
|
|
|
|
|
|
reused_conn = Connections.get_conn("https://httpbin.org", [], name)
|
|
|
|
|
|
|
|
assert conn == reused_conn
|
|
|
|
|
|
|
|
%Connections{
|
|
|
|
conns: %{
|
2019-08-19 08:40:06 -04:00
|
|
|
"https:httpbin.org:443" => %Conn{
|
2019-08-14 07:27:55 -04:00
|
|
|
conn: ^conn,
|
|
|
|
state: :up,
|
2019-08-19 08:40:06 -04:00
|
|
|
waiting_pids: [],
|
|
|
|
used: 2
|
2019-08-14 07:27:55 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} = Connections.get_state(name)
|
|
|
|
end
|
2019-08-13 07:37:19 -04:00
|
|
|
end
|
|
|
|
end
|