Packaging 3.2.1
This commit is contained in:
parent
02a6731f58
commit
3097e90156
@ -1,15 +0,0 @@
|
||||
{application,aebytecode,
|
||||
[{description,"A library and stand alone assembler for aeternity bytecode. This version supports AEVM bytecode and FATE bytecode."},
|
||||
{registered,[]},
|
||||
{included_applications,[]},
|
||||
{applications,[stdlib,kernel]},
|
||||
{vsn,"3.2.0"},
|
||||
{modules,[aeb_fate_code_tests,aeb_fate_data_tests,
|
||||
aeb_fate_encoding_tests,aefate_code_eqc,aefate_eqc,
|
||||
aefate_type_eqc,aeb_aevm_abi,aeb_aevm_data,aeb_asm,
|
||||
aeb_disassemble,aeb_fate_abi,aeb_fate_asm,
|
||||
aeb_fate_code,aeb_fate_data,aeb_fate_encoding,
|
||||
aeb_fate_generate_docs,aeb_fate_generate_ops,
|
||||
aeb_fate_maps,aeb_heap,aeb_memory,aeb_opcodes,
|
||||
aeb_primops,aefateasm,aeb_data_test,aeb_fate_asm_test,
|
||||
aeb_serialize_test,aebytecode_SUITE]}]}.
|
@ -1,27 +0,0 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Allow to run QuickCheck tests as eunit tests
|
||||
%%% `rebar3 as eqc eunit --cover`
|
||||
%%% or `rebar3 as eqc eunit --module=aeb_fate_code`
|
||||
%%% Note that for obtainign cover file, one needs `rebar3 as eqc cover
|
||||
%%%
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aeb_fate_code_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
-define(EQC_EUNIT(Module, PropName, Ms),
|
||||
{ atom_to_list(PropName),
|
||||
{timeout, (Ms * 10) div 1000, ?_assert(eqc:quickcheck(eqc:testing_time(Ms / 1000, Module:PropName())))}}).
|
||||
|
||||
quickcheck_test_() ->
|
||||
{setup, fun() -> eqc:start() end,
|
||||
[ ?EQC_EUNIT(aefate_code_eqc, prop_opcodes, 200),
|
||||
?EQC_EUNIT(aefate_code_eqc, prop_serializes, 3000),
|
||||
?EQC_EUNIT(aefate_code_eqc, prop_fail_serializes, 3000),
|
||||
?EQC_EUNIT(aefate_code_eqc, prop_fuzz, 3000)
|
||||
]}.
|
@ -1,27 +0,0 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Allow to run QuickCheck tests as eunit tests
|
||||
%%% `rebar3 as eqc eunit --cover`
|
||||
%%% or `rebar3 as eqc eunit --module=aeb_fate_data`
|
||||
%%% Note that for obtainign cover file, one needs `rebar3 as eqc cover
|
||||
%%%
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aeb_fate_data_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
-define(EQC_EUNIT(Module, PropName, Ms),
|
||||
{ atom_to_list(PropName),
|
||||
{timeout, (Ms * 3) / 1000, ?_assert(eqc:quickcheck(eqc:testing_time(Ms / 1000, Module:PropName())))}}).
|
||||
|
||||
quickcheck_test_() ->
|
||||
{setup, fun() -> eqc:start() end,
|
||||
[ ?EQC_EUNIT(aefate_eqc, prop_roundtrip, 500),
|
||||
?EQC_EUNIT(aefate_eqc, prop_format_scan, 2000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_order, 2000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_fuzz, 2000)
|
||||
]}.
|
@ -1,27 +0,0 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Allow to run QuickCheck tests as eunit tests
|
||||
%%% `rebar3 as eqc eunit --cover`
|
||||
%%% or `rebar3 as eqc eunit --module=aeb_fate_encoding`
|
||||
%%% Note that for obtaining cover file, one needs `rebar3 as eqc cover
|
||||
%%%
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts
|
||||
|
||||
-module(aeb_fate_encoding_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
-define(EQC_EUNIT(Module, PropName, Ms),
|
||||
{ atom_to_list(PropName),
|
||||
{timeout, (Ms * 3) / 1000, ?_assert(eqc:quickcheck(eqc:testing_time(Ms / 1000, Module:PropName())))}}).
|
||||
|
||||
quickcheck_test_() ->
|
||||
{setup, fun() -> eqc:start() end,
|
||||
[ ?EQC_EUNIT(aefate_type_eqc, prop_roundtrip, 1000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_serializes, 1000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_no_maps_in_keys, 1000),
|
||||
?EQC_EUNIT(aefate_eqc, prop_idempotent, 1000)
|
||||
]}.
|
@ -1,167 +0,0 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Use `rebar3 as eqc shell` to run properties in the shell
|
||||
%%%
|
||||
%%% We want to be sure that we can deserialize all FATE assembler that is accepted on chain.
|
||||
%%%
|
||||
%%% We test something slightly weaker here,
|
||||
%%% viz. All FATE assembler we serialize, we can deserialize
|
||||
%%%
|
||||
%%% Negative testing modelled:
|
||||
%%% Failure 1: function names differ from 4 bytes
|
||||
%%% Failure 2: pointer to empty code block
|
||||
%%% Failure 3: end_BB operation as not ending block or not at end of block
|
||||
%%% - empty code blocks
|
||||
%%% - blocks that are not of the form (not end_bb)* end_bb.
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aefate_code_eqc).
|
||||
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
%%-define(Failure(Failures, Number), case lists:member(Number, Failures) of true -> 1; false -> 0 end)
|
||||
|
||||
|
||||
prop_serializes() ->
|
||||
in_parallel(
|
||||
?FORALL(FateCode, fate_code(0),
|
||||
begin
|
||||
{T0, Binary} = timer:tc(fun() -> aeb_fate_code:serialize(FateCode) end),
|
||||
?WHENFAIL(eqc:format("serialized:\n ~120p~n", [Binary]),
|
||||
begin
|
||||
{T1, Decoded} = timer:tc(fun() -> aeb_fate_code:deserialize(Binary) end),
|
||||
measure(binary_size, size(Binary),
|
||||
measure(serialize, T0 / 1000,
|
||||
measure(deserialize, T1 / 1000,
|
||||
conjunction([{equal, equals(Decoded, FateCode)},
|
||||
{serialize_time, T0 / 1000 < 500},
|
||||
{deserialize_time, T1 / 1000 < 500}]))))
|
||||
end)
|
||||
end)).
|
||||
|
||||
prop_fail_serializes() ->
|
||||
conjunction([{Failure, eqc:counterexample(
|
||||
?FORALL(FateCode, fate_code(Failure),
|
||||
?FORALL(Binary, catch aeb_fate_code:serialize(FateCode),
|
||||
is_binary(Binary))))
|
||||
=/= true} || Failure <- [1, 2, 3, 4, 5] ]).
|
||||
|
||||
prop_fuzz() ->
|
||||
in_parallel(
|
||||
?FORALL(Binary, ?LET(FateCode, fate_code(0), aeb_fate_code:serialize(FateCode)),
|
||||
?FORALL(FuzzedBin, fuzz(Binary),
|
||||
try aeb_fate_code:deserialize(FuzzedBin) of
|
||||
Code ->
|
||||
?WHENFAIL(eqc:format("Code:\n ~p\n", [Code]),
|
||||
begin
|
||||
Bin1 = aeb_fate_code:serialize(Code),
|
||||
Code1 = aeb_fate_code:deserialize(Bin1),
|
||||
?WHENFAIL(eqc:format("Reserialized\n ~120p\n", [Bin1]),
|
||||
equals(Code, Code1))
|
||||
end)
|
||||
catch _:_ -> true
|
||||
end))).
|
||||
|
||||
prop_opcodes() ->
|
||||
?FORALL(Opcode, choose(0, 16#ff),
|
||||
try M = aeb_fate_opcodes:mnemonic(Opcode),
|
||||
?WHENFAIL(eqc:format("opcode ~p -> ~p", [Opcode, M]),
|
||||
conjunction([{valid, lists:member(Opcode, valid_opcodes())},
|
||||
{eq, equals(aeb_fate_opcodes:m_to_op(M), Opcode)}]))
|
||||
catch
|
||||
_:_ ->
|
||||
not lists:member(Opcode, valid_opcodes())
|
||||
end).
|
||||
|
||||
|
||||
valid_opcodes() ->
|
||||
[ Op || #{opcode := Op} <- aeb_fate_generate_ops:get_ops() ].
|
||||
|
||||
|
||||
fate_code(Failure) ->
|
||||
?SIZED(Size,
|
||||
?LET({FMap, SMap, AMap},
|
||||
{non_empty(map(if Failure == 1 -> binary(1);
|
||||
true -> binary(4) end,
|
||||
{sublist(lists:sort([private, payable])), %% deserialize sorts them
|
||||
{list(aefate_type_eqc:fate_type(Size div 3)), aefate_type_eqc:fate_type(Size div 3)}, bbs_code(Failure)})),
|
||||
small_map(small_fate_data_key(5), small_fate_data(4)),
|
||||
small_map(small_fate_data_key(5), small_fate_data(4))},
|
||||
aeb_fate_code:update_annotations(
|
||||
aeb_fate_code:update_symbols(
|
||||
aeb_fate_code:update_functions(
|
||||
aeb_fate_code:new(), FMap), SMap), AMap))).
|
||||
|
||||
short_list(Max, Gen) ->
|
||||
?LET(N, choose(0, Max), eqc_gen:list(N, Gen)).
|
||||
|
||||
small_map(KeyGen, ValGen) ->
|
||||
?LET(KeyVals, short_list(6, {KeyGen, ValGen}),
|
||||
return(maps:from_list(KeyVals))).
|
||||
|
||||
bbs_code(Failure) ->
|
||||
frequency([{if Failure == 2 -> 5; true -> 0 end, #{0 => []}},
|
||||
{10, ?LET(BBs, short_list(6, bb_code(Failure)),
|
||||
maps:from_list(
|
||||
lists:zip(lists:seq(0, length(BBs)-1), BBs)))}]).
|
||||
|
||||
bb_code(Failure) ->
|
||||
EndBB = [ Op || Op <- valid_opcodes(), aeb_fate_opcodes:end_bb(Op) ],
|
||||
NonEndBB = valid_opcodes() -- EndBB,
|
||||
frequency(
|
||||
[{if Failure == 3 -> 5; true -> 0 end, ?LET(Ops, non_empty(short_list(6, elements(NonEndBB))), bblock(Failure, Ops))},
|
||||
{if Failure == 4 -> 5; true -> 0 end, ?LET({Ops, Op}, {short_list(6, elements(valid_opcodes())), elements(EndBB)}, bblock(Failure, Ops ++ [Op]))},
|
||||
{10, ?LET({Ops, Op}, {short_list(6, elements(NonEndBB)), elements(EndBB)},
|
||||
bblock(Failure, Ops ++ [Op]))}]).
|
||||
|
||||
bblock(Failure, Ops) ->
|
||||
[ begin
|
||||
Mnemonic = aeb_fate_opcodes:mnemonic(Op),
|
||||
Arity = aeb_fate_opcodes:args(Op),
|
||||
case Arity of
|
||||
0 -> Mnemonic;
|
||||
_ -> list_to_tuple([Mnemonic |
|
||||
[ frequency([{if Failure == 5 -> 5; true -> 0 end, {stack, nat()}},
|
||||
{5, {stack, 0}},
|
||||
{5, {arg, nat()}},
|
||||
{5, {var, nat()}},
|
||||
{5, {immediate, small_fate_data(4)}}]) ||
|
||||
_ <- lists:seq(1, Arity) ]])
|
||||
end
|
||||
end || Op <- Ops ].
|
||||
|
||||
fuzz(Binary) ->
|
||||
?LET({N, Inj}, {choose(0, byte_size(Binary) - 1), choose(0, 255)},
|
||||
begin
|
||||
M = N * 8,
|
||||
<<X:M, _:8, Z/binary>> = Binary,
|
||||
<<X:M, Inj:8, Z/binary>>
|
||||
end).
|
||||
|
||||
prop_small() ->
|
||||
?FORALL(Value, small_fate_data(4),
|
||||
begin
|
||||
Bin = aeb_fate_encoding:serialize(Value),
|
||||
Size = byte_size(Bin),
|
||||
measure(size, Size,
|
||||
?WHENFAIL(eqc:format("Size: ~p\n", [Size]),
|
||||
Size < 1000))
|
||||
end).
|
||||
|
||||
prop_small_type() ->
|
||||
?FORALL(Type, ?SIZED(Size, aefate_type_eqc:fate_type(Size div 3)),
|
||||
begin
|
||||
Bin = iolist_to_binary(aeb_fate_encoding:serialize_type(Type)),
|
||||
Size = byte_size(Bin),
|
||||
measure(size, Size,
|
||||
?WHENFAIL(eqc:format("Size: ~p\n", [Size]),
|
||||
Size < 1000))
|
||||
end).
|
||||
|
||||
small_fate_data(N) ->
|
||||
?SIZED(Size, resize(Size div N, aefate_eqc:fate_data())).
|
||||
|
||||
small_fate_data_key(N) ->
|
||||
?SIZED(Size, ?LET(Data, aefate_eqc:fate_data(Size div N, []), eqc_symbolic:eval(Data))).
|
@ -1,211 +0,0 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Use `rebar3 as eqc shell` to run properties in the shell
|
||||
%%%
|
||||
%%% We need to be able to generate data that serializes with ?LONG_LIST, ?LONG_TUPLE etc.
|
||||
%%% In other words make some rather broad terms as well as some deep terms
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aefate_eqc).
|
||||
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
-include("../include/aeb_fate_data.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
prop_roundtrip() ->
|
||||
?FORALL(FateData, fate_data(),
|
||||
measure(bytes, size(term_to_binary(FateData)),
|
||||
begin
|
||||
Serialized = aeb_fate_encoding:serialize(FateData),
|
||||
?WHENFAIL(eqc:format("Serialized ~p to ~p~n", [FateData, Serialized]),
|
||||
equals(aeb_fate_encoding:deserialize(Serialized), FateData))
|
||||
end)).
|
||||
|
||||
prop_format_scan() ->
|
||||
?FORALL(FateData, fate_data([variant, map]),
|
||||
?WHENFAIL(eqc:format("Trying to format ~p failed~n", [FateData]),
|
||||
begin
|
||||
String = aeb_fate_data:format(FateData),
|
||||
{ok, _Scanned, _} = aeb_fate_asm_scan:scan(unicode:characters_to_list(String)),
|
||||
true
|
||||
end)).
|
||||
|
||||
prop_serializes() ->
|
||||
?FORALL({Data, Garbage}, {fate_data(), binary()},
|
||||
?WHENFAIL(eqc:format("Trying to serialize/deserialize ~p failed~n", [Data]),
|
||||
begin
|
||||
Binary = <<(aeb_fate_encoding:serialize(Data))/binary, Garbage/binary>>,
|
||||
{FateData, Rest} = aeb_fate_encoding:deserialize_one(Binary),
|
||||
measure(binary_size, size(Binary),
|
||||
conjunction([{equal, equals(Data, FateData)},
|
||||
{rest, equals(Garbage, Rest)},
|
||||
{size, size(Binary) < 500000}]))
|
||||
end)).
|
||||
|
||||
prop_no_maps_in_keys() ->
|
||||
?FORALL(FateData, fate_bad_map(), %% may contain a map in its keys
|
||||
begin
|
||||
HasMapInKeys = lists:any(fun(K) -> has_map(K) end, maps:keys(FateData)),
|
||||
try aeb_fate_encoding:serialize(FateData),
|
||||
?WHENFAIL(eqc:format("Should not serialize, contains a map in key\n", []),
|
||||
not HasMapInKeys)
|
||||
catch error:Reason ->
|
||||
?WHENFAIL(eqc:format("(~p) Should serialize\n", [Reason]), HasMapInKeys)
|
||||
end
|
||||
end).
|
||||
|
||||
prop_fuzz() ->
|
||||
in_parallel(
|
||||
?FORALL(Binary, ?LET(FateData, ?SIZED(Size, resize(Size div 4, fate_data())), aeb_fate_encoding:serialize(FateData)),
|
||||
?FORALL(InjectedBin, injection(Binary),
|
||||
try Org = aeb_fate_encoding:deserialize(InjectedBin),
|
||||
NewBin = aeb_fate_encoding:serialize(Org),
|
||||
NewOrg = aeb_fate_encoding:deserialize(NewBin),
|
||||
measure(success, 1,
|
||||
?WHENFAIL(eqc:format("Deserialize ~p gives\n~p\nSerializes to ~p\n", [InjectedBin, Org, NewOrg]),
|
||||
equals(NewBin, InjectedBin)))
|
||||
catch _:_ ->
|
||||
true
|
||||
end))).
|
||||
|
||||
|
||||
prop_order() ->
|
||||
?FORALL(Items, vector(3, fate_data([variant, map])),
|
||||
begin
|
||||
%% Use lt to take minimum
|
||||
Min = lt_min(Items),
|
||||
Max = lt_max(Items),
|
||||
conjunction([ {minimum, is_empty([ {Min, '>', I} || I<-Items, aeb_fate_data:lt(I, Min)])},
|
||||
{maximum, is_empty([ {Max, '<', I} || I<-Items, aeb_fate_data:lt(Max, I)])},
|
||||
{asym, aeb_fate_data:lt(Min, Max) orelse Min == Max}])
|
||||
end).
|
||||
|
||||
lt_min([X, Y | Rest]) ->
|
||||
case aeb_fate_data:lt(X, Y) of
|
||||
true -> lt_min([X | Rest]);
|
||||
false -> lt_min([Y| Rest])
|
||||
end;
|
||||
lt_min([X]) -> X.
|
||||
|
||||
lt_max([X, Y | Rest]) ->
|
||||
case aeb_fate_data:lt(X, Y) of
|
||||
true -> lt_max([Y | Rest]);
|
||||
false -> lt_max([X| Rest])
|
||||
end;
|
||||
lt_max([X]) -> X.
|
||||
|
||||
prop_idempotent() ->
|
||||
?FORALL(Items, list({fate_data_key(), fate_data()}),
|
||||
equals(aeb_fate_encoding:sort(Items),
|
||||
aeb_fate_encoding:sort(aeb_fate_encoding:sort(Items)))).
|
||||
|
||||
|
||||
|
||||
fate_data(Kind) ->
|
||||
?SIZED(Size, ?LET(Data, fate_data(Size, Kind), eqc_symbolic:eval(Data))).
|
||||
|
||||
fate_data() ->
|
||||
fate_data([map, variant, store_map]).
|
||||
|
||||
%% keys may contain variants but no maps
|
||||
fate_data_key() ->
|
||||
fate_data([variant]).
|
||||
|
||||
fate_data(0, Options) ->
|
||||
?LAZY(
|
||||
frequency(
|
||||
[{50, oneof([fate_integer(), fate_boolean(), fate_nil(), fate_unit()])},
|
||||
{10, oneof([fate_string(), fate_address(), fate_bytes(), fate_contract(),
|
||||
fate_oracle(), fate_oracle_q(), fate_bits(), fate_channel()])}] ++
|
||||
[{1, fate_store_map()} || lists:member(store_map, Options)]));
|
||||
fate_data(Size, Options) ->
|
||||
?LAZY(
|
||||
oneof([fate_data(0, Options),
|
||||
fate_list(Size, Options),
|
||||
fate_tuple(Size, Options)] ++
|
||||
[fate_variant(Size, Options)
|
||||
|| lists:member(variant, Options)] ++
|
||||
[fate_map(Size, Options)
|
||||
|| lists:member(map, Options)])).
|
||||
|
||||
|
||||
fate_integer() -> ?LET(X, oneof([int(), largeint()]), return(aeb_fate_data:make_integer(X))).
|
||||
fate_bits() -> ?LET(X, oneof([int(), largeint()]), return(aeb_fate_data:make_bits(X))).
|
||||
fate_boolean() -> ?LET(X, elements([true, false]), return(aeb_fate_data:make_boolean(X))).
|
||||
fate_nil() -> aeb_fate_data:make_list([]).
|
||||
fate_unit() -> aeb_fate_data:make_unit().
|
||||
fate_string() -> ?LET(X, frequency([{10, non_quote_string()}, {2, list(non_quote_string())},
|
||||
{1, ?LET(N, choose(64-3, 64+3), vector(N, $a))}]),
|
||||
return(aeb_fate_data:make_string(X))).
|
||||
fate_address() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_address(X))).
|
||||
fate_bytes() -> ?LET(X, non_empty(binary()), return(aeb_fate_data:make_bytes(X))).
|
||||
fate_contract() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_contract(X))).
|
||||
fate_oracle() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_oracle(X))).
|
||||
fate_oracle_q() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_oracle_query(X))).
|
||||
fate_channel() -> ?LET(X, binary(256 div 8), return(aeb_fate_data:make_channel(X))).
|
||||
|
||||
fate_values(Size, N, Options) ->
|
||||
eqc_gen:list(N, fate_data(Size div max(1, N), Options)).
|
||||
|
||||
%% May shrink to fate_unit
|
||||
fate_tuple(Size, Options) ->
|
||||
?LET(N, choose(0, 6),
|
||||
?LETSHRINK(Elements, fate_values(Size, N, Options),
|
||||
return(aeb_fate_data:make_tuple(list_to_tuple(Elements))))).
|
||||
|
||||
fate_variant(Size, Options) ->
|
||||
?LET({L1, L2, {tuple, Args}}, {list(choose(0, 255)), list(choose(0,255)), fate_tuple(Size, Options)},
|
||||
return(aeb_fate_data:make_variant(L1 ++ [tuple_size(Args)] ++ L2,
|
||||
length(L1), Args))).
|
||||
|
||||
fate_list(Size, Options) ->
|
||||
?LET(N, frequency([{20, choose(0, 6)}, {1, choose(64 - 3, 64 + 3)}]),
|
||||
?LETSHRINK(Vs, fate_values(Size, N, Options),
|
||||
return(aeb_fate_data:make_list(Vs)))).
|
||||
|
||||
fate_map(Size, Options) ->
|
||||
?LET(N, choose(0, 6),
|
||||
?LETSHRINK(Values, fate_values(Size, N, Options),
|
||||
?LET(Keys, vector(length(Values), fate_data(Size div max(1, N * 2), Options -- [map, store_map])),
|
||||
return(aeb_fate_data:make_map(maps:from_list(lists:zip(Keys, Values))))))).
|
||||
|
||||
fate_store_map() ->
|
||||
%% only #{} is allowed as cache in serialization
|
||||
?LET(X, oneof([int(), largeint()]),
|
||||
return(aeb_fate_data:make_store_map(abs(X)))).
|
||||
|
||||
fate_bad_map() ->
|
||||
?LET(N, choose(0, 6),
|
||||
?LET(Values, vector(N, ?SIZED(Size, resize(Size div 8, fate_data()))),
|
||||
?LET(Keys, vector(N, ?SIZED(Size, resize(Size div 4, fate_data()))),
|
||||
return(aeb_fate_data:make_map(maps:from_list(lists:zip(Keys, Values))))))).
|
||||
|
||||
non_quote_string() ->
|
||||
?SUCHTHAT(S, utf8(), [ quote || <<34>> <= S ] == []).
|
||||
|
||||
char() ->
|
||||
choose(1, 255).
|
||||
|
||||
injection(Binary) ->
|
||||
?LET({N, Inj}, {choose(0, byte_size(Binary) - 1), choose(0,255)},
|
||||
begin
|
||||
M = N * 8,
|
||||
<<X:M, _:8, Z/binary>> = Binary,
|
||||
<<X:M, Inj:8, Z/binary>>
|
||||
end).
|
||||
|
||||
is_empty(L) ->
|
||||
?WHENFAIL(eqc:format("~p\n", [L]), L == []).
|
||||
|
||||
has_map(L) when is_list(L) ->
|
||||
lists:any(fun(V) -> has_map(V) end, L);
|
||||
has_map(T) when is_tuple(T) ->
|
||||
has_map(tuple_to_list(T));
|
||||
has_map(M) when is_map(M) ->
|
||||
true;
|
||||
has_map(?FATE_STORE_MAP(_, _)) ->
|
||||
true;
|
||||
has_map(_) ->
|
||||
false.
|
@ -1,56 +0,0 @@
|
||||
%%% @author Thomas Arts
|
||||
%%% @doc Use `rebar3 as eqc shell` to run properties in the shell
|
||||
%%% Properties for testing Fate type representations
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 13 Dec 2018 by Thomas Arts <thomas@SpaceGrey.lan>
|
||||
|
||||
-module(aefate_type_eqc).
|
||||
|
||||
-include_lib("eqc/include/eqc.hrl").
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
kind(X) when is_atom(X) -> X;
|
||||
kind(T) when is_tuple(T) -> element(1, T).
|
||||
|
||||
prop_roundtrip() ->
|
||||
?FORALL(FateType, fate_type(),
|
||||
collect(kind(FateType),
|
||||
begin
|
||||
Serialized = aeb_fate_encoding:serialize_type(FateType),
|
||||
BinSerialized = list_to_binary(Serialized),
|
||||
?WHENFAIL(eqc:format("Serialized ~p to ~p (~p)~n", [FateType, Serialized, BinSerialized]),
|
||||
begin
|
||||
{Type, <<>>} = aeb_fate_encoding:deserialize_type(BinSerialized),
|
||||
equals(Type, FateType)
|
||||
end)
|
||||
end)).
|
||||
|
||||
|
||||
fate_type() ->
|
||||
?SIZED(Size, fate_type(Size)).
|
||||
|
||||
fate_type(0) ->
|
||||
oneof([integer,
|
||||
boolean,
|
||||
address,
|
||||
{bytes, nat()},
|
||||
contract,
|
||||
oracle,
|
||||
channel,
|
||||
bits,
|
||||
string]);
|
||||
fate_type(Size) ->
|
||||
?LAZY(
|
||||
oneof([fate_type(0),
|
||||
{list, fate_type(Size div 2)},
|
||||
?LETSHRINK(Ts, fate_types(Size), {tuple, Ts}),
|
||||
?LETSHRINK(Ts, fate_types(Size), {variant, Ts}),
|
||||
?LETSHRINK([T1, T2], vector(2, fate_type(Size div 2)),
|
||||
{map, T1, T2})])).
|
||||
|
||||
fate_types(Size) ->
|
||||
?LET(N, choose(0, 6),
|
||||
eqc_gen:list(N, fate_type(Size div max(2, N)))).
|
||||
|
59
rebar.config
59
rebar.config
@ -1,59 +0,0 @@
|
||||
%% -*- mode: erlang; indent-tabs-mode: nil -*-
|
||||
|
||||
{minimum_otp_vsn, "20.1"}.
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [ {eblake2, "1.0.0"}
|
||||
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
||||
{ref, "eb68fe3"}}}
|
||||
, {getopt, "1.0.1"}
|
||||
]}.
|
||||
|
||||
{escript_incl_apps, [aebytecode, eblake2, aeserialization, getopt]}.
|
||||
{escript_main_app, aebytecode}.
|
||||
{escript_name, aefateasm}.
|
||||
{escript_emu_args, "%%!"}.
|
||||
|
||||
{pre_hooks,
|
||||
[{"(linux|darwin|solaris|win32)", compile, "make sources"},
|
||||
{"(freebsd)", compile, "gmake sources"}]}.
|
||||
|
||||
{provider_hooks, [{post, [{compile, escriptize}]}]}.
|
||||
|
||||
|
||||
{dialyzer, [
|
||||
{warnings, [unknown]},
|
||||
{plt_apps, all_deps},
|
||||
{base_plt_apps, [erts, kernel, stdlib, crypto, getopt]}
|
||||
]}.
|
||||
|
||||
|
||||
{relx, [{release, {aebytecode, "3.2.0"},
|
||||
[aebytecode, eblake2, getopt]},
|
||||
|
||||
{dev_mode, true},
|
||||
{include_erts, false},
|
||||
|
||||
{extended_start_script, true}]}.
|
||||
|
||||
{profiles, [{binary, [
|
||||
{deps, [ {eblake2, "1.0.0"}
|
||||
, {aeserialization, {git, "https://github.com/aeternity/aeserialization.git",
|
||||
{ref, "47aaa8f"}}}
|
||||
, {getopt, "1.0.1"}
|
||||
]},
|
||||
|
||||
{post_hooks, [{"(linux|darwin|solaris|freebsd|netbsd|openbsd)",
|
||||
escriptize,
|
||||
"cp \"$REBAR_BUILD_DIR/bin/aefateasm\" ./aefateasm"},
|
||||
{"win32",
|
||||
escriptize,
|
||||
"robocopy \"%REBAR_BUILD_DIR%/bin/\" ./ aefateasm* "
|
||||
"/njs /njh /nfl /ndl & exit /b 0"} % silence things
|
||||
]}
|
||||
]},
|
||||
{eqc, [{erl_opts, [{parse_transform, eqc_cover}, {d, 'EQC'}]},
|
||||
{extra_src_dirs, ["quickcheck"]} %% May not be called eqc!
|
||||
]}
|
||||
]}.
|
23
rebar.lock
23
rebar.lock
@ -1,23 +0,0 @@
|
||||
{"1.2.0",
|
||||
[{<<"aeserialization">>,
|
||||
{git,"https://github.com/aeternity/aeserialization.git",
|
||||
{ref,"eb68fe331bd476910394966b7f5ede7a74d37e35"}},
|
||||
0},
|
||||
{<<"base58">>,
|
||||
{git,"https://github.com/aeternity/erl-base58.git",
|
||||
{ref,"60a335668a60328a29f9731b67c4a0e9e3d50ab6"}},
|
||||
1},
|
||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
||||
{<<"enacl">>,
|
||||
{git,"https://github.com/aeternity/enacl.git",
|
||||
{ref,"793ddb502f7fe081302e1c42227dca70b09f8e17"}},
|
||||
1},
|
||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}]}.
|
||||
[
|
||||
{pkg_hash,[
|
||||
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>},
|
||||
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]},
|
||||
{pkg_hash_ext,[
|
||||
{<<"eblake2">>, <<"3C4D300A91845B25D501929A26AC2E6F7157480846FAB2347A4C11AE52E08A99">>},
|
||||
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]}
|
||||
].
|
Loading…
x
Reference in New Issue
Block a user