Skip to content

Instantly share code, notes, and snippets.

@owickstrom
Last active July 28, 2020 20:52
Show Gist options
  • Save owickstrom/e00ce3c33df44f4352af to your computer and use it in GitHub Desktop.
Save owickstrom/e00ce3c33df44f4352af to your computer and use it in GitHub Desktop.
Exposing a synchronous API in Elixir. Inspired by http://elixir-lang.org/getting_started/mix_otp/3.html.
defmodule State.Counter do
use GenServer
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, :ok, opts)
end
## Client API
@doc "Gets the counter's current value."
def get(counter) do
GenServer.call(counter, {:get})
end
@doc "Increases the counter's value by one."
def incr(counter) do
GenServer.call(counter, {:incr})
end
@doc "Decreases the counter's value by one."
def decr(counter) do
GenServer.call(counter, {:decr})
end
@doc "Resets the counter to zero."
def reset(counter) do
GenServer.call(counter, {:reset})
end
## Server Callbacks
def init(:ok) do
{:ok, 0}
end
def handle_call({:get}, _, count) do
{:reply, count, count}
end
def handle_call({:incr}, _, count) do
new = count + 1
{:reply, new, new}
end
def handle_call({:decr}, _, count) do
new = count - 1
{:reply, new, new}
end
def handle_call({:reset}, _, _) do
{:reply, 0, 0}
end
end
defmodule State.CounterTest do
use ExUnit.Case
test "incr" do
{:ok, counter} = State.Counter.start_link
State.Counter.incr(counter)
value = State.Counter.get(counter)
assert value == 1
end
test "incr twice" do
{:ok, counter} = State.Counter.start_link
State.Counter.incr(counter)
State.Counter.incr(counter)
value = State.Counter.get(counter)
assert value == 2
end
test "incr and decr" do
{:ok, counter} = State.Counter.start_link
State.Counter.incr(counter)
State.Counter.decr(counter)
value = State.Counter.get(counter)
assert value == 0
end
test "decr" do
{:ok, counter} = State.Counter.start_link
State.Counter.decr(counter)
value = State.Counter.get(counter)
assert value == -1
end
test "decr twice" do
{:ok, counter} = State.Counter.start_link
State.Counter.decr(counter)
State.Counter.decr(counter)
value = State.Counter.get(counter)
assert value == -2
end
test "decr and incr" do
{:ok, counter} = State.Counter.start_link
State.Counter.decr(counter)
State.Counter.incr(counter)
value = State.Counter.get(counter)
assert value == 0
end
test "reset from 0" do
{:ok, counter} = State.Counter.start_link
State.Counter.reset(counter)
value = State.Counter.get(counter)
assert value == 0
end
test "reset from not 0" do
{:ok, counter} = State.Counter.start_link
State.Counter.incr(counter)
State.Counter.reset(counter)
value = State.Counter.get(counter)
assert value == 0
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment