Skip to content

Commit

Permalink
Merge pull request #2670 from aeternity/PT-167778774-mock-block-mining
Browse files Browse the repository at this point in the history
[PT-167778774] Decrease test runtime
  • Loading branch information
gorbak25 committed Aug 21, 2019
2 parents 9506e5e + 66fc907 commit b4d1956
Show file tree
Hide file tree
Showing 19 changed files with 398 additions and 64 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ references:
key: *machine_build_cache_key
paths:
- "_build"
- ".contracts_test_cache"

macos_package_cache_key: &macos_package_cache_key macos-package-cache-v1
restore_macos_package_cache: &restore_macos_package_cache
Expand Down
Empty file added .contracts_test_cache/.gitkeep
Empty file.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,5 @@ eqc-lib
eqc
/docs/.tools/
/docs/state-channels/*.svg
# The compilation cache is currently immovable - this must be cached in CI
.contracts_test_cache/aect_test_utils_compilation_cache_*
6 changes: 6 additions & 0 deletions apps/aechannel/src/aesc_session_noise.erl
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,15 @@ sleep(T, Ref) ->
ok
end.

-ifdef(TEST).
get_reconnect_params() ->
%% The increased granuality decreases the runtime of some tests by half :)
{50, 20}. %% Up to a second in the test environment
-else.
get_reconnect_params() ->
%% {ConnectTimeout, Retries}
{3000, 40}. %% max 4 minutes (up to 40 retries, where each retry is up to 3 seconds TCP connection timeout and 3 seconds sleep time).
-endif.

handle_call(close, _From, #st{econn = EConn} = St) ->
lager:debug("got close request", []),
Expand Down
68 changes: 34 additions & 34 deletions apps/aechannel/test/aesc_fsm_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ init_per_group_(Config) ->
true -> Config;
false ->
aecore_suite_utils:start_node(dev1, Config),
aecore_suite_utils:connect(aecore_suite_utils:node_name(dev1)),
aecore_suite_utils:connect(aecore_suite_utils:node_name(dev1), [block_pow]),
ct:log("dev1 connected", []),
try begin
Initiator = prep_initiator(dev1),
Expand Down Expand Up @@ -432,7 +432,7 @@ t_create_channel_(Cfg) ->
SignedTx = await_on_chain_report(R, ?TIMEOUT), % same tx
wait_for_signed_transaction_in_block(dev1, SignedTx, Debug),
verify_close_mutual_tx(SignedTx, ChannelId),
check_info(500),
check_info(20),
ok.

channel_insufficent_tokens(Cfg) ->
Expand Down Expand Up @@ -468,7 +468,7 @@ inband_msgs(Cfg) ->
fun(#{info := #{info := <<"i2r hello">>}}) -> ok end, 1000, true),

shutdown_(I, R, Cfg),
check_info(500).
check_info(20).

upd_transfer(Cfg) ->
Debug = get_debug(Cfg),
Expand All @@ -490,7 +490,7 @@ upd_transfer(Cfg) ->
SignedTx = await_on_chain_report(R, ?TIMEOUT), % same tx
wait_for_signed_transaction_in_block(dev1, SignedTx, Debug),
verify_close_mutual_tx(SignedTx, ChannelId),
check_info(500),
check_info(20),
ok.

update_with_conflict(Cfg) ->
Expand All @@ -511,7 +511,7 @@ update_with_conflict(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -536,7 +536,7 @@ update_with_soft_reject(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R1, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -558,7 +558,7 @@ deposit_with_conflict(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -583,7 +583,7 @@ deposit_with_soft_reject(Cfg) ->
{ok,_} = receive_from_fsm(conflict, R1, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -605,7 +605,7 @@ withdraw_with_conflict(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -630,7 +630,7 @@ withdraw_with_soft_reject(Cfg) ->
{ok,_} = receive_from_fsm(conflict, R1, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -652,7 +652,7 @@ upd_dep_with_conflict(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -674,7 +674,7 @@ upd_wdraw_with_conflict(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -696,7 +696,7 @@ dep_wdraw_with_conflict(Cfg) ->
{ok, _} = receive_from_fsm(conflict, R, any_msg(), ?TIMEOUT, Debug),
{ok, Round0} = rpc(dev1, aesc_fsm, get_round, [FsmI]),
{BalI, BalR} = get_both_balances(FsmI, PubI, PubR),
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand Down Expand Up @@ -743,7 +743,7 @@ do_update(From, To, Amount, #{fsm := FsmI} = I, R, Debug, Cfg) ->
rpc(dev1, aesc_fsm, upd_transfer, [FsmI, From, To, Amount], Debug),
{I1, _} = await_signing_request(update, I, Debug, Cfg),
{R1, _} = await_signing_request(update_ack, R, Debug, Cfg),
check_info(if_debug(Debug, 100, 0), Debug),
check_info(if_debug(Debug, 20, 0), Debug),
{I1, R1}.

msg_volley(#{fsm := FsmI, pub := PubI} = I, #{fsm := FsmR, pub := PubR} = R, _) ->
Expand Down Expand Up @@ -771,7 +771,7 @@ deposit(Cfg) ->
{IAmt0, RAmt0, _, Round0 = 1} = check_fsm_state(FsmI),
check_info(0),
{ok, I1, R1} = deposit_(I, R, Deposit, Round0, Debug, Cfg),
check_info(500),
check_info(20),
shutdown_(I1, R1, Cfg),
ok.

Expand Down Expand Up @@ -840,7 +840,7 @@ withdraw(Cfg) ->
{Expected, Expected} = {{IAmt0 - Withdrawal, RAmt0}, Expected},
SignedTx = await_on_chain_report(I1, #{info => channel_changed}, ?TIMEOUT), % same tx
SignedTx = await_on_chain_report(R1, #{info => channel_changed}, ?TIMEOUT), % same tx
check_info(500),
check_info(20),
shutdown_(I, R, Cfg),
ok.

Expand All @@ -859,9 +859,9 @@ channel_detects_close_solo(Cfg) ->
SignedTx = await_on_chain_report(R, #{info => solo_closing}, ?TIMEOUT),
{ok,_} = receive_from_fsm(info, I1, fun closing/1, ?TIMEOUT, Debug),
{ok,_} = receive_from_fsm(info, R, fun closing/1, ?TIMEOUT, Debug),
check_info(500),
check_info(20),
settle_(LockPeriod, maps:get(minimum_depth, Spec), I1, R, Debug, Cfg),
check_info(500),
check_info(20),
ok.

close_solo_tx(#{ fsm := Fsm
Expand Down Expand Up @@ -979,7 +979,7 @@ change_config_get_history(Cfg) ->
{error, invalid_config} =
rpc(dev1, aesc_fsm, change_config, [FsmI, invalid, config]),
shutdown_(I, R, Cfg),
check_info(500).
check_info(20).

check_history(Log) ->
%% Expected events for initiator so far, in reverse cronological order
Expand Down Expand Up @@ -1181,15 +1181,15 @@ check_incorrect_withdrawal(Cfg) ->
check_incorrect_update(Cfg) ->
config(Cfg),
Fun = proplists:get_value(wrong_action, Cfg),
InitialPort = proplists:get_value(port, Cfg, ?PORT),
Test =
fun(Depositor, Malicious) ->
fun({Depositor, Malicious}, CurPort) ->
Cfg1 = load_idx(Cfg),
Debug = true,
#{ i := #{pub := IPub, fsm := FsmI} = I
, r := #{pub := RPub, fsm := FsmR} = R
, spec := Spec} = create_channel_([?SLOGAN|Cfg1]),
Port = proplists:get_value(port, Cfg, ?PORT),
Data = {I, R, Spec, Port, Debug},
, spec := Spec} = create_channel_([{port, CurPort}, ?SLOGAN|Cfg1]),
Data = {I, R, Spec, CurPort, Debug},
Deposit =
fun() ->
Fun(Data, Depositor, Malicious,
Expand All @@ -1202,13 +1202,13 @@ check_incorrect_update(Cfg) ->
responder -> FsmR
end,
ok = gen_statem:stop(AliveFsm),
timer:sleep(1000), % so all sockets are free
bump_idx(),
ok
CurPort + 1
end,
Roles = [initiator, responder],
[Test(Depositor, Malicious) || Depositor <- Roles,
Malicious <- Roles],
Combinations = [{Depositor, Malicious} || Depositor <- Roles,
Malicious <- Roles],
lists:foldl(Test, InitialPort, Combinations),
ok.

check_incorrect_mutual_close(Cfg) ->
Expand All @@ -1227,7 +1227,7 @@ check_incorrect_mutual_close(Cfg) ->
{shutdown, [], shutdown,
shutdown_ack},
fun(#{fsm := FsmPid}, _Debug) ->
timer:sleep(1000),
timer:sleep(50),
true = rpc(dev1, erlang, process_info, [FsmPid]) =:= undefined
end),
bump_idx(),
Expand All @@ -1249,7 +1249,7 @@ check_mutual_close_with_wrong_amounts(Cfg) ->
create_channel_from_spec(Si, Sr, Spec, Port, Debug, Cfg),
%% We don't have enough funds to cover the closing fee
{error, insufficient_funds} = rpc(dev1, aesc_fsm, shutdown, [FsmI]),
timer:sleep(1000),
timer:sleep(50),
%% Fsms should be unaffected
true = (rpc(dev1, erlang, process_info, [FsmI]) =/= undefined),
true = (rpc(dev1, erlang, process_info, [FsmR]) =/= undefined),
Expand Down Expand Up @@ -1311,7 +1311,7 @@ check_mutual_close_after_close_solo(Cfg) ->
channel_closing = fsm_state(FsmR, Debug),

% Test that closing works
check_info(500),
check_info(20),
shutdown_(I, R, Cfg)
end,
ok.
Expand Down Expand Up @@ -1518,7 +1518,7 @@ wrong_action({I, R, _Spec, _Port, Debug}, Poster, Malicious,
DetectConflictFun(A, Debug),
rpc(dev1, aesc_fsm, strict_checks, [FsmA, true], Debug)
end,
check_info(500),
check_info(20),
ok.

shutdown_(#{fsm := FsmI, channel_id := ChannelId} = I, R, Cfg) ->
Expand Down Expand Up @@ -1588,7 +1588,7 @@ client_reconnect_(Role, Cfg) ->
log(Debug, "Reconnecting before disconnecting failed: ~p", [Err]),
unlink(Proxy),
exit(Proxy, kill),
timer:sleep(100), % give the above exit time to propagate
timer:sleep(50), % give the above exit time to propagate
ok = things_that_should_fail_if_no_client(Role, I, R, Debug, Cfg),
Res = reconnect(Fsm, Role, RoleI, Debug),
ct:log("Reconnect req -> ~p", [Res]),
Expand Down Expand Up @@ -1859,7 +1859,7 @@ create_channel_from_spec(I, R, Spec, Port, UseAny, Debug, Cfg) ->
R4 = await_update(R3, ?TIMEOUT, Debug),
I5 = await_open_report(I4, ?TIMEOUT, Debug),
R5 = await_open_report(R4, ?TIMEOUT, Debug),
check_info(500, Debug),
check_info(20, Debug),
#{i => I5, r => R5, spec => Spec}.

spawn_responder(Port, Spec, R, UseAny, Debug) ->
Expand Down Expand Up @@ -1985,7 +1985,7 @@ reestablish(ChId, I0, R0, SignedTx, Spec0, Port, Debug) ->
["localhost", Port, Spec], Debug),
I1 = await_open_report(I#{fsm => FsmI}, ?TIMEOUT, Debug),
R1 = await_open_report(R#{fsm => FsmR}, ?TIMEOUT, Debug),
check_info(500),
check_info(20),
#{i => I1, r => R1, spec => Spec}.

tx_amounts(SignedTx) ->
Expand Down
95 changes: 95 additions & 0 deletions apps/aecontract/test/aect_cache_restorer.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2019, Aeternity Anstalt
%%% @doc CT hook for restoring a persisted contract cache.
%%% Due to it subsequent test runs don't need to recompile contracts.
%%% @end
%%%-------------------------------------------------------------------
-module(aect_cache_restorer).

%% Callbacks
-export([id/1]).
-export([init/2]).
-export([terminate/1]).

-include("include/aect_contract_cache.hrl").

-record(state, {cache_dir :: string() | undefined, deps_hash :: binary() | undefined}).

%% Return a unique id for this CTH.
id(_Opts) ->
aect_cache_restorer.

init(_Id, _Opts) ->
{ok, Cwd} = file:get_cwd(),
case string:split(Cwd, "_build") of
[RootDir, _] ->
CacheDir = cache_dir(RootDir),
ensure_cache_dir_exists(CacheDir),

Deps = ["aesophia", "aesophia_cli", "aeserialization", "aebytecode"],
DepsHashes = [calculate_git_revision(RootDir, Dep) || Dep <- Deps],
DepsHash = base58:binary_to_base58(crypto:hash(sha256, string:join(DepsHashes, ""))),

ct:log("Cache: ~p, DepsHash: ~p", [CacheDir, DepsHash]),

[try_load_cache(CacheDir, DepsHash, ETSTable) || {ETSTable, _} <- cached_tables()],

{ok, #state{cache_dir = CacheDir, deps_hash = DepsHash}};
_ ->
ct:log("Ignoring persisted contract cache in system/smoke tests"),
{ok, #state{}}
end.

terminate(#state{cache_dir = undefined, deps_hash = undefined}) ->
ok;
terminate(#state{cache_dir = CacheDir, deps_hash = DepsHash}) ->
[save_cache(CacheDir, DepsHash, ETSTable) || {ETSTable, _} <- cached_tables()],
ok.

%%% ------------------------ INTERNAL --------------------

calculate_git_revision(RootDir, GitDep) ->
PathComponents = [RootDir, "_build", "test", "lib", GitDep],
Path = filename:join(PathComponents),
Cmd = io_lib:format("cd ~p; git rev-parse HEAD", [Path]),
os:cmd(Cmd).

cache_dir(RootDir) ->
filename:absname_join(RootDir, ".contracts_test_cache").

ensure_cache_dir_exists(CacheDir) ->
case file:make_dir(CacheDir) of
ok ->
ok;
{error, eexist} ->
ok
end.

ets_cache_filename(DepsHash, ETSTable) ->
atom_to_list(ETSTable) ++ "_" ++ DepsHash.

ets_cache_path(CacheDir, DepsHash, ETSTable) ->
filename:absname_join(CacheDir, ets_cache_filename(DepsHash, ETSTable)).

try_load_cache(CacheDir, DepsHash, ETSTable) ->
Path = ets_cache_path(CacheDir, DepsHash, ETSTable),
case filelib:is_file(Path) of
true ->
ct:log("Restoring persisted cache for: ~p", [ETSTable]),
case ets:info(ETSTable, name) of
undefined ->
ok;
_ ->
true = ets:delete(ETSTable)
end,
{ok, ETSTable} = ets:file2tab(Path, [{verify, true}]),
ok;
false ->
ct:log("Persisted cache for: ~p not available", [ETSTable]),
ok
end.

save_cache(CacheDir, DepsHash, ETSTable) ->
Path = ets_cache_path(CacheDir, DepsHash, ETSTable),
_ = ets:tab2file(ETSTable, Path, [{sync, true}, {extended_info, [md5sum, object_count]}]),
ok.

0 comments on commit b4d1956

Please sign in to comment.