From 8d6bbffc2ac7afcc955fb7850561c463806b9a5c Mon Sep 17 00:00:00 2001 From: liubo Date: Tue, 5 Dec 2023 17:15:54 +0800 Subject: [PATCH] Add introspection of which modules are currently mocked Signed-off-by: liubo --- ...n-of-which-modules-are-currently-moc.patch | 131 ++++++++++++++++++ erlang-meck.spec | 8 +- 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 0001-Add-introspection-of-which-modules-are-currently-moc.patch diff --git a/0001-Add-introspection-of-which-modules-are-currently-moc.patch b/0001-Add-introspection-of-which-modules-are-currently-moc.patch new file mode 100644 index 0000000..1f567cf --- /dev/null +++ b/0001-Add-introspection-of-which-modules-are-currently-moc.patch @@ -0,0 +1,131 @@ +From 1ed7933038d709faae7d7fa8152e2c07ad2d6e50 Mon Sep 17 00:00:00 2001 +From: Filipe Cristovao +Date: Tue, 12 May 2020 22:13:51 +0200 +Subject: [PATCH] Add introspection of which modules are currently mocked + +There's already an `meck:expects/[1,2]`, allowing introspection into +what kind of expectations are set. +This allows one to also check which modules is meck handling at any +point. + +Introduced a `foldl_mocks` internal function to reuse the same logic +for both `unload/0` and `mocked/0` +--- + src/meck.erl | 47 ++++++++++++++++++++++++++------------------- + test/meck_tests.erl | 21 ++++++++++++++++++++ + 2 files changed, 48 insertions(+), 20 deletions(-) + +diff --git a/src/meck.erl b/src/meck.erl +index 9f4efc2..8eb0365 100644 +--- a/src/meck.erl ++++ b/src/meck.erl +@@ -54,6 +54,7 @@ + -export([wait/4]). + -export([wait/5]). + -export([wait/6]). ++-export([mocked/0]). + + %% Syntactic sugar + -export([loop/1]). +@@ -460,7 +461,15 @@ history(Mod, OptCallerPid) + -spec unload() -> Unloaded when + Unloaded :: [Mod], + Mod :: atom(). +-unload() -> lists:foldl(fun unload_if_mocked/2, [], registered()). ++unload() -> ++ foldl_mocks(fun(Mod, Acc) -> ++ try ++ unload(Mod), ++ [Mod | Acc] ++ catch error:{not_mocked, Mod} -> ++ Acc ++ end ++ end, []). + + %% @doc Unload a mocked module or a list of mocked modules. + %% +@@ -723,6 +732,11 @@ capture(Occur, Mod, Func, OptArgsSpec, ArgNum, OptCallerPid) -> + capture(Occur, Mod, Func, OptArgsSpec, ArgNum) -> + meck_history:capture(Occur, '_', Mod, Func, OptArgsSpec, ArgNum). + ++%% @doc Returns the currently mocked modules. ++-spec mocked() -> list(atom()). ++mocked() -> ++ foldl_mocks(fun(M, Acc) -> [M | Acc] end, []). ++ + %%%============================================================================ + %%% Internal functions + %%%============================================================================ +@@ -732,25 +746,18 @@ wait_for_exit(Mod) -> + MonitorRef = erlang:monitor(process, meck_util:proc_name(Mod)), + receive {'DOWN', MonitorRef, _Type, _Object, _Info} -> ok end. + +--spec unload_if_mocked(Mod::atom() | string(), Unloaded::[atom()]) -> +- NewUnloaded::[atom()]. +-unload_if_mocked(Mod, Unloaded) when is_atom(Mod) -> +- unload_if_mocked(atom_to_list(Mod), Unloaded); +-unload_if_mocked(ModName, Unloaded) when length(ModName) > 5 -> +- case lists:split(length(ModName) - 5, ModName) of +- {Name, "_meck"} -> +- Mocked = erlang:list_to_existing_atom(Name), +- try +- unload(Mocked) +- catch error:{not_mocked, Mocked} -> +- ok +- end, +- [Mocked | Unloaded]; +- _Else -> +- Unloaded +- end; +-unload_if_mocked(_P, Unloaded) -> +- Unloaded. ++-spec foldl_mocks(Fun, AccIn) -> AccOut when ++ Fun :: fun((Elem :: module(), AccIn) -> AccOut), ++ AccIn :: term(), ++ AccOut :: term(). ++foldl_mocks(Fun, Acc0) when is_function(Fun, 2) -> ++ lists:foldl(fun(Mod, Acc) -> ++ ModName = atom_to_list(Mod), ++ case lists:split(max(length(ModName) - 5, 0), ModName) of ++ {Name, "_meck"} -> Fun(erlang:list_to_existing_atom(Name), Acc); ++ _Else -> Acc ++ end ++ end, Acc0, erlang:registered()). + + -spec check_expect_result(ok | {error, Reason::any()}) -> ok. + check_expect_result(ok) -> ok; +diff --git a/test/meck_tests.erl b/test/meck_tests.erl +index f17223c..988ded7 100644 +--- a/test/meck_tests.erl ++++ b/test/meck_tests.erl +@@ -1547,6 +1547,27 @@ wait_purge_expired_tracker_test() -> + %% Clean + meck:unload(). + ++mocked_test() -> ++ %% At start, no modules should be mocked: ++ [] = meck:mocked(), ++ ++ %% Mocking a new module adds it to the list of mocked modules: ++ meck:new(mocked_test, [non_strict]), ++ [mocked_test] = meck:mocked(), ++ ++ %% Mocking with implicit `meck:new` also adds to the list of mocked modules: ++ meck:expect(meck_test_module, c, 2, ok), ++ [meck_test_module, mocked_test] = lists:sort(meck:mocked()), ++ ++ meck:new([foo, bar], [non_strict]), ++ [bar, foo, meck_test_module, mocked_test] = lists:sort(meck:mocked()), ++ ++ ok = meck:unload([foo, meck_test_module]), ++ [bar, mocked_test] = lists:sort(meck:mocked()), ++ ++ meck:unload(), ++ %% After unload all, no modules should be mocked again ++ [] = meck:mocked(). + + meck_passthrough_test_() -> + {foreach, fun setup_passthrough/0, fun teardown/1, +-- +2.42.0.windows.2 + diff --git a/erlang-meck.spec b/erlang-meck.spec index 7f447ab..9d8c196 100644 --- a/erlang-meck.spec +++ b/erlang-meck.spec @@ -2,7 +2,7 @@ %global upstream eproxus Name: erlang-meck Version: 0.8.13 -Release: 1 +Release: 2 BuildArch: noarch Summary: A mocking library for Erlang License: ASL 2.0 @@ -11,6 +11,9 @@ Source0: https://github.com/eproxus/meck/archive/%{version}/meck-%{version}.tar. Patch1: erlang-meck-0001-Workaround-for-Rebar-2.x.patch BuildRequires: erlang-hamcrest BuildRequires: erlang-rebar + +Patch0002: 0001-Add-introspection-of-which-modules-are-currently-moc.patch + %description With meck you can easily mock modules in Erlang. Since meck is intended to be used in testing, you can also perform some basic validations on the mocked @@ -34,5 +37,8 @@ modules, such as making sure no function is called in a way it should not. %{erlang_appdir}/ %changelog +* Tue Dec 5 2023 liubo - 0.8.13-2 +- Add introspection of which modules are currently mocked + * Sat Aug 29 2020 yaokai - 0.8.13-1 - package init -- Gitee