| defmodule Plausible.Session.SaltsTest do |
| use Plausible.DataCase, async: false |
|
|
| alias Plausible.Session.Salts |
| import Ecto.Query |
|
|
| test "agent starts and responds with current salt" do |
| {:ok, _} = Salts.start_link(name: __MODULE__) |
| %{current: current, previous: nil} = Salts.fetch(__MODULE__) |
| assert is_binary(current) |
| end |
|
|
| test "agent starts and responds with current and previous salt after rotation" do |
| {:ok, _} = Salts.start_link(name: __MODULE__) |
| %{current: first, previous: nil} = Salts.fetch(__MODULE__) |
| :ok = Salts.rotate(__MODULE__) |
|
|
| %{current: current, previous: ^first} = Salts.fetch(__MODULE__) |
| assert is_binary(current) |
| end |
|
|
| test "old salts can be cleaned" do |
| t1 = ~U[2025-06-10 15:29:40Z] |
|
|
| {:ok, _} = Salts.start_link(name: __MODULE__, now: t1) |
|
|
| t2 = ~U[2025-06-11 15:29:40Z] |
|
|
| :ok = Salts.rotate(__MODULE__, t2) |
|
|
| %{current: old_current, previous: _old_previous} = |
| Salts.fetch(__MODULE__) |
|
|
| q = from(s in "salts") |
| count = Repo.aggregate(q, :count) |
| assert count == 2 |
|
|
| t3 = ~U[2025-06-13 15:34:40Z] |
|
|
| :ok = Salts.rotate(__MODULE__, t3) |
|
|
| %{current: _current, previous: ^old_current} = |
| Salts.fetch(__MODULE__) |
|
|
| q = from(s in "salts") |
| count = Repo.aggregate(q, :count) |
| assert count == 2 |
| end |
|
|
| test "salts refresh when another node rotates them" do |
| t1 = ~U[2024-06-10 15:29:40Z] |
| {:ok, _} = Salts.start_link(name: :node_1, now: t1) |
| {:ok, _} = Salts.start_link(name: :node_2, now: t1) |
|
|
| t2 = ~U[2024-06-11 15:29:40Z] |
|
|
| :ok = Salts.rotate(:node_2, t2) |
|
|
| assert Salts.fetch(:node_1) != Salts.fetch(:node_2) |
|
|
| send(:node_1, {:refresh, t2}) |
|
|
| assert eventually(fn -> |
| {Salts.fetch(:node_1) == Salts.fetch(:node_2), :ok} |
| end) |
| end |
| end |
|
|