From ee78d0ff2b1c1175c819c431b45f4c30e07ea75c Mon Sep 17 00:00:00 2001 From: Nick Vatamaniuc Date: Sun, 15 Mar 2020 13:08:24 -0400 Subject: [fixup] Move pmap/2,3 to fabric_util Enhance it to behave closer to lists:map such that exceptions with stacktraces will are re-thrown. Also use a macro to avoid the stacktrace deprecation warning. This also eliminates the need to validate its results as we can use EUnit asserts directly in the executor function. --- src/fabric/src/fabric2_util.erl | 49 ++++++++++++++++++++++++++++++- src/fabric/test/fabric2_db_crud_tests.erl | 16 ++++------ src/fabric/test/fabric2_test_util.erl | 23 --------------- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/fabric/src/fabric2_util.erl b/src/fabric/src/fabric2_util.erl index a4faf3987..46f9abeef 100644 --- a/src/fabric/src/fabric2_util.erl +++ b/src/fabric/src/fabric2_util.erl @@ -37,7 +37,10 @@ from_hex/1, uuid/0, - encode_all_doc_key/1 + encode_all_doc_key/1, + + pmap/2, + pmap/3 ]). @@ -298,3 +301,47 @@ encode_all_doc_key(N) when is_number(N) -> <<>>; encode_all_doc_key(B) when is_binary(B) -> B; encode_all_doc_key(L) when is_list(L) -> <<255>>; encode_all_doc_key({O}) when is_list(O) -> <<255>>. + + +pmap(Fun, Args) -> + pmap(Fun, Args, []). + + +pmap(Fun, Args, Opts) -> + Refs = lists:map(fun(Arg) -> + {_, Ref} = spawn_monitor(fun() -> exit(pmap_exec(Fun, Arg)) end), + Ref + end, Args), + Timeout = fabric2_util:get_value(timeout, Opts, 5000), + lists:map(fun(Ref) -> + receive + {'DOWN', Ref, _, _, {'$res', Res}} -> + Res; + {'DOWN', Ref, _, _, {'$err', Tag, Reason, Stack}} -> + erlang:raise(Tag, Reason, Stack) + after Timeout -> + error({pmap_timeout, Timeout}) + end + end, Refs). + + +% OTP_RELEASE is defined in OTP 21+ only +-ifdef(OTP_RELEASE). + +pmap_exec(Fun, Arg) -> + try + {'$res', Fun(Arg)} + catch Tag:Reason:Stack -> + {'$err', Tag, Reason, Stack} + end. + +-else. + +pmap_exec(Fun, Arg) -> + try + {'$res', Fun(Arg)} + catch Tag:Reason -> + {'$err', Tag, Reason, erlang:get_stacktrace()} + end. + +-endif. diff --git a/src/fabric/test/fabric2_db_crud_tests.erl b/src/fabric/test/fabric2_db_crud_tests.erl index 39fc757c6..c0a65ebd8 100644 --- a/src/fabric/test/fabric2_db_crud_tests.erl +++ b/src/fabric/test/fabric2_db_crud_tests.erl @@ -201,16 +201,12 @@ list_dbs_info_tx_too_old(_) -> % so create more than 100 dbs so make sure we have 100+ dbs in our test DbCount = 101, - DbNames = fabric2_test_util:pmap(fun(_) -> + DbNames = fabric2_util:pmap(fun(_) -> DbName = ?tempdb(), - {ok, _} = fabric2_db:create(DbName, []), + ?assertMatch({ok, _}, fabric2_db:create(DbName, [])), DbName end, lists:seq(1, DbCount)), - % Sanity check the pmap results - ?assertEqual(DbCount, length(DbNames)), - ?assert(lists:all(fun(DbName) -> is_binary(DbName) end, DbNames)), - UserFun = fun(Row, Acc) -> fabric2_test_util:tx_too_old_raise_in_user_fun(), {ok, [Row, Acc]} @@ -255,11 +251,9 @@ list_dbs_info_tx_too_old(_) -> fabric2_test_util:tx_too_old_setup_errors(1, {1, 1}), ?assertEqual({ok, DbInfos}, fabric2_db:list_dbs_info(UserFun, [], [])), - DeleteResults = fabric2_test_util:pmap(fun(DbName) -> - fabric2_db:delete(DbName, []) - end, DbNames), - - ?assert(lists:all(fun(Res) -> Res =:= ok end, DeleteResults)). + fabric2_util:pmap(fun(DbName) -> + ?assertEqual(ok, fabric2_db:delete(DbName, [])) + end, DbNames). is_db_info_member(_, []) -> diff --git a/src/fabric/test/fabric2_test_util.erl b/src/fabric/test/fabric2_test_util.erl index b4dc978a8..acbe252b1 100644 --- a/src/fabric/test/fabric2_test_util.erl +++ b/src/fabric/test/fabric2_test_util.erl @@ -14,9 +14,6 @@ -export([ - pmap/2, - pmap/3, - tx_too_old_mock_erlfdb/0, tx_too_old_setup_errors/2, tx_too_old_reset_errors/0, @@ -28,26 +25,6 @@ -define(PDICT_ERROR_IN_USER_FUN, '$fabric2_error_throw_in_user_fun'). -pmap(Fun, Args) -> - pmap(Fun, Args, []). - - -pmap(Fun, Args, Opts) -> - Refs = lists:map(fun(Arg) -> - {_, Ref} = spawn_monitor(fun() -> exit({'$pmap_res', Fun(Arg)}) end), - Ref - end, Args), - Timeout = fabric2_util:get_value(timeout, Opts, 5000), - lists:map(fun(Ref) -> - receive - {'DOWN', Ref, _, _, {'$pmap_res', Res}} -> Res; - {'DOWN', Ref, _, _, Error} -> {pmap_error, Error} - after Timeout -> - {pmap_error, timeout} - end - end, Refs). - - % Set of function to test scenarios where the FDB throws transaction_too_long % (1007) errors. The general pattern is to call tx_too_old_mock_erlfdb() in % setup. Then, before tests call tx_too_old_setup_errors(UserErrs, FoldErrs) -- cgit v1.2.1