From cf4c24d39c6878cd5c1f6f2ca7e56d1784ecbe06 Mon Sep 17 00:00:00 2001 From: Felipe Sere Date: Mon, 7 Mar 2016 23:24:16 +0000 Subject: [PATCH] Adds more extensive koans about spawn, spawn_link and spawn_monitor --- lib/blank_assertions.ex | 6 ++- lib/koans/10_processes.ex | 100 ++++++++++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 17 deletions(-) diff --git a/lib/blank_assertions.ex b/lib/blank_assertions.ex index 59df636..12c1de8 100644 --- a/lib/blank_assertions.ex +++ b/lib/blank_assertions.ex @@ -48,8 +48,10 @@ defmodule BlankAssertions do ExUnit.Assertions.refute(value, opts) end - def flunk(message \\ "Flunked!") do - assert false, message: message + defmacro flunk(message \\ "Flunked!") do + quote do + assert false, message: unquote(message) + end end defp contains_blank?(expr) do diff --git a/lib/koans/10_processes.ex b/lib/koans/10_processes.ex index 48168d7..62173cf 100644 --- a/lib/koans/10_processes.ex +++ b/lib/koans/10_processes.ex @@ -13,19 +13,7 @@ defmodule Processes do koan "process can send messages to itself" do send self(), "hola!" - receive do - message -> assert message == "hola!" - end - end - - koan "a spawned process is independent of the current process" do - pid = spawn(fn -> receive do - {:hello, thing} -> assert thing == "world" - _ -> assert false - end - end) - - send pid, {:hello, "world"} + assert_receive "hola!" end koan "a common pattern is to include the sender in the message" do @@ -40,9 +28,9 @@ defmodule Processes do end koan "you don't have to wait forever for messages" do - parent = self + parent = self() spawn(fn -> receive do - _ -> assert false + _anything -> flunk "I really wasn't expecting messages" after 10 -> send parent, {:waited_too_long, "I am inpatient"} end @@ -50,4 +38,86 @@ defmodule Processes do assert_receive {:waited_too_long, "I am inpatient"} end + + koan "killing a process will terminate it" do + pid = spawn(fn -> Process.exit(self(), :kill) end) + :timer.sleep(500) + refute Process.alive?(pid) + end + + koan "killing a process kills it for good" do + pid = spawn(fn -> receive do + end + end) + assert Process.alive?(pid) + Process.exit(pid, :kill) + refute Process.alive?(pid) + end + + koan "can trap a signal in a child process" do + parent = self() + pid = spawn(fn -> + Process.flag(:trap_exit, true) + send parent, :ready + receive do + {:EXIT, _pid, reason} -> send parent, {:exited, reason} + end + end) + wait() + Process.exit(pid, :random_reason) + + assert_receive {:exited, :random_reason} + refute Process.alive?(pid) + end + + koan "quitting normally has no effect" do + pid = spawn(fn -> receive do + end + end) + Process.exit(pid, :normal) + assert Process.alive?(pid) + end + + koan "quititing your own process normally does terminate it though" do + pid = spawn(fn -> receive do + :bye -> Process.exit(self(), :normal) + end + end) + + assert Process.alive?(pid) + send pid, :bye + :timer.sleep(100) + refute Process.alive?(pid) + end + + koan "linked processes are informed about exit signals of children when trapping those signals" do + parent = self() + spawn(fn -> + Process.flag(:trap_exit, true) + spawn_link(fn -> Process.exit(self(), :normal) end) + receive do + {:EXIT, _pid ,reason} -> send parent, {:exited, reason} + end + end) + + assert_receive {:exited, :normal} + end + + koan "monitoring processes are informed via messages without having trapping" do + parent = self() + spawn(fn -> + spawn_monitor(fn -> Process.exit(self(), :normal) end) + receive do + {:DOWN, _ref, :process, _pid, reason} -> send parent, {:exited, reason} + end + end) + + assert_receive {:exited, :normal} + end + + def wait do + receive do + :ready -> true + end + end end