diff --git a/lib/harald/hci.ex b/lib/harald/hci.ex index 6a1b73f..5c21777 100644 --- a/lib/harald/hci.ex +++ b/lib/harald/hci.ex @@ -91,7 +91,11 @@ defmodule Harald.HCI do @impl Serializable def deserialize(<<4, rest::binary>>) do - Event.deserialize(rest) + case Event.deserialize(rest) do + {:ok, _} = ret -> ret + {:error, bin} when is_binary(bin) -> {:error, <<4, bin::binary>>} + {:error, data} -> {:error, data} + end end def deserialize(bin), do: {:error, bin} diff --git a/lib/harald/serializable.ex b/lib/harald/serializable.ex index c7e3f3a..ad4bc39 100644 --- a/lib/harald/serializable.ex +++ b/lib/harald/serializable.ex @@ -6,4 +6,21 @@ defmodule Harald.Serializable do @callback serialize(term()) :: {:ok, binary()} | {:error, term()} @callback deserialize(binary()) :: {:ok, term()} | {:error, term()} + + @doc """ + Asserts that `bin` will serialize symmetrically. + + If `bin` deserializes into `{:ok, data}`, `data` should serialize perfectly back into `bin`. + """ + defmacro assert_symmetry(mod, bin) do + quote bind_quoted: [bin: bin, mod: mod] do + import ExUnit.Assertions, only: [assert: 1, assert: 2] + + case mod.deserialize(bin) do + {:ok, data} -> assert {:ok, bin} == mod.serialize(data) + {:error, data} when not is_binary(data) -> true + {:error, bin2} -> assert bin == bin2 + end + end + end end diff --git a/test/harald/hci_test.exs b/test/harald/hci_test.exs index ebd9fd1..0d10f9e 100644 --- a/test/harald/hci_test.exs +++ b/test/harald/hci_test.exs @@ -3,6 +3,7 @@ defmodule Harald.HCITest do use ExUnitProperties alias Harald.Generators.HCI, as: HCIGen alias Harald.HCI + require Harald.Serializable, as: Serializable doctest Harald.HCI, import: true @@ -61,11 +62,8 @@ defmodule Harald.HCITest do end end - check all parameters <- StreamData.binary() do - case HCI.deserialize(parameters) do - {:ok, data} -> assert {:ok, parameters} == HCI.serialize(data) - {:error, _} -> :ok - end + check all bin <- StreamData.binary() do + Serializable.assert_symmetry(HCI, bin) end end end