From 17a34411b92c284a3568292876de4db766cabcf1 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Tue, 1 Feb 2022 08:01:04 -0600 Subject: [PATCH 1/9] Create elixir.yml --- .github/workflows/elixir.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/elixir.yml diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml new file mode 100644 index 0000000..8b30956 --- /dev/null +++ b/.github/workflows/elixir.yml @@ -0,0 +1,31 @@ +name: Elixir CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + name: Build and test + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Elixir + uses: erlef/setup-beam@988e02bfe678367a02564f65ca2e37726dc0268f + with: + elixir-version: '1.12.3' # Define the elixir version [required] + otp-version: '24.1' # Define the OTP version [required] + - name: Restore dependencies cache + uses: actions/cache@v2 + with: + path: deps + key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix- + - name: Install dependencies + run: mix deps.get + - name: Run tests + run: mix test From 779178299ff4a0d4cc2a414326820a4102ad9706 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Tue, 1 Feb 2022 08:06:21 -0600 Subject: [PATCH 2/9] Install inotify-tools --- .github/workflows/elixir.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 8b30956..646bcdf 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -14,6 +14,10 @@ jobs: steps: - uses: actions/checkout@v2 + - name: System dependencies + run: | + sudo apt update + sudo apt install -y inotify-tools - name: Set up Elixir uses: erlef/setup-beam@988e02bfe678367a02564f65ca2e37726dc0268f with: From 277e43c8dd289dd3702ee0cd3416fe551751071a Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Thu, 27 Jan 2022 08:46:26 -0600 Subject: [PATCH 3/9] Fix up test answer values that diverged from example --- test/koans/protocols_koans_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/koans/protocols_koans_test.exs b/test/koans/protocols_koans_test.exs index 88dcbb7..c23513a 100644 --- a/test/koans/protocols_koans_test.exs +++ b/test/koans/protocols_koans_test.exs @@ -4,8 +4,8 @@ defmodule ProtocolsTests do test "Protocols" do answers = [ - {:multiple, ["Andre signed up for violin", "Darcy enrolled for ballet"]}, - "Pupil enrolled at school", + {:multiple, ["Andre played violin", "Darcy performed ballet"]}, + "Artist showed performance", Protocol.UndefinedError ] From b8f7d1b411251eb3ffba70e041587078b9de3583 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Tue, 1 Feb 2022 07:27:48 -0600 Subject: [PATCH 4/9] Name Agent modules to avoid process leaking between examples :thinking: I'm not sure why this was an issue, because the agents are started with a "link" and each example is run in a process itself... Seems like we need better isolation between tests. --- lib/koans/17_agents.ex | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/koans/17_agents.ex b/lib/koans/17_agents.ex index ec0ce28..c6e17f2 100644 --- a/lib/koans/17_agents.ex +++ b/lib/koans/17_agents.ex @@ -14,31 +14,31 @@ defmodule Agents do end koan "Update to update the state" do - Agent.start_link(fn -> "Hi there" end, name: __MODULE__) + Agent.start_link(fn -> "Hi there" end, name: :greeter) - Agent.update(__MODULE__, fn old -> + Agent.update(:greeter, fn old -> String.upcase(old) end) - assert Agent.get(__MODULE__, & &1) == ___ + assert Agent.get(:greeter, & &1) == ___ end koan "Use get_and_update when you need to read and change a value in one go" do - Agent.start_link(fn -> ["Milk"] end, name: __MODULE__) + Agent.start_link(fn -> ["Milk"] end, name: :groceries) old_list = - Agent.get_and_update(__MODULE__, fn old -> + Agent.get_and_update(:groceries, fn old -> {old, ["Bread" | old]} end) assert old_list == ___ - assert Agent.get(__MODULE__, & &1) == ___ + assert Agent.get(:groceries, & &1) == ___ end koan "Somebody has to switch off the light at the end of the day" do - {:ok, pid} = Agent.start_link(fn -> ["Milk"] end, name: __MODULE__) + {:ok, pid} = Agent.start_link(fn -> "Fin." end, name: :stoppable) - Agent.stop(__MODULE__) + Agent.stop(:stoppable) assert Process.alive?(pid) == ___ end From ad5952c7ab06306f61f5fd6e3eda015762d3b82b Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Tue, 1 Feb 2022 07:29:25 -0600 Subject: [PATCH 5/9] Remove extra, unneeded MapSets answer --- test/koans/map_sets_koans_test.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/koans/map_sets_koans_test.exs b/test/koans/map_sets_koans_test.exs index 043001d..327ebf9 100644 --- a/test/koans/map_sets_koans_test.exs +++ b/test/koans/map_sets_koans_test.exs @@ -4,7 +4,6 @@ defmodule MapSetsTest do test "MapSets" do answers = [ - 1, 3, {:multiple, [false, true]}, true, From 20927cc1dfe91ff5fce759fa3edf6818d1801e38 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Tue, 1 Feb 2022 07:53:51 -0600 Subject: [PATCH 6/9] Combine Laptop Genserver examples to avoid process leaking issue --- lib/koans/18_genservers.ex | 8 ++------ test/koans/genservers_koans_test.exs | 3 +-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/koans/18_genservers.ex b/lib/koans/18_genservers.ex index 8e78761..0c3440e 100644 --- a/lib/koans/18_genservers.ex +++ b/lib/koans/18_genservers.ex @@ -135,15 +135,11 @@ defmodule GenServers do koan "Our server works but it's pretty ugly to use; so lets use a cleaner interface" do Laptop.start_link("EL!73") - assert Laptop.unlock("EL!73") == ___ - end - koan "Let's use the remaining functions in the external API" do - Laptop.start_link("EL!73") - {_, response} = Laptop.unlock("EL!73") - assert response == ___ + assert Laptop.unlock("EL!73") == ___ Laptop.change_password("EL!73", "Elixir") + {_, response} = Laptop.unlock("EL!73") assert response == ___ diff --git a/test/koans/genservers_koans_test.exs b/test/koans/genservers_koans_test.exs index 3a6569e..57ddd74 100644 --- a/test/koans/genservers_koans_test.exs +++ b/test/koans/genservers_koans_test.exs @@ -11,8 +11,7 @@ defmodule GenServersTests do "73x7!n9", {:error, "Incorrect password!"}, "Congrats! Your process was successfully named.", - {:ok, "Laptop unlocked!"}, - {:multiple, ["Laptop unlocked!", "Incorrect password!", "Jack Sparrow"]} + {:multiple, [{:ok, "Laptop unlocked!"}, "Incorrect password!", "Jack Sparrow"]} ] test_all(GenServers, answers) From 090187ce889cdd5f12ecc2a340c1147a8ac5a473 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Tue, 1 Feb 2022 07:54:13 -0600 Subject: [PATCH 7/9] Set ExUnit timeout for quicker process debugging --- test/test_helper.exs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_helper.exs b/test/test_helper.exs index 56d98f4..2006538 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,4 +1,5 @@ -ExUnit.start() +timeout = 1000 # ms +ExUnit.start(timeout: timeout) defmodule TestHarness do import ExUnit.Assertions From 11601a6945b8f37f147b0d241313f24bcaf72018 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Thu, 10 Feb 2022 07:57:30 -0600 Subject: [PATCH 8/9] Split genserver koans back up --- lib/koans/18_genservers.ex | 10 ++++++++-- test/koans/genservers_koans_test.exs | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/koans/18_genservers.ex b/lib/koans/18_genservers.ex index 0c3440e..f864e0a 100644 --- a/lib/koans/18_genservers.ex +++ b/lib/koans/18_genservers.ex @@ -134,9 +134,15 @@ defmodule GenServers do end koan "Our server works but it's pretty ugly to use; so lets use a cleaner interface" do - Laptop.start_link("EL!73") - + Laptop.start("EL!73") assert Laptop.unlock("EL!73") == ___ + end + + koan "Let's use the remaining functions in the external API" do + Laptop.start("EL!73") + + {_, response} = Laptop.unlock("EL!73") + assert response == ___ Laptop.change_password("EL!73", "Elixir") diff --git a/test/koans/genservers_koans_test.exs b/test/koans/genservers_koans_test.exs index 57ddd74..3a6569e 100644 --- a/test/koans/genservers_koans_test.exs +++ b/test/koans/genservers_koans_test.exs @@ -11,7 +11,8 @@ defmodule GenServersTests do "73x7!n9", {:error, "Incorrect password!"}, "Congrats! Your process was successfully named.", - {:multiple, [{:ok, "Laptop unlocked!"}, "Incorrect password!", "Jack Sparrow"]} + {:ok, "Laptop unlocked!"}, + {:multiple, ["Laptop unlocked!", "Incorrect password!", "Jack Sparrow"]} ] test_all(GenServers, answers) From b598df498e507c9655d5aa304ee9b0c26ed41bb9 Mon Sep 17 00:00:00 2001 From: Jay Hayes Date: Thu, 10 Feb 2022 07:57:49 -0600 Subject: [PATCH 9/9] Manually manage process rather than relying on linking This prevents the race condition that was causing issues between koans as each is run in its own process. --- lib/koans/18_genservers.ex | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/koans/18_genservers.ex b/lib/koans/18_genservers.ex index f864e0a..ab6d7dc 100644 --- a/lib/koans/18_genservers.ex +++ b/lib/koans/18_genservers.ex @@ -12,9 +12,13 @@ defmodule GenServers do {:ok, args} end - def start_link(init_password) do + def start(init_password) do # The __MODULE__ macro returns the current module name as an atom - GenServer.start_link(__MODULE__, init_password, name: __MODULE__) + GenServer.start(__MODULE__, init_password, name: __MODULE__) + end + + def stop do + GenServer.stop(__MODULE__) end def unlock(password) do @@ -151,5 +155,7 @@ defmodule GenServers do {_, response} = Laptop.owner_name() assert response == ___ + + :ok = Laptop.stop() end end