Refactor tests for Backups

This commit is contained in:
Mark Felder 2024-06-24 10:10:53 -04:00
parent 8f285a787f
commit e5a738d465
6 changed files with 80 additions and 193 deletions

View File

@ -1,49 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.User.BackupAsyncTest do
use Pleroma.DataCase, async: true
import Pleroma.Factory
import Mox
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
alias Pleroma.User.Backup
alias Pleroma.User.Backup.ProcessorMock
setup do
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
{:ok, backup} = user |> Backup.new() |> Repo.insert()
%{backup: backup}
end
test "it handles unrecoverable exceptions", %{backup: backup} do
ProcessorMock
|> expect(:do_process, fn _, _ ->
raise "mock exception"
end)
ConfigMock
|> stub_with(Pleroma.Config)
{:error, %{backup: backup, reason: :exit}} = Backup.process(backup, ProcessorMock)
assert backup.state == :failed
end
test "it handles timeouts", %{backup: backup} do
ProcessorMock
|> expect(:do_process, fn _, _ ->
Process.sleep(:timer.seconds(4))
end)
ConfigMock
|> expect(:get, fn [Pleroma.User.Backup, :process_wait_time] -> :timer.seconds(2) end)
{:error, %{backup: backup, reason: :timeout}} = Backup.process(backup, ProcessorMock)
assert backup.state == :failed
end
end

View File

