All checks were successful
Sophia Tests / tests (push) Successful in 48m54s
A few references to oracles still remain, but they have been removed as a feature, at least. Reviewed-on: #985 Reviewed-by: Ulf Wiger <ulfwiger@qpq.swiss> Co-authored-by: Craig Everett <zxq9@zxq9.com> Co-committed-by: Craig Everett <zxq9@zxq9.com>
142 lines
5.2 KiB
Erlang
142 lines
5.2 KiB
Erlang
-module(so_aci_tests).
|
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
simple_aci_test_() ->
|
|
[{"Test contract " ++ integer_to_list(N),
|
|
fun() -> test_contract(N) end}
|
|
|| N <- [1, 2, 3]].
|
|
|
|
test_contract(N) ->
|
|
{Contract,MapACI,DecACI} = test_cases(N),
|
|
{ok,JSON} = so_aci:contract_interface(json, Contract),
|
|
?assertEqual([MapACI], JSON),
|
|
?assertEqual({ok, DecACI}, so_aci:render_aci_json(JSON)),
|
|
%% Check if the compiler provides correct aci
|
|
{ok,#{aci := JSON2}} = so_compiler:from_string(Contract, [{aci, json}]),
|
|
?assertEqual(JSON, JSON2).
|
|
|
|
test_cases(1) ->
|
|
Contract = <<"payable contract C =\n"
|
|
" payable stateful entrypoint a(i : int) = i+1\n">>,
|
|
MapACI = #{contract =>
|
|
#{name => <<"C">>,
|
|
typedefs => [],
|
|
payable => true,
|
|
kind => contract_main,
|
|
functions =>
|
|
[#{name => <<"a">>,
|
|
arguments =>
|
|
[#{name => <<"i">>,
|
|
type => <<"int">>}],
|
|
returns => <<"int">>,
|
|
stateful => true,
|
|
payable => true}]}},
|
|
DecACI = <<"payable main contract C =\n"
|
|
" payable stateful entrypoint a : (int) => int\n">>,
|
|
{Contract,MapACI,DecACI};
|
|
|
|
test_cases(2) ->
|
|
Contract = <<"main contract C =\n"
|
|
" type allan = int\n"
|
|
" entrypoint a(i : allan) = i+1\n">>,
|
|
MapACI = #{contract =>
|
|
#{name => <<"C">>, payable => false,
|
|
kind => contract_main,
|
|
typedefs =>
|
|
[#{name => <<"allan">>,
|
|
typedef => <<"int">>,
|
|
vars => []}],
|
|
functions =>
|
|
[#{arguments =>
|
|
[#{name => <<"i">>,
|
|
type => <<"C.allan">>}],
|
|
name => <<"a">>,
|
|
returns => <<"int">>,
|
|
stateful => false,
|
|
payable => false}]}},
|
|
DecACI = <<"main contract C =\n"
|
|
" type allan = int\n"
|
|
" entrypoint a : (C.allan) => int\n">>,
|
|
{Contract,MapACI,DecACI};
|
|
test_cases(3) ->
|
|
Contract = <<"main contract C =\n"
|
|
" type state = unit\n"
|
|
" datatype event = SingleEventDefined\n"
|
|
" datatype bert('a) = Bin('a)\n"
|
|
" entrypoint a(i : bert(string)) = 1\n">>,
|
|
MapACI = #{contract =>
|
|
#{functions =>
|
|
[#{arguments =>
|
|
[#{name => <<"i">>,
|
|
type =>
|
|
#{<<"C.bert">> => [<<"string">>]}}],
|
|
name => <<"a">>,returns => <<"int">>,
|
|
stateful => false, payable => false}],
|
|
name => <<"C">>, payable => false, kind => contract_main,
|
|
event => #{variant => [#{<<"SingleEventDefined">> => []}]},
|
|
state => <<"unit">>,
|
|
typedefs =>
|
|
[#{name => <<"bert">>,
|
|
typedef =>
|
|
#{variant =>
|
|
[#{<<"Bin">> => [<<"'a">>]}]},
|
|
vars => [#{name => <<"'a">>}]}]}},
|
|
DecACI = <<"main contract C =\n"
|
|
" type state = unit\n"
|
|
" datatype event = SingleEventDefined\n"
|
|
" datatype bert('a) = Bin('a)\n"
|
|
" entrypoint a : (C.bert(string)) => int\n">>,
|
|
{Contract,MapACI,DecACI}.
|
|
|
|
%% Roundtrip
|
|
aci_test_() ->
|
|
[{"Testing ACI generation for " ++ ContractName,
|
|
fun() -> aci_test_contract(ContractName) end}
|
|
|| ContractName <- all_contracts()].
|
|
|
|
all_contracts() -> so_compiler_tests:compilable_contracts().
|
|
|
|
aci_test_contract(Name) ->
|
|
String = so_test_utils:read_contract(Name),
|
|
Opts = case lists:member(Name, so_compiler_tests:debug_mode_contracts()) of
|
|
true -> [debug_mode];
|
|
false -> []
|
|
end ++ [{include, {file_system, [so_test_utils:contract_path()]}}],
|
|
JSON = case so_aci:contract_interface(json, String, Opts) of
|
|
{ok, J} -> J;
|
|
{error, ErrorStringJ} when is_binary(ErrorStringJ) -> error(ErrorStringJ);
|
|
{error, ErrorJ} -> so_compiler_tests:print_and_throw(ErrorJ)
|
|
end,
|
|
case so_compiler:from_string(String, [{aci, json} | Opts]) of
|
|
{ok, #{aci := JSON1}} ->
|
|
?assertEqual(JSON, JSON1),
|
|
io:format("JSON:\n~p\n", [JSON]),
|
|
{ok, ContractStub} = so_aci:render_aci_json(JSON),
|
|
|
|
io:format("STUB:\n~s\n", [ContractStub]),
|
|
check_stub(ContractStub, [{src_file, Name}]),
|
|
|
|
ok;
|
|
{error, ErrorString} when is_binary(ErrorString) -> error(ErrorString);
|
|
{error, Error} -> so_compiler_tests:print_and_throw(Error)
|
|
end.
|
|
|
|
check_stub(Stub, Options) ->
|
|
try so_parser:string(binary_to_list(Stub), Options) of
|
|
Ast ->
|
|
try
|
|
%% io:format("AST: ~120p\n", [Ast]),
|
|
so_ast_infer_types:infer(Ast, [no_code])
|
|
catch throw:{type_errors, TE} ->
|
|
io:format("Type error:\n~s\n", [TE]),
|
|
error(TE);
|
|
_:R ->
|
|
io:format("Error: ~p\n", [R]),
|
|
error(R)
|
|
end
|
|
catch throw:{error, Errs} ->
|
|
_ = [ io:format("~s\n", [so_errors:pp(E)]) || E <- Errs ],
|
|
error({parse_errors, Errs})
|
|
end.
|