From 8c79c17611c37217345e969aa2c344fe34e0375e Mon Sep 17 00:00:00 2001 From: Andrey Pampukha Date: Tue, 23 Feb 2010 15:31:12 +0100 Subject: Remove configuration handling from ct_util completely --- lib/common_test/src/ct.erl | 21 +- lib/common_test/src/ct_config.erl | 579 +++++++++++++++++++++++++++++++- lib/common_test/src/ct_config_plain.erl | 6 +- lib/common_test/src/ct_framework.erl | 10 +- lib/common_test/src/ct_run.erl | 2 +- lib/common_test/src/ct_snmp.erl | 12 +- lib/common_test/src/ct_util.erl | 534 ++--------------------------- 7 files changed, 638 insertions(+), 526 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 8ae041e5b4..3cc6154592 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -135,7 +135,8 @@ run(TestDirs) -> %%% @spec run_test(Opts) -> Result %%% Opts = [OptTuples] %%% OptTuples = {config,CfgFiles} | {dir,TestDirs} | {suite,Suites} | -%%% {testcase,Cases} | {group,Groups} | {spec,TestSpecs} | +%%% {userconfig, Callback, CfgFiles} | +%%% {testcase,Cases} | {group,Groups} | {spec,TestSpecs} | %%% {allow_user_terms,Bool} | {logdir,LogDir} | %%% {silent_connections,Conns} | {cover,CoverSpecFile} | %%% {step,StepOpts} | {event_handler,EventHandlers} | {include,InclDirs} | @@ -269,7 +270,7 @@ stop_interactive() -> %%% @see get_config/2 %%% @see get_config/3 require(Required) -> - ct_util:require(Required). + ct_config:require(Required). %%%----------------------------------------------------------------- %%% @spec require(Name,Required) -> ok | {error,Reason} @@ -304,19 +305,19 @@ require(Required) -> %%% @see get_config/2 %%% @see get_config/3 require(Name,Required) -> - ct_util:require(Name,Required). + ct_config:require(Name,Required). %%%----------------------------------------------------------------- %%% @spec get_config(Required) -> Value %%% @equiv get_config(Required,undefined,[]) get_config(Required) -> - ct_util:get_config(Required,undefined,[]). + ct_config:get_config(Required,undefined,[]). %%%----------------------------------------------------------------- %%% @spec get_config(Required,Default) -> Value %%% @equiv get_config(Required,Default,[]) get_config(Required,Default) -> - ct_util:get_config(Required,Default,[]). + ct_config:get_config(Required,Default,[]). %%%----------------------------------------------------------------- %%% @spec get_config(Required,Default,Opts) -> ValueOrElement @@ -375,7 +376,7 @@ get_config(Required,Default) -> %%% @see require/1 %%% @see require/2 get_config(Required,Default,Opts) -> - ct_util:get_config(Required,Default,Opts). + ct_config:get_config(Required,Default,Opts). %%%----------------------------------------------------------------- %%% @spec log(Format) -> ok @@ -734,7 +735,7 @@ abort_current_testcase(Reason) -> %%%

See the crypto application for details on DES3 %%% encryption/decryption.

encrypt_config_file(SrcFileName, EncryptFileName) -> - ct_util:encrypt_config_file(SrcFileName, EncryptFileName). + ct_config:encrypt_config_file(SrcFileName, EncryptFileName). %%%----------------------------------------------------------------- %%% @spec encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) -> @@ -754,7 +755,7 @@ encrypt_config_file(SrcFileName, EncryptFileName) -> %%%

See the crypto application for details on DES3 %%% encryption/decryption.

encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) -> - ct_util:encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile). + ct_config:encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile). %%%----------------------------------------------------------------- %%% @spec decrypt_config_file(EncryptFileName, TargetFileName) -> @@ -770,7 +771,7 @@ encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) -> %%% .ct_config.crypt in the current directory, or the %%% home directory of the user (it is searched for in that order).

decrypt_config_file(EncryptFileName, TargetFileName) -> - ct_util:decrypt_config_file(EncryptFileName, TargetFileName). + ct_config:decrypt_config_file(EncryptFileName, TargetFileName). %%%----------------------------------------------------------------- %%% @spec decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile) -> @@ -785,5 +786,5 @@ decrypt_config_file(EncryptFileName, TargetFileName) -> %%% file contents is saved in the target file. The key must have the %%% the same value as that used for encryption.

decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile) -> - ct_util:decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile). + ct_config:decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile). diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index f344813128..9a1f23201f 100755 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -24,16 +24,169 @@ %%---------------------------------------------------------------------- -module(ct_config). +% start of the config server +-export([start/0, start/1, start/2, stop/0]). + +% manipulating with config files -export([read_config_files/1, - set_config/1, set_config/2, set_config/3, - delete_config/1, get_config_file_list/1]). --include("ct_event.hrl"). +% require +-export([require/1, require/2]). + +% get config data +-export([get_config/1, get_config/2, get_config/3, + get_all_config/0]). + +% set config data +-export([set_config/1, set_config/2, set_config/3, + set_default_config/2, set_default_config/3]). + +% delete config data +-export([delete_config/1, delete_default_config/1]). + +% update and reload config +-export([%reload_config/1, + update_config/2]). + +% ? +-export([release_allocated/0]). + +-export([encrypt_config_file/2, encrypt_config_file/3, + decrypt_config_file/2, decrypt_config_file/3, + get_crypt_key_from_file/0, get_crypt_key_from_file/1]). + +% references +-export([get_ref_from_name/1, get_name_from_ref/1, get_key_from_name/1]). + -include("ct_util.hrl"). +-include("ct_event.hrl"). + +-define(cryptfile, ".ct_config.crypt"). +% TODO: add handler field here -record(ct_conf,{key,value,ref,name='_UNDEF',default=false}). -%% default = {true,suite} | {true,testcase} | false + +%%%----------------------------------------------------------------- +%%% @spec start(Mode) -> Pid | exit(Error) +%%% Mode = normal | interactive +%%% Pid = pid() +%%% +%%% @doc Start start the ct_config_server process +%%% (tool-internal use only). +%%% +%%%

