defmodule Tarakan.GitSSH.AuthSweeperTest do
  use ExUnit.Case, async: false

  alias Tarakan.GitSSH.AuthSweeper
  alias Tarakan.GitSSH.Server

  setup do
    # The table is only created when the SSH daemon is enabled; make sure it
    # exists for this test regardless of suite ordering.
    if :ets.whereis(Server.auth_table()) == :undefined do
      :ets.new(Server.auth_table(), [:named_table, :public, :set])
    end

    :ets.delete_all_objects(Server.auth_table())
    :ok
  end

  test "sweep removes entries whose pid is no longer alive" do
    table = Server.auth_table()

    dead = spawn(fn -> :ok end)
    ref = Process.monitor(dead)
    assert_receive {:DOWN, ^ref, :process, ^dead, _reason}

    :ets.insert(table, {dead, 1, 2})
    :ets.insert(table, {self(), 3, 4})

    assert :ok = AuthSweeper.sweep()

    assert :ets.lookup(table, dead) == []
    assert :ets.lookup(table, self()) == [{self(), 3, 4}]
  end

  test "sweep is a no-op when the table does not exist" do
    table = Server.auth_table()
    :ets.delete(table)

    assert :ok = AuthSweeper.sweep()
  end

  test "the sweeper GenServer sweeps on its timer" do
    pid = start_supervised!({AuthSweeper, name: nil})

    dead = spawn(fn -> :ok end)
    ref = Process.monitor(dead)
    assert_receive {:DOWN, ^ref, :process, ^dead, _reason}

    :ets.insert(Server.auth_table(), {dead, 1, 2})

    send(pid, :sweep)
    _ = :sys.get_state(pid)

    assert :ets.lookup(Server.auth_table(), dead) == []
  end
end
