S3 Test: Remove global state dependencies

This commit is contained in:
Lain Soykaf 2023-12-11 09:25:05 +04:00
parent 0e005acd44
commit 90a47ca050
5 changed files with 81 additions and 43 deletions

View File

@ -147,6 +147,9 @@ config :pleroma, Pleroma.PromEx, disabled: true
# Mox definitions. Only read during compile time. # Mox definitions. Only read during compile time.
config :pleroma, Pleroma.User.Backup, config_impl: Pleroma.UnstubbedConfigMock config :pleroma, Pleroma.User.Backup, config_impl: Pleroma.UnstubbedConfigMock
config :pleroma, Pleroma.Uploaders.S3, ex_aws_impl: Pleroma.Uploaders.S3.ExAwsMock
config :pleroma, Pleroma.Uploaders.S3, config_impl: Pleroma.UnstubbedConfigMock
config :pleroma, Pleroma.Upload, config_impl: Pleroma.UnstubbedConfigMock
if File.exists?("./config/test.secret.exs") do if File.exists?("./config/test.secret.exs") do
import_config "test.secret.exs" import_config "test.secret.exs"

View File

@ -34,7 +34,6 @@ defmodule Pleroma.Upload do
""" """
alias Ecto.UUID alias Ecto.UUID
alias Pleroma.Config
alias Pleroma.Maps alias Pleroma.Maps
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
require Logger require Logger
@ -76,6 +75,8 @@ defmodule Pleroma.Upload do
:path :path
] ]
@config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
defp get_description(upload) do defp get_description(upload) do
case {upload.description, Pleroma.Config.get([Pleroma.Upload, :default_description])} do case {upload.description, Pleroma.Config.get([Pleroma.Upload, :default_description])} do
{description, _} when is_binary(description) -> description {description, _} when is_binary(description) -> description
@ -244,18 +245,18 @@ defmodule Pleroma.Upload do
defp url_from_spec(_upload, _base_url, {:url, url}), do: url defp url_from_spec(_upload, _base_url, {:url, url}), do: url
def base_url do def base_url do
uploader = Config.get([Pleroma.Upload, :uploader]) uploader = @config_impl.get([Pleroma.Upload, :uploader])
upload_base_url = Config.get([Pleroma.Upload, :base_url]) upload_base_url = @config_impl.get([Pleroma.Upload, :base_url])
public_endpoint = Config.get([uploader, :public_endpoint]) public_endpoint = @config_impl.get([uploader, :public_endpoint])
case uploader do case uploader do
Pleroma.Uploaders.Local -> Pleroma.Uploaders.Local ->
upload_base_url || Pleroma.Web.Endpoint.url() <> "/media/" upload_base_url || Pleroma.Web.Endpoint.url() <> "/media/"
Pleroma.Uploaders.S3 -> Pleroma.Uploaders.S3 ->
bucket = Config.get([Pleroma.Uploaders.S3, :bucket]) bucket = @config_impl.get([Pleroma.Uploaders.S3, :bucket])
truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace]) truncated_namespace = @config_impl.get([Pleroma.Uploaders.S3, :truncated_namespace])
namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace]) namespace = @config_impl.get([Pleroma.Uploaders.S3, :bucket_namespace])
bucket_with_namespace = bucket_with_namespace =
cond do cond do

View File

@ -6,7 +6,8 @@ defmodule Pleroma.Uploaders.S3 do
@behaviour Pleroma.Uploaders.Uploader @behaviour Pleroma.Uploaders.Uploader
require Logger require Logger
alias Pleroma.Config @ex_aws_impl Application.compile_env(:pleroma, [__MODULE__, :ex_aws_impl], ExAws)
@config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
# The file name is re-encoded with S3's constraints here to comply with previous # The file name is re-encoded with S3's constraints here to comply with previous
# links with less strict filenames # links with less strict filenames
@ -22,7 +23,7 @@ defmodule Pleroma.Uploaders.S3 do
@impl true @impl true
def put_file(%Pleroma.Upload{} = upload) do def put_file(%Pleroma.Upload{} = upload) do
config = Config.get([__MODULE__]) config = @config_impl.get([__MODULE__])
bucket = Keyword.get(config, :bucket) bucket = Keyword.get(config, :bucket)
streaming = Keyword.get(config, :streaming_enabled) streaming = Keyword.get(config, :streaming_enabled)
@ -56,7 +57,7 @@ defmodule Pleroma.Uploaders.S3 do
]) ])
end end
case ExAws.request(op) do case @ex_aws_impl.request(op) do
{:ok, _} -> {:ok, _} ->
{:ok, {:file, s3_name}} {:ok, {:file, s3_name}}
@ -69,9 +70,9 @@ defmodule Pleroma.Uploaders.S3 do
@impl true @impl true
def delete_file(file) do def delete_file(file) do
[__MODULE__, :bucket] [__MODULE__, :bucket]
|> Config.get() |> @config_impl.get()
|> ExAws.S3.delete_object(file) |> ExAws.S3.delete_object(file)
|> ExAws.request() |> @ex_aws_impl.request()
|> case do |> case do
{:ok, %{status_code: 204}} -> :ok {:ok, %{status_code: 204}} -> :ok
error -> {:error, inspect(error)} error -> {:error, inspect(error)}
@ -83,3 +84,7 @@ defmodule Pleroma.Uploaders.S3 do
String.replace(name, @regex, "-") String.replace(name, @regex, "-")
end end
end end
defmodule Pleroma.Uploaders.S3.ExAwsAPI do
@callback request(op :: ExAws.Operation.t()) :: {:ok, ExAws.Operation.t()} | {:error, term()}
end

