⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 megaco_appup_test.erl

📁 OTP是开放电信平台的简称
💻 ERL
字号:
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%%%----------------------------------------------------------------------%% Purpose: Verify the application specifics of the Megaco application%%-----------------------------------------------------------------------module(megaco_appup_test).-compile(export_all).-include("megaco_test_lib.hrl").-define(APPLICATION, megaco).t()     -> megaco_test_lib:t(?MODULE).t(Case) -> megaco_test_lib:t({?MODULE, Case}).%% Test server callbacksinit_per_testcase(Case, Config) ->    megaco_test_lib:init_per_testcase(Case, Config).fin_per_testcase(Case, Config) ->    megaco_test_lib:fin_per_testcase(Case, Config).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%all(suite) ->    Cases = 	[	 appup	],    {req, [], {conf, appup_init, Cases, appup_fin}}.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%appup_init(suite) -> [];appup_init(doc) -> [];appup_init(Config) when list(Config) ->    AppFile   = file_name(?APPLICATION, ".app"),    AppupFile = file_name(?APPLICATION, ".appup"),    [{app_file, AppFile}, {appup_file, AppupFile}|Config].    file_name(App, Ext) ->    LibDir = code:lib_dir(App),    filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]).appup_fin(suite) -> [];appup_fin(doc) -> [];appup_fin(Config) when list(Config) ->    Config.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%appup(suite) ->    [];appup(doc) ->    "perform a simple check of the appup file";appup(Config) when list(Config) ->    AppupFile = key1search(appup_file, Config),    AppFile   = key1search(app_file, Config),    Modules   = modules(AppFile),    check_appup(AppupFile, Modules).modules(File) ->    case file:consult(File) of        {ok, [{application,megaco,Info}]} ->            case lists:keysearch(modules,1,Info) of                {value, {modules, Modules}} ->                    Modules;                false ->                    fail({bad_appinfo, Info})            end;        Error ->            fail({bad_appfile, Error})    end.    check_appup(AppupFile, Modules) ->    case file:consult(AppupFile) of	{ok, [{V, UpFrom, DownTo}]} ->	    check_appup(V, UpFrom, DownTo, Modules);	Else ->	    fail({bad_appupfile, Else})    end.check_appup(V, UpFrom, DownTo, Modules) ->    check_version(V),    check_depends(up,   UpFrom, Modules),    check_depends(down, DownTo, Modules),    check_module_subset(UpFrom),    check_module_subset(DownTo),    ok.check_depends(_, [], _) ->    ok;check_depends(UpDown, [Dep|Deps], Modules) ->    check_depend(UpDown, Dep, Modules),    check_depends(UpDown, Deps, Modules).check_depend(up = UpDown, {add_application, ?APPLICATION} = Instr, Modules) ->     d("check_instructions(~w) -> entry with"       "~n   Instruction: ~p"       "~n   Modules:     ~p", [UpDown, Instr, Modules]),     ok;check_depend(down = UpDown, {remove_application, ?APPLICATION} = Instr, 	     Modules) ->     d("check_instructions(~w) -> entry with"       "~n   Instruction: ~p"       "~n   Modules:     ~p", [UpDown, Instr, Modules]),     ok;check_depend(UpDown, {V, Instructions}, Modules) ->    d("check_instructions(~w) -> entry with"      "~n   V:       ~p"      "~n   Modules: ~p", [UpDown, V, Modules]),    check_version(V),    case check_instructions(UpDown, 			    Instructions, Instructions, [], [], Modules) of	{_Good, []} ->	    ok;	{_, Bad} ->	    fail({bad_instructions, Bad, UpDown})    end.check_instructions(_, [], _, Good, Bad, _) ->    {lists:reverse(Good), lists:reverse(Bad)};check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) ->    d("check_instructions(~w) -> entry with"      "~n   Instr: ~p", [UpDown,Instr]),    case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of        ok ->            check_instructions(UpDown, Instrs, AllInstr, 			       [Instr|Good], Bad, Modules);        {error, Reason} ->	    d("check_instructions(~w) -> bad instruction: "	      "~n   Reason: ~p", [UpDown,Reason]),            check_instructions(UpDown, Instrs, AllInstr, Good,                                [{Instr, Reason}|Bad], Modules)    end.%% A new module is addedcheck_instruction(up, {add_module, Module}, _, Modules)   when atom(Module) ->    d("check_instruction -> entry when up-add_module instruction with"      "~n   Module: ~p", [Module]),    check_module(Module, Modules);%% An old module is re-addedcheck_instruction(down, {add_module, Module}, _, Modules)   when atom(Module) ->    d("check_instruction -> entry when down-add_module instruction with"      "~n   Module: ~p", [Module]),    case (catch check_module(Module, Modules)) of	{error, {unknown_module, Module, Modules}} ->	    ok;	ok ->	    error({existing_readded_module, Module})    end;%% Removing a module on upgrade: %% - the module has been removed from the app-file.%% - check that no module depends on this (removed) modulecheck_instruction(up, {remove, {Module, Pre, Post}}, _, Modules)   when atom(Module), atom(Pre), atom(Post) ->    d("check_instruction -> entry when up-remove instruction with"      "~n   Module: ~p"      "~n   Pre:    ~p"      "~n   Post:   ~p", [Module, Pre, Post]),    case (catch check_module(Module, Modules)) of	{error, {unknown_module, Module, Modules}} ->	    check_purge(Pre),	    check_purge(Post);	ok ->	    error({existing_removed_module, Module})    end;%% Removing a module on downgrade: the module exist%% in the app-file.check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules)   when atom(Module), atom(Pre), atom(Post) ->    d("check_instruction -> entry when down-remove instruction with"      "~n   Module: ~p"      "~n   Pre:    ~p"      "~n   Post:   ~p", [Module, Pre, Post]),    case (catch check_module(Module, Modules)) of	ok ->	    check_purge(Pre),	    check_purge(Post),	    check_no_remove_depends(Module, AllInstr);	{error, {unknown_module, Module, Modules}} ->	    error({nonexisting_removed_module, Module})    end;check_instruction(_, {load_module, Module, Pre, Post, Depend}, 		  AllInstr, Modules)   when atom(Module), atom(Pre), atom(Post), list(Depend) ->    d("check_instruction -> entry when load_module instruction with"      "~n   Module: ~p"      "~n   Pre:    ~p"      "~n   Post:   ~p"      "~n   Depend: ~p", [Module, Pre, Post, Depend]),    check_module(Module, Modules),    check_module_depend(Module, Depend, Modules),    check_module_depend(Module, Depend, updated_modules(AllInstr, [])),    check_purge(Pre),    check_purge(Post);check_instruction(_, {update, Module, Change, Pre, Post, Depend}, 		  AllInstr, Modules)   when atom(Module), atom(Pre), atom(Post), list(Depend) ->    d("check_instruction -> entry when update instruction with"      "~n   Module: ~p"      "~n   Change: ~p"      "~n   Pre:    ~p"      "~n   Post:   ~p"      "~n   Depend: ~p", [Module, Change, Pre, Post, Depend]),    check_module(Module, Modules),    check_module_depend(Module, Depend, Modules),    check_module_depend(Module, Depend, updated_modules(AllInstr, [])),    check_change(Change),    check_purge(Pre),    check_purge(Post);check_instruction(_, {update, Module, supervisor}, _, Modules)   when is_atom(Module) ->    check_module(Module, Modules);check_instruction(_, {apply, {Module, Function, Args}}, _, Modules)   when atom(Module), atom(Function), list(Args) ->     d("check_instruction -> entry when down-apply instruction with"       "~n   Module:   ~p"       "~n   Function: ~p"       "~n   Args:     ~p", [Module, Function, Args]),     check_module(Module, Modules),     check_apply(Module, Function, Args);check_instruction(_, Instr, _AllInstr, _Modules) ->    d("check_instruction -> entry when unknown instruction with"      "~n   Instr: ~p", [Instr]),    error({error, {unknown_instruction, Instr}}).%% If Module X depends on Module Y, then module Y must have an update%% instruction of some sort (otherwise the depend is faulty).updated_modules([], Modules) ->    d("update_modules -> entry when done with"      "~n   Modules: ~p", [Modules]),    Modules;updated_modules([Instr|Instrs], Modules) ->    d("update_modules -> entry with"      "~n   Instr:   ~p"      "~n   Modules: ~p", [Instr,Modules]),    Module = instruction_module(Instr),    d("update_modules -> Module: ~p", [Module]),    updated_modules(Instrs, [Module|Modules]).    instruction_module({add_module, Module}) ->    Module;instruction_module({remove, {Module, _, _}}) ->    Module;instruction_module({load_module, Module, _, _, _}) ->    Module;instruction_module({update, Module, _, _, _, _}) ->    Module;instruction_module({apply, {Module, _, _}}) ->     Module;instruction_module(Instr) ->    d("instruction_module -> entry when unknown instruction with"      "~n   Instr: ~p", [Instr]),    error({error, {unknown_instruction, Instr}}).    %% Check that the modules handled in an instruction set for version X%% is a subset of the instruction set for version X-1.check_module_subset(Instructions) ->    do_check_module_subset(modules_of(Instructions)). do_check_module_subset([]) ->    ok;do_check_module_subset([_]) ->    ok;do_check_module_subset([{_V1, Mods1}|T]) ->    {V2, Mods2} = hd(T),    %% Check that the modules in V1 is a subset of V2    case do_check_module_subset2(Mods1, Mods2) of        ok ->            do_check_module_subset(T);        {error, Modules} ->            fail({subset_missing_instructions, V2, Modules})    end. do_check_module_subset2(Mods1, Mods2) ->    do_check_module_subset2(Mods1, Mods2, []). do_check_module_subset2([], _, []) ->    ok;do_check_module_subset2([], _, Acc) ->    {error, lists:reverse(Acc)};do_check_module_subset2([Mod|Mods], Mods2, Acc) ->    case lists:member(Mod, Mods2) of        true ->            do_check_module_subset2(Mods, Mods2, Acc);        false ->            do_check_module_subset2(Mods, Mods2, [Mod|Acc])    end.      modules_of(Instructions) ->    modules_of(Instructions, []). modules_of([], Acc) ->    lists:reverse(Acc);modules_of([{V,Instructions}|T], Acc) ->    Mods = modules_of2(Instructions, []),    modules_of(T, [{V, Mods}|Acc]). modules_of2([], Acc) ->    lists:reverse(Acc);modules_of2([Instr|Instructions], Acc) ->    case module_of(Instr) of        {value, Mod} ->            modules_of2(Instructions, [Mod|Acc]);        false ->            modules_of2(Instructions, Acc)    end. module_of({add_module, Module}) ->    {value, Module};module_of({remove, {Module, _Pre, _Post}}) ->    {value, Module};module_of({load_module, Module, _Pre, _Post, _Depend}) ->    {value, Module};module_of({update, Module, _Change, _Pre, _Post, _Depend}) ->    {value, Module};module_of(_) ->    false. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The version is a string consting of numbers separated by dots: "."%% Example: "3.3.3"%% check_version(V) when list(V) ->    case do_check_version(string:tokens(V, [$.])) of	ok ->	    ok;	{error, BadVersionPart} ->	    throw({error, {bad_version, V, BadVersionPart}})    end;check_version(V) ->    error({bad_version, V}).do_check_version([]) ->    ok;do_check_version([H|T]) ->    case (catch list_to_integer(H)) of	I when is_integer(I) ->	    do_check_version(T);	_ ->	    {error, H}    end.	    check_module(M, Modules) when atom(M) ->    case lists:member(M,Modules) of        true ->            ok;        false ->            error({unknown_module, M, Modules})    end;check_module(M, _) ->    error({bad_module, M}).check_module_depend(M, [], _) when atom(M) ->    d("check_module_depend -> entry with"      "~n   M: ~p", [M]),        ok;check_module_depend(M, Deps, Modules) when atom(M), list(Deps) ->    d("check_module_depend -> entry with"      "~n   M: ~p"      "~n   Deps: ~p"      "~n   Modules: ~p", [M, Deps, Modules]),        case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of        [] ->            ok;        Unknown ->            error({unknown_depend_modules, Unknown})    end;check_module_depend(_M, D, _Modules) ->    d("check_module_depend -> entry when bad depend with"      "~n   D: ~p", [D]),        error({bad_depend, D}).check_no_remove_depends(_Module, []) ->    ok;check_no_remove_depends(Module, [Instr|Instrs]) ->    check_no_remove_depend(Module, Instr),    check_no_remove_depends(Module, Instrs).check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) ->    case lists:member(Module, Depend) of	true ->	    error({removed_module_in_depend, load_module, Mod, Module});	false ->	    ok    end;check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) ->    case lists:member(Module, Depend) of	true ->	    error({removed_module_in_depend, update, Mod, Module});	false ->	    ok    end;check_no_remove_depend(_, _) ->    ok.    check_change(soft) ->    ok;check_change({advanced, _Something}) ->    ok;check_change(Change) ->    error({bad_change, Change}).check_purge(soft_purge) ->    ok;check_purge(brutal_purge) ->    ok;check_purge(Purge) ->    error({bad_purge, Purge}).check_apply(Module, Function, Args) ->     case (catch Module:module_info()) of	Info when list(Info) ->	    check_exported(Function, Args, Info);	{'EXIT', {undef, _}} ->	    error({not_existing_module, Module})     end.check_exported(Function, Args, Info) ->     case lists:keysearch(exports, 1, Info) of	{value, {exports, FuncList}} ->	     Arity   = length(Args), 	     Arities = [A || {F, A} <- FuncList, F == Function],	     case lists:member(Arity, Arities) of		 true ->		     ok;		 false ->		     error({not_exported_function, Function, Arity})	     end;	 _ ->	     error({bad_export, Info})     end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%error(Reason) ->    throw({error, Reason}).fail(Reason) ->    exit({suite_failed, Reason}).key1search(Key, L) ->    case lists:keysearch(Key, 1, L) of	undefined ->	    fail({not_found, Key, L});	{value, {Key, Value}} ->	    Value    end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%d(F, A) ->    d(false, F, A).d(true, F, A) ->    io:format(F ++ "~n", A);d(_, _, _) ->    ok.    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -