aboutsummaryrefslogtreecommitdiff
path: root/test/pleroma/config/versioning_test.exs
diff options
context:
space:
mode:
Diffstat (limited to 'test/pleroma/config/versioning_test.exs')
-rw-r--r--test/pleroma/config/versioning_test.exs414
1 files changed, 414 insertions, 0 deletions
diff --git a/test/pleroma/config/versioning_test.exs b/test/pleroma/config/versioning_test.exs
new file mode 100644
index 000000000..783952e98
--- /dev/null
+++ b/test/pleroma/config/versioning_test.exs
@@ -0,0 +1,414 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Config.VersioningTest do
+ use Pleroma.DataCase, async: true
+
+ import Pleroma.Factory
+
+ alias Pleroma.Config.Version
+ alias Pleroma.Config.Versioning
+ alias Pleroma.ConfigDB
+ alias Pleroma.Repo
+
+ @with_key %{
+ group: :pleroma,
+ key: :instance,
+ value: [name: "Instance name"]
+ }
+
+ @without_key %{
+ group: :quack,
+ key: nil,
+ value: [
+ level: :warn,
+ meta: [:all],
+ webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
+ ]
+ }
+
+ @value_not_keyword %{
+ group: :pleroma,
+ key: Pleroma.Web.Auth.Authenticator,
+ value: Pleroma.Web.Auth.PleromaAuthenticator
+ }
+
+ describe "new_version/1" do
+ test "creates version" do
+ changes = [@with_key, @without_key, @value_not_keyword]
+
+ {:ok,
+ %{
+ :insert_version => version,
+ :update_all_versions => {0, nil},
+ {:insert_or_update, :pleroma, :instance} => _,
+ {:insert_or_update, :quack, nil} => _
+ }} = Versioning.new_version(changes)
+
+ assert version.current
+ assert backup_length(version) == 2
+
+ assert version.backup[:quack] == @without_key[:value]
+
+ assert version.backup[:pleroma][:instance] == @with_key[:value]
+
+ assert version.backup[:pleroma][Pleroma.Web.Auth.Authenticator] ==
+ @value_not_keyword[:value]
+
+ assert Repo.aggregate(ConfigDB, :count) == 3
+ assert Repo.aggregate(Version, :count) == 1
+ end
+
+ test "creates several versions" do
+ change1 = [@with_key]
+
+ {:ok,
+ %{
+ :insert_version => version1,
+ :update_all_versions => {0, nil},
+ {:insert_or_update, :pleroma, :instance} => _
+ }} = Versioning.new_version(change1)
+
+ change2 = [@without_key]
+
+ {:ok,
+ %{
+ :insert_version => version2,
+ :update_all_versions => {1, nil},
+ {:insert_or_update, :quack, nil} => _
+ }} = Versioning.new_version(change2)
+
+ version1 = refresh_record(version1)
+ refute version1.current
+
+ assert backup_length(version1) == 1
+
+ version2 = refresh_record(version2)
+ assert version2.current
+
+ assert backup_length(version2) == 2
+ end
+
+ test "error on empty list" do
+ assert Versioning.new_version([]) == {:error, :empty_changes}
+ end
+
+ test "error on bad format" do
+ assert Versioning.new_version(nil) == {:error, :bad_format}
+ end
+
+ test "process changes as single map" do
+ {:ok,
+ %{
+ :insert_version => _,
+ :update_all_versions => {0, nil},
+ {:insert_or_update, :pleroma, :instance} => _
+ }} = Versioning.new_version(@with_key)
+
+ assert Repo.aggregate(ConfigDB, :count) == 1
+ end
+
+ test "error if value is not keyword" do
+ assert Versioning.new_version([
+ %{group: :pleroma, key: :key, value: %{}}
+ ]) ==
+ {:error, {:error, :pleroma, :key},
+ {:value_must_be_keyword, %{group: :pleroma, key: :key, value: %{}}}, %{}}
+ end
+
+ test "error if value is list" do
+ assert Versioning.new_version([
+ %{group: :pleroma, key: :key, value: [1]}
+ ]) ==
+ {:error, {:error, :pleroma, :key},
+ {:value_must_be_keyword, %{group: :pleroma, key: :key, value: [1]}}, %{}}
+ end
+ end
+
+ describe "rollback/1" do
+ test "bad steps format" do
+ assert Versioning.rollback(nil) == {:error, :steps_format}
+ end
+
+ test "no versions" do
+ assert Versioning.rollback() == {:error, :no_current_version}
+ end
+
+ test "rollback not possible, because there is only one version" do
+ {:ok, _} = Versioning.new_version(@with_key)
+
+ assert Versioning.rollback() == {:error, :rollback_not_possible}
+ end
+
+ test "rollbacks to previous version" do
+ {:ok, _} = Versioning.new_version(@with_key)
+
+ {:ok, _} = Versioning.new_version(@value_not_keyword)
+
+ {:ok, _} = Versioning.new_version(@without_key)
+
+ {:ok, _} = Versioning.rollback()
+
+ configs = ConfigDB.all()
+
+ Enum.each(configs, fn
+ %{key: :instance} = config ->
+ config.value == @with_key[:value]
+
+ %{key: Pleroma.Web.Auth.Authenticator} = config ->
+ config.value == @value_not_keyword[:value]
+ end)
+
+ assert Repo.aggregate(Version, :count) == 2
+
+ version = Repo.get_by(Version, current: true)
+
+ assert version.backup[:pleroma][:instance] == @with_key[:value]
+
+ assert version.backup[:pleroma][Pleroma.Web.Auth.Authenticator] ==
+ @value_not_keyword[:value]
+ end
+
+ test "rollbacks with 2 steps" do
+ {:ok, _} = Versioning.new_version(@with_key)
+
+ {:ok, _} = Versioning.new_version(@without_key)
+
+ {:ok, _} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :instance,
+ value: [name: "New name"]
+ })
+
+ assert Repo.aggregate(ConfigDB, :count) == 2
+ assert Repo.aggregate(Version, :count) == 3
+ {:ok, _} = Versioning.rollback(2)
+
+ assert Repo.aggregate(Version, :count) == 1
+
+ [with_key] = ConfigDB.all()
+
+ assert with_key.value == @with_key[:value]
+ end
+
+ test "rollbacks with 2 steps and creates new version for new change" do
+ {:ok, _} = Versioning.new_version(@with_key)
+
+ {:ok, _} = Versioning.new_version(@without_key)
+
+ {:ok, _} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :instance,
+ value: [name: "New name"]
+ })
+
+ {:ok, _} = Versioning.rollback(2)
+
+ {:ok, _} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :instance,
+ value: [name: "Last name"]
+ })
+
+ [with_key] = ConfigDB.all()
+ assert with_key.value == [name: "Last name"]
+ end
+
+ test "properly rollbacks with settings without keys" do
+ {:ok, _} = Versioning.new_version(@with_key)
+
+ {:ok, _} = Versioning.new_version(@without_key)
+
+ {:ok, _} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :instance,
+ value: [name: "New name"]
+ })
+
+ {:ok, _} = Versioning.rollback()
+
+ config = ConfigDB.get_by_params(%{group: :quack})
+ assert config.value == @without_key[:value]
+ end
+
+ test "properly rollbacks with logger settings" do
+ {:ok, _} = Versioning.new_version(@with_key)
+
+ {:ok, _} =
+ Versioning.new_version([
+ %{
+ group: :logger,
+ value: [
+ console: [
+ level: :debug,
+ format: "\n$time $metadata[$level] $message\n",
+ metadata: [:request_id]
+ ],
+ backends: [:console]
+ ]
+ }
+ ])
+
+ {:ok, _} = Versioning.new_version(@without_key)
+
+ {:ok, _} = Versioning.rollback()
+
+ logger = ConfigDB.get_by_params(%{group: :logger})
+
+ assert logger.value == [
+ console: [
+ level: :debug,
+ format: "\n$time $metadata[$level] $message\n",
+ metadata: [:request_id]
+ ],
+ backends: [:console]
+ ]
+ end
+ end
+
+ describe "migrate/1" do
+ test "migrates settings from config file" do
+ {:ok, _} = Versioning.migrate("test/fixtures/config/temp.secret.exs")
+
+ assert Repo.aggregate(ConfigDB, :count) == 3
+
+ config1 = ConfigDB.get_by_params(%{group: :pleroma, key: :first_setting})
+ config2 = ConfigDB.get_by_params(%{group: :pleroma, key: :second_setting})
+ config3 = ConfigDB.get_by_params(%{group: :quack})
+
+ assert config1.value == [key: "value", key2: [Repo]]
+ assert config2.value == [key: "value2", key2: ["Activity"]]
+ assert config3.value == [level: :info]
+
+ [version] = Repo.all(Version)
+
+ assert version.backup == [
+ pleroma: [
+ second_setting: [key: "value2", key2: ["Activity"]],
+ first_setting: [key: "value", key2: [Repo]]
+ ],
+ quack: [level: :info]
+ ]
+ end
+
+ test "truncates table on migration" do
+ insert_list(4, :config)
+
+ assert Repo.aggregate(ConfigDB, :count) == 4
+
+ {:ok, _} = Versioning.migrate("test/fixtures/config/temp.secret.exs")
+
+ assert Repo.aggregate(ConfigDB, :count) == 3
+ end
+ end
+
+ describe "migrate_namespace/2" do
+ test "common namespace rename" do
+ value_before_migration = [name: "Name"]
+
+ {:ok, %{:insert_version => version1}} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :key1,
+ value: value_before_migration
+ })
+
+ {:ok, %{:insert_version => version2}} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :key2,
+ value: [name: "Name"]
+ })
+
+ {:ok, %{:insert_version => version3}} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :key3,
+ value: [name: "Name"]
+ })
+
+ {:ok, _} = Versioning.migrate_namespace({:pleroma, :key1}, {:ex_aws, :new_key})
+
+ version1 = refresh_record(version1)
+ assert version1.backup == [ex_aws: [new_key: [name: "Name"]]]
+ version2 = refresh_record(version2)
+
+ assert version2.backup == [
+ ex_aws: [new_key: [name: "Name"]],
+ pleroma: [key2: [name: "Name"]]
+ ]
+
+ version3 = refresh_record(version3)
+
+ assert version3.backup == [
+ ex_aws: [new_key: [name: "Name"]],
+ pleroma: [key2: [name: "Name"], key3: [name: "Name"]]
+ ]
+
+ assert Repo.aggregate(from(c in ConfigDB, where: c.group == ^:pleroma), :count, :id) == 2
+ config = ConfigDB.get_by_params(%{group: :ex_aws, key: :new_key})
+ assert config.value == value_before_migration
+
+ {:ok, _} = Versioning.migrate_namespace({:pleroma, :key2}, {:pleroma, :new_key})
+
+ version1 = refresh_record(version1)
+ assert version1.backup == [ex_aws: [new_key: [name: "Name"]]]
+ version2 = refresh_record(version2)
+
+ assert version2.backup == [
+ pleroma: [new_key: [name: "Name"]],
+ ex_aws: [new_key: [name: "Name"]]
+ ]
+
+ version3 = refresh_record(version3)
+
+ assert version3.backup == [
+ ex_aws: [new_key: [name: "Name"]],
+ pleroma: [new_key: [name: "Name"], key3: [name: "Name"]]
+ ]
+ end
+
+ test "old namespace exists in old backups" do
+ {:ok, %{:insert_version => version1}} =
+ Versioning.new_version(%{
+ group: :pleroma,
+ key: :key1,
+ value: [name: "Name"]
+ })
+
+ {:ok, %{:insert_version => version2}} =
+ Versioning.new_version([
+ %{
+ group: :pleroma,
+ key: :key2,
+ value: [name: "Name"]
+ },
+ %{group: :pleroma, key: :key1, delete: true}
+ ])
+
+ {:ok, _} = Versioning.migrate_namespace({:pleroma, :key1}, {:ex_aws, :new_key})
+
+ version1 = refresh_record(version1)
+ assert version1.backup == [ex_aws: [new_key: [name: "Name"]]]
+ version2 = refresh_record(version2)
+
+ assert version2.backup == [
+ pleroma: [key2: [name: "Name"]]
+ ]
+
+ assert Repo.aggregate(from(c in ConfigDB, where: c.group == ^:pleroma), :count, :id) == 1
+ refute ConfigDB.get_by_params(%{group: :ex_aws, key: :new_key})
+ end
+ end
+
+ defp backup_length(%{backup: backup}) do
+ backup
+ |> Keyword.keys()
+ |> length()
+ end
+end