-module(cabal_peer_suite).
-include_lib("eunit/include/eunit.hrl").
open_close_test() ->
A = make_test_args(),
{ok, PSup} = cabal_sup:start_link(A),
P = cabal_sup:get_peer_pid(PSup),
?assertNotEqual(P, 0),
ok = cabal_sup:stop(PSup).
empty_state_test() ->
A = make_test_args(),
{ok, PSup} = cabal_sup:start_link(A),
P = cabal_sup:get_peer_pid(PSup),
{ok, Chans} = cabal:channels_joined(P),
?assertEqual([], Chans),
{ok, Known} = cabal:channels_known(P),
?assertEqual([], Known),
ok = cabal_sup:stop(PSup).
join_and_leave_test() ->
A = make_test_args(),
{ok, PSup} = cabal_sup:start_link(A),
P = cabal_sup:get_peer_pid(PSup),
{ok, []} = cabal:channels_joined(P),
{ok, []} = cabal:channels_known(P),
cabal:join(P, "default"),
{ok, ["default"]} = cabal:channels_joined(P),
{ok, ["default"]} = cabal:channels_known(P),
ok = cabal:leave(P, "default"),
{ok, []} = cabal:channels_joined(P),
{ok, ["default"]} = cabal:channels_known(P),
ok = cabal_sup:stop(PSup).
multi_channel_membership_test() ->
A = make_test_args(),
{ok, PSup} = cabal_sup:start_link(A),
P = cabal_sup:get_peer_pid(PSup),
{ok, PubKey} = cabal:node_public_key(P),
cabal:join(P, "ChannelA"),
{ok, MembersA} = cabal:channel_members(P, "ChannelA"),
MembersMapA = proplists:get_value(members, MembersA),
?assert(maps:is_key(PubKey, MembersMapA)),
cabal:join(P, "ChannelB"),
{ok, MembersB} = cabal:channel_members(P, "ChannelB"),
MembersMapB = proplists:get_value(members, MembersB),
?assert(maps:is_key(PubKey, MembersMapB)),
{ok, MembersA2} = cabal:channel_members(P, "ChannelA"),
MembersMapA2 = proplists:get_value(members, MembersA2),
?assert(maps:is_key(PubKey, MembersMapA2)),
ok = cabal_sup:stop(PSup).
channels_known_test() ->
A = make_test_args(),
{ok, PSup} = cabal_sup:start_link(A),
P = cabal_sup:get_peer_pid(PSup),
{ok, []} = cabal:channels_known(P),
cabal:join(P, "general"),
cabal:join(P, "random"),
cabal:join(P, "dev"),
{ok, Known1} = cabal:channels_known(P),
?assertEqual(3, length(Known1)),
?assert(lists:member("general", Known1)),
?assert(lists:member("random", Known1)),
?assert(lists:member("dev", Known1)),
ok = cabal:write(P, "general", "Hello world!"),
{ok, Known2} = cabal:channels_known(P),
?assertEqual(3, length(Known2)),
ok = cabal:leave(P, "dev"),
{ok, Known3} = cabal:channels_known(P),
?assertEqual(3, length(Known3)),
?assert(lists:member("dev", Known3)),
{ok, Joined} = cabal:channels_joined(P),
?assertEqual(2, length(Joined)),
?assertNot(lists:member("dev", Joined)),
ok = cabal_sup:stop(PSup).
connect_two_peers_test() ->
[A, B] = [make_test_args(Name) || Name <- ["Alfi", "Bert"]],
{ok, AlfiSup} = cabal_sup:start_link(A),
Alfi = cabal_sup:get_peer_pid(AlfiSup),
{ok, BertSup} = cabal_sup:start_link(B),
Bert = cabal_sup:get_peer_pid(BertSup),
cabal:join(Alfi, "test"),
cabal:join(Bert, "test"),
{ok, AlfiAddr} = cabal:node_addr(Alfi),
ok = cabal:dial(Bert, AlfiAddr),
timer:sleep(1000),
AlfisList = cabal:peer_list(Alfi),
?debugFmt("~nA's list: ~p~n", [AlfisList]),
?assertEqual(1, length(AlfisList)),
BertsList = cabal:peer_list(Bert),
?debugFmt("~nB's list: ~p~n", [BertsList]),
?assertEqual(1, length(BertsList)),
ok = cabal_sup:stop(AlfiSup),
ok = cabal_sup:stop(BertSup).
channels_known_from_peers_test() ->
[A, B] = [make_test_args(Name) || Name <- ["Alice", "Bob"]],
{ok, AliceSup} = cabal_sup:start_link(A),
Alice = cabal_sup:get_peer_pid(AliceSup),
{ok, BobSup} = cabal_sup:start_link(B),
Bob = cabal_sup:get_peer_pid(BobSup),
cabal:join(Alice, "announcements"),
cabal:join(Alice, "watercooler"),
ok = cabal:write(Alice, "announcements", "Important news!"),
ok = cabal:write(Alice, "watercooler", "How's everyone doing?"),
cabal:join(Bob, "watercooler"),
{ok, AliceAddr} = cabal:node_addr(Alice),
ok = cabal:dial(Bob, AliceAddr),
timer:sleep(1500),
{ok, AliceKnown} = cabal:channels_known(Alice),
?assertEqual(2, length(AliceKnown)),
?assert(lists:member("announcements", AliceKnown)),
?assert(lists:member("watercooler", AliceKnown)),
{ok, BobKnown} = cabal:channels_known(Bob),
?debugFmt("~nBob's known channels: ~p~n", [BobKnown]),
?assert(length(BobKnown) >= 1),
?assert(lists:member("watercooler", BobKnown)),
{ok, BobJoined} = cabal:channels_joined(Bob),
?assertEqual(["watercooler"], BobJoined),
ok = cabal_sup:stop(AliceSup),
ok = cabal_sup:stop(BobSup).
channel_list_request_test() ->
[A, B] = [make_test_args(Name) || Name <- ["Alice", "Bob"]],
{ok, AliceSup} = cabal_sup:start_link(A),
Alice = cabal_sup:get_peer_pid(AliceSup),
{ok, BobSup} = cabal_sup:start_link(B),
Bob = cabal_sup:get_peer_pid(BobSup),
cabal:join(Alice, "general"),
cabal:join(Alice, "random"),
cabal:join(Alice, "dev"),
cabal:join(Bob, "announcements"),
{ok, AliceListenAddr} = cabal:node_addr(Alice),
ok = cabal:dial(Bob, AliceListenAddr),
timer:sleep(500),
BobPeerList = cabal:peer_list(Bob),
?assertEqual(1, length(BobPeerList)),
[{AliceActualAddr, _}] = BobPeerList,
AlicePeerList = cabal:peer_list(Alice),
?assertEqual(1, length(AlicePeerList)),
[{BobActualAddr, _}] = AlicePeerList,
ok = cabal:request_channel_list(Bob, AliceActualAddr),
timer:sleep(1000),
{ok, AliceChannels} = cabal:peer_channel_list(Bob, AliceActualAddr),
?assertEqual(3, length(AliceChannels)),
?assert(lists:member("general", AliceChannels)),
?assert(lists:member("random", AliceChannels)),
?assert(lists:member("dev", AliceChannels)),
ok = cabal:request_channel_list(Alice, BobActualAddr),
timer:sleep(1000),
{ok, BobChannels} = cabal:peer_channel_list(Alice, BobActualAddr),
?assertEqual(1, length(BobChannels)),
?assert(lists:member("announcements", BobChannels)),
ok = cabal_sup:stop(AliceSup),
ok = cabal_sup:stop(BobSup).
set_nick_and_topic_test() ->
[A, B] = [make_test_args() || _ <- lists:seq(1, 2)],
{ok, AlfiSup} = cabal_sup:start_link(A),
Alfi = cabal_sup:get_peer_pid(AlfiSup),
{ok, BertSup} = cabal_sup:start_link(B),
Bert = cabal_sup:get_peer_pid(BertSup),
{ok, PubAlfi} = cabal:node_public_key(Alfi),
{ok, PubBert} = cabal:node_public_key(Bert),
ok = cabal:set_nick(Alfi, "Alfi"),
ok = cabal:set_nick(Bert, "Not Ernie!"),
C = "test",
cabal:join(Alfi, C),
cabal:join(Bert, C),
T = "the mega testing channel",
ok = cabal:set_topic(Alfi, C, T),
{ok, PeerAddr} = cabal:node_addr(Bert),
ok = cabal:dial(Alfi, PeerAddr),
timer:sleep(1000),
CheckState = fun(Peer) ->
{ok, CState} = cabal:channel_members(Peer, C),
?assertEqual(T, proplists:get_value(topic, CState)),
Members = proplists:get_value(members, CState),
?assertEqual(2, maps:size(Members)),
{AlfiName, AlfiWhen, false} = maps:get(PubAlfi, Members),
?assertEqual("Alfi", AlfiName),
?assert(AlfiWhen > 0),
{BertName, BertWhen, false} = maps:get(PubBert, Members),
?assertEqual("Not Ernie!", BertName),
?assert(BertWhen > 0)
end,
lists:foreach(CheckState, [Alfi, Bert]),
ok = cabal_sup:stop(AlfiSup),
ok = cabal_sup:stop(BertSup).
chat_test() ->
[A, B] = [make_test_args() || _ <- lists:seq(1, 2)],
{ok, AlfiSup} = cabal_sup:start_link(A),
Alfi = cabal_sup:get_peer_pid(AlfiSup),
{ok, BertSup} = cabal_sup:start_link(B),
Bert = cabal_sup:get_peer_pid(BertSup),
{ok, PubAlfi} = cabal:node_public_key(Alfi),
{ok, PubBert} = cabal:node_public_key(Bert),
NickAlfi = "Alfi",
NickBert = "Not ernie!!",
ok = cabal:set_nick(Alfi, NickAlfi),
ok = cabal:set_nick(Bert, NickBert),
C = "test",
cabal:join(Alfi, C),
cabal:join(Bert, C),
T1 = "someone here?",
T2 = "is this thing on?",
ok = cabal:write(Alfi, C, T1),
timer:sleep(500),
ok = cabal:write(Bert, C, T2),
{ok, PeerAddr} = cabal:node_addr(Bert),
ok = cabal:dial(Alfi, PeerAddr),
timer:sleep(1000),
Check = fun(Peer) ->
{ok, {Texts, Users}} = cabal:read(Peer, C),
[{UserIdAlfi, _, T1}, {UserIdBert, _, T2}] = Texts,
{AlfiInfo, UsersSansAlfi} = maps:take(UserIdAlfi, Users),
?assertEqual({NickAlfi, PubAlfi}, AlfiInfo),
{BertInfo, #{}} = maps:take(UserIdBert, UsersSansAlfi),
?assertEqual({NickBert, PubBert}, BertInfo)
end,
lists:foreach(Check, [Alfi, Bert]),
ok = cabal:write(Alfi, C, "ohai! o/"),
timer:sleep(500),
{ok, {Texts, _}} = cabal:read(Bert, C),
?assertEqual(3, length(Texts)),
ok = cabal:write(Bert, C, "nice to meet you!"),
timer:sleep(250),
{ok, {Texts2, _}} = cabal:read(Alfi, C),
?assertEqual(4, length(Texts2)),
ok = cabal_sup:stop(AlfiSup),
ok = cabal_sup:stop(BertSup).
hashing_test() ->
Table = [
{"Two hands clap and there is a sound. What is the sound of one hand?",
"fcd7c41883c3564c5a6abec78e214159efe62d50f124b4afafc184ea3b764cd4"},
{"茶色", "46b321c236880cd861dafae3040cf8cc52990516d1a69ab2c170b1e615a7ebd5"},
{"elf", "ffe809405a3e1eaf77938bde2138832b177a51e47df02935edc12aacf8279f61"},
{"love collapses spacetime",
"fea16c09f8aa581500fcf6ee2f6aabc59ccaa271d2a3568843930b7ff929ad86"}
],
lists:foreach(
fun({InStr, Want}) ->
In = unicode:characters_to_binary(InStr),
Got = enacl:generichash(32, In),
GotHex = hex:bin_to_hexstr(Got),
?assertEqual(Want, string:lowercase(GotHex))
end,
Table
).
make_test_args(Name) ->
S = string:chomp(os:cmd("mktemp --tmpdir -d caberl-peer-XXXXX")),
?debugFmt("~nUsing Storage for ~s: ~p~n", [Name, S]),
[
{nickname, Name},
{listener, ["localhost", 0]},
{storage, S}
].
make_test_args() ->
make_test_args("unnamed").