Pipeline test: Switch from Mock to Mox.

Speeds up the test and makes it possible to run async.
This commit is contained in:
lain 2020-12-16 17:51:48 +01:00
parent 0ef0aed205
commit 5db1e6c8d3
10 changed files with 152 additions and 143 deletions

View file

@ -124,6 +124,14 @@
config :pleroma, :mrf, policies: [] config :pleroma, :mrf, policies: []
config :pleroma, :pipeline,
object_validator: Pleroma.Web.ActivityPub.ObjectValidatorMock,
mrf: Pleroma.Web.ActivityPub.MRFMock,
activity_pub: Pleroma.Web.ActivityPub.ActivityPubMock,
side_effects: Pleroma.Web.ActivityPub.SideEffectsMock,
federator: Pleroma.Web.FederatorMock,
config: Pleroma.ConfigMock
config :pleroma, :cachex, provider: Pleroma.CachexMock config :pleroma, :cachex, provider: Pleroma.CachexMock
if File.exists?("./config/test.secret.exs") do if File.exists?("./config/test.secret.exs") do

View file

@ -2,15 +2,24 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Config.Getting do
@callback get(any()) :: any()
@callback get(any(), any()) :: any()
end
defmodule Pleroma.Config do defmodule Pleroma.Config do
@behaviour Pleroma.Config.Getting
defmodule Error do defmodule Error do
defexception [:message] defexception [:message]
end end
@impl true
def get(key), do: get(key, nil) def get(key), do: get(key, nil)
@impl true
def get([key], default), do: get(key, default) def get([key], default), do: get(key, default)
@impl true
def get([_ | _] = path, default) do def get([_ | _] = path, default) do
case fetch(path) do case fetch(path) do
{:ok, value} -> value {:ok, value} -> value
@ -18,6 +27,7 @@ def get([_ | _] = path, default) do
end end
end end
@impl true
def get(key, default) do def get(key, default) do
Application.get_env(:pleroma, key, default) Application.get_env(:pleroma, key, default)
end end

View file

