Skip to content

Instantly share code, notes, and snippets.

@pavlos
Created March 6, 2016 16:11
Show Gist options
  • Save pavlos/5b3141992e577b4ae049 to your computer and use it in GitHub Desktop.
Save pavlos/5b3141992e577b4ae049 to your computer and use it in GitHub Desktop.
Code.require_file "test_helper.exs", __DIR__
defmodule ProcessTest do
use ExUnit.Case, async: true
doctest Process
test "dictionary" do
assert Process.put(:foo, :bar) == nil
assert Process.put(:foo, :baz) == :bar
assert Process.get_keys() == [:foo]
assert Process.get_keys(:bar) == []
assert Process.get_keys(:baz) == [:foo]
assert Process.get(:foo) == :baz
assert Process.delete(:foo) == :baz
assert Process.get(:foo) == nil
end
test "group_leader/2 and group_leader/0" do
another = spawn_link(fn -> :timer.sleep(1000) end)
assert Process.group_leader(self, another)
assert Process.group_leader == another
end
test "monitoring functions are inlined by the compiler" do
assert expand(quote(do: Process.monitor(pid())), __ENV__) ==
quote(do: :erlang.monitor(:process, pid()))
end
test "sleep/1" do
assert Process.sleep(0) == :ok
end
test "info/2" do
pid = spawn fn -> :timer.sleep(1000) end
assert Process.info(pid, :priority) == {:priority, :normal}
assert Process.info(pid, [:priority]) == [priority: :normal]
Process.exit(pid, :kill)
assert Process.info(pid, :backtrace) == nil
assert Process.info(pid, [:backtrace, :status]) == nil
end
test "info/2 with registered name" do
pid = spawn fn -> nil end
Process.exit(pid, :kill)
assert Process.info(pid, :registered_name) ==
nil
assert Process.info(pid, [:registered_name]) ==
nil
assert Process.info(self, :registered_name) ==
{:registered_name, []}
assert Process.info(self, [:registered_name]) ==
[registered_name: []]
Process.register(self, __MODULE__)
assert Process.info(self, :registered_name) ==
{:registered_name, __MODULE__}
assert Process.info(self, [:registered_name]) ==
[registered_name: __MODULE__]
end
test "send_after/3 sends messages once expired" do
Process.send_after(self(), :hello, 10)
assert_receive :hello
end
test "send_after/3 returns a timer reference that can be read or cancelled" do
timer = Process.send_after(self(), :hello, 100_000)
refute_received :hello
assert is_integer Process.read_timer(timer)
assert is_integer Process.cancel_timer(timer)
timer = Process.send_after(self(), :hello, 0)
assert_receive :hello
assert Process.read_timer(timer) == false
assert Process.cancel_timer(timer) == false
end
test "exit(pid, :normal) does not cause the target process to exit" do
pid = spawn_link fn ->
receive do
:done -> nil
end
end
trap = Process.flag(:trap_exit, true)
true = Process.exit(pid, :normal)
refute_receive {:EXIT, ^pid, :normal}
assert Process.alive?(pid)
# now exit the process for real so it doesn't hang around
true = Process.exit(pid, :abnormal)
assert_receive {:EXIT, ^pid, :abnormal}
refute Process.alive?(pid)
Process.flag(:trap_exit, trap)
end
test "exit(pid, :normal) makes the process receive a message if it traps exits" do
parent = self()
pid = spawn_link fn ->
Process.flag(:trap_exit, true)
receive do
{:EXIT, ^parent, :normal} -> send(parent, {:ok, self()})
end
end
refute_receive _
Process.exit(pid, :normal)
assert_receive {:ok, ^pid}
refute Process.alive?(pid)
end
test "exit(self(), :normal) causes the calling process to exit" do
trap = Process.flag(:trap_exit, true)
pid = spawn_link fn -> Process.exit(self(), :normal) end
assert_receive {:EXIT, ^pid, :normal}
refute Process.alive?(pid)
Process.flag(:trap_exit, trap)
end
test "register/2 can register a name" do
# test that a name can be registered
{pid, ref} = spawn_monitor fn -> receive do; end; end
assert Process.register pid, :foo
cleanup_monitored_process(pid, ref)
end
test "register/2 fails when trying to register a name to a dead pid" do
{pid, ref} = spawn_monitor fn -> Process.exit(self(), :normal) end
# wait for process to exit
receive do
{:DOWN, ^ref, :process, ^pid, :normal} -> nil
end
Process.demonitor ref
refute Process.alive? pid
assert_raise ArgumentError, fn ->
Process.register pid, :foo
end
end
test "register/2 fails when trying to register a name to a pid that already has a name" do
{pid, ref} = spawn_monitor fn -> receive do; end; end
assert Process.register pid, :foo
assert_raise ArgumentError, fn ->
Process.register pid, :bar
end
cleanup_monitored_process(pid, ref)
end
test "register/2 fails when trying to register a name that is already registered" do
name = :foo
{pid, ref} = spawn_monitor fn -> receive do; end; end
{other_pid, other_ref} = spawn_monitor fn -> receive do; end; end
assert Process.register pid, name
assert_raise ArgumentError, fn ->
Process.register other_pid, name
end
cleanup_monitored_process(pid, ref)
cleanup_monitored_process(other_pid, other_ref)
end
test "unregister/1 fails when trying to unregister a name that is not registered" do
name = :foo
refute Process.whereis name
assert_raise ArgumentError, fn ->
Process.unregister name
end
end
defp cleanup_monitored_process(pid, ref) do
# demonitor so :DOWN messages don't show up in the mailbox
Process.demonitor ref
Process.exit pid, :kill
end
defp expand(expr, env) do
{expr, _env} = :elixir_exp.expand(expr, env)
expr
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment