6af8be15d0cdacfc98df2b655c84b912fbaa56ce
[akkoma] / test / http / adapter_helper / gun_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.HTTP.AdapterHelper.GunTest do
6 use ExUnit.Case, async: true
7 use Pleroma.Tests.Helpers
8
9 import ExUnit.CaptureLog
10 import Mox
11
12 alias Pleroma.Config
13 alias Pleroma.Gun.Conn
14 alias Pleroma.HTTP.AdapterHelper.Gun
15 alias Pleroma.Pool.Connections
16
17 setup :verify_on_exit!
18
19 defp gun_mock(_) do
20 gun_mock()
21 :ok
22 end
23
24 defp gun_mock do
25 Pleroma.GunMock
26 |> stub(:open, fn _, _, _ -> Task.start_link(fn -> Process.sleep(1000) end) end)
27 |> stub(:await_up, fn _, _ -> {:ok, :http} end)
28 |> stub(:set_owner, fn _, _ -> :ok end)
29 end
30
31 describe "options/1" do
32 clear_config([:http, :adapter]) do
33 Config.put([:http, :adapter], a: 1, b: 2)
34 end
35
36 test "https url with default port" do
37 uri = URI.parse("https://example.com")
38
39 opts = Gun.options([receive_conn: false], uri)
40 assert opts[:certificates_verification]
41 assert opts[:tls_opts][:log_level] == :warning
42 end
43
44 test "https ipv4 with default port" do
45 uri = URI.parse("https://127.0.0.1")
46
47 opts = Gun.options([receive_conn: false], uri)
48 assert opts[:certificates_verification]
49 assert opts[:tls_opts][:log_level] == :warning
50 end
51
52 test "https ipv6 with default port" do
53 uri = URI.parse("https://[2a03:2880:f10c:83:face:b00c:0:25de]")
54
55 opts = Gun.options([receive_conn: false], uri)
56 assert opts[:certificates_verification]
57 assert opts[:tls_opts][:log_level] == :warning
58 end
59
60 test "https url with non standart port" do
61 uri = URI.parse("https://example.com:115")
62
63 opts = Gun.options([receive_conn: false], uri)
64
65 assert opts[:certificates_verification]
66 assert opts[:transport] == :tls
67 end
68
69 test "get conn on next request" do
70 gun_mock()
71 level = Application.get_env(:logger, :level)
72 Logger.configure(level: :debug)
73 on_exit(fn -> Logger.configure(level: level) end)
74 uri = URI.parse("http://some-domain2.com")
75
76 assert capture_log(fn ->
77 opts = Gun.options(uri)
78
79 assert opts[:conn] == nil
80 assert opts[:close_conn] == nil
81 end) =~
82 "Gun connections pool checkin was not successful. Trying to open conn for next request."
83
84 opts = Gun.options(uri)
85
86 assert is_pid(opts[:conn])
87 assert opts[:close_conn] == false
88 end
89
90 test "merges with defaul http adapter config" do
91 defaults = Gun.options([receive_conn: false], URI.parse("https://example.com"))
92 assert Keyword.has_key?(defaults, :a)
93 assert Keyword.has_key?(defaults, :b)
94 end
95
96 test "default ssl adapter opts with connection" do
97 gun_mock()
98 uri = URI.parse("https://some-domain.com")
99
100 :ok = Conn.open(uri, :gun_connections)
101
102 opts = Gun.options(uri)
103
104 assert opts[:certificates_verification]
105 refute opts[:tls_opts] == []
106
107 assert opts[:close_conn] == false
108 assert is_pid(opts[:conn])
109 end
110
111 test "parses string proxy host & port" do
112 proxy = Config.get([:http, :proxy_url])
113 Config.put([:http, :proxy_url], "localhost:8123")
114 on_exit(fn -> Config.put([:http, :proxy_url], proxy) end)
115
116 uri = URI.parse("https://some-domain.com")
117 opts = Gun.options([receive_conn: false], uri)
118 assert opts[:proxy] == {'localhost', 8123}
119 end
120
121 test "parses tuple proxy scheme host and port" do
122 proxy = Config.get([:http, :proxy_url])
123 Config.put([:http, :proxy_url], {:socks, 'localhost', 1234})
124 on_exit(fn -> Config.put([:http, :proxy_url], proxy) end)
125
126 uri = URI.parse("https://some-domain.com")
127 opts = Gun.options([receive_conn: false], uri)
128 assert opts[:proxy] == {:socks, 'localhost', 1234}
129 end
130
131 test "passed opts have more weight than defaults" do
132 proxy = Config.get([:http, :proxy_url])
133 Config.put([:http, :proxy_url], {:socks5, 'localhost', 1234})
134 on_exit(fn -> Config.put([:http, :proxy_url], proxy) end)
135 uri = URI.parse("https://some-domain.com")
136 opts = Gun.options([receive_conn: false, proxy: {'example.com', 4321}], uri)
137
138 assert opts[:proxy] == {'example.com', 4321}
139 end
140 end
141
142 describe "options/1 with receive_conn parameter" do
143 setup :gun_mock
144
145 test "receive conn by default" do
146 uri = URI.parse("http://another-domain.com")
147 :ok = Conn.open(uri, :gun_connections)
148
149 received_opts = Gun.options(uri)
150 assert received_opts[:close_conn] == false
151 assert is_pid(received_opts[:conn])
152 end
153
154 test "don't receive conn if receive_conn is false" do
155 uri = URI.parse("http://another-domain.com")
156 :ok = Conn.open(uri, :gun_connections)
157
158 opts = [receive_conn: false]
159 received_opts = Gun.options(opts, uri)
160 assert received_opts[:close_conn] == nil
161 assert received_opts[:conn] == nil
162 end
163 end
164
165 describe "after_request/1" do
166 setup :gun_mock
167
168 test "body_as not chunks" do
169 uri = URI.parse("http://some-domain.com")
170 :ok = Conn.open(uri, :gun_connections)
171 opts = Gun.options(uri)
172 :ok = Gun.after_request(opts)
173 conn = opts[:conn]
174
175 assert %Connections{
176 conns: %{
177 "http:some-domain.com:80" => %Pleroma.Gun.Conn{
178 conn: ^conn,
179 conn_state: :idle,
180 used_by: []
181 }
182 }
183 } = Connections.get_state(:gun_connections)
184 end
185
186 test "body_as chunks" do
187 uri = URI.parse("http://some-domain.com")
188 :ok = Conn.open(uri, :gun_connections)
189 opts = Gun.options([body_as: :chunks], uri)
190 :ok = Gun.after_request(opts)
191 conn = opts[:conn]
192 self = self()
193
194 assert %Connections{
195 conns: %{
196 "http:some-domain.com:80" => %Pleroma.Gun.Conn{
197 conn: ^conn,
198 conn_state: :active,
199 used_by: [{^self, _}]
200 }
201 }
202 } = Connections.get_state(:gun_connections)
203 end
204
205 test "with no connection" do
206 uri = URI.parse("http://uniq-domain.com")
207
208 :ok = Conn.open(uri, :gun_connections)
209
210 opts = Gun.options([body_as: :chunks], uri)
211 conn = opts[:conn]
212 opts = Keyword.delete(opts, :conn)
213 self = self()
214
215 :ok = Gun.after_request(opts)
216
217 assert %Connections{
218 conns: %{
219 "http:uniq-domain.com:80" => %Pleroma.Gun.Conn{
220 conn: ^conn,
221 conn_state: :active,
222 used_by: [{^self, _}]
223 }
224 }
225 } = Connections.get_state(:gun_connections)
226 end
227
228 test "with ipv4" do
229 uri = URI.parse("http://127.0.0.1")
230 :ok = Conn.open(uri, :gun_connections)
231 opts = Gun.options(uri)
232 :ok = Gun.after_request(opts)
233 conn = opts[:conn]
234
235 assert %Connections{
236 conns: %{
237 "http:127.0.0.1:80" => %Pleroma.Gun.Conn{
238 conn: ^conn,
239 conn_state: :idle,
240 used_by: []
241 }
242 }
243 } = Connections.get_state(:gun_connections)
244 end
245
246 test "with ipv6" do
247 uri = URI.parse("http://[2a03:2880:f10c:83:face:b00c:0:25de]")
248 :ok = Conn.open(uri, :gun_connections)
249 opts = Gun.options(uri)
250 :ok = Gun.after_request(opts)
251 conn = opts[:conn]
252
253 assert %Connections{
254 conns: %{
255 "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Pleroma.Gun.Conn{
256 conn: ^conn,
257 conn_state: :idle,
258 used_by: []
259 }
260 }
261 } = Connections.get_state(:gun_connections)
262 end
263 end
264 end