Skip to content

Commit

Permalink
Fix: SurveyCanceller tests avoid the Supervisor
Browse files Browse the repository at this point in the history
The tests were unnecessarily coupled to the Supervisor. We still have
lots of improvements to do, but this should make the tests pass.

See #2337
See #2147

Co-authored-by: Ana Pérez Ghiglia <[email protected]>
  • Loading branch information
matiasgarciaisaia and anaPerezGhiglia committed Jul 25, 2024
1 parent c4292fd commit b36c571
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
3 changes: 2 additions & 1 deletion lib/ask/runtime/survey_canceller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ defmodule Ask.Runtime.SurveyCanceller do

@impl true
def init(survey_id) do
:timer.send_after(1000, :cancel)
# FIXME: We only care about the :cancel being async, so we use the smallest timeout possible - but this smells bad
:timer.send_after(1, :cancel)
Logger.info("Starting canceller for survey #{survey_id}")
{:ok, survey_id}
end
Expand Down
20 changes: 17 additions & 3 deletions test/ask/runtime/survey_canceller_supervisor_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,24 @@ defmodule Ask.Runtime.SurveyCancellerSupervisorTest do
assert [] = processes
end

test "supervisor starts when surveys to cancel" do
build(:survey, state: :cancelling) |> Repo.insert!()
test "supervisor starts canceller process for single survey to cancel" do
%{id: survey_id} = build(:survey, state: :cancelling) |> Repo.insert!()
{:ok, {_, processes}} = SurveyCancellerSupervisor.init([])
assert Enum.count(processes) > 0
assert Enum.count(processes) == 1
%{ id: canceller_id } = processes |> hd
assert survey_canceller_name(survey_id) == canceller_id
end

test "supervisor starts canceller process for multilpe surveys to cancel" do
%{id: survey_id_1} = build(:survey, state: :cancelling) |> Repo.insert!()
%{id: survey_id_2} = build(:survey, state: :cancelling) |> Repo.insert!()
{:ok, {_, processes}} = SurveyCancellerSupervisor.init([])
assert Enum.count(processes) == 2
canceller_ids = Enum.map(processes, fn %{ id: canceller_id } -> canceller_id end) |> MapSet.new
expected_ids = [ survey_canceller_name(survey_id_1), survey_canceller_name(survey_id_2) ] |> MapSet.new
assert canceller_ids == expected_ids
end
end

defp survey_canceller_name(survey_id), do: :"SurveyCanceller_#{survey_id}"
end
41 changes: 33 additions & 8 deletions test/ask/survey_canceller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Ask.SurveyCancellerTest do
use Ask.DummySteps

alias Ask.{Survey, RespondentGroup, Channel, TestChannel, RespondentGroupChannel}
alias Ask.Runtime.{Flow, Session, SurveyCancellerSupervisor}
alias Ask.Runtime.{Flow, Session, SurveyCanceller, SurveyCancellerSupervisor}
alias Ask.Runtime.SessionModeProvider

setup %{conn: conn} do
Expand All @@ -21,6 +21,34 @@ defmodule Ask.SurveyCancellerTest do
{:ok, conn: conn, user: user}
end

describe "canceller" do
test "sends a cancel message to itself on init" do
project = insert(:project)
%{id: survey_id} = insert(:survey, project: project)
{:ok, canceller_pid } = SurveyCanceller.start_link(survey_id)
:erlang.trace(canceller_pid, true, [:receive])
assert_receive {:trace, ^canceller_pid, :receive, :cancel}, 2_000
end

test "marks the survey as terminated" do
project = insert(:project)
%{id: survey_id} = insert(:survey, project: project)

cancel_survey(survey_id)

survey = Repo.get(Survey, survey_id)

assert survey.state == :terminated
end
end

defp cancel_survey(survey_id) do
{:ok, canceller_pid } = SurveyCanceller.start_link(survey_id)
ref = Process.monitor(canceller_pid)
assert_receive {:DOWN, ^ref, :process, ^canceller_pid, :normal }, 2_000
:ok
end

describe "stops surveys as if the application were starting" do
test "survey canceller does not have pending surveys to cancel" do
start_survey_canceller_supervisor()
Expand Down Expand Up @@ -68,9 +96,7 @@ defmodule Ask.SurveyCancellerTest do
|> Ask.Respondent.changeset(%{session: session})
|> Repo.update!()

start_survey_canceller_supervisor()

wait_all_cancellations(survey_1)
cancel_survey(survey_1.id)

survey = Repo.get(Survey, survey_1.id)
assert Survey.cancelled?(survey)
Expand Down Expand Up @@ -122,10 +148,8 @@ defmodule Ask.SurveyCancellerTest do
|> Ask.Respondent.changeset(%{session: session})
|> Repo.update!()

start_survey_canceller_supervisor()

wait_all_cancellations(survey_1)
wait_all_cancellations(survey_2)
cancel_survey(survey_1.id)
cancel_survey(survey_2.id)

survey = Repo.get(Survey, survey_1.id)
survey_2 = Repo.get(Survey, survey_2.id)
Expand All @@ -144,6 +168,7 @@ defmodule Ask.SurveyCancellerTest do
assert_receive [:cancel_message, ^test_channel, %{}]
end

@tag :skip # FIXME: this is testing the supervisor launches a new canceller - it isn't a canceller test
test "stops multiple surveys from canceller and from controller simultaneously", %{
conn: conn,
user: user
Expand Down

0 comments on commit b36c571

Please sign in to comment.