Skip to content

Instantly share code, notes, and snippets.

@adkron
Created August 2, 2017 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adkron/3358fa8802ee030f101d1e500018abec to your computer and use it in GitHub Desktop.
Save adkron/3358fa8802ee030f101d1e500018abec to your computer and use it in GitHub Desktop.
defmodule Zipato.Sessions.Server.Test do
use ExUnit.Case, async: true
@subject Zipato.Sessions.Server
@creds Application.get_env(:zipato, :credentials)
alias Zipato.{TestHelper, Request}
alias HTTPoison.{Response}
defmodule TestImpl do
use GenServer
alias Zipato.Sessions.Behaviour
use Behaviour
def listener(test_process) do
GenServer.start_link(__MODULE__, test_process, name: __MODULE__)
end
@impl Behaviour
def connect(session, creds) do
GenServer.call(__MODULE__, {:do, {:connect, {session, creds}}})
end
@impl Behaviour
def request(session, request) do
GenServer.call(__MODULE__, {:do, {:request, {session, request}}})
end
def handle_call({:do, message}, _from, test) do
send(test, message)
receive do
{:result, result} ->
{:reply, result, test}
after
500 -> {:reply, :no_response, test}
end
end
end
defmacro on(message, reply: reply) do
quote do
impl = GenServer.whereis(TestImpl)
assert_receive unquote(message)
send impl, {:result, unquote(reply)}
end
end
setup do
{:ok, _} = TestImpl.listener(self())
:ok
end
describe "with a serial" do
setup do
serial = TestHelper.random_serial |> String.to_atom()
{:ok, subject} = GenServer.start_link(@subject, [TestImpl, serial])
{:ok, subject: subject, serial: serial}
end
test "initializes with serial and initializing state for hub sessions then connects",
%{subject: subject, serial: serial} do
assert {TestImpl, %{serial: serial, id: :initializing}} == :sys.get_state(subject)
end
test "connects after initialization",
%{subject: subject, serial: serial} do
on {:connect, {%{serial: ^serial, id: :initializing}, @creds}},
reply: %{serial: serial, id: "connected"}
assert {TestImpl, %{serial: serial, id: "connected"}} == :sys.get_state(subject)
end
test "request after connection initialized returns the response",
%{subject: subject, serial: serial} do
on {:connect, {%{serial: ^serial, id: :initializing}, @creds}},
reply: %{serial: serial, id: "connected"}
request = Request.init("/example", :get)
response = %Response{}
assertion = Task.async fn ->
assert response == GenServer.call(subject, {:request, request})
end
on {:request, {%{serial: ^serial, id: "connected"}, ^request}},
reply: response
Task.await(assertion)
end
test "request before connection is initialized waits on connection and then responds",
%{subject: subject, serial: serial} do
request = Request.init("/example", :get)
response = %Response{}
assertion = Task.async fn ->
assert response == GenServer.call(subject, {:request, request})
end
Process.sleep(10)
on {:connect, {%{serial: ^serial, id: :initializing}, @creds}},
reply: %{serial: serial, id: "connected"}
on {:request, {%{serial: ^serial, id: "connected"}, ^request}},
reply: response
Task.await(assertion)
end
end
describe "with no serial" do
setup do
{:ok, subject} = GenServer.start_link(@subject, TestImpl)
{:ok, subject: subject}
end
test "initializes with serial and initializing state for hub sessions then connects",
%{subject: subject} do
assert {TestImpl, %{id: :initializing}} == :sys.get_state(subject)
end
test "connects after initialization",
%{subject: subject} do
on {:connect, {%{id: :initializing}, @creds}},
reply: %{id: "connected"}
assert {TestImpl, %{id: "connected"}} == :sys.get_state(subject)
end
test "request after connection initialized returns the response",
%{subject: subject} do
on {:connect, {%{id: :initializing}, @creds}},
reply: %{id: "connected"}
request = Request.init("/example", :get)
response = %Response{}
assertion = Task.async fn ->
assert response == GenServer.call(subject, {:request, request})
end
on {:request, {%{id: "connected"}, ^request}},
reply: response
Task.await(assertion)
end
test "request before connection is initialized waits on connection and then responds",
%{subject: subject} do
request = Request.init("/example", :get)
response = %Response{}
assertion = Task.async fn ->
assert response == GenServer.call(subject, {:request, request})
end
Process.sleep(10)
on {:connect, {%{id: :initializing}, @creds}},
reply: %{id: "connected"}
on {:request, {%{id: "connected"}, ^request}},
reply: response
Task.await(assertion)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment