4
%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
6
%% The contents of this file are subject to the Erlang Public License,
7
%% Version 1.1, (the "License"); you may not use this file except in
8
%% compliance with the License. You should have received a copy of the
9
%% Erlang Public License along with this software. If not, it can be
10
%% retrieved online at http://www.erlang.org/.
12
%% Software distributed under the License is distributed on an "AS IS"
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
%% the License for the specific language governing rights and limitations
20
%%----------------------------------------------------------------------
21
%% Purpose: Verify the application specifics of the Inets application
22
%%----------------------------------------------------------------------
23
-module(inets_appup_test).
26
-compile({no_auto_import,[error/1]}).
28
-include("inets_test_lib.hrl").
31
% t() -> megaco_test_lib:t(?MODULE).
32
% t(Case) -> megaco_test_lib:t({?MODULE, Case}).
35
%% Test server callbacks
36
init_per_testcase(_Case, Config) ->
39
end_per_testcase(_Case, Config) ->
42
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50
init_per_group(_GroupName, Config) ->
53
end_per_group(_GroupName, Config) ->
57
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59
init_per_suite(suite) -> [];
60
init_per_suite(doc) -> [];
61
init_per_suite(Config) when is_list(Config) ->
62
AppFile = file_name(inets, ".app"),
63
AppupFile = file_name(inets, ".appup"),
64
[{app_file, AppFile}, {appup_file, AppupFile}|Config].
67
file_name(App, Ext) ->
68
LibDir = code:lib_dir(App),
69
filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]).
72
end_per_suite(suite) -> [];
73
end_per_suite(doc) -> [];
74
end_per_suite(Config) when is_list(Config) ->
78
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83
"perform a simple check of the appup file";
84
appup(Config) when is_list(Config) ->
85
AppupFile = key1search(appup_file, Config),
86
AppFile = key1search(app_file, Config),
87
Modules = modules(AppFile),
88
check_appup(AppupFile, Modules).
91
case file:consult(File) of
92
{ok, [{application,inets,Info}]} ->
93
case lists:keysearch(modules,1,Info) of
94
{value, {modules, Modules}} ->
97
fail({bad_appinfo, Info})
100
fail({bad_appfile, Error})
104
check_appup(AppupFile, Modules) ->
105
case file:consult(AppupFile) of
106
{ok, [{V, UpFrom, DownTo}]} ->
110
% "~n", [V, UpFrom, DownTo]),
111
check_appup(V, UpFrom, DownTo, Modules);
113
fail({bad_appupfile, Else})
117
check_appup(V, UpFrom, DownTo, Modules) ->
119
check_depends(up, UpFrom, Modules),
120
check_depends(down, DownTo, Modules),
124
check_depends(_, [], _) ->
126
check_depends(UpDown, [Dep|Deps], Modules) ->
127
check_depend(UpDown, Dep, Modules),
128
check_depends(UpDown, Deps, Modules).
131
check_depend(UpDown, {V, Instructions}, Modules) ->
133
case check_instructions(UpDown,
134
Instructions, Instructions, [], [], Modules) of
138
fail({bad_instructions, Bad, UpDown})
142
check_instructions(_, [], _, Good, Bad, _) ->
143
{lists:reverse(Good), lists:reverse(Bad)};
144
check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) ->
145
case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of
147
check_instructions(UpDown, Instrs, AllInstr,
148
[Instr|Good], Bad, Modules);
150
check_instructions(UpDown, Instrs, AllInstr, Good,
151
[{Instr, Reason}|Bad], Modules)
153
check_instructions(UpDown, Instructions, _, _, _, _) ->
154
fail({bad_instructions, {UpDown, Instructions}}).
156
%% A new module is added
157
check_instruction(up, {add_module, Module}, _, Modules)
158
when is_atom(Module) ->
159
check_module(Module, Modules);
161
%% An old module is re-added
162
check_instruction(down, {add_module, Module}, _, Modules)
163
when is_atom(Module) ->
164
case (catch check_module(Module, Modules)) of
165
{error, {unknown_module, Module, Modules}} ->
168
error({existing_readded_module, Module})
171
%% Removing a module on upgrade:
172
%% - the module has been removed from the app-file.
173
%% - check that no module depends on this (removed) module
174
check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules)
175
when is_atom(Module), is_atom(Pre), is_atom(Post) ->
176
case (catch check_module(Module, Modules)) of
177
{error, {unknown_module, Module, Modules}} ->
181
error({existing_removed_module, Module})
184
%% Removing a module on downgrade: the module exist
186
check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules)
187
when is_atom(Module), is_atom(Pre), is_atom(Post) ->
188
case (catch check_module(Module, Modules)) of
192
check_no_remove_depends(Module, AllInstr);
193
{error, {unknown_module, Module, Modules}} ->
194
error({nonexisting_removed_module, Module})
197
check_instruction(up, {load_module, Module, Pre, Post, Depend}, _, Modules)
198
when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
199
check_module(Module, Modules),
200
check_module_depend(Module, Depend, Modules),
204
check_instruction(down, {load_module, Module, Pre, Post, Depend}, _, Modules)
205
when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
206
check_module(Module, Modules),
207
% Can not be sure that the the dependent module exists in the new appfile
208
%%check_module_depend(Module, Depend, Modules),
214
check_instruction(up, {delete_module, Module}, _, Modules)
215
when is_atom(Module) ->
216
case (catch check_module(Module, Modules)) of
217
{error, {unknown_module, Module, Modules}} ->
220
error({existing_module_deleted, Module})
223
check_instruction(down, {delete_module, Module}, _, Modules)
224
when is_atom(Module) ->
225
check_module(Module, Modules);
228
check_instruction(_, {apply, {Module, Function, Args}}, _, _) when is_atom(Module), is_atom(Function), is_list(Args) ->
231
check_instruction(_, {update, Module, supervisor}, _, Modules) when is_atom(Module) ->
232
check_module(Module, Modules);
234
check_instruction(_, {update, Module, {advanced, _}, DepMods}, _, Modules) when is_atom(Module), is_list(DepMods) ->
235
check_module(Module, Modules),
236
check_module_depend(Module, DepMods, Modules);
238
check_instruction(_, {update, Module, Change, Pre, Post, Depend}, _, Modules)
239
when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
240
check_module(Module, Modules),
241
check_module_depend(Module, Depend, Modules),
242
check_change(Change),
246
check_instruction(_, {restart_application, inets}, _AllInstr, _Modules) ->
249
check_instruction(_, {update, Module, {advanced, _}}, _, Modules) ->
250
check_module(Module, Modules);
252
check_instruction(_, Instr, _AllInstr, _Modules) ->
253
error({error, {unknown_instruction, Instr}}).
256
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258
check_version(V) when is_list(V) ->
261
error({bad_version, V}).
264
check_module(M, Modules) when is_atom(M) ->
265
case lists:member(M,Modules) of
269
error({unknown_module, M, Modules})
271
check_module(M, _) ->
272
error({bad_module, M}).
275
check_module_depend(M, [], _) when is_atom(M) ->
277
check_module_depend(M, Deps, Modules) when is_atom(M), is_list(Deps) ->
278
case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of
282
error({unknown_depend_modules, Unknown})
284
check_module_depend(_M, D, _Modules) ->
285
error({bad_depend, D}).
288
check_no_remove_depends(_Module, []) ->
290
check_no_remove_depends(Module, [Instr|Instrs]) ->
291
check_no_remove_depend(Module, Instr),
292
check_no_remove_depends(Module, Instrs).
294
check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) ->
295
case lists:member(Module, Depend) of
297
error({removed_module_in_depend, load_module, Mod, Module});
301
check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) ->
302
case lists:member(Module, Depend) of
304
error({removed_module_in_depend, update, Mod, Module});
308
check_no_remove_depend(_, _) ->
312
check_change(soft) ->
314
check_change({advanced, _Something}) ->
316
check_change(Change) ->
317
error({bad_change, Change}).
320
check_purge(soft_purge) ->
322
check_purge(brutal_purge) ->
324
check_purge(Purge) ->
325
error({bad_purge, Purge}).
329
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332
throw({error, Reason}).
335
exit({suite_failed, Reason}).
337
key1search(Key, L) ->
338
case lists:keysearch(Key, 1, L) of
340
fail({not_found, Key, L});
341
{value, {Key, Value}} ->