Skip to content

Commit 9183026

Browse files
committed
Update and extend genserver koans
1 parent 3975e54 commit 9183026

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

lib/koans/18_genservers.ex

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,86 @@ defmodule GenServers do
160160

161161
:ok = Laptop.stop()
162162
end
163+
164+
defmodule TimeoutServer do
165+
use GenServer
166+
167+
def start_link(timeout) do
168+
GenServer.start_link(__MODULE__, timeout, name: __MODULE__)
169+
end
170+
171+
def init(timeout) do
172+
{:ok, %{count: 0}, timeout}
173+
end
174+
175+
def get_count do
176+
GenServer.call(__MODULE__, :get_count)
177+
end
178+
179+
def handle_call(:get_count, _from, state) do
180+
{:reply, state.count, state}
181+
end
182+
183+
def handle_info(:timeout, state) do
184+
new_state = %{state | count: state.count + 1}
185+
{:noreply, new_state}
186+
end
187+
end
188+
189+
koan "GenServers can handle info messages and timeouts" do
190+
{:ok, _pid} = TimeoutServer.start_link(100)
191+
# Wait for timeout to occur
192+
:timer.sleep(101)
193+
count = TimeoutServer.get_count()
194+
assert count == ___
195+
196+
GenServer.stop(TimeoutServer)
197+
end
198+
199+
defmodule CrashableServer do
200+
use GenServer
201+
202+
def start_link(initial) do
203+
GenServer.start_link(__MODULE__, initial, name: __MODULE__)
204+
end
205+
206+
def init(initial) do
207+
{:ok, initial}
208+
end
209+
210+
def crash do
211+
GenServer.cast(__MODULE__, :crash)
212+
end
213+
214+
def get_state do
215+
GenServer.call(__MODULE__, :get_state)
216+
end
217+
218+
def handle_call(:get_state, _from, state) do
219+
{:reply, state, state}
220+
end
221+
222+
def handle_cast(:crash, _state) do
223+
raise "Intentional crash for testing"
224+
end
225+
end
226+
227+
koan "GenServers can be supervised and restarted" do
228+
# Start under a supervisor
229+
children = [{CrashableServer, "the state"}]
230+
{:ok, supervisor} = Supervisor.start_link(children, strategy: :one_for_one)
231+
232+
# Server should be running
233+
initial_state = CrashableServer.get_state()
234+
assert initial_state == ___
235+
236+
:ok = CrashableServer.crash()
237+
# Wait for recovery
238+
:timer.sleep(100)
239+
240+
state_after_crash_recovery = CrashableServer.get_state()
241+
assert state_after_crash_recovery == ___
242+
243+
Supervisor.stop(supervisor)
244+
end
163245
end

test/koans/genservers_koans_test.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ defmodule GenServersTests do
1212
{:error, "Incorrect password!"},
1313
"Congrats! Your process was successfully named.",
1414
{:ok, "Laptop unlocked!"},
15-
{:multiple, ["Laptop unlocked!", "Incorrect password!", "Jack Sparrow"]}
15+
{:multiple, ["Laptop unlocked!", "Incorrect password!", "Jack Sparrow"]},
16+
1,
17+
{:multiple, ["the state", "the state"]}
1618
]
1719

1820
test_all(GenServers, answers)

0 commit comments

Comments
 (0)