@ -6,7 +6,6 @@ defmodule Pleroma.User.BackupTest do
use Oban.Testing, repo: Pleroma.Repo use Oban.Testing, repo: Pleroma.Repo
use Pleroma.DataCase use Pleroma.DataCase
import Mock
import Pleroma.Factory import Pleroma.Factory
import Swoosh.TestAssertions import Swoosh.TestAssertions
import Mox import Mox
@ -16,7 +15,6 @@ defmodule Pleroma.User.BackupTest do
alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.UnstubbedConfigMock, as: ConfigMock
alias Pleroma.Uploaders.S3.ExAwsMock alias Pleroma.Uploaders.S3.ExAwsMock
alias Pleroma.User.Backup alias Pleroma.User.Backup
alias Pleroma.User.Backup.ProcessorMock
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Workers.BackupWorker alias Pleroma.Workers.BackupWorker
@ -28,79 +26,56 @@ defmodule Pleroma.User.BackupTest do
ConfigMock ConfigMock
|> stub_with(Pleroma.Config) |> stub_with(Pleroma.Config)
ProcessorMock
|> stub_with(Pleroma.User.Backup.Processor)
:ok :ok
end end
test "it does not requrie enabled email" do test "it does not requrie enabled email" do
clear_config([Pleroma.Emails.Mailer, :enabled], false) clear_config([Pleroma.Emails.Mailer, :enabled], false)
user = insert(:user) user = insert(:user)
assert {:ok, _} = Backup.create(user) assert {:ok, _} = Backup.user(user)
end end
test "it does not require user's email" do test "it does not require user's email" do
user = insert(:user, %{email: nil}) user = insert(:user, %{email: nil})
assert {:ok, _} = Backup.create(user) assert {:ok, _} = Backup.user(user)
end end
test "it creates a backup record and an Oban job" do test "it creates a backup record and an Oban job" do
%{id: user_id} = user = insert(:user) user = insert(:user)
assert {:ok, %Oban.Job{args: args}} = Backup.create(user) assert {:ok, %Backup{} = backup} = Backup.user(user)
assert {:ok, %Oban.Job{args: args}} = Backup.schedule_backup(backup)
assert_enqueued(worker: BackupWorker, args: args) assert_enqueued(worker: BackupWorker, args: args)
backup = Backup.get(args["backup_id"]) backup = Backup.get_by_id(args["backup_id"])
assert %Backup{user_id: ^user_id, processed: false, file_size: 0, state: :pending} = backup assert %Backup{processed: false, file_size: 0} = backup
end end
test "it return an error if the export limit is over" do test "it return an error if the export limit is over" do
%{id: user_id} = user = insert(:user) user = insert(:user)
limit_days = Pleroma.Config.get([Backup, :limit_days]) limit_days = Pleroma.Config.get([Backup, :limit_days])
assert {:ok, %Oban.Job{args: args}} = Backup.create(user) {:ok, first_backup} = Backup.user(user)
backup = Backup.get(args["backup_id"]) {:ok, _run_backup} = Backup.run(first_backup)
assert %Backup{user_id: ^user_id, processed: false, file_size: 0} = backup
assert Backup.create(user) == {:error, "Last export was less than #{limit_days} days ago"} assert Backup.user(user) == {:error, "Last export was less than #{limit_days} days ago"}
end end
test "it process a backup record" do test "it process a backup record" do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
%{id: user_id} = user = insert(:user) %{id: user_id} = user = insert(:user)
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user) assert {:ok, %Backup{id: backup_id}} = Backup.user(user)
assert {:ok, backup} = perform_job(BackupWorker, args)
oban_args = %{"op" => "process", "backup_id" => backup_id}
assert {:ok, backup} = perform_job(BackupWorker, oban_args)
assert backup.file_size > 0 assert backup.file_size > 0
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id, state: :complete} = backup assert match?(%Backup{id: ^backup_id, processed: true, user_id: ^user_id}, backup)
delete_job_args = %{"op" => "delete", "backup_id" => backup_id} delete_job_args = %{"op" => "delete", "backup_id" => backup_id}
assert_enqueued(worker: BackupWorker, args: delete_job_args) assert_enqueued(worker: BackupWorker, args: delete_job_args)
assert {:ok, backup} = perform_job(BackupWorker, delete_job_args) assert {:ok, backup} = perform_job(BackupWorker, delete_job_args)
refute Backup.get(backup_id) refute Backup.get_by_id(backup_id)
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
assert_email_sent(
to: {user.name, user.email},
html_body: email.html_body
)
end
test "it updates states of the backup" do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
%{id: user_id} = user = insert(:user)
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
assert {:ok, backup} = perform_job(BackupWorker, args)
assert backup.file_size > 0
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id, state: :complete} = backup
delete_job_args = %{"op" => "delete", "backup_id" => backup_id}
assert_enqueued(worker: BackupWorker, args: delete_job_args)
assert {:ok, backup} = perform_job(BackupWorker, delete_job_args)
refute Backup.get(backup_id)
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup) email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
@ -114,10 +89,15 @@ defmodule Pleroma.User.BackupTest do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
%{id: user_id} = user = insert(:user, %{email: nil}) %{id: user_id} = user = insert(:user, %{email: nil})
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user) assert {:ok, %Backup{} = backup} = Backup.user(user)
assert {:ok, backup} = perform_job(BackupWorker, args)
assert backup.file_size > 0 expected_args = %{"op" => "process", "backup_id" => backup.id}
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
assert_enqueued(worker: BackupWorker, args: %{"backup_id" => backup.id})
assert {:ok, completed_backup} = perform_job(BackupWorker, expected_args)
assert completed_backup.file_size > 0
assert completed_backup.processed
assert completed_backup.user_id == user_id
assert_no_email_sent() assert_no_email_sent()
end end
@ -127,10 +107,13 @@ defmodule Pleroma.User.BackupTest do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
%{id: user_id} = user = insert(:user) %{id: user_id} = user = insert(:user)
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user) assert {:ok, %Backup{id: backup_id}} = Backup.user(user)
assert {:ok, backup} = perform_job(BackupWorker, args)
oban_args = %{"op" => "process", "backup_id" => backup_id}
assert {:ok, backup} = perform_job(BackupWorker, oban_args)
assert backup.file_size > 0 assert backup.file_size > 0
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup assert match?(%Backup{id: ^backup_id, processed: true, user_id: ^user_id}, backup)
assert_no_email_sent() assert_no_email_sent()
end end
@ -139,10 +122,15 @@ defmodule Pleroma.User.BackupTest do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
%{id: user_id} = user = insert(:user, %{email: ""}) %{id: user_id} = user = insert(:user, %{email: ""})
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user) assert {:ok, %Backup{id: backup_id} = backup} = Backup.user(user)
assert {:ok, backup} = perform_job(BackupWorker, args)
expected_args = %{"op" => "process", "backup_id" => backup.id}
assert_enqueued(worker: BackupWorker, args: expected_args)
assert {:ok, backup} = perform_job(BackupWorker, expected_args)
assert backup.file_size > 0 assert backup.file_size > 0
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup assert match?(%Backup{id: ^backup_id, processed: true, user_id: ^user_id}, backup)
assert_no_email_sent() assert_no_email_sent()
end end
@ -152,16 +140,13 @@ defmodule Pleroma.User.BackupTest do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
user = insert(:user) user = insert(:user)
assert {:ok, job1} = Backup.create(user) assert {:ok, %{id: backup_one_id}} = Backup.user(user)
assert {:ok, %{id: _backup_two_id}} = Backup.user(user)
assert {:ok, %Backup{}} = ObanHelpers.perform(job1)
assert {:ok, job2} = Backup.create(user)
assert Pleroma.Repo.aggregate(Backup, :count) == 2
assert {:ok, backup2} = ObanHelpers.perform(job2)
# Run the backups
ObanHelpers.perform_all() ObanHelpers.perform_all()
assert [^backup2] = Pleroma.Repo.all(Backup) assert_enqueued(worker: BackupWorker, args: %{"op" => "delete", "backup_id" => backup_one_id})
end end
test "it creates a zip archive with user data" do test "it creates a zip archive with user data" do
@ -185,9 +170,12 @@ defmodule Pleroma.User.BackupTest do
CommonAPI.follow(other_user, user) CommonAPI.follow(other_user, user)
assert {:ok, backup} = user |> Backup.new() |> Repo.insert() assert {:ok, backup} = Backup.user(user)
assert {:ok, path} = Backup.export(backup, self()) assert {:ok, run_backup} = Backup.run(backup)
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(path), [:memory])
tempfile = Path.join([run_backup.tempdir, run_backup.file_name])
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(tempfile), [:memory])
assert {:ok, {~c"actor.json", json}} = :zip.zip_get(~c"actor.json", zipfile) assert {:ok, {~c"actor.json", json}} = :zip.zip_get(~c"actor.json", zipfile)
assert %{ assert %{
@ -275,10 +263,10 @@ defmodule Pleroma.User.BackupTest do
} = Jason.decode!(json) } = Jason.decode!(json)
:zip.zip_close(zipfile) :zip.zip_close(zipfile)
File.rm!(path) File.rm_rf!(run_backup.tempdir)
end end
test "it counts the correct number processed" do test "correct number processed" do
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"}) user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
Enum.map(1..120, fn i -> Enum.map(1..120, fn i ->
@ -288,43 +276,21 @@ defmodule Pleroma.User.BackupTest do
end) end)
assert {:ok, backup} = user |> Backup.new() |> Repo.insert() assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
{:ok, backup} = Backup.process(backup) {:ok, backup} = Backup.run(backup)
assert backup.processed_number == 1 + 120 + 120 + 120 zip_path = Path.join([backup.tempdir, backup.file_name])
Backup.delete(backup) assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(zip_path), [:memory])
end
test "it handles errors" do backup_parts = [~c"likes.json", ~c"bookmarks.json", ~c"outbox.json"]
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
Enum.map(1..120, fn i -> Enum.each(backup_parts, fn part ->
{:ok, _status} = CommonAPI.post(user, %{status: "status #{i}"}) assert {:ok, {_part, part_json}} = :zip.zip_get(part, zipfile)
{:ok, decoded_part} = Jason.decode(part_json)
assert decoded_part["totalItems"] == 120
end) end)
assert {:ok, backup} = user |> Backup.new() |> Repo.insert() Backup.delete_archive(backup)
with_mock Pleroma.Web.ActivityPub.Transmogrifier,
[:passthrough],
prepare_outgoing: fn data ->
object =
data["object"]
|> Pleroma.Object.normalize(fetch: false)
|> Map.get(:data)
data = data |> Map.put("object", object)
if String.contains?(data["object"]["content"], "119"),
do: raise(%Postgrex.Error{}),
else: {:ok, data}
end do
{:ok, backup} = Backup.process(backup)
assert backup.processed
assert backup.state == :complete
assert backup.processed_number == 1 + 119
Backup.delete(backup)
end
end end
describe "it uploads and deletes a backup archive" do describe "it uploads and deletes a backup archive" do
@ -343,12 +309,11 @@ defmodule Pleroma.User.BackupTest do
Bookmark.create(user.id, status3.id) Bookmark.create(user.id, status3.id)
assert {:ok, backup} = user |> Backup.new() |> Repo.insert() assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
assert {:ok, path} = Backup.export(backup, self())
[path: path, backup: backup] [backup: backup]
end end
test "S3", %{path: path, backup: backup} do test "S3", %{backup: backup} do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3)
clear_config([Pleroma.Uploaders.S3, :streaming_enabled], false) clear_config([Pleroma.Uploaders.S3, :streaming_enabled], false)
@ -358,15 +323,17 @@ defmodule Pleroma.User.BackupTest do
%{http_method: :delete} -> {:ok, %{status_code: 204}} %{http_method: :delete} -> {:ok, %{status_code: 204}}
end) end)
assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path) assert {:ok, backup} = Backup.run(backup)
assert {:ok, _backup} = Backup.delete(backup) assert {:ok, %Backup{processed: true}} = Backup.upload(backup)
assert {:ok, _backup} = Backup.delete_archive(backup)
end end
test "Local", %{path: path, backup: backup} do test "Local", %{backup: backup} do
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path) assert {:ok, backup} = Backup.run(backup)
assert {:ok, _backup} = Backup.delete(backup) assert {:ok, %Backup{processed: true}} = Backup.upload(backup)
assert {:ok, _backup} = Backup.delete_archive(backup)
end end
end end
end end