@ -2,6 +2,10 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ActivityPub.Persisting do
@callback persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
end
defmodule Pleroma.Web.ActivityPub.ActivityPub do defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Activity.Ir.Topics alias Pleroma.Activity.Ir.Topics
@ -32,6 +36,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
require Logger require Logger
require Pleroma.Constants require Pleroma.Constants
@behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting
defp get_recipients(%{"type" => "Create"} = data) do defp get_recipients(%{"type" => "Create"} = data) do
to = Map.get(data, "to", []) to = Map.get(data, "to", [])
cc = Map.get(data, "cc", []) cc = Map.get(data, "cc", [])
@ -85,13 +91,14 @@ defp increase_replies_count_if_reply(%{
defp increase_replies_count_if_reply(_create_data), do: :noop defp increase_replies_count_if_reply(_create_data), do: :noop
@object_types ~w[ChatMessage Question Answer Audio Video Event Article] @object_types ~w[ChatMessage Question Answer Audio Video Event Article]
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} @impl true
def persist(%{"type" => type} = object, meta) when type in @object_types do def persist(%{"type" => type} = object, meta) when type in @object_types do
with {:ok, object} <- Object.create(object) do with {:ok, object} <- Object.create(object) do
{:ok, object, meta} {:ok, object, meta}
end end
end end
@impl true
def persist(object, meta) do def persist(object, meta) do
with local <- Keyword.fetch!(meta, :local), with local <- Keyword.fetch!(meta, :local),
{recipients, _, _} <- get_recipients(object), {recipients, _, _} <- get_recipients(object),

View file

@ -2,9 +2,15 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.PipelineFiltering do
@callback pipeline_filter(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
end
defmodule Pleroma.Web.ActivityPub.MRF do defmodule Pleroma.Web.ActivityPub.MRF do
require Logger require Logger
@behaviour Pleroma.Web.ActivityPub.MRF.PipelineFiltering
@mrf_config_descriptions [ @mrf_config_descriptions [
%{ %{
group: :pleroma, group: :pleroma,
@ -70,6 +76,7 @@ def filter(policies, %{} = message) do
def filter(%{} = object), do: get_policies() |> filter(object) def filter(%{} = object), do: get_policies() |> filter(object)
@impl true
def pipeline_filter(%{} = message, meta) do def pipeline_filter(%{} = message, meta) do
object = meta[:object_data] object = meta[:object_data]
ap_id = message["object"] ap_id = message["object"]

View file

@ -2,6 +2,10 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidator.Validating do
@callback validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
end
defmodule Pleroma.Web.ActivityPub.ObjectValidator do defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@moduledoc """ @moduledoc """
This module is responsible for validating an object (which can be an activity) This module is responsible for validating an object (which can be an activity)
@ -9,6 +13,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
the system. the system.
""" """
@behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object alias Pleroma.Object
@ -32,7 +38,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()} @impl true
def validate(object, meta) def validate(object, meta)
def validate(%{"type" => type} = object, meta) def validate(%{"type" => type} = object, meta)

View file

@ -14,12 +14,19 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
@side_effects Config.get([:pipeline, :side_effects], SideEffects)
@federator Config.get([:pipeline, :federator], Federator)
@object_validator Config.get([:pipeline, :object_validator], ObjectValidator)
@mrf Config.get([:pipeline, :mrf], MRF)
@activity_pub Config.get([:pipeline, :activity_pub], ActivityPub)
@config Config.get([:pipeline, :config], Config)
@spec common_pipeline(map(), keyword()) :: @spec common_pipeline(map(), keyword()) ::
{:ok, Activity.t() | Object.t(), keyword()} | {:error, any()} {:ok, Activity.t() | Object.t(), keyword()} | {:error, any()}
def common_pipeline(object, meta) do def common_pipeline(object, meta) do
case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do
{:ok, {:ok, activity, meta}} -> {:ok, {:ok, activity, meta}} ->
SideEffects.handle_after_transaction(meta) @side_effects.handle_after_transaction(meta)
{:ok, activity, meta} {:ok, activity, meta}
{:ok, value} -> {:ok, value} ->
@ -35,13 +42,13 @@ def common_pipeline(object, meta) do
def do_common_pipeline(object, meta) do def do_common_pipeline(object, meta) do
with {_, {:ok, validated_object, meta}} <- with {_, {:ok, validated_object, meta}} <-
{:validate_object, ObjectValidator.validate(object, meta)}, {:validate_object, @object_validator.validate(object, meta)},
{_, {:ok, mrfd_object, meta}} <- {_, {:ok, mrfd_object, meta}} <-
{:mrf_object, MRF.pipeline_filter(validated_object, meta)}, {:mrf_object, @mrf.pipeline_filter(validated_object, meta)},
{_, {:ok, activity, meta}} <- {_, {:ok, activity, meta}} <-
{:persist_object, ActivityPub.persist(mrfd_object, meta)}, {:persist_object, @activity_pub.persist(mrfd_object, meta)},
{_, {:ok, activity, meta}} <- {_, {:ok, activity, meta}} <-
{:execute_side_effects, SideEffects.handle(activity, meta)}, {:execute_side_effects, @side_effects.handle(activity, meta)},
{_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do {_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do
{:ok, activity, meta} {:ok, activity, meta}
else else
@ -54,7 +61,7 @@ defp maybe_federate(%Object{}, _), do: {:ok, :not_federated}
defp maybe_federate(%Activity{} = activity, meta) do defp maybe_federate(%Activity{} = activity, meta) do
with {:ok, local} <- Keyword.fetch(meta, :local) do with {:ok, local} <- Keyword.fetch(meta, :local) do
do_not_federate = meta[:do_not_federate] || !Config.get([:instance, :federating]) do_not_federate = meta[:do_not_federate] || !@config.get([:instance, :federating])
if !do_not_federate and local and not Visibility.is_local_public?(activity) do if !do_not_federate and local and not Visibility.is_local_public?(activity) do
activity = activity =
@ -64,7 +71,7 @@ defp maybe_federate(%Activity{} = activity, meta) do
activity activity
end end
Federator.publish(activity) @federator.publish(activity)
{:ok, :federated} {:ok, :federated}
else else
{:ok, :not_federated} {:ok, :not_federated}

View file

@ -2,6 +2,11 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.SideEffects.Handling do
@callback handle(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
@callback handle_after_transaction(map()) :: map()
end
defmodule Pleroma.Web.ActivityPub.SideEffects do defmodule Pleroma.Web.ActivityPub.SideEffects do
@moduledoc """ @moduledoc """
This module looks at an inserted object and executes the side effects that it This module looks at an inserted object and executes the side effects that it
@ -29,11 +34,15 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
@cachex Pleroma.Config.get([:cachex, :provider], Cachex) @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@behaviour Pleroma.Web.ActivityPub.SideEffects.Handling
@impl true
def handle(object, meta \\ []) def handle(object, meta \\ [])
# Task this handles # Task this handles
# - Follows # - Follows
# - Sends a notification # - Sends a notification
@impl true
def handle( def handle(
%{ %{
data: %{ data: %{
@ -61,6 +70,7 @@ def handle(
# - Rejects all existing follow activities for this person # - Rejects all existing follow activities for this person
# - Updates the follow state # - Updates the follow state
# - Dismisses notification # - Dismisses notification
@impl true
def handle( def handle(
%{ %{
data: %{ data: %{
@ -87,6 +97,7 @@ def handle(
# - Follows if possible # - Follows if possible
# - Sends a notification # - Sends a notification
# - Generates accept or reject if appropriate # - Generates accept or reject if appropriate
@impl true
def handle( def handle(
%{ %{
data: %{ data: %{
@ -128,6 +139,7 @@ def handle(
# Tasks this handles: # Tasks this handles:
# - Unfollow and block # - Unfollow and block
@impl true
def handle( def handle(
%{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} = %{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} =
object, object,
@ -146,6 +158,7 @@ def handle(
# #
# For a local user, we also get a changeset with the full information, so we # For a local user, we also get a changeset with the full information, so we
# can update non-federating, non-activitypub settings as well. # can update non-federating, non-activitypub settings as well.
@impl true
def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do
if changeset = Keyword.get(meta, :user_update_changeset) do if changeset = Keyword.get(meta, :user_update_changeset) do
changeset changeset
@ -164,6 +177,7 @@ def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object,
# Tasks this handles: # Tasks this handles:
# - Add like to object # - Add like to object
# - Set up notification # - Set up notification
@impl true
def handle(%{data: %{"type" => "Like"}} = object, meta) do def handle(%{data: %{"type" => "Like"}} = object, meta) do
liked_object = Object.get_by_ap_id(object.data["object"]) liked_object = Object.get_by_ap_id(object.data["object"])
Utils.add_like_to_object(object, liked_object) Utils.add_like_to_object(object, liked_object)
@ -181,6 +195,7 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
# - Increase replies count # - Increase replies count
# - Set up ActivityExpiration # - Set up ActivityExpiration
# - Set up notifications # - Set up notifications
@impl true
def handle(%{data: %{"type" => "Create"}} = activity, meta) do def handle(%{data: %{"type" => "Create"}} = activity, meta) do
with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta), with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta),
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
@ -209,6 +224,7 @@ def handle(%{data: %{"type" => "Create"}} = activity, meta) do
# - Add announce to object # - Add announce to object
# - Set up notification # - Set up notification
# - Stream out the announce # - Stream out the announce
@impl true
def handle(%{data: %{"type" => "Announce"}} = object, meta) do def handle(%{data: %{"type" => "Announce"}} = object, meta) do
announced_object = Object.get_by_ap_id(object.data["object"]) announced_object = Object.get_by_ap_id(object.data["object"])
user = User.get_cached_by_ap_id(object.data["actor"]) user = User.get_cached_by_ap_id(object.data["actor"])
@ -226,6 +242,7 @@ def handle(%{data: %{"type" => "Announce"}} = object, meta) do
{:ok, object, meta} {:ok, object, meta}
end end
@impl true
def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do
with undone_object <- Activity.get_by_ap_id(undone_object), with undone_object <- Activity.get_by_ap_id(undone_object),
:ok <- handle_undoing(undone_object) do :ok <- handle_undoing(undone_object) do
@ -236,6 +253,7 @@ def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, met
# Tasks this handles: # Tasks this handles:
# - Add reaction to object # - Add reaction to object
# - Set up notification # - Set up notification
@impl true
def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
reacted_object = Object.get_by_ap_id(object.data["object"]) reacted_object = Object.get_by_ap_id(object.data["object"])
Utils.add_emoji_reaction_to_object(object, reacted_object) Utils.add_emoji_reaction_to_object(object, reacted_object)
@ -252,6 +270,7 @@ def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
# - Reduce the user note count # - Reduce the user note count
# - Reduce the reply count # - Reduce the reply count
# - Stream out the activity # - Stream out the activity
@impl true
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
deleted_object = deleted_object =
Object.normalize(deleted_object, false) || Object.normalize(deleted_object, false) ||
@ -297,6 +316,7 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object,
end end
# Nothing to do # Nothing to do
@impl true
def handle(object, meta) do def handle(object, meta) do
{:ok, object, meta} {:ok, object, meta}
end end
@ -441,6 +461,7 @@ defp add_notifications(meta, notifications) do
|> Keyword.put(:notifications, notifications ++ existing) |> Keyword.put(:notifications, notifications ++ existing)
end end
@impl true
def handle_after_transaction(meta) do def handle_after_transaction(meta) do
meta meta
|> send_notifications() |> send_notifications()

View file

@ -2,6 +2,10 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Federator.Publishing do
@callback publish(map()) :: any()
end
defmodule Pleroma.Web.Federator do defmodule Pleroma.Web.Federator do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Object.Containment alias Pleroma.Object.Containment
@ -15,6 +19,8 @@ defmodule Pleroma.Web.Federator do
require Logger require Logger
@behaviour Pleroma.Web.Federator.Publishing
@doc """ @doc """
Returns `true` if the distance to target object does not exceed max configured value. Returns `true` if the distance to target object does not exceed max configured value.
Serves to prevent fetching of very long threads, especially useful on smaller instances. Serves to prevent fetching of very long threads, especially useful on smaller instances.
@ -39,10 +45,12 @@ def incoming_ap_doc(params) do
ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params}) ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params})
end end
@impl true
def publish(%{id: "pleroma:fakeid"} = activity) do def publish(%{id: "pleroma:fakeid"} = activity) do
perform(:publish, activity) perform(:publish, activity)
end end
@impl true
def publish(activity) do def publish(activity) do
PublisherWorker.enqueue("publish", %{"activity_id" => activity.id}) PublisherWorker.enqueue("publish", %{"activity_id" => activity.id})
end end

View file

@ -3,14 +3,35 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.PipelineTest do defmodule Pleroma.Web.ActivityPub.PipelineTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Mock import Mox
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Web.ActivityPub.ActivityPubMock
alias Pleroma.Web.ActivityPub.MRFMock
alias Pleroma.Web.ActivityPub.ObjectValidatorMock
alias Pleroma.Web.ActivityPub.SideEffectsMock
alias Pleroma.Web.FederatorMock
alias Pleroma.ConfigMock
setup :verify_on_exit!
describe "common_pipeline/2" do describe "common_pipeline/2" do
setup do setup do
clear_config([:instance, :federating], true) ObjectValidatorMock
|> expect(:validate, fn o, m -> {:ok, o, m} end)
MRFMock
|> expect(:pipeline_filter, fn o, m -> {:ok, o, m} end)
ActivityPubMock
|> expect(:persist, fn o, m -> {:ok, o, m} end)
SideEffectsMock
|> expect(:handle, fn o, m -> {:ok, o, m} end)
|> expect(:handle_after_transaction, fn m -> m end)
:ok :ok
end end
@ -21,159 +42,53 @@ test "when given an `object_data` in meta, Federation will receive a the origina
activity_with_object = %{activity | data: Map.put(activity.data, "object", object)} activity_with_object = %{activity | data: Map.put(activity.data, "object", object)}
with_mocks([ FederatorMock
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]}, |> expect(:publish, fn ^activity_with_object -> :ok end)
{
Pleroma.Web.ActivityPub.MRF,
[],
[pipeline_filter: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.ActivityPub,
[],
[persist: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.SideEffects,
[],
[
handle: fn o, m -> {:ok, o, m} end,
handle_after_transaction: fn m -> m end
]
},
{
Pleroma.Web.Federator,
[],
[publish: fn _o -> :ok end]
}
]) do
assert {:ok, ^activity, ^meta} =
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) ConfigMock
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta)) |> expect(:get, fn [:instance, :federating] -> true end)
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta)) assert {:ok, ^activity, ^meta} =
refute called(Pleroma.Web.Federator.publish(activity)) Pleroma.Web.ActivityPub.Pipeline.common_pipeline(
assert_called(Pleroma.Web.Federator.publish(activity_with_object)) activity,
end meta
)
end end
test "it goes through validation, filtering, persisting, side effects and federation for local activities" do test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
activity = insert(:note_activity) activity = insert(:note_activity)
meta = [local: true] meta = [local: true]
with_mocks([ FederatorMock
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]}, |> expect(:publish, fn ^activity -> :ok end)
{
Pleroma.Web.ActivityPub.MRF, ConfigMock
[], |> expect(:get, fn [:instance, :federating] -> true end)
[pipeline_filter: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.ActivityPub,
[],
[persist: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.SideEffects,
[],
[
handle: fn o, m -> {:ok, o, m} end,
handle_after_transaction: fn m -> m end
]
},
{
Pleroma.Web.Federator,
[],
[publish: fn _o -> :ok end]
}
]) do
assert {:ok, ^activity, ^meta} = assert {:ok, ^activity, ^meta} =
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta) Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
assert_called(Pleroma.Web.Federator.publish(activity))
end
end end
test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do
activity = insert(:note_activity) activity = insert(:note_activity)
meta = [local: false] meta = [local: false]
with_mocks([ ConfigMock
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]}, |> expect(:get, fn [:instance, :federating] -> true end)
{
Pleroma.Web.ActivityPub.MRF,
[],
[pipeline_filter: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.ActivityPub,
[],
[persist: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.SideEffects,
[],
[handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
},
{
Pleroma.Web.Federator,
[],
[]
}
]) do
assert {:ok, ^activity, ^meta} = assert {:ok, ^activity, ^meta} =
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta) Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
end
end end
test "it goes through validation, filtering, persisting, side effects without federation for local activities if federation is deactivated" do test "it goes through validation, filtering, persisting, side effects without federation for local activities if federation is deactivated" do
clear_config([:instance, :federating], false)
activity = insert(:note_activity) activity = insert(:note_activity)
meta = [local: true] meta = [local: true]
with_mocks([ ConfigMock
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]}, |> expect(:get, fn [:instance, :federating] -> false end)
{
Pleroma.Web.ActivityPub.MRF,
[],
[pipeline_filter: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.ActivityPub,
[],
[persist: fn o, m -> {:ok, o, m} end]
},
{
Pleroma.Web.ActivityPub.SideEffects,
[],
[handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
},
{
Pleroma.Web.Federator,
[],
[]
}
]) do
assert {:ok, ^activity, ^meta} = assert {:ok, ^activity, ^meta} =
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta) Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
end
end end
end end
end end

View file

@ -3,3 +3,23 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
Mox.defmock(Pleroma.CachexMock, for: Pleroma.Caching) Mox.defmock(Pleroma.CachexMock, for: Pleroma.Caching)
Mox.defmock(Pleroma.Web.ActivityPub.ObjectValidatorMock,
for: Pleroma.Web.ActivityPub.ObjectValidator.Validating
)
Mox.defmock(Pleroma.Web.ActivityPub.MRFMock,
for: Pleroma.Web.ActivityPub.MRF.PipelineFiltering
)
Mox.defmock(Pleroma.Web.ActivityPub.ActivityPubMock,
for: Pleroma.Web.ActivityPub.ActivityPub.Persisting
)
Mox.defmock(Pleroma.Web.ActivityPub.SideEffectsMock,
for: Pleroma.Web.ActivityPub.SideEffects.Handling
)
Mox.defmock(Pleroma.Web.FederatorMock, for: Pleroma.Web.Federator.Publishing)
Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting)