-module(enoise_cable_test).
-include_lib("eunit/include/eunit.hrl").
cable_framing_test() ->
AliceKeys = enoise_keypair:new(dh25519),
BobKeys = enoise_keypair:new(dh25519),
PSK =
hex:hexstr_to_bin("0808080808080808080808080808080808080808080808080808080808080808"),
Self = self(),
ServerPid =
spawn_link(fun() ->
{ok, ListenerPid} = enoise_cable:listen(0),
{ok, Port} = enoise_cable:port(ListenerPid),
Self ! {server_port, Port},
{ok, BobConn} =
enoise_cable:accept(ListenerPid, [{keypair, BobKeys}, {psk, PSK}]),
Self ! server_ready,
server_receive_loop(BobConn, Self, [])
end),
Port =
receive
{server_port, P} ->
P
end,
spawn_link(fun() ->
{ok, AliceConn} =
enoise_cable:connect("localhost", Port, [{keypair, AliceKeys}, {psk, PSK}]),
Self ! client_ready,
Msg1 = <<"Hello, Cable!">>,
ok = enoise_cable:send(AliceConn, Msg1),
LargeMsg = binary:copy(<<"X">>, 100000),
ok = enoise_cable:send(AliceConn, LargeMsg),
receive
{cable_transport, _, Msg2} ->
Self ! {client_received, Msg2},
ok
after 5000 -> Self ! {client_error, timeout_recv}
end,
enoise_cable:close(AliceConn)
end),
wait_for_ready(),
receive
{server_received, <<"Hello, Cable!">>} ->
ok;
Other1 ->
error({unexpected_msg1, Other1})
after 5000 ->
error(timeout_msg1)
end,
LargeMsg = binary:copy(<<"X">>, 100000),
receive
{server_received, ReceivedLarge} ->
?assertEqual(LargeMsg, ReceivedLarge),
ok;
OtherLarge ->
error({unexpected_large_msg, OtherLarge})
after 10000 ->
error(timeout_large_msg)
end,
ServerPid ! {send_response, <<"Hello, Alice!">>},
receive
{client_received, <<"Hello, Alice!">>} ->
ok
after 5000 ->
error(timeout_msg2)
end,
ok.
server_receive_loop(Conn, TestPid, Seen) ->
receive
{send_response, Msg} ->
ok = enoise_cable:send(Conn, Msg),
server_receive_loop(Conn, TestPid, Seen);
{cable_transport, _, Msg} ->
io:format(user, "[test] Server loop received ~p bytes~n", [byte_size(Msg)]),
TestPid ! {server_received, Msg},
server_receive_loop(Conn, TestPid, [Msg | Seen])
after 10000 ->
io:format(user, "[test] Server loop timeout, closing~n", []),
enoise_cable:close(Conn)
end.
wait_for_ready() ->
wait_for_ready(undefined, undefined).
wait_for_ready(M1, M2) when M1 =/= undefined, M2 =/= undefined ->
io:format(user, "both ready~n", []),
ok;
wait_for_ready(Srv, Cli) ->
receive
client_ready ->
io:format(user, "Client ready~n", []),
wait_for_ready(Srv, client_read);
server_ready ->
io:format(user, "Server ready~n", []),
wait_for_ready(server_ready, Cli)
after 5000 ->
error(timeout_waiting_for_ready)
end.