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 @@
# 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 @@ defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) 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 @@ def get_file(file) 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 @@ def put_file(%Pleroma.Upload{} = upload) 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 @@ def put_file(%Pleroma.Upload{} = upload) 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 @@ def strict_encode(name) 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 @@ test "it returns path to local folder for files" 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 @@ test "it returns path without bucket when truncated_namespace set to ''" 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 @@ test "it returns path with bucket namespace when namespace is set" 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.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)