Refactor mocks
This commit is contained in:
parent
a17857576d
commit
9c3523d9d1
|
@ -21,5 +21,8 @@ config :phoenix, :plug_init_mode, :runtime
|
||||||
|
|
||||||
config :chronoscope, Chronoscope.NTS,
|
config :chronoscope, Chronoscope.NTS,
|
||||||
behaviour: Chronoscope.NTS.BehaviourMock,
|
behaviour: Chronoscope.NTS.BehaviourMock,
|
||||||
datetime: Chronoscope.NTS.DateTimeMock,
|
date_time: Chronoscope.NTS.DateTimeMock,
|
||||||
ssl: Chronoscope.NTS.SSLMock
|
ssl: Chronoscope.NTS.SSLMock,
|
||||||
|
registry: Chronoscope.NTS.RegistryMock,
|
||||||
|
dynamic_supervisor: Chronoscope.NTS.DynamicSupervisorMock,
|
||||||
|
gen_server: Chronoscope.NTS.GenServerMock
|
||||||
|
|
|
@ -9,22 +9,26 @@ defmodule Chronoscope.NTS do
|
||||||
|
|
||||||
alias Chronoscope.NTS
|
alias Chronoscope.NTS
|
||||||
|
|
||||||
|
@registry Application.compile_env(:chronoscope, Chronoscope.NTS)[:registry] || Registry
|
||||||
|
@genserver Application.compile_env(:chronoscope, Chronoscope.NTS)[:gen_server] || GenServer
|
||||||
|
@dynamic_supervisor Application.compile_env(:chronoscope, Chronoscope.NTS)[:dynamic_supervisor] || DynamicSupervisor
|
||||||
|
|
||||||
def healthy?() do
|
def healthy?() do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def list() do
|
def list() do
|
||||||
NTS.DynamicSupervisor
|
NTS.DynamicSupervisor
|
||||||
|> DynamicSupervisor.which_children()
|
|> @dynamic_supervisor.which_children()
|
||||||
|> Enum.map(fn {_, pid, _, _} -> GenServer.call(pid, :list) end)
|
|> Enum.map(fn {_, pid, _, _} -> @genserver.call(pid, :list) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove(host, port) do
|
def remove(host, port) do
|
||||||
name = client_name(%{host: host, port: port})
|
name = client_name(%{host: host, port: port})
|
||||||
|
|
||||||
case Registry.lookup(NTS.Registry, name) do
|
case @registry.lookup(NTS.Registry, name) do
|
||||||
[{pid, _}] -> GenServer.call(pid, :terminate)
|
[{pid, _}] -> {:ok, @genserver.call(pid, :terminate)}
|
||||||
[] -> {:error, :notfound}
|
[] -> {:error, :not_found}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -32,13 +36,13 @@ defmodule Chronoscope.NTS do
|
||||||
def key_establishment(host, port) do
|
def key_establishment(host, port) do
|
||||||
%{host: host, port: port}
|
%{host: host, port: port}
|
||||||
|> client_pid()
|
|> client_pid()
|
||||||
|> GenServer.call(:key_establishment)
|
|> @genserver.call(:key_establishment)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp client_pid(server) do
|
defp client_pid(server) do
|
||||||
name = client_name(server)
|
name = client_name(server)
|
||||||
|
|
||||||
case Registry.lookup(NTS.Registry, name) do
|
case @registry.lookup(NTS.Registry, name) do
|
||||||
[{pid, _}] -> pid
|
[{pid, _}] -> pid
|
||||||
[] -> start_client(server, name)
|
[] -> start_client(server, name)
|
||||||
end
|
end
|
||||||
|
@ -50,7 +54,7 @@ defmodule Chronoscope.NTS do
|
||||||
|
|
||||||
defp start_client(server, name) do
|
defp start_client(server, name) do
|
||||||
NTS.DynamicSupervisor
|
NTS.DynamicSupervisor
|
||||||
|> DynamicSupervisor.start_child({NTS.Client, server: server, name: {:via, Registry, {NTS.Registry, name}}})
|
|> @dynamic_supervisor.start_child({NTS.Client, server: server, name: {:via, @registry, {NTS.Registry, name}}})
|
||||||
|> then(fn {:ok, pid} -> pid end)
|
|> then(fn {:ok, pid} -> pid end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
defmodule Chronoscope.NTS.Certificate do
|
defmodule Chronoscope.NTS.Certificate do
|
||||||
|
@date_time Application.compile_env(:chronoscope, Chronoscope.NTS)[:date_time] || DateTime
|
||||||
|
|
||||||
def expiration_date(certificate) do
|
def expiration_date(certificate) do
|
||||||
{:Validity, _, {:utcTime, expiration}} =
|
{:Validity, _, {:utcTime, expiration}} =
|
||||||
certificate
|
certificate
|
||||||
|
@ -20,7 +22,7 @@ defmodule Chronoscope.NTS.Certificate do
|
||||||
|
|
||||||
defp short_year_to_full_year(short_year) do
|
defp short_year_to_full_year(short_year) do
|
||||||
{century, current_year} =
|
{century, current_year} =
|
||||||
datetime().utc_now().year
|
@date_time.utc_now().year
|
||||||
|> to_string()
|
|> to_string()
|
||||||
|> String.split_at(-2)
|
|> String.split_at(-2)
|
||||||
|
|
||||||
|
@ -32,8 +34,4 @@ defmodule Chronoscope.NTS.Certificate do
|
||||||
|> then(&"#{&1 + 1}#{short_year}")
|
|> then(&"#{&1 + 1}#{short_year}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp datetime() do
|
|
||||||
Application.get_env(:chronoscope, Chronoscope.NTS)[:datetime] || DateTime
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ defmodule Chronoscope.NTS.Client do
|
||||||
alias Chronoscope.NTS.KeyEstablishmentClient
|
alias Chronoscope.NTS.KeyEstablishmentClient
|
||||||
|
|
||||||
@interval_in_seconds 30
|
@interval_in_seconds 30
|
||||||
|
@date_time Application.compile_env(:chronoscope, Chronoscope.NTS)[:date_time] || DateTime
|
||||||
|
|
||||||
def start_link(server: server, name: name) do
|
def start_link(server: server, name: name) do
|
||||||
GenServer.start_link(__MODULE__, server, name: name)
|
GenServer.start_link(__MODULE__, server, name: name)
|
||||||
|
@ -70,10 +71,6 @@ defmodule Chronoscope.NTS.Client do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp utc_now() do
|
defp utc_now() do
|
||||||
datetime().utc_now()
|
@date_time.utc_now()
|
||||||
end
|
|
||||||
|
|
||||||
defp datetime() do
|
|
||||||
Application.get_env(:chronoscope, Chronoscope.NTS)[:datetime] || DateTime
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
||||||
alias Chronoscope.NTS.KeyEstablishmentResponse
|
alias Chronoscope.NTS.KeyEstablishmentResponse
|
||||||
|
|
||||||
@timeout_in_milliseconds 3000
|
@timeout_in_milliseconds 3000
|
||||||
|
@ssl Application.compile_env(:chronoscope, Chronoscope.NTS)[:ssl] || :ssl
|
||||||
|
|
||||||
def key_establishment(%{host: host, port: port}) do
|
def key_establishment(%{host: host, port: port}) do
|
||||||
case ssl_connect(host, port) do
|
case ssl_connect(host, port) do
|
||||||
|
@ -21,7 +22,7 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
||||||
defp ssl_connect(host, port) do
|
defp ssl_connect(host, port) do
|
||||||
host
|
host
|
||||||
|> String.to_charlist()
|
|> String.to_charlist()
|
||||||
|> ssl().connect(port, tls_options(host), @timeout_in_milliseconds)
|
|> @ssl.connect(port, tls_options(host), @timeout_in_milliseconds)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp tls_options(host) do
|
defp tls_options(host) do
|
||||||
|
@ -31,21 +32,21 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp perform_key_establishment(socket) do
|
defp perform_key_establishment(socket) do
|
||||||
:ok = ssl().send(socket, KeyEstablishmentRequest.create())
|
:ok = @ssl.send(socket, KeyEstablishmentRequest.create())
|
||||||
{:ok, peercert} = ssl().peercert(socket)
|
{:ok, peercert} = @ssl.peercert(socket)
|
||||||
|
|
||||||
receive do
|
receive do
|
||||||
{:ssl, _socket, response} ->
|
{:ssl, _socket, response} ->
|
||||||
ssl().close(socket)
|
@ssl.close(socket)
|
||||||
parse_response(response, peercert)
|
parse_response(response, peercert)
|
||||||
|
|
||||||
msg ->
|
msg ->
|
||||||
ssl().close(socket)
|
@ssl.close(socket)
|
||||||
Logger.error("received unexpected message: #{inspect(msg)}")
|
Logger.error("received unexpected message: #{inspect(msg)}")
|
||||||
{:error, :no_response}
|
{:error, :no_response}
|
||||||
after
|
after
|
||||||
@timeout_in_milliseconds ->
|
@timeout_in_milliseconds ->
|
||||||
ssl().close(socket)
|
@ssl.close(socket)
|
||||||
Logger.error("timed out waiting for response")
|
Logger.error("timed out waiting for response")
|
||||||
{:error, :timeout}
|
{:error, :timeout}
|
||||||
end
|
end
|
||||||
|
@ -67,8 +68,4 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
||||||
{:error, String.trim(error)}
|
{:error, String.trim(error)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp ssl() do
|
|
||||||
Application.get_env(:chronoscope, Chronoscope.NTS)[:ssl] || :ssl
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule ChronoscopeWeb.API.V1.NTS.KeyEstablishmentController do
|
||||||
|
|
||||||
@default_port 4460
|
@default_port 4460
|
||||||
@max_host_length 255
|
@max_host_length 255
|
||||||
|
@nts Application.compile_env(:chronoscope, NTS)[:behaviour] || NTS
|
||||||
|
|
||||||
def get(conn, %{"host" => host, "port" => port}) do
|
def get(conn, %{"host" => host, "port" => port}) do
|
||||||
try do
|
try do
|
||||||
|
@ -41,7 +42,7 @@ defmodule ChronoscopeWeb.API.V1.NTS.KeyEstablishmentController do
|
||||||
defp key_establishment_response(host, port) do
|
defp key_establishment_response(host, port) do
|
||||||
host
|
host
|
||||||
|> String.slice(0, @max_host_length)
|
|> String.slice(0, @max_host_length)
|
||||||
|> nts_behaviour().key_establishment(port)
|
|> @nts.key_establishment(port)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_response(response) do
|
defp format_response(response) do
|
||||||
|
@ -55,8 +56,4 @@ defmodule ChronoscopeWeb.API.V1.NTS.KeyEstablishmentController do
|
||||||
|> put_status(:bad_request)
|
|> put_status(:bad_request)
|
||||||
|> json(%{error: message})
|
|> json(%{error: message})
|
||||||
end
|
end
|
||||||
|
|
||||||
defp nts_behaviour() do
|
|
||||||
Application.get_env(:chronoscope, NTS)[:behaviour] || NTS
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
defmodule Chronoscope.NTSTest do
|
defmodule Chronoscope.NTSTest do
|
||||||
use Chronoscope.Case
|
use Chronoscope.Case
|
||||||
|
|
||||||
|
alias Chronoscope.NTS.DynamicSupervisorMock
|
||||||
|
alias Chronoscope.NTS.GenServerMock
|
||||||
|
alias Chronoscope.NTS.RegistryMock
|
||||||
|
|
||||||
import Chronoscope.NTS
|
import Chronoscope.NTS
|
||||||
|
import Mox
|
||||||
|
|
||||||
|
setup :verify_on_exit!
|
||||||
|
|
||||||
describe "Chronoscope.NTS.healthy?()" do
|
describe "Chronoscope.NTS.healthy?()" do
|
||||||
test "is healthy" do
|
test "is healthy" do
|
||||||
|
@ -11,13 +18,30 @@ defmodule Chronoscope.NTSTest do
|
||||||
|
|
||||||
describe "Chronoscope.NTS.list()" do
|
describe "Chronoscope.NTS.list()" do
|
||||||
test "shows empty client list" do
|
test "shows empty client list" do
|
||||||
|
DynamicSupervisorMock
|
||||||
|
|> expect(:which_children, fn _ -> [] end)
|
||||||
|
|
||||||
assert list() == []
|
assert list() == []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "lists all children" do
|
||||||
|
DynamicSupervisorMock
|
||||||
|
|> expect(:which_children, fn _ -> [{1, 2, 3, 4}, {5, 6, 7, 8}] end)
|
||||||
|
|
||||||
|
GenServerMock
|
||||||
|
|> expect(:call, fn 2, :list -> :one end)
|
||||||
|
|> expect(:call, fn 6, :list -> :two end)
|
||||||
|
|
||||||
|
assert list() == [:one, :two]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Chronoscope.NTS.remove()" do
|
describe "Chronoscope.NTS.remove()" do
|
||||||
test "does nothing if the client doesn't exist" do
|
test "does nothing if the client doesn't exist" do
|
||||||
assert remove("localhost", 1111) == {:error, :notfound}
|
RegistryMock
|
||||||
|
|> expect(:lookup, fn _, _ -> [] end)
|
||||||
|
|
||||||
|
assert remove("localhost", 1111) == {:error, :not_found}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
defmodule Chronoscope.DateTime.Behaviour do
|
||||||
|
@callback utc_now :: DateTime.t()
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Chronoscope.SSL.Behaviour do
|
||||||
|
@callback connect(any(), any(), any(), any()) :: {:ok, any()} | {:error, any()}
|
||||||
|
@callback send(any(), any()) :: :ok | {:error, any()}
|
||||||
|
@callback peercert(any()) :: {:ok, any()} | {:error, any()}
|
||||||
|
@callback close(any()) :: :ok | {:error, any()}
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Chronoscope.Registry.Behaviour do
|
||||||
|
@callback lookup(atom(), any()) :: [{pid(), any()}]
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Chronoscope.DynamicSupervisor.Behaviour do
|
||||||
|
@callback start_child(Supervisor.supervisor(), any()) :: any()
|
||||||
|
@callback which_children(Supervisor.supervisor()) :: [any()]
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Chronoscope.GenServer.Behaviour do
|
||||||
|
@callback call(pid(), any()) :: any()
|
||||||
|
end
|
|
@ -1,19 +1,6 @@
|
||||||
defmodule Chronoscope.DateTime.Behaviour do
|
|
||||||
@callback utc_now :: DateTime.t()
|
|
||||||
end
|
|
||||||
|
|
||||||
defmodule Chronoscope.DateTime.Stub do
|
|
||||||
@behaviour Chronoscope.DateTime.Behaviour
|
|
||||||
def utc_now(), do: DateTime.utc_now()
|
|
||||||
end
|
|
||||||
|
|
||||||
defmodule Chronoscope.SSL.Behaviour do
|
|
||||||
@callback connect(any(), any(), any(), any()) :: {:ok, any()} | {:error, any()}
|
|
||||||
@callback send(any(), any()) :: :ok | {:error, any()}
|
|
||||||
@callback peercert(any()) :: {:ok, any()} | {:error, any()}
|
|
||||||
@callback close(any()) :: :ok | {:error, any()}
|
|
||||||
end
|
|
||||||
|
|
||||||
Mox.defmock(Chronoscope.NTS.BehaviourMock, for: Chronoscope.NTS.Behaviour)
|
Mox.defmock(Chronoscope.NTS.BehaviourMock, for: Chronoscope.NTS.Behaviour)
|
||||||
Mox.defmock(Chronoscope.NTS.DateTimeMock, for: Chronoscope.DateTime.Behaviour)
|
Mox.defmock(Chronoscope.NTS.DateTimeMock, for: Chronoscope.DateTime.Behaviour)
|
||||||
Mox.defmock(Chronoscope.NTS.SSLMock, for: Chronoscope.SSL.Behaviour)
|
Mox.defmock(Chronoscope.NTS.SSLMock, for: Chronoscope.SSL.Behaviour)
|
||||||
|
Mox.defmock(Chronoscope.NTS.RegistryMock, for: Chronoscope.Registry.Behaviour)
|
||||||
|
Mox.defmock(Chronoscope.NTS.DynamicSupervisorMock, for: Chronoscope.DynamicSupervisor.Behaviour)
|
||||||
|
Mox.defmock(Chronoscope.NTS.GenServerMock, for: Chronoscope.GenServer.Behaviour)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
defmodule Chronoscope.DateTime.Stub do
|
||||||
|
@behaviour Chronoscope.DateTime.Behaviour
|
||||||
|
def utc_now(), do: DateTime.utc_now()
|
||||||
|
end
|
Loading…
Reference in New Issue