diff options
Diffstat (limited to 'shard/test')
-rw-r--r-- | shard/test/conn_test.exs | 62 | ||||
-rw-r--r-- | shard/test/mkllst_test.exs | 18 | ||||
-rw-r--r-- | shard/test/mst_test.exs | 197 | ||||
-rw-r--r-- | shard/test/test_helper.exs | 8 |
4 files changed, 285 insertions, 0 deletions
diff --git a/shard/test/conn_test.exs b/shard/test/conn_test.exs new file mode 100644 index 0000000..275f6dd --- /dev/null +++ b/shard/test/conn_test.exs @@ -0,0 +1,62 @@ +defmodule ShardTest.Conn do + use ExUnit.Case + doctest Shard.Application + + require Salty.Box.Curve25519xchacha20poly1305, as: Box + require Salty.Sign.Ed25519, as: Sign + + test "crypto connection" do + {:ok, srv_pkey, srv_skey} = Sign.keypair + {:ok, sess_pkey, sess_skey} = Box.keypair + {:ok, challenge} = Salty.Random.buf 32 + {:ok, socket} = :gen_tcp.connect {127,0,0,1}, 4044, [:binary, packet: 2, active: false] + + hello = {srv_pkey, sess_pkey, challenge, 0} + :gen_tcp.send(socket, :erlang.term_to_binary hello) + {:ok, pkt} = :gen_tcp.recv(socket, 0) + {cli_pkey, cli_sess_pkey, cli_challenge, _his_port} = :erlang.binary_to_term(pkt, [:safe]) + + {:ok, cli_challenge_sign} = Sign.sign_detached(cli_challenge, srv_skey) + sendmsg(socket, cli_challenge_sign, cli_sess_pkey, sess_skey) + + challenge_sign = recvmsg(socket, cli_sess_pkey, sess_skey) + :ok = Sign.verify_detached(challenge_sign, challenge, cli_pkey) + + pkt = :erlang.binary_to_term(recvmsg(socket, cli_sess_pkey, sess_skey), [:safe]) + IO.puts (inspect pkt) + end + + defp sendmsg(sock, msg, pk, sk) do + {:ok, n} = Salty.Random.buf Box.noncebytes + {:ok, msg} = Box.easy(msg, n, pk, sk) + :gen_tcp.send(sock, n <> msg) + end + + defp recvmsg(sock, pk, sk) do + {:ok, pkt} = :gen_tcp.recv(sock, 0) + n = binary_part(pkt, 0, Box.noncebytes) + enc = binary_part(pkt, Box.noncebytes, (byte_size pkt) - Box.noncebytes) + {:ok, msg} = Box.open_easy(enc, n, pk, sk) + msg + end + + + test "set nickname" do + Shard.Identity.set_nickname "test bot" + end + + test "connect to other instance" do + Shard.Manager.add_peer({127, 0, 0, 1}, 4045) + receive do after 100 -> nil end + end + + test "connect to chat rooms" do + {:ok, pid1} = DynamicSupervisor.start_child(Shard.DynamicSupervisor, {SApp.Chat, "test"}) + {:ok, pid2} = DynamicSupervisor.start_child(Shard.DynamicSupervisor, {SApp.Chat, "other_test"}) + GenServer.cast(pid1, {:chat_send, "test msg 1"}) + GenServer.cast(pid2, {:chat_send, "test msg 2"}) + + {:error, :redundant} = DynamicSupervisor.start_child(Shard.DynamicSupervisor, {SApp.Chat, "test"}) + end + +end diff --git a/shard/test/mkllst_test.exs b/shard/test/mkllst_test.exs new file mode 100644 index 0000000..68dacf3 --- /dev/null +++ b/shard/test/mkllst_test.exs @@ -0,0 +1,18 @@ +defmodule ShardTest.MklLst do + use ExUnit.Case + doctest Shard.Application + + test "merkle list" do + alias SData.MerkleList, as: ML + + mkl = ML.new(&SData.cmp_ts_str/2) + + {:ok, [], nil} = ML.read(mkl) + + mkl = ML.insert(mkl, {12, "aa, bb"}) + mkl = ML.insert_many(mkl, [{14, "qwerty"}, {8, "haha"}]) + mkl = ML.insert(mkl, {14, "qwerty"}) + {:ok, list, nil} = ML.read(mkl, nil, nil) + assert length(list) == 3 + end +end diff --git a/shard/test/mst_test.exs b/shard/test/mst_test.exs new file mode 100644 index 0000000..c1758ad --- /dev/null +++ b/shard/test/mst_test.exs @@ -0,0 +1,197 @@ +defmodule ShardTest.MST do + use ExUnit.Case + alias SData.MerkleSearchTree, as: MST + doctest Shard.Application + + test "merkle search tree 1" do + y = Enum.reduce(0..1000, %MST{}, + fn i, acc -> MST.insert(acc, i) end) + + + z = Enum.reduce(Enum.shuffle(0..1000), %MST{}, + fn i, acc -> MST.insert(acc, i) end) + + for i <- 0..1000 do + assert MST.get(y, i) == true + assert MST.get(z, i) == true + end + assert MST.get(y, 9999) == nil + assert MST.get(z, -1001) == nil + assert MST.get(z, 1.01) == nil + + IO.puts "y.root: #{y.root|>Base.encode16}" + IO.puts "z.root: #{z.root|>Base.encode16}" + assert y.root == z.root + end + + test "merkle search tree 2" do + items = for i <- 0..1000 do + h = SData.term_hash i + {h, SData.term_hash h} + end + + merge = fn a, b -> if a > b do a else b end end + + y = Enum.reduce(items, %MST{merge: merge}, + fn {k, v}, acc -> MST.insert(acc, k, v) end) + + z = Enum.reduce(Enum.shuffle(items), %MST{merge: merge}, + fn {k, v}, acc -> MST.insert(acc, k, v) end) + + for {k, v} <- items do + assert MST.get(y, k) == v + assert MST.get(z, k) == v + end + + IO.puts "y.root: #{y.root|>Base.encode16}" + IO.puts "z.root: #{z.root|>Base.encode16}" + assert y.root == z.root + end + + test "merkle search tree 3" do + merge = fn a, b -> if a > b do a else b end end + + y = Enum.reduce(0..1000, %MST{merge: merge}, + fn i, acc -> MST.insert(acc, i, i) end) + y = Enum.reduce(0..1000, y, + fn i, acc -> MST.insert(acc, i, i + 2 * rem(i, 2) - 1) end) + + + z = Enum.reduce(Enum.shuffle(0..1000), %MST{merge: merge}, + fn i, acc -> MST.insert(acc, i, i) end) + z = Enum.reduce(Enum.shuffle(0..1000), z, + fn i, acc -> MST.insert(acc, i, i + 2 * rem(i, 2) - 1) end) + + for i <- 0..1000 do + val = if rem(i, 2) == 1 do i+1 else i end + assert MST.get(y, i) == val + assert MST.get(z, i) == val + end + assert MST.get(y, 9999) == nil + assert MST.get(z, -1001) == nil + assert MST.get(z, 1.01) == nil + + IO.puts "y.root: #{y.root|>Base.encode16}" + IO.puts "z.root: #{z.root|>Base.encode16}" + assert y.root == z.root + end + + test "merkle search tree 4" do + items = for i <- 0..1000 do + h = SData.term_hash i + {h, SData.term_hash h} + end + + cmp = fn {a1, b1}, {a2, b2} -> + cond do + a1 < a2 -> :before + a1 > a2 -> :after + b1 > b2 -> :before + b1 < b2 -> :after + true -> :duplicate + end + end + + y = Enum.reduce(items, %MST{cmp: cmp}, + fn {a, b}, acc -> MST.insert(acc, {a, b}) end) + + z = Enum.reduce(Enum.shuffle(items), %MST{cmp: cmp}, + fn {a, b}, acc -> MST.insert(acc, {a, b}) end) + + for {k, v} <- items do + assert MST.get(y, {k, v}) == true + assert MST.get(z, {k, v}) == true + end + assert MST.get(z, {"foo", "bar"}) == nil + + IO.puts "y.root: #{y.root|>Base.encode16}" + IO.puts "z.root: #{z.root|>Base.encode16}" + assert y.root == z.root + + MST.last(y, nil, 10) + end + + test "merkle search tree 5: MST.last" do + y = Enum.reduce(0..1000, %MST{}, + fn i, acc -> MST.insert(acc, i) end) + + assert(MST.last(y, nil, 2) == [{999, true}, {1000, true}]) + assert(MST.last(y, 42, 2) == [{40, true}, {41, true}]) + + stuff = for i <- 100..199, do: {i, true} + assert MST.last(y, 200, 100) == stuff + + stuff = for i <- 200..299, do: {i, true} + assert MST.last(y, 300, 100) == stuff + + stuff = for i <- 200..499, do: {i, true} + assert MST.last(y, 500, 300) == stuff + end + + test "merkle search tree 6: MST.merge" do + y = Enum.reduce([1, 2, 42], %MST{}, fn i, acc -> MST.insert(acc, i) end) + z = Enum.reduce([2, 12], %MST{}, fn i, acc -> MST.insert(acc, i) end) + + IO.puts "y: " + MST.dump y + IO.puts "z: " + MST.dump z + + mg1 = MST.merge(y, z) + IO.puts "mg1: " + MST.dump mg1 + + mg2 = MST.merge(y, z) + IO.puts "mg2: " + MST.dump mg2 + assert mg1.root == mg2.root + end + + test "merkle search tree 7: MST.merge" do + items1 = (for i <- 1..1000, do: i*2+40) + items2 = (for i <- 1..1000, do: i*3) + + y = Enum.reduce(items1, %MST{}, fn i, acc -> MST.insert(acc, i) end) + z = Enum.reduce(items2, %MST{}, fn i, acc -> MST.insert(acc, i) end) + + IO.puts "(merge) y.root: #{y.root|>Base.encode16}" + IO.puts "(merge) z.root: #{z.root|>Base.encode16}" + + mg1 = MST.merge(y, z) + IO.puts "(merge) mg1.root: #{mg1.root|>Base.encode16}" + + mg2 = MST.merge(y, z) + IO.puts "(merge) mg2.root: #{mg2.root|>Base.encode16}" + + assert mg1.root == mg2.root + + items1t = (for i <- items1, do: {i, true}) + items2t = (for i <- items2, do: {i, true}) + assert MST.last(y, nil, 1000) == items1t + assert MST.last(z, nil, 1000) == items2t + + all_items = (items1t ++ items2t) |> Enum.sort |> Enum.uniq + assert MST.last(mg1, nil, 2000) == all_items + end + + test "merkle search tree 8: MST.merge callback" do + items1 = (for i <- 1..1000, do: i*2+40) + items2 = (for i <- 1..1000, do: i*3) + + y = Enum.reduce(items1, %MST{}, fn i, acc -> MST.insert(acc, i) end) + z = Enum.reduce(items2, %MST{}, fn i, acc -> MST.insert(acc, i) end) + + {:ok, cb_called} = Agent.start_link fn -> [] end + + cb = fn i, true -> Agent.update(cb_called, fn x -> [i | x] end) end + mg = MST.merge(y, z, cb) + + cb_vals = Agent.get cb_called, &(&1) + expected = MapSet.difference(MapSet.new(items2), MapSet.new(items1)) + |> MapSet.to_list + |> Enum.sort + |> Enum.reverse + assert expected == cb_vals + end + +end diff --git a/shard/test/test_helper.exs b/shard/test/test_helper.exs new file mode 100644 index 0000000..e5b6600 --- /dev/null +++ b/shard/test/test_helper.exs @@ -0,0 +1,8 @@ +ExUnit.start() + +case :gen_tcp.connect('localhost', 4045, []) do + {:ok, socket} -> + :gen_tcp.close(socket) + {:error, _reason} -> + Mix.raise "Please have another instance of Shard running at 127.0.0.1:4045, it can be launched with the command: PORT=4045 iex -S mix" +end |