Add tests
This commit is contained in:
parent
684daf43cc
commit
fb5fb1b181
|
@ -21,4 +21,5 @@ config :phoenix, :plug_init_mode, :runtime
|
|||
|
||||
config :chronoscope, Chronoscope.NTS,
|
||||
behaviour: Chronoscope.NTS.BehaviourMock,
|
||||
datetime: Chronoscope.NTS.DateTimeMock
|
||||
datetime: Chronoscope.NTS.DateTimeMock,
|
||||
ssl: Chronoscope.NTS.SSLMock
|
||||
|
|
|
@ -21,20 +21,20 @@ defmodule Chronoscope.NTS do
|
|||
|
||||
@impl true
|
||||
def key_establishment(host, port) do
|
||||
GenServer.call(client_pid(host, port), :key_establishment)
|
||||
end
|
||||
|
||||
defp client_pid(host, port) do
|
||||
name = "#{host}:#{port}"
|
||||
|
||||
case Registry.lookup(NTS.Registry, name) do
|
||||
[{pid, _}] ->
|
||||
GenServer.call(pid, :key_establishment)
|
||||
pid
|
||||
|
||||
[] ->
|
||||
{:ok, pid} =
|
||||
DynamicSupervisor.start_child(
|
||||
NTS.DynamicSupervisor,
|
||||
{NTS.Client, host: host, port: port, name: {:via, Registry, {NTS.Registry, name}}}
|
||||
)
|
||||
|
||||
GenServer.call(pid, :key_establishment)
|
||||
NTS.DynamicSupervisor
|
||||
|> DynamicSupervisor.start_child({NTS.Client, host: host, port: port, name: {:via, Registry, {NTS.Registry, name}}})
|
||||
|> then(fn {:ok, pid} -> pid end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
|||
defp ssl_connect(host, port) do
|
||||
host
|
||||
|> String.to_charlist()
|
||||
|> :ssl.connect(port, tls_options(host), @timeout_in_milliseconds)
|
||||
|> ssl().connect(port, tls_options(host), @timeout_in_milliseconds)
|
||||
end
|
||||
|
||||
defp tls_options(host) do
|
||||
|
@ -31,21 +31,21 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
|||
end
|
||||
|
||||
defp perform_key_establishment(socket) do
|
||||
:ok = :ssl.send(socket, KeyEstablishmentRequest.create())
|
||||
{:ok, peercert} = :ssl.peercert(socket)
|
||||
:ok = ssl().send(socket, KeyEstablishmentRequest.create())
|
||||
{:ok, peercert} = ssl().peercert(socket)
|
||||
|
||||
receive do
|
||||
{:ssl, _socket, response} ->
|
||||
:ssl.close(socket)
|
||||
ssl().close(socket)
|
||||
parse_response(response, peercert)
|
||||
|
||||
msg ->
|
||||
:ssl.close(socket)
|
||||
ssl().close(socket)
|
||||
Logger.error("received unexpected message: #{inspect(msg)}")
|
||||
{:error, :no_response}
|
||||
after
|
||||
@timeout_in_milliseconds ->
|
||||
:ssl.close(socket)
|
||||
ssl().close(socket)
|
||||
Logger.error("timed out waiting for response")
|
||||
{:error, :timeout}
|
||||
end
|
||||
|
@ -67,4 +67,8 @@ defmodule Chronoscope.NTS.KeyEstablishmentClient do
|
|||
{:error, String.trim(error)}
|
||||
end
|
||||
end
|
||||
|
||||
defp ssl() do
|
||||
Application.get_env(:chronoscope, Chronoscope.NTS)[:ssl] || :ssl
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
defmodule Chronoscope.NTS.KeyEstablishmentClientTest do
|
||||
use Chronoscope.Case
|
||||
|
||||
alias Chronoscope.NTS.SSLMock
|
||||
alias Chronoscope.NTS.KeyEstablishmentRequest
|
||||
|
||||
import Chronoscope.NTS.KeyEstablishmentClient
|
||||
import Mox
|
||||
|
||||
setup :verify_on_exit!
|
||||
|
||||
@timeout 3000
|
||||
|
||||
defp peercert() do
|
||||
:secp256r1
|
||||
|> X509.PrivateKey.new_ec()
|
||||
|> X509.Certificate.self_signed("/C=US/ST=CA/L=San Francisco/O=Acme/CN=Test")
|
||||
|> X509.Certificate.to_der()
|
||||
end
|
||||
|
||||
defp send_ssl_response(response) do
|
||||
send(self(), {:ssl, nil, response})
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "Chronoscope.NTS.KeyEstablishmentClient.key_establishment()" do
|
||||
test "handles an empty response" do
|
||||
request = KeyEstablishmentRequest.create()
|
||||
|
||||
SSLMock
|
||||
|> expect(:connect, fn ~c"localhost", 2222, _tls_options, @timeout -> {:ok, :socket} end)
|
||||
|> expect(:send, fn :socket, ^request -> send_ssl_response([]) end)
|
||||
|> expect(:peercert, fn :socket -> {:ok, peercert()} end)
|
||||
|> expect(:close, fn :socket -> :ok end)
|
||||
|
||||
assert {:ok, %{cert_expiration: _expiration}} = key_establishment(%{host: "localhost", port: 2222})
|
||||
end
|
||||
|
||||
test "sends the correct TLS options" do
|
||||
SSLMock
|
||||
|> expect(:connect, fn ~c"localhost", 2222, tls_options, @timeout ->
|
||||
assert tls_options[:alpn_advertised_protocols] == ["ntske/1"]
|
||||
{:ok, :socket}
|
||||
end)
|
||||
|> expect(:send, fn :socket, _request -> send_ssl_response([]) end)
|
||||
|> expect(:peercert, fn :socket -> {:ok, peercert()} end)
|
||||
|> expect(:close, fn :socket -> :ok end)
|
||||
|
||||
key_establishment(%{host: "localhost", port: 2222})
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Chronoscope.NTS.KeyEstablishmentRequestTest do
|
||||
use ExUnit.Case
|
||||
use Chronoscope.Case
|
||||
|
||||
import Chronoscope.NTS.KeyEstablishmentRequest
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Chronoscope.NTS.KeyEstablishmentResponseTest do
|
||||
use ExUnit.Case
|
||||
use Chronoscope.Case
|
||||
|
||||
import Chronoscope.NTS.KeyEstablishmentResponse
|
||||
|
||||
|
|
|
@ -7,5 +7,13 @@ defmodule Chronoscope.DateTime.Stub do
|
|||
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.DateTimeMock, for: Chronoscope.DateTime.Behaviour)
|
||||
Mox.defmock(Chronoscope.NTS.SSLMock, for: Chronoscope.SSL.Behaviour)
|
||||
|
|
Loading…
Reference in New Issue