This function is called from ct_run.erl. It starts and initiates +%%% the ct_config_server

+%%% +%%%

Returns the process identity of the +%%% ct_config_server.

+%%% +%%% @see ct +start() -> + start(normal,"."). + +start(LogDir) when is_list(LogDir) -> + start(normal,LogDir); +start(Mode) -> + start(Mode,"."). + +start(Mode,LogDir) -> + case whereis(ct_config_server) of + undefined -> + Me = self(), + Pid = spawn_link(fun() -> do_start(Me) end), + receive + {Pid,started} -> Pid; + {Pid,Error} -> exit(Error) + end; + Pid -> + case ct_util:get_mode() of + interactive when Mode==interactive -> + Pid; + interactive -> + {error,interactive_mode}; + _OtherMode -> + Pid + end + end. + +do_start(Parent) -> + process_flag(trap_exit,true), + register(ct_config_server,self()), + ct_util:create_table(?attr_table,bag,#ct_conf.key), + {ok,StartDir} = file:get_cwd(), + Opts = case ct_util:read_opts() of + {ok,Opts1} -> + Opts1; + Error -> + Parent ! {self(),Error}, + exit(Error) + end, + case read_config_files(Opts) of + ok -> + Parent ! {self(),started}, + loop(StartDir); + ReadError -> + Parent ! {self(),ReadError}, + exit(ReadError) + end. + +%%%----------------------------------------------------------------- +%%% @spec stop() -> ok +%%% +%%% @doc Stop the ct_config_server and close all existing connections +%%% (tool-internal use only). +%%% +%%% @see ct +stop() -> + case whereis(ct_config_server) of + undefined -> ok; + _ -> call({stop}) + end. + +call(Msg) -> + MRef = erlang:monitor(process, whereis(ct_config_server)), + Ref = make_ref(), + ct_config_server ! {Msg,{self(),Ref}}, + receive + {Ref, Result} -> + erlang:demonitor(MRef), + Result; + {'DOWN',MRef,process,_,Reason} -> + {error,{ct_util_server_down,Reason}} + end. + +return({To,Ref},Result) -> + To ! {Ref, Result}. + + +loop(StartDir) -> + receive + {{require,Name,Tag,SubTags},From} -> + Result = do_require(Name,Tag,SubTags), + return(From,Result), + loop(StartDir); + {{set_default_config,{Config,Scope}},From} -> + ct_config:set_config(Config,{true,Scope}), + return(From,ok), + loop(StartDir); + {{set_default_config,{Name,Config,Scope}},From} -> + ct_config:set_config(Name,Config,{true,Scope}), + return(From,ok), + loop(StartDir); + {{delete_default_config,Scope},From} -> + ct_config:delete_config({true,Scope}), + return(From,ok), + loop(StartDir); + {{update_config,{Name,NewConfig}},From} -> + update_conf(Name,NewConfig), + return(From,ok), + loop(StartDir); + {{stop},From} -> + ets:delete(?attr_table), + file:set_cwd(StartDir), + return(From,ok) + end. read_config_files(Opts) -> AddCallback = fun(CallBack, Files)-> @@ -74,6 +227,180 @@ set_config(Name,Config,Default) -> name=Name,default=Default}) || {Key,Val} <- Config]. +get_config(KeyOrName,Default,Opts) when is_atom(KeyOrName) -> + case lookup_config(KeyOrName) of + [] -> + Default; + [{_Ref,Val}|_] = Vals -> + case {lists:member(all,Opts),lists:member(element,Opts)} of + {true,true} -> + [{KeyOrName,V} || {_R,V} <- lists:sort(Vals)]; + {true,false} -> + [V || {_R,V} <- lists:sort(Vals)]; + {false,true} -> + {KeyOrName,Val}; + {false,false} -> + Val + end + end; + +get_config({KeyOrName,SubKey},Default,Opts) -> + case lookup_config(KeyOrName) of + [] -> + Default; + Vals -> + Vals1 = case [Val || {_Ref,Val} <- lists:sort(Vals)] of + Result=[L|_] when is_list(L) -> + case L of + [{_,_}|_] -> + Result; + _ -> + [] + end; + _ -> + [] + end, + case get_subconfig([SubKey],Vals1,[],Opts) of + {ok,[{_,SubVal}|_]=SubVals} -> + case {lists:member(all,Opts),lists:member(element,Opts)} of + {true,true} -> + [{{KeyOrName,SubKey},Val} || {_,Val} <- SubVals]; + {true,false} -> + [Val || {_SubKey,Val} <- SubVals]; + {false,true} -> + {{KeyOrName,SubKey},SubVal}; + {false,false} -> + SubVal + end; + _ -> + Default + end + end. + + +%%%----------------------------------------------------------------- +%%% @spec +%%% +%%% @doc +update_conf(Name, NewConfig) -> + Old = ets:select(?attr_table,[{#ct_conf{name=Name,_='_'},[],['$_']}]), + lists:foreach(fun(OldElem) -> + NewElem = OldElem#ct_conf{value=NewConfig}, + ets:delete_object(?attr_table, OldElem), + ets:insert(?attr_table, NewElem) + end, Old), + ok. + +%%%----------------------------------------------------------------- +%%% @spec release_allocated() -> ok +%%% +%%% @doc Release all allocated resources, but don't take down any +%%% connections. +release_allocated() -> + Allocated = ets:select(?attr_table,[{#ct_conf{name='$1',_='_'}, + [{'=/=','$1','_UNDEF'}], + ['$_']}]), + release_allocated(Allocated). +release_allocated([H|T]) -> + ets:delete_object(?attr_table,H), + ets:insert(?attr_table,H#ct_conf{name='_UNDEF'}), + release_allocated(T); +release_allocated([]) -> + ok. + +allocate(Name,Key,SubKeys) -> + case ets:match_object(?attr_table,#ct_conf{key=Key,name='_UNDEF',_='_'}) of + [] -> + {error,{not_available,Key}}; + Available -> + case allocate_subconfig(Name,SubKeys,Available,false) of + ok -> + ok; + Error -> + Error + end + end. + +allocate_subconfig(Name,SubKeys,[C=#ct_conf{value=Value}|Rest],Found) -> + case do_get_config(SubKeys,Value,[]) of + {ok,_SubMapped} -> + ets:insert(?attr_table,C#ct_conf{name=Name}), + allocate_subconfig(Name,SubKeys,Rest,true); + _Error -> + allocate_subconfig(Name,SubKeys,Rest,Found) + end; +allocate_subconfig(_Name,_SubKeys,[],true) -> + ok; +allocate_subconfig(_Name,SubKeys,[],false) -> + {error,{not_available,SubKeys}}. + +%%%----------------------------------------------------------------- +%%% @hidden +%%% @equiv ct:get_config/1 +get_config(KeyOrName) -> + ct_config:get_config(KeyOrName,undefined,[]). + +%%%----------------------------------------------------------------- +%%% @hidden +%%% @equiv ct:get_config/2 +get_config(KeyOrName,Default) -> + ct_config:get_config(KeyOrName,Default,[]). + +get_subconfig(SubKeys,Values) -> + get_subconfig(SubKeys,Values,[],[]). + +get_subconfig(SubKeys,[Value|Rest],Mapped,Opts) -> + case do_get_config(SubKeys,Value,[]) of + {ok,SubMapped} -> + case lists:member(all,Opts) of + true -> + get_subconfig(SubKeys,Rest,Mapped++SubMapped,Opts); + false -> + {ok,SubMapped} + end; + _Error -> + get_subconfig(SubKeys,Rest,Mapped,Opts) + end; +get_subconfig(SubKeys,[],[],_) -> + {error,{not_available,SubKeys}}; +get_subconfig(_SubKeys,[],Mapped,_) -> + {ok,Mapped}. + +do_get_config([Key|Required],Available,Mapped) -> + case lists:keysearch(Key,1,Available) of + {value,{Key,Value}} -> + NewAvailable = lists:keydelete(Key,1,Available), + NewMapped = [{Key,Value}|Mapped], + do_get_config(Required,NewAvailable,NewMapped); + false -> + {error,{not_available,Key}} + end; +do_get_config([],_Available,Mapped) -> + {ok,lists:reverse(Mapped)}. + +get_all_config() -> + ets:select(?attr_table,[{#ct_conf{name='$1',key='$2',value='$3', + default='$4',_='_'}, + [], + [{{'$1','$2','$3','$4'}}]}]). + +lookup_config(KeyOrName) -> + case lookup_name(KeyOrName) of + [] -> + lookup_key(KeyOrName); + Values -> + Values + end. + +lookup_name(Name) -> + ets:select(?attr_table,[{#ct_conf{ref='$1',value='$2',name=Name,_='_'}, + [], + [{{'$1','$2'}}]}]). +lookup_key(Key) -> + ets:select(?attr_table,[{#ct_conf{key=Key,ref='$1',value='$2',name='_UNDEF',_='_'}, + [], + [{{'$1','$2'}}]}]). + delete_config(Default) -> ets:match_delete(?attr_table,#ct_conf{default=Default,_='_'}), ok. @@ -115,3 +442,247 @@ get_config_file_list(Opts)-> end ++ process_user_configs(Opts, []), CfgFiles. + +%%%----------------------------------------------------------------- +%%% @hidden +%%% @equiv ct:require/1 +require(Key) when is_atom(Key) -> + require({Key,[]}); +require({Key,SubKeys}) when is_atom(Key) -> + allocate('_UNDEF',Key,to_list(SubKeys)); +require(Key) -> + {error,{invalid,Key}}. + + +%%%----------------------------------------------------------------- +%%% @hidden +%%% @equiv ct:require/2 +require(Name,Key) when is_atom(Key) -> + require(Name,{Key,[]}); +require(Name,{Key,SubKeys}) when is_atom(Name), is_atom(Key) -> + call({require,Name,Key,to_list(SubKeys)}); +require(Name,Keys) -> + {error,{invalid,{Name,Keys}}}. + +to_list(X) when is_list(X) -> X; +to_list(X) -> [X]. + +do_require(Name,Key,SubKeys) when is_list(SubKeys) -> + case get_key_from_name(Name) of + {error,_} -> + allocate(Name,Key,SubKeys); + {ok,Key} -> + %% already allocated - check that it has all required subkeys + Vals = [Val || {_Ref,Val} <- lookup_name(Name)], + case get_subconfig(SubKeys,Vals) of + {ok,_SubMapped} -> + ok; + Error -> + Error + end; + {ok,OtherKey} -> + {error,{name_in_use,Name,OtherKey}} + end. + +%%%----------------------------------------------------------------- +%%% @spec +%%% +%%% @doc +encrypt_config_file(SrcFileName, EncryptFileName) -> + case get_crypt_key_from_file() of + {error,_} = E -> + E; + Key -> + encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) + end. + + +get_ref_from_name(Name) -> + case ets:select(?attr_table,[{#ct_conf{name=Name,ref='$1',_='_'}, + [], + ['$1']}]) of + [Ref] -> + {ok,Ref}; + _ -> + {error,{no_such_name,Name}} + end. + +get_name_from_ref(Ref) -> + case ets:select(?attr_table,[{#ct_conf{name='$1',ref=Ref,_='_'}, + [], + ['$1']}]) of + [Name] -> + {ok,Name}; + _ -> + {error,{no_such_ref,Ref}} + end. + +get_key_from_name(Name) -> + case ets:select(?attr_table,[{#ct_conf{name=Name,key='$1',_='_'}, + [], + ['$1']}]) of + [Key|_] -> + {ok,Key}; + _ -> + {error,{no_such_name,Name}} + end. + +%%%----------------------------------------------------------------- +%%% @spec +%%% +%%% @doc +encrypt_config_file(SrcFileName, EncryptFileName, {file,KeyFile}) -> + case get_crypt_key_from_file(KeyFile) of + {error,_} = E -> + E; + Key -> + encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) + end; + +encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) -> + crypto:start(), + {K1,K2,K3,IVec} = make_crypto_key(Key), + case file:read_file(SrcFileName) of + {ok,Bin0} -> + Bin1 = term_to_binary({SrcFileName,Bin0}), + Bin2 = case byte_size(Bin1) rem 8 of + 0 -> Bin1; + N -> list_to_binary([Bin1,random_bytes(8-N)]) + end, + EncBin = crypto:des3_cbc_encrypt(K1, K2, K3, IVec, Bin2), + case file:write_file(EncryptFileName, EncBin) of + ok -> + io:format("~s --(encrypt)--> ~s~n", + [SrcFileName,EncryptFileName]), + ok; + {error,Reason} -> + {error,{Reason,EncryptFileName}} + end; + {error,Reason} -> + {error,{Reason,SrcFileName}} + end. + +%%%----------------------------------------------------------------- +%%% @spec +%%% +%%% @doc +decrypt_config_file(EncryptFileName, TargetFileName) -> + case get_crypt_key_from_file() of + {error,_} = E -> + E; + Key -> + decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) + end. + + +set_default_config(NewConfig, Scope) -> + call({set_default_config, {NewConfig, Scope}}). + +set_default_config(Name, NewConfig, Scope) -> + call({set_default_config, {Name, NewConfig, Scope}}). + +delete_default_config(Scope) -> + call({delete_default_config, Scope}). + +update_config(Name, Config) -> + call({update_config, {Name, Config}}). + +%%%----------------------------------------------------------------- +%%% @spec +%%% +%%% @doc +decrypt_config_file(EncryptFileName, TargetFileName, {file,KeyFile}) -> + case get_crypt_key_from_file(KeyFile) of + {error,_} = E -> + E; + Key -> + decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) + end; + +decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) -> + crypto:start(), + {K1,K2,K3,IVec} = make_crypto_key(Key), + case file:read_file(EncryptFileName) of + {ok,Bin} -> + DecBin = crypto:des3_cbc_decrypt(K1, K2, K3, IVec, Bin), + case catch binary_to_term(DecBin) of + {'EXIT',_} -> + {error,bad_file}; + {_SrcFile,SrcBin} -> + case TargetFileName of + undefined -> + {ok,SrcBin}; + _ -> + case file:write_file(TargetFileName, SrcBin) of + ok -> + io:format("~s --(decrypt)--> ~s~n", + [EncryptFileName,TargetFileName]), + ok; + {error,Reason} -> + {error,{Reason,TargetFileName}} + end + end + end; + {error,Reason} -> + {error,{Reason,EncryptFileName}} + end. + + +get_crypt_key_from_file(File) -> + case file:read_file(File) of + {ok,Bin} -> + case catch string:tokens(binary_to_list(Bin), [$\n,$\r]) of + [Key] -> + Key; + _ -> + {error,{bad_crypt_file,File}} + end; + {error,Reason} -> + {error,{Reason,File}} + end. + +get_crypt_key_from_file() -> + CwdFile = filename:join(".",?cryptfile), + {Result,FullName} = + case file:read_file(CwdFile) of + {ok,Bin} -> + {Bin,CwdFile}; + _ -> + case init:get_argument(home) of + {ok,[[Home]]} -> + HomeFile = filename:join(Home,?cryptfile), + case file:read_file(HomeFile) of + {ok,Bin} -> + {Bin,HomeFile}; + _ -> + {{error,no_crypt_file},noent} + end; + _ -> + {{error,no_crypt_file},noent} + end + end, + case FullName of + noent -> + Result; + _ -> + case catch string:tokens(binary_to_list(Result), [$\n,$\r]) of + [Key] -> + io:format("~nCrypt key file: ~s~n", [FullName]), + Key; + _ -> + {error,{bad_crypt_file,FullName}} + end + end. + +make_crypto_key(String) -> + <> = First = erlang:md5(String), + <> = erlang:md5([First|lists:reverse(String)]), + {K1,K2,K3,IVec}. + +random_bytes(N) -> + {A,B,C} = now(), + random:seed(A, B, C), + random_bytes_1(N, []). + +random_bytes_1(0, Acc) -> Acc; +random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]). diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl index a5947cafef..be0433aa9f 100755 --- a/lib/common_test/src/ct_config_plain.erl +++ b/lib/common_test/src/ct_config_plain.erl @@ -38,10 +38,10 @@ read_config_file(ConfigFile) -> {key,K} -> K; {file,F} -> - ct_util:get_crypt_key_from_file(F) + ct_config:get_crypt_key_from_file(F) end; _ -> - ct_util:get_crypt_key_from_file() + ct_config:get_crypt_key_from_file() end, case Key of {error,no_crypt_file} -> @@ -49,7 +49,7 @@ read_config_file(ConfigFile) -> {error,CryptError} -> {error, decrypt_file_error, CryptError}; _ when is_list(Key) -> - case ct_util:decrypt_config_file(ConfigFile, undefined, {key,Key}) of + case ct_config:decrypt_config_file(ConfigFile, undefined, {key,Key}) of {ok,CfgBin} -> case read_config_terms(CfgBin) of {error,ReadFail} -> diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index ed8b564921..89bbc2448f 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -113,9 +113,9 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> ok; true -> %% delete all default values used in previous suite - ct_util:delete_default_config(suite), + ct_config:delete_default_config(suite), %% release all name -> key bindings (once per suite) - ct_util:release_allocated() + ct_config:release_allocated() end, TestCaseInfo = case catch apply(Mod,Func,[]) of @@ -125,7 +125,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> %% clear all config data default values set by previous %% testcase info function (these should only survive the %% testcase, not the whole suite) - ct_util:delete_default_config(testcase), + ct_config:delete_default_config(testcase), case add_defaults(Mod,Func,TestCaseInfo,DoInit) of Error = {suite0_failed,_} -> ct_logs:init_tc(), @@ -381,10 +381,10 @@ try_set_default(Name,Key,Info,Where) -> {_,[]} -> no_default; {'_UNDEF',_} -> - [ct_util:set_default_config([CfgVal],Where) || CfgVal <- CfgElems], + [ct_config:set_default_config([CfgVal],Where) || CfgVal <- CfgElems], ok; _ -> - [ct_util:set_default_config(Name,[CfgVal],Where) || CfgVal <- CfgElems], + [ct_config:set_default_config(Name,[CfgVal],Where) || CfgVal <- CfgElems], ok end. diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index b86dd8fe2f..04bc047f43 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -222,7 +222,7 @@ script_start1(Parent, Args) -> end, Config = ConfigFiles ++ UserConfigs, case Config of - false -> + [] -> case install([{config,[]}, {event_handler,EvHandlers}], LogDir) of diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl index 7ff88ad7d3..b515c578c7 100644 --- a/lib/common_test/src/ct_snmp.erl +++ b/lib/common_test/src/ct_snmp.erl @@ -332,7 +332,7 @@ set_info(Config) -> register_users(MgrAgentConfName, Users) -> {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {users, Users}), - ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), setup_users(Users). %%% @spec register_agents(MgrAgentConfName, ManagedAgents) -> ok | {error, Reason} @@ -347,7 +347,7 @@ register_agents(MgrAgentConfName, ManagedAgents) -> {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), NewSnmpVals = lists:keyreplace(managed_agents, 1, SnmpVals, {managed_agents, ManagedAgents}), - ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), setup_managed_agents(ManagedAgents). %%% @spec register_usm_users(MgrAgentConfName, UsmUsers) -> ok | {error, Reason} @@ -361,7 +361,7 @@ register_agents(MgrAgentConfName, ManagedAgents) -> register_usm_users(MgrAgentConfName, UsmUsers) -> {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {usm_users, UsmUsers}), - ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), setup_usm_users(UsmUsers, EngineID). @@ -376,7 +376,7 @@ unregister_users(MgrAgentConfName) -> ct:get_config({MgrAgentConfName, users})), {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {users, []}), - ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), takedown_users(Users). %%% @spec unregister_agents(MgrAgentConfName) -> ok | {error, Reason} @@ -393,7 +393,7 @@ unregister_agents(MgrAgentConfName) -> {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), NewSnmpVals = lists:keyreplace(managed_agents, 1, SnmpVals, {managed_agents, []}), - ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), takedown_managed_agents(ManagedAgents). @@ -409,7 +409,7 @@ update_usm_users(MgrAgentConfName, UsmUsers) -> {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), NewSnmpVals = lists:keyreplace(usm_users, 1, SnmpVals, {usm_users, UsmUsers}), - ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), do_update_usm_users(UsmUsers, EngineID). diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index 814bd97840..df124e1ca8 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -30,10 +30,7 @@ -export([register_connection/4,unregister_connection/1, does_connection_exist/3,get_key_from_name/1]). --export([require/1, require/2, get_config/1, get_config/2, get_config/3, - set_default_config/2, set_default_config/3, delete_default_config/1, - get_all_config/0, update_config/2, - release_allocated/0, close_connections/0]). +-export([close_connections/0]). -export([save_suite_data/3, save_suite_data/2, read_suite_data/1, delete_suite_data/0, delete_suite_data/1, match_delete_suite_data/1, @@ -46,6 +43,8 @@ silence_all_connections/0, silence_connections/1, is_silenced/1, reset_silent_connections/0]). +-export([get_mode/0, create_table/3, read_opts/0]). + -export([set_cwd/1, reset_cwd/0]). -export([parse_table/1]). @@ -56,9 +55,6 @@ -export([is_test_dir/1, get_testdir/2]). --export([encrypt_config_file/2, encrypt_config_file/3, - decrypt_config_file/2, decrypt_config_file/3]). - -export([kill_attached/2, get_attached/1, ct_make_ref/0]). -export([warn_duplicates/1]). @@ -66,13 +62,8 @@ -include("ct_event.hrl"). -include("ct_util.hrl"). --record(ct_conf,{key,value,ref,name='_UNDEF',default=false}). -%% default = {true,suite} | {true,testcase} | false - -record(suite_data, {key,name,value}). --define(cryptfile, ".ct_config.crypt"). - %%%----------------------------------------------------------------- %%% @spec start(Mode) -> Pid | exit(Error) %%% Mode = normal | interactive @@ -119,7 +110,6 @@ start(Mode,LogDir) -> do_start(Parent,Mode,LogDir) -> process_flag(trap_exit,true), register(ct_util_server,self()), - create_table(?attr_table,bag,#ct_conf.key), create_table(?conn_table,#conn.handle), create_table(?board_table,2), create_table(?suite_table,#suite_data.key), @@ -148,38 +138,34 @@ do_start(Parent,Mode,LogDir) -> ct_event:add_handler([{vts,VtsPid}]) end end, - case ct_config:read_config_files(Opts) of - ok -> - %% add user handlers - case lists:keysearch(event_handler,1,Opts) of - {value,{_,Handlers}} -> - Add = fun({H,Args}) -> - case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of - ok -> ok; - {'EXIT',Why} -> exit(Why); - Other -> exit({event_handler,Other}) - end - end, - case catch lists:foreach(Add,Handlers) of - {'EXIT',Reason} -> - Parent ! {self(),Reason}; - _ -> - ok - end; - false -> + %% start ct_config server + CTCSResult = ct_config:start(Mode, LogDir), + %% add user event handlers + case lists:keysearch(event_handler,1,Opts) of + {value,{_,Handlers}} -> + Add = fun({H,Args}) -> + case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of + ok -> ok; + {'EXIT',Why} -> exit(Why); + Other -> exit({event_handler,Other}) + end + end, + case catch lists:foreach(Add,Handlers) of + {'EXIT',Reason} -> + Parent ! {self(),Reason}; + _ -> ok - end, - {StartTime,TestLogDir} = ct_logs:init(Mode), - ct_event:notify(#event{name=test_start, - node=node(), - data={StartTime, - lists:flatten(TestLogDir)}}), - Parent ! {self(),started}, - loop(Mode,[],StartDir); - ReadError -> - Parent ! {self(),ReadError}, - exit(ReadError) - end. + end; + false -> + ok + end, + {StartTime,TestLogDir} = ct_logs:init(Mode), + ct_event:notify(#event{name=test_start, + node=node(), + data={StartTime, + lists:flatten(TestLogDir)}}), + Parent ! {self(),started}, + loop(Mode,[],StartDir). create_table(TableName,KeyPos) -> create_table(TableName,set,KeyPos). @@ -197,18 +183,6 @@ read_opts() -> {error,{bad_installation,Error}} end. -set_default_config(NewConfig, Scope) -> - call({set_default_config, {NewConfig, Scope}}). - -set_default_config(Name, NewConfig, Scope) -> - call({set_default_config, {Name, NewConfig, Scope}}). - -delete_default_config(Scope) -> - call({delete_default_config, Scope}). - -update_config(Name, Config) -> - call({update_config, {Name, Config}}). - save_suite_data(Key, Value) -> call({save_suite_data, {Key, undefined, Value}}). @@ -254,26 +228,6 @@ loop(Mode,TestData,StartDir) -> ct_logs:make_last_run_index(), return(From,ok), loop(Mode,TestData,StartDir); - {{require,Name,Tag,SubTags},From} -> - Result = do_require(Name,Tag,SubTags), - return(From,Result), - loop(Mode,TestData,StartDir); - {{set_default_config,{Config,Scope}},From} -> - ct_config:set_config(Config,{true,Scope}), - return(From,ok), - loop(Mode,TestData,StartDir); - {{set_default_config,{Name,Config,Scope}},From} -> - ct_config:set_config(Name,Config,{true,Scope}), - return(From,ok), - loop(Mode,TestData,StartDir); - {{delete_default_config,Scope},From} -> - ct_config:delete_config({true,Scope}), - return(From,ok), - loop(Mode,TestData,StartDir); - {{update_config,{Name,NewConfig}},From} -> - update_conf(Name,NewConfig), - return(From,ok), - loop(Mode,TestData,StartDir); {{save_suite_data,{Key,Name,Value}},From} -> ets:insert(?suite_table, #suite_data{key=Key, name=Name, @@ -346,7 +300,6 @@ loop(Mode,TestData,StartDir) -> ct_event:sync_notify(#event{name=test_done, node=node(), data=Time}), - ets:delete(?attr_table), close_connections(ets:tab2list(?conn_table)), ets:delete(?conn_table), ets:delete(?board_table), @@ -354,6 +307,7 @@ loop(Mode,TestData,StartDir) -> ct_logs:close(How), file:set_cwd(StartDir), ct_event:stop(), + ct_config:stop(), return(From,ok); {get_mode,From} -> return(From,Mode), @@ -375,6 +329,8 @@ close_connections([#conn{handle=Handle,callback=CB}|Conns]) -> close_connections([]) -> ok. +get_key_from_name(Name)-> + ct_config:get_key_from_name(Name). %%%----------------------------------------------------------------- %%% @spec register_connection(TargetName,Address,Callback,Handle) -> @@ -392,7 +348,7 @@ close_connections([]) -> %%% test is finished by calling Callback:close/1.

register_connection(TargetName,Address,Callback,Handle) -> TargetRef = - case get_ref_from_name(TargetName) of + case ct_config:get_ref_from_name(TargetName) of {ok,Ref} -> Ref; _ -> @@ -430,7 +386,7 @@ unregister_connection(Handle) -> %%% %%% @doc Check if a connection already exists. does_connection_exist(TargetName,Address,Callback) -> - case get_ref_from_name(TargetName) of + case ct_config:get_ref_from_name(TargetName) of {ok,TargetRef} -> case ets:select(?conn_table,[{#conn{handle='$1', targetref=TargetRef, @@ -460,7 +416,7 @@ does_connection_exist(TargetName,Address,Callback) -> %%% @doc Return all connections for the Callback on the %%% given target (TargetName). get_connections(TargetName,Callback) -> - case get_ref_from_name(TargetName) of + case ct_config:get_ref_from_name(TargetName) of {ok,Ref} -> {ok,ets:select(?conn_table,[{#conn{handle='$1', address='$2', @@ -480,236 +436,11 @@ get_target_name(ConnPid) -> [], ['$1']}]) of [TargetRef] -> - get_name_from_ref(TargetRef); + ct_config:get_name_from_ref(TargetRef); [] -> {error,{unknown_connection,ConnPid}} end. - -%%%----------------------------------------------------------------- -%%% @hidden -%%% @equiv ct:require/1 -require(Key) when is_atom(Key) -> - require({Key,[]}); -require({Key,SubKeys}) when is_atom(Key) -> - allocate('_UNDEF',Key,to_list(SubKeys)); -require(Key) -> - {error,{invalid,Key}}. - - -%%%----------------------------------------------------------------- -%%% @hidden -%%% @equiv ct:require/2 -require(Name,Key) when is_atom(Key) -> - require(Name,{Key,[]}); -require(Name,{Key,SubKeys}) when is_atom(Name), is_atom(Key) -> - call({require,Name,Key,to_list(SubKeys)}); -require(Name,Keys) -> - {error,{invalid,{Name,Keys}}}. - -to_list(X) when is_list(X) -> X; -to_list(X) -> [X]. - -do_require(Name,Key,SubKeys) when is_list(SubKeys) -> - case get_key_from_name(Name) of - {error,_} -> - allocate(Name,Key,SubKeys); - {ok,Key} -> - %% already allocated - check that it has all required subkeys - Vals = [Val || {_Ref,Val} <- lookup_name(Name)], - case get_subconfig(SubKeys,Vals) of - {ok,_SubMapped} -> - ok; - Error -> - Error - end; - {ok,OtherKey} -> - {error,{name_in_use,Name,OtherKey}} - end. - -allocate(Name,Key,SubKeys) -> - case ets:match_object(?attr_table,#ct_conf{key=Key,name='_UNDEF',_='_'}) of - [] -> - {error,{not_available,Key}}; - Available -> - case allocate_subconfig(Name,SubKeys,Available,false) of - ok -> - ok; - Error -> - Error - end - end. - -allocate_subconfig(Name,SubKeys,[C=#ct_conf{value=Value}|Rest],Found) -> - case do_get_config(SubKeys,Value,[]) of - {ok,_SubMapped} -> - ets:insert(?attr_table,C#ct_conf{name=Name}), - allocate_subconfig(Name,SubKeys,Rest,true); - _Error -> - allocate_subconfig(Name,SubKeys,Rest,Found) - end; -allocate_subconfig(_Name,_SubKeys,[],true) -> - ok; -allocate_subconfig(_Name,SubKeys,[],false) -> - {error,{not_available,SubKeys}}. - - - - -%%%----------------------------------------------------------------- -%%% @hidden -%%% @equiv ct:get_config/1 -get_config(KeyOrName) -> - get_config(KeyOrName,undefined,[]). - -%%%----------------------------------------------------------------- -%%% @hidden -%%% @equiv ct:get_config/2 -get_config(KeyOrName,Default) -> - get_config(KeyOrName,Default,[]). - -%%%----------------------------------------------------------------- -%%% @hidden -%%% @equiv ct:get_config/3 -get_config(KeyOrName,Default,Opts) when is_atom(KeyOrName) -> - case lookup_config(KeyOrName) of - [] -> - Default; - [{_Ref,Val}|_] = Vals -> - case {lists:member(all,Opts),lists:member(element,Opts)} of - {true,true} -> - [{KeyOrName,V} || {_R,V} <- lists:sort(Vals)]; - {true,false} -> - [V || {_R,V} <- lists:sort(Vals)]; - {false,true} -> - {KeyOrName,Val}; - {false,false} -> - Val - end - end; - -get_config({KeyOrName,SubKey},Default,Opts) -> - case lookup_config(KeyOrName) of - [] -> - Default; - Vals -> - Vals1 = case [Val || {_Ref,Val} <- lists:sort(Vals)] of - Result=[L|_] when is_list(L) -> - case L of - [{_,_}|_] -> - Result; - _ -> - [] - end; - _ -> - [] - end, - case get_subconfig([SubKey],Vals1,[],Opts) of - {ok,[{_,SubVal}|_]=SubVals} -> - case {lists:member(all,Opts),lists:member(element,Opts)} of - {true,true} -> - [{{KeyOrName,SubKey},Val} || {_,Val} <- SubVals]; - {true,false} -> - [Val || {_SubKey,Val} <- SubVals]; - {false,true} -> - {{KeyOrName,SubKey},SubVal}; - {false,false} -> - SubVal - end; - _ -> - Default - end - end. - - -get_subconfig(SubKeys,Values) -> - get_subconfig(SubKeys,Values,[],[]). - -get_subconfig(SubKeys,[Value|Rest],Mapped,Opts) -> - case do_get_config(SubKeys,Value,[]) of - {ok,SubMapped} -> - case lists:member(all,Opts) of - true -> - get_subconfig(SubKeys,Rest,Mapped++SubMapped,Opts); - false -> - {ok,SubMapped} - end; - _Error -> - get_subconfig(SubKeys,Rest,Mapped,Opts) - end; -get_subconfig(SubKeys,[],[],_) -> - {error,{not_available,SubKeys}}; -get_subconfig(_SubKeys,[],Mapped,_) -> - {ok,Mapped}. - -do_get_config([Key|Required],Available,Mapped) -> - case lists:keysearch(Key,1,Available) of - {value,{Key,Value}} -> - NewAvailable = lists:keydelete(Key,1,Available), - NewMapped = [{Key,Value}|Mapped], - do_get_config(Required,NewAvailable,NewMapped); - false -> - {error,{not_available,Key}} - end; -do_get_config([],_Available,Mapped) -> - {ok,lists:reverse(Mapped)}. - -get_all_config() -> - ets:select(?attr_table,[{#ct_conf{name='$1',key='$2',value='$3', - default='$4',_='_'}, - [], - [{{'$1','$2','$3','$4'}}]}]). - -lookup_config(KeyOrName) -> - case lookup_name(KeyOrName) of - [] -> - lookup_key(KeyOrName); - Values -> - Values - end. - -lookup_name(Name) -> - ets:select(?attr_table,[{#ct_conf{ref='$1',value='$2',name=Name,_='_'}, - [], - [{{'$1','$2'}}]}]). -lookup_key(Key) -> - ets:select(?attr_table,[{#ct_conf{key=Key,ref='$1',value='$2',name='_UNDEF',_='_'}, - [], - [{{'$1','$2'}}]}]). - - - - -%%%----------------------------------------------------------------- -%%% @spec release_allocated() -> ok -%%% -%%% @doc Release all allocated resources, but don't take down any -%%% connections. -release_allocated() -> - Allocated = ets:select(?attr_table,[{#ct_conf{name='$1',_='_'}, - [{'=/=','$1','_UNDEF'}], - ['$_']}]), - release_allocated(Allocated). -release_allocated([H|T]) -> - ets:delete_object(?attr_table,H), - ets:insert(?attr_table,H#ct_conf{name='_UNDEF'}), - release_allocated(T); -release_allocated([]) -> - ok. - -%%%----------------------------------------------------------------- -%%% @spec -%%% -%%% @doc -update_conf(Name, NewConfig) -> - Old = ets:select(?attr_table,[{#ct_conf{name=Name,_='_'},[],['$_']}]), - lists:foreach(fun(OldElem) -> - NewElem = OldElem#ct_conf{value=NewConfig}, - ets:delete_object(?attr_table, OldElem), - ets:insert(?attr_table, NewElem) - end, Old), - ok. - %%%----------------------------------------------------------------- %%% @spec close_connections() -> ok %%% @@ -889,166 +620,6 @@ get_testdir(Dir, Suite) when is_list(Suite) -> get_testdir(Dir, _) -> get_testdir(Dir, all). -%%%----------------------------------------------------------------- -%%% @spec -%%% -%%% @doc -encrypt_config_file(SrcFileName, EncryptFileName) -> - case get_crypt_key_from_file() of - {error,_} = E -> - E; - Key -> - encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) - end. - -%%%----------------------------------------------------------------- -%%% @spec -%%% -%%% @doc -encrypt_config_file(SrcFileName, EncryptFileName, {file,KeyFile}) -> - case get_crypt_key_from_file(KeyFile) of - {error,_} = E -> - E; - Key -> - encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) - end; - -encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) -> - crypto:start(), - {K1,K2,K3,IVec} = make_crypto_key(Key), - case file:read_file(SrcFileName) of - {ok,Bin0} -> - Bin1 = term_to_binary({SrcFileName,Bin0}), - Bin2 = case byte_size(Bin1) rem 8 of - 0 -> Bin1; - N -> list_to_binary([Bin1,random_bytes(8-N)]) - end, - EncBin = crypto:des3_cbc_encrypt(K1, K2, K3, IVec, Bin2), - case file:write_file(EncryptFileName, EncBin) of - ok -> - io:format("~s --(encrypt)--> ~s~n", - [SrcFileName,EncryptFileName]), - ok; - {error,Reason} -> - {error,{Reason,EncryptFileName}} - end; - {error,Reason} -> - {error,{Reason,SrcFileName}} - end. - -%%%----------------------------------------------------------------- -%%% @spec -%%% -%%% @doc -decrypt_config_file(EncryptFileName, TargetFileName) -> - case get_crypt_key_from_file() of - {error,_} = E -> - E; - Key -> - decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) - end. - - -%%%----------------------------------------------------------------- -%%% @spec -%%% -%%% @doc -decrypt_config_file(EncryptFileName, TargetFileName, {file,KeyFile}) -> - case get_crypt_key_from_file(KeyFile) of - {error,_} = E -> - E; - Key -> - decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) - end; - -decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) -> - crypto:start(), - {K1,K2,K3,IVec} = make_crypto_key(Key), - case file:read_file(EncryptFileName) of - {ok,Bin} -> - DecBin = crypto:des3_cbc_decrypt(K1, K2, K3, IVec, Bin), - case catch binary_to_term(DecBin) of - {'EXIT',_} -> - {error,bad_file}; - {_SrcFile,SrcBin} -> - case TargetFileName of - undefined -> - {ok,SrcBin}; - _ -> - case file:write_file(TargetFileName, SrcBin) of - ok -> - io:format("~s --(decrypt)--> ~s~n", - [EncryptFileName,TargetFileName]), - ok; - {error,Reason} -> - {error,{Reason,TargetFileName}} - end - end - end; - {error,Reason} -> - {error,{Reason,EncryptFileName}} - end. - - -get_crypt_key_from_file(File) -> - case file:read_file(File) of - {ok,Bin} -> - case catch string:tokens(binary_to_list(Bin), [$\n,$\r]) of - [Key] -> - Key; - _ -> - {error,{bad_crypt_file,File}} - end; - {error,Reason} -> - {error,{Reason,File}} - end. - -get_crypt_key_from_file() -> - CwdFile = filename:join(".",?cryptfile), - {Result,FullName} = - case file:read_file(CwdFile) of - {ok,Bin} -> - {Bin,CwdFile}; - _ -> - case init:get_argument(home) of - {ok,[[Home]]} -> - HomeFile = filename:join(Home,?cryptfile), - case file:read_file(HomeFile) of - {ok,Bin} -> - {Bin,HomeFile}; - _ -> - {{error,no_crypt_file},noent} - end; - _ -> - {{error,no_crypt_file},noent} - end - end, - case FullName of - noent -> - Result; - _ -> - case catch string:tokens(binary_to_list(Result), [$\n,$\r]) of - [Key] -> - io:format("~nCrypt key file: ~s~n", [FullName]), - Key; - _ -> - {error,{bad_crypt_file,FullName}} - end - end. - -make_crypto_key(String) -> - <> = First = erlang:md5(String), - <> = erlang:md5([First|lists:reverse(String)]), - {K1,K2,K3,IVec}. - -random_bytes(N) -> - {A,B,C} = now(), - random:seed(A, B, C), - random_bytes_1(N, []). - -random_bytes_1(0, Acc) -> Acc; -random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]). - %%%----------------------------------------------------------------- %%% @spec @@ -1142,37 +713,6 @@ ct_make_ref_loop(N) -> From ! {self(),N}, ct_make_ref_loop(N+1) end. - -get_ref_from_name(Name) -> - case ets:select(?attr_table,[{#ct_conf{name=Name,ref='$1',_='_'}, - [], - ['$1']}]) of - [Ref] -> - {ok,Ref}; - _ -> - {error,{no_such_name,Name}} - end. - -get_name_from_ref(Ref) -> - case ets:select(?attr_table,[{#ct_conf{name='$1',ref=Ref,_='_'}, - [], - ['$1']}]) of - [Name] -> - {ok,Name}; - _ -> - {error,{no_such_ref,Ref}} - end. - -get_key_from_name(Name) -> - case ets:select(?attr_table,[{#ct_conf{name=Name,key='$1',_='_'}, - [], - ['$1']}]) of - [Key|_] -> - {ok,Key}; - _ -> - {error,{no_such_name,Name}} - end. - abs_name(Dir0) -> Abs = filename:absname(Dir0), -- cgit v1.2.3