3.0 KiB · text History 4b6fe3b
defmodule OhMyExOhIrcd.ChannelsCloseTest do
  @moduledoc """
  `Channels.close_unregistered/1` and `close_empty_unregistered/0` stop
  live Channel singletons (which hit the DB in `init/1`), so this needs
  the shared sandbox: `async: false`.
  """

  use OhMyExOhIrcd.DataCase, async: false

  import OhMyExOhIrcd.AccountsFixtures

  alias OhMyExOhIrcd.Channels
  alias OhMyExOhIrcd.Cluster.HordeRegistry
  alias OhMyExOhIrcd.IRC.Channel

  defp unique_name(tag), do: "#close#{tag}#{System.unique_integer([:positive])}"

  defp start_channel(name) do
    {:ok, pid} = Channel.ensure_started(name)
    pid
  end

  defp assert_stopped(pid) do
    ref = Process.monitor(pid)
    assert_receive {:DOWN, ^ref, :process, ^pid, _}
  end

  describe "close_unregistered/1" do
    test "stops an empty unregistered channel and deletes its topic row" do
      name = unique_name("empty")
      pid = start_channel(name)
      :ok = Channels.put_topic(name, "someone", "old topic", 1)
      assert Channels.get_topic(name)

      assert {:ok, :closed} = Channels.close_unregistered(name)
      assert_stopped(pid)
      refute Channels.get_topic(name)
    end

    test "refuses a channel with members" do
      name = unique_name("busy")
      pid = start_channel(name)
      :ok = Channel.join(name, "closer#{System.unique_integer([:positive])}", self())
      :ok = Channels.put_topic(name, "someone", "keep me", 1)

      assert {:error, :in_use} = Channels.close_unregistered(name)
      assert HordeRegistry.whereis({:channel, name}) == pid
      assert Channels.get_topic(name).topic == "keep me"
    end

    test "refuses a registered channel and leaves its data alone" do
      name = unique_name("reg")
      {:ok, _} = Channels.register(name, user_fixture())
      pid = start_channel(name)
      :ok = Channels.put_topic(name, "someone", "registered topic", 1)

      assert {:error, :registered} = Channels.close_unregistered(name)
      assert HordeRegistry.whereis({:channel, name}) == pid
      assert Channels.get(name)
      assert Channels.get_topic(name)
    end

    test "is :not_running for a channel that isn't live, and doesn't start it" do
      name = unique_name("gone")
      assert {:error, :not_running} = Channels.close_unregistered(name)
      assert HordeRegistry.whereis({:channel, name}) == nil
    end
  end

  describe "close_empty_unregistered/0" do
    test "closes the empty ones and counts the occupied ones" do
      empty = unique_name("bulkempty")
      busy = unique_name("bulkbusy")
      reg = unique_name("bulkreg")

      empty_pid = start_channel(empty)
      busy_pid = start_channel(busy)
      :ok = Channel.join(busy, "bulk#{System.unique_integer([:positive])}", self())
      {:ok, _} = Channels.register(reg, user_fixture())
      reg_pid = start_channel(reg)

      %{closed: closed, in_use: in_use} = Channels.close_empty_unregistered()
      assert closed >= 1
      assert in_use >= 1

      assert_stopped(empty_pid)
      assert HordeRegistry.whereis({:channel, busy}) == busy_pid
      assert HordeRegistry.whereis({:channel, reg}) == reg_pid
    end
  end
end