View File

@ -1096,9 +1096,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
ObanHelpers.perform_all() ObanHelpers.perform_all()
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup, admin.id) email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
assert String.contains?(
email.html_body,
"A full backup of your Pleroma account was requested"
)
assert String.contains?(email.html_body, "Admin @#{admin.nickname} requested a full backup")
assert_email_sent(to: {user.name, user.email}, html_body: email.html_body) assert_email_sent(to: {user.name, user.email}, html_body: email.html_body)
log_message = "@#{admin_nickname} requested account backup for @#{user_nickname}" log_message = "@#{admin_nickname} requested account backup for @#{user_nickname}"

View File

@ -20,9 +20,7 @@ defmodule Pleroma.Web.PleromaAPI.BackupControllerTest do
end end
test "GET /api/v1/pleroma/backups", %{user: user, conn: conn} do test "GET /api/v1/pleroma/backups", %{user: user, conn: conn} do
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id}}} = Backup.create(user) assert {:ok, %Backup{} = backup} = Backup.user(user)
backup = Backup.get(backup_id)
response = response =
conn conn

View File

@ -27,42 +27,11 @@ defmodule Pleroma.Web.PleromaAPI.BackupViewTest do
assert result.id == backup.id assert result.id == backup.id
end end
test "it renders the state and processed_number" do test "it renders the processed state" do
user = insert(:user) user = insert(:user)
backup = Backup.new(user) backup = Backup.new(user)
result = BackupView.render("show.json", backup: backup) result = BackupView.render("show.json", backup: backup)
assert result.state == to_string(backup.state) refute result.processed
assert result.processed_number == backup.processed_number
end
test "it renders failed state with legacy records" do
backup = %Backup{
id: 0,
content_type: "application/zip",
file_name: "dummy",
file_size: 1,
state: :invalid,
processed: true,
processed_number: 1,
inserted_at: NaiveDateTime.utc_now()
}
result = BackupView.render("show.json", backup: backup)
assert result.state == "complete"
backup = %Backup{
id: 0,
content_type: "application/zip",
file_name: "dummy",
file_size: 1,
state: :invalid,
processed: false,
processed_number: 1,
inserted_at: NaiveDateTime.utc_now()
}
result = BackupView.render("show.json", backup: backup)
assert result.state == "failed"
end end
end end

View File

@ -32,6 +32,4 @@ Mox.defmock(Pleroma.StubbedHTTPSignaturesMock, for: Pleroma.HTTPSignaturesAPI)
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.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI) Mox.defmock(Pleroma.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI)