./ct_report/coverage/mongoose_modules.COVER.html

1 -module(mongoose_modules).
2
3 -include("mongoose.hrl").
4
5 %% API
6 -export([start/0, stop/0]).
7
8 %% Module management utilities for tests
9 -export([replace_modules/3, ensure_stopped/2, ensure_started/3]).
10 -ignore_xref([replace_modules/3, ensure_stopped/2, ensure_started/3]).
11
12 -type module_opts() :: gen_mod:module_opts().
13 -type module_map() :: gen_mod_deps:module_map().
14 -type module_list() :: gen_mod_deps:module_list().
15
16 %% @doc Start all configured modules in the dependency order.
17 -spec start() -> 'ok'.
18 start() ->
19 93 [gen_mod:start_module(HostType, Mod, Opts) || HostType <- ?ALL_HOST_TYPES,
20 508 {Mod, Opts} <- sorted_modules(HostType)],
21 93 ok.
22
23 %% @doc Stop all configured modules in the reverse dependency order
24 %% to avoid stopping modules which have other modules dependent on them.
25 -spec stop() -> 'ok'.
26 stop() ->
27 93 [gen_mod:stop_module(HostType, Mod) || HostType <- ?ALL_HOST_TYPES,
28 508 {Mod, _} <- lists:reverse(sorted_modules(HostType))],
29 93 ok.
30
31 %% @doc Replace modules at runtime - only for testing and debugging.
32 %% Running modules from ToStop are stopped and modules from ToEnsure are (re)started when needed.
33 %% Unused dependencies are stopped if no running modules depend on them anymore.
34 %% To prevent an unused dependency from being stopped, you need to include it in ToEnsure.
35 -spec replace_modules(mongooseim:host_type(), [module()], module_map()) -> ok.
36 replace_modules(HostType, ToStop, ToEnsure) ->
37 686 Current = get_modules(HostType),
38 686 Old = maps:with(ToStop ++ maps:keys(ToEnsure), Current),
39 686 OldWithDeps = gen_mod_deps:resolve_deps(HostType, Old),
40 686 SortedOldWithDeps = gen_mod_deps:sort_deps(HostType, OldWithDeps),
41 686 WithoutOld = maps:without(maps:keys(OldWithDeps), Current),
42 686 WithNew = maps:merge(WithoutOld, ToEnsure),
43 686 Target = gen_mod_deps:resolve_deps(HostType, WithNew),
44
45 %% Stop each affected module if it is not in Target (stop deps first)
46 686 [ensure_stopped(HostType, Module) || {Module, _} <- lists:reverse(SortedOldWithDeps),
47 4337 not maps:is_key(Module, Target)],
48
49 %% Ensure each module from Target
50 686 [ensure_started(HostType, Module, Opts) ||
51 686 {Module, Opts} <- gen_mod_deps:sort_deps(HostType, Target)],
52 686 ok.
53
54 %% @doc Make sure the module is stopped.
55 -spec ensure_stopped(mongooseim:host_type(), module()) ->
56 already_stopped | {stopped, module_opts()}.
57 ensure_stopped(HostType, Module) ->
58 849 Modules = get_modules(HostType),
59 849 case maps:find(Module, Modules) of
60 error ->
61 19 already_stopped;
62 {_, Opts} ->
63 830 stop_module(HostType, Module, Modules),
64 830 {stopped, Opts}
65 end.
66
67 %% @doc Make sure the module is running with the provided options.
68 -spec ensure_started(mongooseim:host_type(), module(), module_opts()) ->
69 already_started | {started, term()} | {restarted, module_opts(), term()}.
70 ensure_started(HostType, Module, Opts) ->
71 11320 Modules = get_modules(HostType),
72 11320 case maps:find(Module, Modules) of
73 error ->
74 830 {ok, Result} = start_module(HostType, Module, Opts, Modules),
75 830 {started, Result};
76 {_, Opts} ->
77 10193 already_started;
78 {_, PrevOpts} ->
79 297 stop_module(HostType, Module, Modules),
80 297 {ok, Result} = start_module(HostType, Module, Opts, Modules),
81 297 {restarted, PrevOpts, Result}
82 end.
83
84 %% Helpers
85
86 -spec start_module(mongooseim:host_type(), module(), module_opts(), module_map()) -> {ok, term()}.
87 start_module(HostType, Module, Opts, Modules) ->
88 1127 set_modules(HostType, Modules#{Module => Opts}),
89 1127 try
90 1127 gen_mod:start_module(HostType, Module, Opts)
91 catch
92 C:R:S ->
93
:-(
set_modules(HostType, Modules),
94
:-(
erlang:raise(C, R, S)
95 end.
96
97 -spec stop_module(mongooseim:host_type(), module(), module_map()) -> ok.
98 stop_module(HostType, Module, Modules) ->
99 1127 gen_mod:stop_module(HostType, Module),
100 1127 set_modules(HostType, maps:remove(Module, Modules)).
101
102 -spec sorted_modules(mongooseim:host_type()) -> module_list().
103 sorted_modules(HostType) ->
104 1016 gen_mod_deps:sort_deps(HostType, get_modules(HostType)).
105
106 -spec get_modules(mongooseim:host_type()) -> module_map().
107 get_modules(HostType) ->
108 13871 mongoose_config:get_opt({modules, HostType}).
109
110 -spec set_modules(mongooseim:host_type(), module_map()) -> ok.
111 set_modules(HostType, Modules) ->
112 2254 mongoose_config:set_opt({modules, HostType}, Modules).
Line Hits Source