All checks were successful
Gajumaru Serialization Tests / tests (push) Successful in -3m14s
195 lines
6.9 KiB
Erlang
195 lines
6.9 KiB
Erlang
%%%-------------------------------------------------------------------
|
|
%%% @copyright (C) 2025, QPQ AG
|
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
|
%%%-------------------------------------------------------------------
|
|
|
|
-module(gmser_api_encoder_tests).
|
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
-define(TEST_MODULE, gmser_api_encoder).
|
|
-define(TYPES, [ {key_block_hash , 32}
|
|
, {micro_block_hash , 32}
|
|
, {block_tx_hash , 32}
|
|
, {block_state_hash , 32}
|
|
, {channel , 32}
|
|
, {contract_pubkey , 32}
|
|
, {transaction , not_applicable}
|
|
, {tx_hash , 32}
|
|
, {account_pubkey , 32}
|
|
, {signature , 64}
|
|
, {name , not_applicable}
|
|
, {native_token , 32}
|
|
, {commitment , 32}
|
|
, {peer_pubkey , 32}
|
|
, {hash , 32}
|
|
, {state , 32}
|
|
, {poi , not_applicable}]).
|
|
|
|
encode_decode_test_() ->
|
|
encode_decode_test_(?TYPES).
|
|
|
|
encode_decode_known_types_test_() ->
|
|
KnownTypes = known_types(),
|
|
SizedTypes = [{T, ?TEST_MODULE:byte_size_for_type(T)} || T <- KnownTypes],
|
|
encode_decode_test_(SizedTypes).
|
|
|
|
prefixes_are_known_types_test() ->
|
|
MappedPfxs = mapped_prefixes(),
|
|
KnownTypes = known_types(),
|
|
lists:foreach(
|
|
fun({Pfx, Type}) ->
|
|
case lists:member(Type, KnownTypes) of
|
|
true -> ok;
|
|
false ->
|
|
error({not_a_known_type, Pfx, Type})
|
|
end
|
|
end, MappedPfxs),
|
|
lists:foreach(
|
|
fun(Type) ->
|
|
case lists:keyfind(Type, 2, MappedPfxs) of
|
|
{_, _} -> ok;
|
|
false ->
|
|
error({has_no_mapped_prefix, Type})
|
|
end
|
|
end, KnownTypes).
|
|
|
|
encode_decode_test_(Types) ->
|
|
[{"Byte sizes are correct",
|
|
fun() ->
|
|
lists:foreach(
|
|
fun({Type, ByteSize}) ->
|
|
{_Type, _, ByteSize} = {Type, ByteSize,
|
|
?TEST_MODULE:byte_size_for_type(Type)}
|
|
end,
|
|
Types)
|
|
end
|
|
},
|
|
{"Serialize/deserialize known types",
|
|
fun() ->
|
|
lists:foreach(
|
|
fun({Type, Size0}) ->
|
|
ByteSize =
|
|
case Size0 of
|
|
not_applicable -> 42;
|
|
_ when is_integer(Size0) -> Size0
|
|
end,
|
|
Key = <<42:ByteSize/unit:8>>,
|
|
EncodedKey = ?TEST_MODULE:encode(Type, Key),
|
|
{Type, Key} = ?TEST_MODULE:decode(EncodedKey),
|
|
{ok, Key} = ?TEST_MODULE:safe_decode(Type, EncodedKey)
|
|
end,
|
|
Types)
|
|
end
|
|
},
|
|
{"Key size check works",
|
|
fun() ->
|
|
lists:foreach(
|
|
fun({_Type, not_applicable}) -> ok;
|
|
({Type, ByteSize}) ->
|
|
CheckIlligalSize =
|
|
fun(S) ->
|
|
Key = <<42:S/unit:8>>,
|
|
EncodedKey = ?TEST_MODULE:encode(Type, Key),
|
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, EncodedKey)
|
|
end,
|
|
CheckIlligalSize(0),
|
|
CheckIlligalSize(ByteSize - 1),
|
|
CheckIlligalSize(ByteSize + 1)
|
|
end,
|
|
Types)
|
|
end
|
|
},
|
|
{"Missing prefix",
|
|
fun() ->
|
|
lists:foreach(
|
|
fun({Type, Size0}) ->
|
|
ByteSize =
|
|
case Size0 of
|
|
not_applicable -> 42;
|
|
_ when is_integer(Size0) -> Size0
|
|
end,
|
|
Key = <<42:ByteSize/unit:8>>,
|
|
EncodedKey = ?TEST_MODULE:encode(Type, Key),
|
|
<<_PartOfPrefix:1/unit:8, RestOfKey/binary>> = EncodedKey,
|
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey),
|
|
|
|
<<_PrefixWithoutDelimiter:2/unit:8, RestOfKey1/binary>> = EncodedKey,
|
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey1),
|
|
|
|
<<_WholePrefix:3/unit:8, RestOfKey2/binary>> = EncodedKey,
|
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey2)
|
|
end,
|
|
Types)
|
|
end
|
|
},
|
|
{"Piece of encoded key",
|
|
fun() ->
|
|
lists:foreach(
|
|
fun({Type, Size0}) ->
|
|
ByteSize =
|
|
case Size0 of
|
|
not_applicable -> 42;
|
|
_ when is_integer(Size0) -> Size0
|
|
end,
|
|
Key = <<42:ByteSize/unit:8>>,
|
|
EncodedKey = ?TEST_MODULE:encode(Type, Key),
|
|
HalfKeySize = byte_size(EncodedKey) div 2,
|
|
<<HalfKey:HalfKeySize/unit:8, RestOfKey/binary>> = EncodedKey,
|
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, HalfKey),
|
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey)
|
|
end,
|
|
Types)
|
|
end
|
|
},
|
|
{"Encode/decode binary with only zeros",
|
|
fun() ->
|
|
Bins = [<<0:Size/unit:8>> || Size <- lists:seq(1,64)],
|
|
lists:foreach(
|
|
fun(Bin) ->
|
|
lists:foreach(
|
|
fun({Type, S}) ->
|
|
case S =:= byte_size(Bin) orelse S =:= not_applicable of
|
|
true ->
|
|
Encoded = ?TEST_MODULE:encode(Type, Bin),
|
|
{ok, Decoded} = ?TEST_MODULE:safe_decode(Type, Encoded),
|
|
?assertEqual(Decoded, Bin);
|
|
false ->
|
|
ok
|
|
end,
|
|
Encoded1 = base58:binary_to_base58(Bin),
|
|
Decoded1 = base58:base58_to_binary(Encoded1),
|
|
?assertEqual(Bin, Decoded1)
|
|
end, Types)
|
|
end,
|
|
Bins)
|
|
end}
|
|
].
|
|
|
|
known_types() ->
|
|
Forms = get_forms(),
|
|
[{type, _, union, Types}] =
|
|
[Def || {attribute, _, type, {known_type, Def, []}} <- Forms],
|
|
[Name || {atom,_, Name} <- Types].
|
|
|
|
mapped_prefixes() ->
|
|
Forms = get_forms(),
|
|
[Clauses] = [Cs || {function,_,pfx2type,1,Cs} <- Forms],
|
|
Abst = [{B, A} || {clause,_,[B],[],[A]} <- Clauses],
|
|
lists:map(
|
|
fun({B, A}) ->
|
|
{eval_expr(B), eval_expr(A)}
|
|
end, Abst).
|
|
|
|
get_forms() ->
|
|
get_forms(code:which(?TEST_MODULE)).
|
|
|
|
get_forms(Beam) ->
|
|
{ok, {_, [{abstract_code, {raw_abstract_v1, Forms}}]}} =
|
|
beam_lib:chunks(Beam, [abstract_code]),
|
|
Forms.
|
|
|
|
eval_expr(Expr) ->
|
|
{value, Val, []} = erl_eval:expr(Expr, []),
|
|
Val.
|