View File

@ -3,22 +3,27 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Uploaders.S3Test do defmodule Pleroma.Uploaders.S3Test do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Uploaders.S3 alias Pleroma.Uploaders.S3
alias Pleroma.Uploaders.S3.ExAwsMock
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
import Mock import Mox
import ExUnit.CaptureLog import ExUnit.CaptureLog
setup do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3)
clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com")
clear_config([Pleroma.Uploaders.S3])
clear_config([Pleroma.Uploaders.S3, :bucket], "test_bucket")
end
describe "get_file/1" do describe "get_file/1" do
test "it returns path to local folder for files" do test "it returns url for files" do
ConfigMock
|> expect(:get, 6, fn key ->
[
{Pleroma.Upload,
[uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]},
{Pleroma.Uploaders.S3, [bucket: "test_bucket"]}
]
|> get_in(key)
end)
assert S3.get_file("test_image.jpg") == { assert S3.get_file("test_image.jpg") == {
:ok, :ok,
{:url, "https://s3.amazonaws.com/test_bucket/test_image.jpg"} {:url, "https://s3.amazonaws.com/test_bucket/test_image.jpg"}
@ -26,13 +31,16 @@ defmodule Pleroma.Uploaders.S3Test do
end end
test "it returns path without bucket when truncated_namespace set to ''" do test "it returns path without bucket when truncated_namespace set to ''" do
clear_config([Pleroma.Uploaders.S3], ConfigMock
bucket: "test_bucket", |> expect(:get, 6, fn key ->
bucket_namespace: "myaccount", [
truncated_namespace: "" {Pleroma.Upload,
) [uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]},
{Pleroma.Uploaders.S3,
clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com") [bucket: "test_bucket", truncated_namespace: "", bucket_namespace: "myaccount"]}
]
|> get_in(key)
end)
assert S3.get_file("test_image.jpg") == { assert S3.get_file("test_image.jpg") == {
:ok, :ok,
@ -41,10 +49,15 @@ defmodule Pleroma.Uploaders.S3Test do
end end
test "it returns path with bucket namespace when namespace is set" do test "it returns path with bucket namespace when namespace is set" do
clear_config([Pleroma.Uploaders.S3], ConfigMock
bucket: "test_bucket", |> expect(:get, 6, fn key ->
bucket_namespace: "family" [
) {Pleroma.Upload,
[uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]},
{Pleroma.Uploaders.S3, [bucket: "test_bucket", bucket_namespace: "family"]}
]
|> get_in(key)
end)
assert S3.get_file("test_image.jpg") == { assert S3.get_file("test_image.jpg") == {
:ok, :ok,
@ -62,28 +75,42 @@ defmodule Pleroma.Uploaders.S3Test do
tempfile: Path.absname("test/instance_static/add/shortcode.png") tempfile: Path.absname("test/instance_static/add/shortcode.png")
} }
ConfigMock
|> expect(:get, fn [Pleroma.Uploaders.S3] ->
[
bucket: "test_bucket"
]
end)
[file_upload: file_upload] [file_upload: file_upload]
end end
test "save file", %{file_upload: file_upload} do test "save file", %{file_upload: file_upload} do
with_mock ExAws, request: fn _ -> {:ok, :ok} end do ExAwsMock
|> expect(:request, fn _req -> {:ok, %{status_code: 200}} end)
assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}} assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}}
end end
end
test "returns error", %{file_upload: file_upload} do test "returns error", %{file_upload: file_upload} do
with_mock ExAws, request: fn _ -> {:error, "S3 Upload failed"} end do ExAwsMock
|> expect(:request, fn _req -> {:error, "S3 Upload failed"} end)
assert capture_log(fn -> assert capture_log(fn ->
assert S3.put_file(file_upload) == {:error, "S3 Upload failed"} assert S3.put_file(file_upload) == {:error, "S3 Upload failed"}
end) =~ "Elixir.Pleroma.Uploaders.S3: {:error, \"S3 Upload failed\"}" end) =~ "Elixir.Pleroma.Uploaders.S3: {:error, \"S3 Upload failed\"}"
end end
end end
end
describe "delete_file/1" do describe "delete_file/1" do
test_with_mock "deletes file", ExAws, request: fn _req -> {:ok, %{status_code: 204}} end do test "deletes file" do
ExAwsMock
|> expect(:request, fn _req -> {:ok, %{status_code: 204}} end)
ConfigMock
|> expect(:get, fn [Pleroma.Uploaders.S3, :bucket] -> "test_bucket" end)
assert :ok = S3.delete_file("image.jpg") assert :ok = S3.delete_file("image.jpg")
assert_called(ExAws.request(:_))
end end
end end
end end

View File

@ -31,3 +31,5 @@ Mox.defmock(Pleroma.UnstubbedConfigMock, for: Pleroma.Config.Getting)
Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging) Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging)
Mox.defmock(Pleroma.User.Backup.ProcessorMock, for: Pleroma.User.Backup.ProcessorAPI) Mox.defmock(Pleroma.User.Backup.ProcessorMock, for: Pleroma.User.Backup.ProcessorAPI)
Mox.defmock(Pleroma.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI)