diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/pleroma/config/deprecation_warnings_test.exs | 44 | ||||
-rw-r--r-- | test/pleroma/gun/connection_pool_test.exs | 100 | ||||
-rw-r--r-- | test/pleroma/reverse_proxy_test.exs | 320 | ||||
-rw-r--r-- | test/test_helper.exs | 3 |
4 files changed, 122 insertions, 345 deletions
diff --git a/test/pleroma/config/deprecation_warnings_test.exs b/test/pleroma/config/deprecation_warnings_test.exs index f3453ddb0..55d03b70f 100644 --- a/test/pleroma/config/deprecation_warnings_test.exs +++ b/test/pleroma/config/deprecation_warnings_test.exs @@ -336,50 +336,6 @@ defmodule Pleroma.Config.DeprecationWarningsTest do "Your config is using the old setting for controlling the URL of media uploaded to your S3 bucket." end - describe "check_gun_pool_options/0" do - test "await_up_timeout" do - config = Config.get(:connections_pool) - clear_config(:connections_pool, Keyword.put(config, :await_up_timeout, 5_000)) - - assert capture_log(fn -> - DeprecationWarnings.check_gun_pool_options() - end) =~ - "Your config is using old setting `config :pleroma, :connections_pool, await_up_timeout`." - end - - test "pool timeout" do - old_config = [ - federation: [ - size: 50, - max_waiting: 10, - timeout: 10_000 - ], - media: [ - size: 50, - max_waiting: 10, - timeout: 10_000 - ], - upload: [ - size: 25, - max_waiting: 5, - timeout: 15_000 - ], - default: [ - size: 10, - max_waiting: 2, - timeout: 5_000 - ] - ] - - clear_config(:pools, old_config) - - assert capture_log(fn -> - DeprecationWarnings.check_gun_pool_options() - end) =~ - "Your config is using old setting name `timeout` instead of `recv_timeout` in pool settings" - end - end - test "check_old_chat_shoutbox/0" do clear_config([:instance, :chat_limit], 1_000) clear_config([:chat, :enabled], true) diff --git a/test/pleroma/gun/connection_pool_test.exs b/test/pleroma/gun/connection_pool_test.exs deleted file mode 100644 index e0c9e9904..000000000 --- a/test/pleroma/gun/connection_pool_test.exs +++ /dev/null @@ -1,100 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Gun.ConnectionPoolTest do - use Pleroma.DataCase - - import Mox - import ExUnit.CaptureLog - alias Pleroma.Gun.ConnectionPool - - defp gun_mock(_) do - Pleroma.GunMock - |> stub(:open, fn _, _, _ -> Task.start_link(fn -> Process.sleep(100) end) end) - |> stub(:await_up, fn _, _ -> {:ok, :http} end) - |> stub(:set_owner, fn _, _ -> :ok end) - - :ok - end - - setup :gun_mock - - test "gives the same connection to 2 concurrent requests" do - Enum.map( - [ - "http://www.korean-books.com.kp/KBMbooks/en/periodic/pictorial/20200530163914.pdf", - "http://www.korean-books.com.kp/KBMbooks/en/periodic/pictorial/20200528183427.pdf" - ], - fn uri -> - uri = URI.parse(uri) - task_parent = self() - - Task.start_link(fn -> - {:ok, conn} = ConnectionPool.get_conn(uri, []) - ConnectionPool.release_conn(conn) - send(task_parent, conn) - end) - end - ) - - [pid, pid] = - for _ <- 1..2 do - receive do - pid -> pid - end - end - end - - @tag :erratic - test "connection limit is respected with concurrent requests" do - clear_config([:connections_pool, :max_connections]) do - clear_config([:connections_pool, :max_connections], 1) - # The supervisor needs a reboot to apply the new config setting - Process.exit(Process.whereis(Pleroma.Gun.ConnectionPool.WorkerSupervisor), :kill) - - on_exit(fn -> - Process.exit(Process.whereis(Pleroma.Gun.ConnectionPool.WorkerSupervisor), :kill) - end) - end - - capture_log(fn -> - Enum.map( - [ - "https://ninenines.eu/", - "https://youtu.be/PFGwMiDJKNY" - ], - fn uri -> - uri = URI.parse(uri) - task_parent = self() - - Task.start_link(fn -> - result = ConnectionPool.get_conn(uri, []) - # Sleep so that we don't end up with a situation, - # where request from the second process gets processed - # only after the first process already released the connection - Process.sleep(50) - - case result do - {:ok, pid} -> - ConnectionPool.release_conn(pid) - - _ -> - nil - end - - send(task_parent, result) - end) - end - ) - - [{:error, :pool_full}, {:ok, _pid}] = - for _ <- 1..2 do - receive do - result -> result - end - end - |> Enum.sort() - end) - end -end diff --git a/test/pleroma/reverse_proxy_test.exs b/test/pleroma/reverse_proxy_test.exs index 0bd4db8d1..aa52ad561 100644 --- a/test/pleroma/reverse_proxy_test.exs +++ b/test/pleroma/reverse_proxy_test.exs @@ -5,112 +5,57 @@ defmodule Pleroma.ReverseProxyTest do use Pleroma.Web.ConnCase import ExUnit.CaptureLog - import Mox alias Pleroma.ReverseProxy - alias Pleroma.ReverseProxy.ClientMock alias Plug.Conn - setup_all do - {:ok, _} = Registry.start_link(keys: :unique, name: ClientMock) - :ok - end - - setup :verify_on_exit! - - defp request_mock(invokes) do - ClientMock - |> expect(:request, fn :get, url, headers, _body, _opts -> - Registry.register(ClientMock, url, 0) - body = headers |> Enum.into(%{}) |> Jason.encode!() - - {:ok, 200, - [ - {"content-type", "application/json"}, - {"content-length", byte_size(body) |> to_string()} - ], %{url: url, body: body}} - end) - |> expect(:stream_body, invokes, fn %{url: url, body: body} = client -> - case Registry.lookup(ClientMock, url) do - [{_, 0}] -> - Registry.update_value(ClientMock, url, &(&1 + 1)) - {:ok, body, client} - - [{_, 1}] -> - Registry.unregister(ClientMock, url) - :done - end - end) - end - describe "reverse proxy" do test "do not track successful request", %{conn: conn} do - request_mock(2) url = "/success" + Tesla.Mock.mock(fn %{url: ^url} -> + %Tesla.Env{ + status: 200, + body: "" + } + end) + conn = ReverseProxy.call(conn, url) - assert conn.status == 200 + assert response(conn, 200) assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, nil} end - end - - test "use Pleroma's user agent in the request; don't pass the client's", %{conn: conn} do - request_mock(2) - - conn = - conn - |> Plug.Conn.put_req_header("user-agent", "fake/1.0") - |> ReverseProxy.call("/user-agent") - assert json_response(conn, 200) == %{"user-agent" => Pleroma.Application.user_agent()} - end - - test "closed connection", %{conn: conn} do - ClientMock - |> expect(:request, fn :get, "/closed", _, _, _ -> {:ok, 200, [], %{}} end) - |> expect(:stream_body, fn _ -> {:error, :closed} end) - |> expect(:close, fn _ -> :ok end) - - conn = ReverseProxy.call(conn, "/closed") - assert conn.halted - end + test "use Pleroma's user agent in the request; don't pass the client's", %{conn: conn} do + clear_config([:http, :send_user_agent], true) + # Mock will fail if the client's user agent isn't filtered + wanted_headers = [{"user-agent", Pleroma.Application.user_agent()}] - defp stream_mock(invokes, with_close? \\ false) do - ClientMock - |> expect(:request, fn :get, "/stream-bytes/" <> length, _, _, _ -> - Registry.register(ClientMock, "/stream-bytes/" <> length, 0) + Tesla.Mock.mock(fn %{url: "/user-agent", headers: ^wanted_headers} -> + %Tesla.Env{ + status: 200, + body: "" + } + end) - {:ok, 200, [{"content-type", "application/octet-stream"}], - %{url: "/stream-bytes/" <> length}} - end) - |> expect(:stream_body, invokes, fn %{url: "/stream-bytes/" <> length} = client -> - max = String.to_integer(length) - - case Registry.lookup(ClientMock, "/stream-bytes/" <> length) do - [{_, current}] when current < max -> - Registry.update_value( - ClientMock, - "/stream-bytes/" <> length, - &(&1 + 10) - ) - - {:ok, "0123456789", client} - - [{_, ^max}] -> - Registry.unregister(ClientMock, "/stream-bytes/" <> length) - :done - end - end) + conn = + conn + |> Plug.Conn.put_req_header("user-agent", "fake/1.0") + |> ReverseProxy.call("/user-agent") - if with_close? do - expect(ClientMock, :close, fn _ -> :ok end) + assert response(conn, 200) end end describe "max_body" do test "length returns error if content-length more than option", %{conn: conn} do - request_mock(0) + Tesla.Mock.mock(fn %{url: "/huge-file"} -> + %Tesla.Env{ + status: 200, + headers: [{"content-length", "100"}], + body: "This body is too large." + } + end) assert capture_log(fn -> ReverseProxy.call(conn, "/huge-file", max_body_length: 4) @@ -123,22 +68,16 @@ defmodule Pleroma.ReverseProxyTest do ReverseProxy.call(conn, "/huge-file", max_body_length: 4) end) == "" end - - test "max_body_length returns error if streaming body more than that option", %{conn: conn} do - stream_mock(3, true) - - assert capture_log(fn -> - ReverseProxy.call(conn, "/stream-bytes/50", max_body_length: 30) - end) =~ - "Elixir.Pleroma.ReverseProxy request to /stream-bytes/50 failed while reading/chunking: :body_too_large" - end end describe "HEAD requests" do test "common", %{conn: conn} do - ClientMock - |> expect(:request, fn :head, "/head", _, _, _ -> - {:ok, 200, [{"content-type", "text/html; charset=utf-8"}]} + Tesla.Mock.mock(fn %{method: :head, url: "/head"} -> + %Tesla.Env{ + status: 200, + headers: [{"content-type", "text/html; charset=utf-8"}], + body: "" + } end) conn = ReverseProxy.call(Map.put(conn, :method, "HEAD"), "/head") @@ -146,18 +85,17 @@ defmodule Pleroma.ReverseProxyTest do end end - defp error_mock(status) when is_integer(status) do - ClientMock - |> expect(:request, fn :get, "/status/" <> _, _, _, _ -> - {:error, status} - end) - end - describe "returns error on" do test "500", %{conn: conn} do - error_mock(500) url = "/status/500" + Tesla.Mock.mock(fn %{url: ^url} -> + %Tesla.Env{ + status: 500, + body: "" + } + end) + capture_log(fn -> ReverseProxy.call(conn, url) end) =~ "[error] Elixir.Pleroma.ReverseProxy: request to /status/500 failed with HTTP status 500" @@ -168,9 +106,15 @@ defmodule Pleroma.ReverseProxyTest do end test "400", %{conn: conn} do - error_mock(400) url = "/status/400" + Tesla.Mock.mock(fn %{url: ^url} -> + %Tesla.Env{ + status: 400, + body: "" + } + end) + capture_log(fn -> ReverseProxy.call(conn, url) end) =~ "[error] Elixir.Pleroma.ReverseProxy: request to /status/400 failed with HTTP status 400" @@ -179,9 +123,15 @@ defmodule Pleroma.ReverseProxyTest do end test "403", %{conn: conn} do - error_mock(403) url = "/status/403" + Tesla.Mock.mock(fn %{url: ^url} -> + %Tesla.Env{ + status: 403, + body: "" + } + end) + capture_log(fn -> ReverseProxy.call(conn, url, failed_request_ttl: :timer.seconds(120)) end) =~ @@ -190,57 +140,17 @@ defmodule Pleroma.ReverseProxyTest do {:ok, ttl} = Cachex.ttl(:failed_proxy_url_cache, url) assert ttl > 100_000 end - - test "204", %{conn: conn} do - url = "/status/204" - expect(ClientMock, :request, fn :get, _url, _, _, _ -> {:ok, 204, [], %{}} end) - - capture_log(fn -> - conn = ReverseProxy.call(conn, url) - assert conn.resp_body == "Request failed: No Content" - assert conn.halted - end) =~ - "[error] Elixir.Pleroma.ReverseProxy: request to \"/status/204\" failed with HTTP status 204" - - assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true} - assert Cachex.ttl(:failed_proxy_url_cache, url) == {:ok, nil} - end - end - - test "streaming", %{conn: conn} do - stream_mock(21) - conn = ReverseProxy.call(conn, "/stream-bytes/200") - assert conn.state == :chunked - assert byte_size(conn.resp_body) == 200 - assert Conn.get_resp_header(conn, "content-type") == ["application/octet-stream"] - end - - defp headers_mock(_) do - ClientMock - |> expect(:request, fn :get, "/headers", headers, _, _ -> - Registry.register(ClientMock, "/headers", 0) - {:ok, 200, [{"content-type", "application/json"}], %{url: "/headers", headers: headers}} - end) - |> expect(:stream_body, 2, fn %{url: url, headers: headers} = client -> - case Registry.lookup(ClientMock, url) do - [{_, 0}] -> - Registry.update_value(ClientMock, url, &(&1 + 1)) - headers = for {k, v} <- headers, into: %{}, do: {String.capitalize(k), v} - {:ok, Jason.encode!(%{headers: headers}), client} - - [{_, 1}] -> - Registry.unregister(ClientMock, url) - :done - end - end) - - :ok end describe "keep request headers" do - setup [:headers_mock] - test "header passes", %{conn: conn} do + Tesla.Mock.mock(fn %{url: "/headers"} -> + %Tesla.Env{ + status: 200, + body: "" + } + end) + conn = Conn.put_req_header( conn, @@ -249,68 +159,76 @@ defmodule Pleroma.ReverseProxyTest do ) |> ReverseProxy.call("/headers") - %{"headers" => headers} = json_response(conn, 200) - assert headers["Accept"] == "text/html" + assert response(conn, 200) + assert {"accept", "text/html"} in conn.req_headers end test "header is filtered", %{conn: conn} do + # Mock will fail if the accept-language header isn't filtered + wanted_headers = [{"accept-encoding", "*"}] + + Tesla.Mock.mock(fn %{url: "/headers", headers: ^wanted_headers} -> + %Tesla.Env{ + status: 200, + body: "" + } + end) + conn = - Conn.put_req_header( - conn, - "accept-language", - "en-US" - ) + conn + |> Conn.put_req_header("accept-language", "en-US") + |> Conn.put_req_header("accept-encoding", "*") |> ReverseProxy.call("/headers") - %{"headers" => headers} = json_response(conn, 200) - refute headers["Accept-Language"] + assert response(conn, 200) end end test "returns 400 on non GET, HEAD requests", %{conn: conn} do + Tesla.Mock.mock(fn %{url: "/ip"} -> + %Tesla.Env{ + status: 200, + body: "" + } + end) + conn = ReverseProxy.call(Map.put(conn, :method, "POST"), "/ip") - assert conn.status == 400 + assert response(conn, 400) end - describe "cache resp headers" do + describe "cache resp headers not filtered" do test "add cache-control", %{conn: conn} do - ClientMock - |> expect(:request, fn :get, "/cache", _, _, _ -> - {:ok, 200, [{"ETag", "some ETag"}], %{}} + Tesla.Mock.mock(fn %{url: "/cache"} -> + %Tesla.Env{ + status: 200, + headers: [ + {"cache-control", "public, max-age=1209600"}, + {"etag", "some ETag"}, + {"expires", "Wed, 21 Oct 2015 07:28:00 GMT"} + ], + body: "" + } end) - |> expect(:stream_body, fn _ -> :done end) conn = ReverseProxy.call(conn, "/cache") assert {"cache-control", "public, max-age=1209600"} in conn.resp_headers + assert {"etag", "some ETag"} in conn.resp_headers + assert {"expires", "Wed, 21 Oct 2015 07:28:00 GMT"} in conn.resp_headers end end - defp disposition_headers_mock(headers) do - ClientMock - |> expect(:request, fn :get, "/disposition", _, _, _ -> - Registry.register(ClientMock, "/disposition", 0) - - {:ok, 200, headers, %{url: "/disposition"}} - end) - |> expect(:stream_body, 2, fn %{url: "/disposition"} = client -> - case Registry.lookup(ClientMock, "/disposition") do - [{_, 0}] -> - Registry.update_value(ClientMock, "/disposition", &(&1 + 1)) - {:ok, "", client} - - [{_, 1}] -> - Registry.unregister(ClientMock, "/disposition") - :done - end - end) - end - describe "response content disposition header" do - test "not atachment", %{conn: conn} do - disposition_headers_mock([ - {"content-type", "image/gif"}, - {"content-length", "0"} - ]) + test "not attachment", %{conn: conn} do + Tesla.Mock.mock(fn %{url: "/disposition"} -> + %Tesla.Env{ + status: 200, + headers: [ + {"content-type", "image/gif"}, + {"content-length", "0"} + ], + body: "" + } + end) conn = ReverseProxy.call(conn, "/disposition") @@ -318,10 +236,16 @@ defmodule Pleroma.ReverseProxyTest do end test "with content-disposition header", %{conn: conn} do - disposition_headers_mock([ - {"content-disposition", "attachment; filename=\"filename.jpg\""}, - {"content-length", "0"} - ]) + Tesla.Mock.mock(fn %{url: "/disposition"} -> + %Tesla.Env{ + status: 200, + headers: [ + {"content-disposition", "attachment; filename=\"filename.jpg\""}, + {"content-length", "0"} + ], + body: "" + } + end) conn = ReverseProxy.call(conn, "/disposition") diff --git a/test/test_helper.exs b/test/test_helper.exs index 60a61484f..d2016ff53 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -7,9 +7,6 @@ ExUnit.start(exclude: [:federated, :erratic] ++ os_exclude) Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual) -Mox.defmock(Pleroma.ReverseProxy.ClientMock, for: Pleroma.ReverseProxy.Client) -Mox.defmock(Pleroma.GunMock, for: Pleroma.Gun) - {:ok, _} = Application.ensure_all_started(:ex_machina) ExUnit.after_suite(fn _results -> |