diff options
Diffstat (limited to 'lib/stdlib')
50 files changed, 3064 insertions, 2340 deletions
diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml index ddae388a1b..9cd4581a89 100644 --- a/lib/stdlib/doc/src/c.xml +++ b/lib/stdlib/doc/src/c.xml @@ -140,9 +140,9 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w </func> <func> <name name="ls" arity="1"/> - <fsummary>List files in a directory</fsummary> + <fsummary>List files in a directory or a single file</fsummary> <desc> - <p>Lists files in directory <c><anno>Dir</anno></c>.</p> + <p>Lists files in directory <c><anno>Dir</anno></c> or, if Dir is a file, only list it.</p> </desc> </func> <func> diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml index d0622594d9..24940f8396 100644 --- a/lib/stdlib/doc/src/erl_eval.xml +++ b/lib/stdlib/doc/src/erl_eval.xml @@ -288,10 +288,7 @@ Func(FuncSpec, Arguments) </code> <section> <title>Bugs</title> - <p>The evaluator is not complete. <c>receive</c> cannot be - handled properly. - </p> - <p>Any undocumented functions in <c>erl_eval</c> should not be used.</p> + <p>Undocumented functions in <c>erl_eval</c> should not be used.</p> </section> </erlref> diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml index bafc2e0746..56a7131821 100644 --- a/lib/stdlib/doc/src/erl_parse.xml +++ b/lib/stdlib/doc/src/erl_parse.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2011</year> + <year>1996</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -167,6 +167,23 @@ <p>Converts the Erlang data structure <c><anno>Data</anno></c> into an abstract form of type <c><anno>AbsTerm</anno></c>. This is the inverse of <c>normalise/1</c>.</p> + <p><c>erl_parse:abstract(T)</c> is equivalent to + <c>erl_parse:abstract(T, 0)</c>.</p> + </desc> + </func> + <func> + <name name="abstract" arity="2"/> + <fsummary>Convert an Erlang term into an abstract form</fsummary> + <desc> + <p>Converts the Erlang data structure <c><anno>Data</anno></c> into an + abstract form of type <c><anno>AbsTerm</anno></c>.</p> + <p>The <c><anno>Line</anno></c> option is the line that will + be assigned to each node of the abstract form.</p> + <p>The <c><anno>Encoding</anno></c> option is used for + selecting which integer lists will be considered + as strings. The default is to use the encoding returned by + <seealso marker="epp#default_encoding/0"> + <c>epp:default_encoding/0</c></seealso></p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml index b6c0fa4e05..1aff78f4fc 100644 --- a/lib/stdlib/doc/src/lists.xml +++ b/lib/stdlib/doc/src/lists.xml @@ -152,6 +152,31 @@ </desc> </func> <func> + <name name="filtermap" arity="2"/> + <fsummary>Filter and map elements which satisfy a function</fsummary> + <desc> + <p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> on successive elements <c>Elem</c> + of <c><anno>List1</anno></c>. <c><anno>Fun</anno>/2</c> must return either a boolean + or a tuple <c>{true, <anno>Value</anno>}</c>. The function returns the list of elements + for which <c><anno>Fun</anno></c> returns a new value, where a value of <c>true</c> + is synonymous with <c>{true, <anno>Elem</anno>}</c>.</p> + <p>That is, <c>filtermap</c> behaves as if it had been defined as follows:</p> + <code type="none"> +filtermap(Fun, List1) -> + lists:foldr(fun(Elem, Acc) -> + case Fun(Elem) of + false -> Acc; + true -> [Elem|Acc]; + {true,Value} -> [Value|Acc] + end, + end, [], List1).</code> + <p>Example:</p> + <pre> +> <input>lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end, [1,2,3,4,5]).</input> +[1,2]</pre> + </desc> + </func> + <func> <name name="flatlength" arity="1"/> <fsummary>Length of flattened deep list</fsummary> <desc> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index 9021d02ade..3f36c58d24 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -177,12 +177,6 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} child process, it must be implemented in a safe way and its cleanup procedure must always return.</p> </warning> - <p><em>Important note on simple-one-for-one supervisors:</em> - The dynamically created child processes of a - simple-one-for-one supervisor are not explicitly killed, - regardless of shutdown strategy, but are expected to terminate - when the supervisor does (that is, when an exit signal from - the parent process is received).</p> <p>Note that all child processes implemented using the standard OTP behavior modules automatically adhere to the shutdown protocol.</p> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index 073faf2df2..0ffc5bc433 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -211,18 +211,87 @@ <p>Gets the status of the process.</p> <p>The value of <c><anno>Misc</anno></c> varies for different types of processes. For example, a <c>gen_server</c> process returns - the callback module's state, and a <c>gen_fsm</c> process - returns information such as its current state name. Callback - modules for <c>gen_server</c> and <c>gen_fsm</c> can also - customise the value of <c><anno>Misc</anno></c> by exporting - a <c>format_status/2</c> function that contributes - module-specific information; - see <seealso marker="gen_server#Module:format_status/2">gen_server:format_status/2</seealso> - and <seealso marker="gen_fsm#Module:format_status/2">gen_fsm:format_status/2</seealso> + the callback module's state, a <c>gen_fsm</c> process + returns information such as its current state name and state data, + and a <c>gen_event</c> process returns information about each of its + registered handlers. Callback modules for <c>gen_server</c>, + <c>gen_fsm</c>, and <c>gen_event</c> can also customise the value + of <c><anno>Misc</anno></c> by exporting a <c>format_status/2</c> + function that contributes module-specific information; + see <seealso marker="gen_server#Module:format_status/2">gen_server:format_status/2</seealso>, + <seealso marker="gen_fsm#Module:format_status/2">gen_fsm:format_status/2</seealso>, and + <seealso marker="gen_event#Module:format_status/2">gen_event:format_status/2</seealso> for more details.</p> </desc> </func> <func> + <name name="get_state" arity="1"/> + <name name="get_state" arity="2"/> + <fsummary>Get the state of the process</fsummary> + <desc> + <p>Gets the state of the process.</p> + <note> + <p>These functions are intended only to help with debugging. They are provided for + convenience, allowing developers to avoid having to create their own state extraction + functions and also avoid having to interactively extract state from the return values of + <c><seealso marker="#get_status-1">get_status/1</seealso></c> or + <c><seealso marker="#get_status-2">get_status/2</seealso></c> while debugging.</p> + </note> + <p>The value of <c><anno>State</anno></c> varies for different types of + processes. For a <c>gen_server</c> process, the returned <c><anno>State</anno></c> + is simply the callback module's state. For a <c>gen_fsm</c> process, + <c><anno>State</anno></c> is the tuple <c>{CurrentStateName, CurrentStateData}</c>. + For a <c>gen_event</c> process, <c><anno>State</anno></c> a list of tuples, + where each tuple corresponds to an event handler registered in the process and contains + <c>{Module, Id, HandlerState}</c>, where <c>Module</c> is the event handler's module name, + <c>Id</c> is the handler's ID (which is the value <c>false</c> if it was registered without + an ID), and <c>HandlerState</c> is the handler's state.</p> + <p>To obtain more information about a process, including its state, see + <seealso marker="#get_status-1">get_status/1</seealso> and + <seealso marker="#get_status-2">get_status/2</seealso>.</p> + </desc> + </func> + <func> + <name name="replace_state" arity="2"/> + <name name="replace_state" arity="3"/> + <fsummary>Replace the state of the process</fsummary> + <desc> + <p>Replaces the state of the process, and returns the new state.</p> + <note> + <p>These functions are intended only to help with debugging, and they should not be + be called from normal code. They are provided for convenience, allowing developers + to avoid having to create their own custom state replacement functions.</p> + </note> + <p>The <c><anno>StateFun</anno></c> function provides a new state for the process. + The <c><anno>State</anno></c> argument and <c><anno>NewState</anno></c> return value + of <c><anno>StateFun</anno></c> vary for different types of processes. For a + <c>gen_server</c> process, <c><anno>State</anno></c> is simply the callback module's + state, and <c><anno>NewState</anno></c> is a new instance of that state. For a + <c>gen_fsm</c> process, <c><anno>State</anno></c> is the tuple + <c>{CurrentStateName, CurrentStateData}</c>, and <c><anno>NewState</anno></c> + is a similar tuple that may contain a new state name, new state data, or both. + For a <c>gen_event</c> process, <c><anno>State</anno></c> is the tuple + <c>{Module, Id, HandlerState}</c> where <c>Module</c> is the event handler's module name, + <c>Id</c> is the handler's ID (which is the value <c>false</c> if it was registered without + an ID), and <c>HandlerState</c> is the handler's state. <c><anno>NewState</anno></c> is a + similar tuple where <c>Module</c> and <c>Id</c> shall have the same values as in + <c><anno>State</anno></c> but the value of <c>HandlerState</c> may be different. Returning + a <c><anno>NewState</anno></c> whose <c>Module</c> or <c>Id</c> values differ from those of + <c><anno>State</anno></c> will result in the event handler's state remaining unchanged. For a + <c>gen_event</c> process, <c><anno>StateFun</anno></c> is called once for each event handler + registered in the <c>gen_event</c> process.</p> + <p>If a <c><anno>StateFun</anno></c> function decides not to effect any change in process + state, then regardless of process type, it may simply return its <c><anno>State</anno></c> + argument.</p> + <p>If a <c><anno>StateFun</anno></c> function crashes or throws an exception, then + for <c>gen_server</c> and <c>gen_fsm</c> processes, the original state of the process is + unchanged. For <c>gen_event</c> processes, a crashing or failing <c><anno>StateFun</anno></c> + function means that only the state of the particular event handler it was working on when it + failed or crashed is unchanged; it can still succeed in changing the states of other event + handlers registered in the same <c>gen_event</c> process.</p> + </desc> + </func> + <func> <name name="install" arity="2"/> <name name="install" arity="3"/> <fsummary>Install a debug function in the process</fsummary> diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml index c5d476e54b..1f64b38554 100644 --- a/lib/stdlib/doc/src/unicode_usage.xml +++ b/lib/stdlib/doc/src/unicode_usage.xml @@ -625,6 +625,7 @@ Eshell V5.10.1 (abort with ^G) </section> <section> <title>Unicode File Names</title> + <marker id="unicode_file_names"/> <p>Most modern operating systems support Unicode file names in some way or another. There are several different ways to do this and Erlang by default treats the different approaches differently:</p> diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index fe7e0f8e60..2e9ebece0e 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -302,10 +302,10 @@ clear_crypto_key_fun() -> -spec make_crypto_key(mode(), string()) -> {binary(), binary(), binary(), binary()}. -make_crypto_key(des3_cbc, String) -> +make_crypto_key(des3_cbc=Type, String) -> <<K1:8/binary,K2:8/binary>> = First = erlang:md5(String), <<K3:8/binary,IVec:8/binary>> = erlang:md5([First|reverse(String)]), - {K1,K2,K3,IVec}. + {Type,[K1,K2,K3],IVec,8}. %% %% Local functions @@ -864,20 +864,20 @@ mandatory_chunks() -> -define(CRYPTO_KEY_SERVER, beam_lib__crypto_key_server). -decrypt_abst(Mode, Module, File, Id, AtomTable, Bin) -> +decrypt_abst(Type, Module, File, Id, AtomTable, Bin) -> try - KeyString = get_crypto_key({debug_info, Mode, Module, File}), - Key = make_crypto_key(des3_cbc, KeyString), - Term = decrypt_abst_1(Mode, Key, Bin), + KeyString = get_crypto_key({debug_info, Type, Module, File}), + Key = make_crypto_key(Type, KeyString), + Term = decrypt_abst_1(Key, Bin), {AtomTable, {Id, Term}} catch _:_ -> error({key_missing_or_invalid, File, Id}) end. -decrypt_abst_1(des3_cbc, {K1, K2, K3, IVec}, Bin) -> +decrypt_abst_1({Type,Key,IVec,_BlockSize}, Bin) -> ok = start_crypto(), - NewBin = crypto:des3_cbc_decrypt(K1, K2, K3, IVec, Bin), + NewBin = crypto:block_decrypt(Type, Key, IVec, Bin), binary_to_term(NewBin). start_crypto() -> diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl index 91d317489c..6e96e3d564 100644 --- a/lib/stdlib/src/c.erl +++ b/lib/stdlib/src/c.erl @@ -713,8 +713,10 @@ ls(Dir) -> case file:list_dir(Dir) of {ok, Entries} -> ls_print(sort(Entries)); - {error,_E} -> - format("Invalid directory\n") + {error, enotdir} -> + ls_print([Dir]); + {error, Error} -> + format("~s\n", [file:format_error(Error)]) end. ls_print([]) -> ok; diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index ecb509f4b5..50812cc532 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -1246,13 +1246,8 @@ req(Proc, R) -> {'DOWN', Ref, process, Proc, _Info} -> badarg; {Proc, Reply} -> - erlang:demonitor(Ref), - receive - {'DOWN', Ref, process, Proc, _Reason} -> - Reply - after 0 -> - Reply - end + erlang:demonitor(Ref, [flush]), + Reply end. %% Inlined. @@ -2837,14 +2832,18 @@ fsck_try(Fd, Tab, FH, Fname, SlotNumbers, Version) -> tempfile(Fname) -> Tmp = lists:concat([Fname, ".TMP"]), + tempfile(Tmp, 10). + +tempfile(Tmp, 0) -> + Tmp; +tempfile(Tmp, N) -> case file:delete(Tmp) of {error, eacces} -> % 'dets_process_died' happened anyway... (W-nd-ws) - timer:sleep(5000), - file:delete(Tmp); + timer:sleep(1000), + tempfile(Tmp, N-1); _ -> - ok - end, - Tmp. + Tmp + end. %% -> {ok, NewHead} | {try_again, integer()} | Error fsck_try_est(Head, Fd, Fname, SlotNumbers, FH) -> diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 0a1caa7178..d1d060ebc8 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -601,7 +601,7 @@ enter_file2(NewF, Pname, From, St0, AtLocation) -> %% file will depend on the order of file inclusions in the parent files Path = [filename:dirname(Pname) | tl(St0#epp.path)], _ = set_encoding(NewF), - #epp{file=NewF,location=Loc,name=Pname,delta=0, + #epp{file=NewF,location=Loc,name=Pname,name2=Pname,delta=0, sstk=[St0|St0#epp.sstk],path=Path,macs=Ms}. enter_file_reply(From, Name, Location, AtLocation) -> @@ -1339,8 +1339,7 @@ epp_reply(From, Rep) -> wait_epp_reply(Epp, Mref) -> receive {epp_reply,Epp,Rep} -> - erlang:demonitor(Mref), - receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end, + erlang:demonitor(Mref, [flush]), Rep; {'DOWN',Mref,_,_,E} -> receive {epp_reply,Epp,Rep} -> Rep diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 0b57af1b6d..73b8da335a 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -245,10 +245,10 @@ expr({'case',_,E,Cs}, Bs0, Lf, Ef, RBs) -> expr({'try',_,B,Cases,Catches,AB}, Bs, Lf, Ef, RBs) -> try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs); expr({'receive',_,Cs}, Bs, Lf, Ef, RBs) -> - receive_clauses(Cs, Bs, Lf, Ef, [], RBs); + receive_clauses(Cs, Bs, Lf, Ef, RBs); expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs) -> {value,T,Bs} = expr(E, Bs0, Lf, Ef, none), - receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, [], RBs); + receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, RBs); expr({'fun',_Line,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) -> {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef), F = erlang:make_fun(Mod, Name, Arity), @@ -807,66 +807,24 @@ case_clauses(Val, Cs, Bs, Lf, Ef, RBs) -> end. %% -%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, Messages, RBs) +%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, RBs) %% -receive_clauses(Cs, Bs, Lf, Ef, Ms, RBs) -> - receive - Val -> - case match_clause(Cs, [Val], Bs, Lf, Ef) of - {B, Bs1} -> - merge_queue(Ms), - exprs(B, Bs1, Lf, Ef, RBs); - nomatch -> - receive_clauses(Cs, Bs, Lf, Ef, [Val|Ms], RBs) - end - end. +receive_clauses(Cs, Bs, Lf, Ef, RBs) -> + receive_clauses(infinity, Cs, unused, Bs, Lf, Ef, RBs). %% %% receive_clauses(TimeOut, Clauses, TimeoutBody, Bindings, %% ExternalFuncHandler, LocalFuncHandler, RBs) %% -receive_clauses(T, Cs, TB, Bs, Lf, Ef, Ms, RBs) -> - {_,_} = statistics(runtime), - receive - Val -> - case match_clause(Cs, [Val], Bs, Lf, Ef) of - {B, Bs1} -> - merge_queue(Ms), - exprs(B, Bs1, Lf, Ef, RBs); - nomatch -> - {_,T1} = statistics(runtime), - if - T =:= infinity -> - receive_clauses(T, Cs, TB,Bs,Lf,Ef,[Val|Ms],RBs); - T-T1 =< 0 -> - receive_clauses(0, Cs, TB,Bs,Lf,Ef,[Val|Ms],RBs); - true -> - receive_clauses(T-T1, Cs,TB,Bs,Lf,Ef,[Val|Ms],RBs) - end - end - after T -> - merge_queue(Ms), +receive_clauses(T, Cs, TB, Bs, Lf, Ef, RBs) -> + F = fun (M) -> match_clause(Cs, [M], Bs, Lf, Ef) end, + case prim_eval:'receive'(F, T) of + {B, Bs1} -> + exprs(B, Bs1, Lf, Ef, RBs); + timeout -> {B, Bs1} = TB, exprs(B, Bs1, Lf, Ef, RBs) end. -merge_queue([]) -> - true; -merge_queue(Ms) -> - send_all(recv_all(Ms), self()). - -recv_all(Xs) -> - receive - X -> recv_all([X|Xs]) - after 0 -> - reverse(Xs) - end. - -send_all([X|Xs], Self) -> - Self ! X, - send_all(Xs, Self); -send_all([], _) -> true. - - %% match_clause -> {Body, Bindings} or nomatch -spec(match_clause(Clauses, ValueList, Bindings, LocalFunctionHandler) -> diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index 9ff25fcbc5..7145b0858f 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -887,6 +887,7 @@ abstract(T, Options) when is_list(Options) -> abstract(T, Line, Encoding). -define(UNICODE(C), + is_integer(C) andalso (C >= 0 andalso C < 16#D800 orelse C > 16#DFFF andalso C < 16#FFFE orelse C > 16#FFFF andalso C =< 16#10FFFF)). diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index 7c7566e4ec..c0596e5ba6 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -35,7 +35,7 @@ | fun((Expr :: erl_parse:abstract_expr(), CurrentIndentation :: integer(), CurrentPrecedence :: non_neg_integer(), - HookFunction :: hook_function()) -> + Options :: options()) -> io_lib:chars())). -type(option() :: {hook, hook_function()} @@ -225,7 +225,7 @@ lattribute(module, {M,Vs}, _Opts, _State) -> lattribute(module, M, _Opts, _State) -> attr("module", [{var,0,pname(M)}]); lattribute(export, Falist, _Opts, _State) -> - call({var,0,"-export"}, [falist(Falist)], 0, none); + call({var,0,"-export"}, [falist(Falist)], 0, options(none)); lattribute(import, Name, _Opts, _State) when is_list(Name) -> attr("import", [{var,0,pname(Name)}]); lattribute(import, {From,Falist}, _Opts, _State) -> @@ -240,10 +240,10 @@ lattribute(Name, Arg, #options{encoding = Encoding}, _State) -> typeattr(Tag, {TypeName,Type,Args}, _Opts) -> {first,leaf("-"++atom_to_list(Tag)++" "), - typed(call({atom,0,TypeName}, Args, 0, none), Type)}. + typed(call({atom,0,TypeName}, Args, 0, options(none)), Type)}. ltype({ann_type,_Line,[V,T]}) -> - typed(lexpr(V, none), T); + typed(lexpr(V, options(none)), T); ltype({paren_type,_Line,[T]}) -> [$(,ltype(T),$)]; ltype({type,_Line,union,Ts}) -> @@ -253,7 +253,7 @@ ltype({type,_Line,list,[T]}) -> ltype({type,_Line,nonempty_list,[T]}) -> {seq,$[,$],[$,],[ltype(T),leaf("...")]}; ltype({type,Line,nil,[]}) -> - lexpr({nil,Line}, 0, none); + lexpr({nil,Line}, 0, options(none)); ltype({type,Line,tuple,any}) -> simple_type({atom,Line,tuple}, []); ltype({type,_Line,tuple,Ts}) -> @@ -261,7 +261,7 @@ ltype({type,_Line,tuple,Ts}) -> ltype({type,_Line,record,[{atom,_,N}|Fs]}) -> record_type(N, Fs); ltype({type,_Line,range,[_I1,_I2]=Es}) -> - expr_list(Es, '..', fun lexpr/2, none); + expr_list(Es, '..', fun lexpr/2, options(none)); ltype({type,_Line,binary,[I1,I2]}) -> binary_type(I1, I2); % except binary() ltype({type,_Line,'fun',[]}) -> @@ -277,14 +277,14 @@ ltype({remote_type,Line,[M,F,Ts]}) -> ltype({atom,_,T}) -> leaf(write(T)); ltype(E) -> - lexpr(E, 0, none). + lexpr(E, 0, options(none)). binary_type(I1, I2) -> B = [[] || {integer,_,0} <- [I1]] =:= [], U = [[] || {integer,_,0} <- [I2]] =:= [], P = max_prec(), - E1 = [[leaf("_:"),lexpr(I1, P, none)] || B], - E2 = [[leaf("_:_*"),lexpr(I2, P, none)] || U], + E1 = [[leaf("_:"),lexpr(I1, P, options(none))] || B], + E2 = [[leaf("_:_*"),lexpr(I2, P, options(none))] || U], {seq,'<<','>>',[$,],E1++E2}. record_type(Name, Fields) -> @@ -294,7 +294,7 @@ field_types(Fs) -> tuple_type(Fs, fun field_type/1). field_type({type,_Line,field_type,[Name,Type]}) -> - typed(lexpr(Name, none), Type). + typed(lexpr(Name, options(none)), Type). typed(B, {type,_,union,Ts}) -> %% Special layout for :: followed by union. @@ -330,7 +330,8 @@ sig_type(FunType) -> fun_type([], FunType). guard_type(Before, Gs) -> - Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, none)}]}, + Opts = options(none), + Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, Opts)}]}, {list,[{step,Before,Gl}]}. constraint({type,_Line,constraint,[Tag,As]}, _Opts) -> @@ -345,7 +346,7 @@ type_args({type,_line,product,Ts}) -> targs(Ts). simple_type(Tag, Types) -> - {first,lexpr(Tag, 0, none),targs(Types)}. + {first,lexpr(Tag, 0, options(none)),targs(Types)}. targs(Ts) -> {seq,$(,$),[$,],ltypes(Ts)}. @@ -357,7 +358,7 @@ ltypes(Ts, F) -> [F(T) || T <- Ts]. attr(Name, Args) -> - call({var,0,format("-~s", [Name])}, Args, 0, none). + call({var,0,format("-~s", [Name])}, Args, 0, options(none)). pname(['' | As]) -> [$. | pname(As)]; @@ -632,11 +633,11 @@ bit_elem_types([T | Rest]) -> [bit_elem_type(T), $-|bit_elem_types(Rest)]. bit_elem_type({A,B}) -> - [lexpr(erl_parse:abstract(A), none), + [lexpr(erl_parse:abstract(A), options(none)), $:, - lexpr(erl_parse:abstract(B), none)]; + lexpr(erl_parse:abstract(B), options(none))]; bit_elem_type(T) -> - lexpr(erl_parse:abstract(T), none). + lexpr(erl_parse:abstract(T), options(none)). %% end of BITS diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index 3651f608bc..d988a4d8c7 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -338,6 +338,7 @@ string_thing(_) -> "string". -define(DIGIT(C), C >= $0, C =< $9). -define(CHAR(C), is_integer(C), C >= 0). -define(UNICODE(C), + is_integer(C) andalso (C >= 0 andalso C < 16#D800 orelse C > 16#DFFF andalso C < 16#FFFE orelse C > 16#FFFF andalso C =< 16#10FFFF)). diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index 32742e419b..fea718541d 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -602,9 +602,15 @@ parse_beam(S, File, HeaderSz, CheckOnly) -> parse_source(S, File, Fd, StartLine, HeaderSz, CheckOnly) -> {PreDefMacros, Module} = pre_def_macros(File), IncludePath = [], - {ok, _} = file:position(Fd, {bof, HeaderSz}), + %% Read the encoding on the second line, if there is any: + {ok, _} = file:position(Fd, 0), + _ = io:get_line(Fd, ''), + Encoding = epp:set_encoding(Fd), + {ok, _} = file:position(Fd, HeaderSz), case epp:open(File, Fd, StartLine, IncludePath, PreDefMacros) of {ok, Epp} -> + _ = [io:setopts(Fd, [{encoding,Encoding}]) || + Encoding =/= none], {ok, FileForm} = epp:parse_erl_form(Epp), OptModRes = epp:parse_erl_form(Epp), S2 = S#state{source = text, module = Module}, diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 42555aedd7..5df5530ba1 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -17,6 +17,7 @@ %% %CopyrightEnd% %% -module(gen). +-compile({inline,[get_node/1]}). %%%----------------------------------------------------------------- %%% This module implements the really generic stuff of the generic @@ -194,16 +195,6 @@ call({_Name, Node}=Process, Label, Request, Timeout) end. do_call(Process, Label, Request, Timeout) -> - %% We trust the arguments to be correct, i.e - %% Process is either a local or remote pid, - %% or a {Name, Node} tuple (of atoms) and in this - %% case this node (node()) _is_ distributed and Node =/= node(). - Node = case Process of - {_S, N} when is_atom(N) -> - N; - _ when is_pid(Process) -> - node(Process) - end, try erlang:monitor(process, Process) of Mref -> %% If the monitor/2 call failed to set up a connection to a @@ -222,15 +213,12 @@ do_call(Process, Label, Request, Timeout) -> erlang:demonitor(Mref, [flush]), {ok, Reply}; {'DOWN', Mref, _, _, noconnection} -> + Node = get_node(Process), exit({nodedown, Node}); {'DOWN', Mref, _, _, Reason} -> exit(Reason) after Timeout -> - erlang:demonitor(Mref), - receive - {'DOWN', Mref, _, _, _} -> true - after 0 -> true - end, + erlang:demonitor(Mref, [flush]), exit(timeout) end catch @@ -241,6 +229,7 @@ do_call(Process, Label, Request, Timeout) -> %% Do the best possible with monitor_node/2. %% This code may hang indefinitely if the Process %% does not exist. It is only used for featureweak remote nodes. + Node = get_node(Process), monitor_node(Node, true), receive {nodedown, Node} -> @@ -253,6 +242,18 @@ do_call(Process, Label, Request, Timeout) -> end end. +get_node(Process) -> + %% We trust the arguments to be correct, i.e + %% Process is either a local or remote pid, + %% or a {Name, Node} tuple (of atoms) and in this + %% case this node (node()) _is_ distributed and Node =/= node(). + case Process of + {_S, N} when is_atom(N) -> + N; + _ when is_pid(Process) -> + node(Process) + end. + wait_resp(Node, Tag, Timeout) -> receive {Tag, Reply} -> diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl index 2b8ba86909..bfebf29080 100644 --- a/lib/stdlib/src/gen_event.erl +++ b/lib/stdlib/src/gen_event.erl @@ -229,6 +229,24 @@ wake_hib(Parent, ServerName, MSL, Debug) -> fetch_msg(Parent, ServerName, MSL, Debug, Hib) -> receive + {system, From, get_state} -> + States = [{Mod,Id,State} || #handler{module=Mod, id=Id, state=State} <- MSL], + sys:handle_system_msg(get_state, From, Parent, ?MODULE, Debug, + {States, [ServerName, MSL, Hib]}, Hib); + {system, From, {replace_state, StateFun}} -> + {NMSL, NStates} = + lists:unzip([begin + Cur = {Mod,Id,State}, + try + NState = {Mod,Id,NS} = StateFun(Cur), + {HS#handler{state=NS}, NState} + catch + _:_ -> + {HS, Cur} + end + end || #handler{module=Mod, id=Id, state=State}=HS <- MSL]), + sys:handle_system_msg(replace_state, From, Parent, ?MODULE, Debug, + {NStates, [ServerName, NMSL, Hib]}, Hib); {system, From, Req} -> sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, [ServerName, MSL, Hib],Hib); diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl index e480e2ac11..d9411e58cf 100644 --- a/lib/stdlib/src/gen_fsm.erl +++ b/lib/stdlib/src/gen_fsm.erl @@ -422,6 +422,17 @@ wake_hib(Parent, Name, StateName, StateData, Mod, Debug) -> decode_msg(Msg,Parent, Name, StateName, StateData, Mod, Time, Debug, Hib) -> case Msg of + {system, From, get_state} -> + Misc = [Name, StateName, StateData, Mod, Time], + sys:handle_system_msg(get_state, From, Parent, ?MODULE, Debug, + {{StateName, StateData}, Misc}, Hib); + {system, From, {replace_state, StateFun}} -> + State = {StateName, StateData}, + NState = {NStateName, NStateData} = try StateFun(State) + catch _:_ -> State end, + NMisc = [Name, NStateName, NStateData, Mod, Time], + sys:handle_system_msg(replace_state, From, Parent, ?MODULE, Debug, + {NState, NMisc}, Hib); {system, From, Req} -> sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, [Name, StateName, StateData, Mod, Time], Hib); diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index 04308a51b7..30a81ade49 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -372,6 +372,13 @@ wake_hib(Parent, Name, State, Mod, Debug) -> decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) -> case Msg of + {system, From, get_state} -> + sys:handle_system_msg(get_state, From, Parent, ?MODULE, Debug, + {State, [Name, State, Mod, Time]}, Hib); + {system, From, {replace_state, StateFun}} -> + NState = try StateFun(State) catch _:_ -> State end, + sys:handle_system_msg(replace_state, From, Parent, ?MODULE, Debug, + {NState, [Name, NState, Mod, Time]}, Hib); {system, From, Req} -> sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, [Name, State, Mod, Time], Hib); @@ -465,11 +472,11 @@ rec_nodes(Tag, [{N,R}|Tail], Name, Badnodes, Replies, Time, TimerId ) -> {'DOWN', R, _, _, _} -> rec_nodes(Tag, Tail, Name, [N|Badnodes], Replies, Time, TimerId); {{Tag, N}, Reply} -> %% Tag is bound !!! - unmonitor(R), + erlang:demonitor(R, [flush]), rec_nodes(Tag, Tail, Name, Badnodes, [{N,Reply}|Replies], Time, TimerId); {timeout, TimerId, _} -> - unmonitor(R), + erlang:demonitor(R, [flush]), %% Collect all replies that already have arrived rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies) end; @@ -520,10 +527,10 @@ rec_nodes_rest(Tag, [{N,R}|Tail], Name, Badnodes, Replies) -> {'DOWN', R, _, _, _} -> rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies); {{Tag, N}, Reply} -> %% Tag is bound !!! - unmonitor(R), + erlang:demonitor(R, [flush]), rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N,Reply}|Replies]) after 0 -> - unmonitor(R), + erlang:demonitor(R, [flush]), rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies) end; rec_nodes_rest(Tag, [N|Tail], Name, Badnodes, Replies) -> @@ -565,16 +572,6 @@ start_monitor(Node, Name) when is_atom(Node), is_atom(Name) -> end end. -%% Cancels a monitor started with Ref=erlang:monitor(_, _). -unmonitor(Ref) when is_reference(Ref) -> - erlang:demonitor(Ref), - receive - {'DOWN', Ref, _, _, _} -> - true - after 0 -> - true - end. - %%% --------------------------------------------------- %%% Message handling functions %%% --------------------------------------------------- diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl index c92e9e3ade..53728237ca 100644 --- a/lib/stdlib/src/io.erl +++ b/lib/stdlib/src/io.erl @@ -598,11 +598,7 @@ default_output() -> wait_io_mon_reply(From, Mref) -> receive {io_reply, From, Reply} -> - erlang:demonitor(Mref), - receive - {'DOWN', Mref, _, _, _} -> true - after 0 -> true - end, + erlang:demonitor(Mref, [flush]), Reply; {'EXIT', From, _What} -> receive diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl index 961c060019..0c033acd88 100644 --- a/lib/stdlib/src/lists.erl +++ b/lib/stdlib/src/lists.erl @@ -36,7 +36,7 @@ -export([merge/3, rmerge/3, sort/2, umerge/3, rumerge/3, usort/2]). -export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2, - partition/2,zf/2, + partition/2,zf/2,filtermap/2, mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2, split/2]). @@ -1291,18 +1291,28 @@ partition(Pred, [H | T], As, Bs) -> partition(Pred, [], As, Bs) when is_function(Pred, 1) -> {reverse(As), reverse(Bs)}. --spec zf(fun((T) -> boolean() | {'true', X}), [T]) -> [(T | X)]. +-spec filtermap(Fun, List1) -> List2 when + Fun :: fun((Elem) -> boolean() | {'true', Value}), + List1 :: [Elem], + List2 :: [Elem | Value], + Elem :: term(), + Value :: term(). -zf(F, [Hd|Tail]) -> +filtermap(F, [Hd|Tail]) -> case F(Hd) of true -> - [Hd|zf(F, Tail)]; + [Hd|filtermap(F, Tail)]; {true,Val} -> - [Val|zf(F, Tail)]; + [Val|filtermap(F, Tail)]; false -> - zf(F, Tail) + filtermap(F, Tail) end; -zf(F, []) when is_function(F, 1) -> []. +filtermap(F, []) when is_function(F, 1) -> []. + +-spec zf(fun((T) -> boolean() | {'true', X}), [T]) -> [(T | X)]. + +zf(F, L) -> + filtermap(F, L). -spec foreach(Fun, List) -> ok when Fun :: fun((Elem :: T) -> term()), diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index a4f4035c79..42a42b7fd7 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -66,6 +66,183 @@ obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 -> {deprecated, {rpc, multi_server_call, A}}; +%% *** CRYPTO add in R16B01 *** + +obsolete_1(crypto, md4, 1) -> + {deprecated, {crypto, hash, 2}}; +obsolete_1(crypto, md5, 1) -> + {deprecated, {crypto, hash, 2}}; +obsolete_1(crypto, sha, 1) -> + {deprecated, {crypto, hash, 2}}; + +obsolete_1(crypto, md4_init, 0) -> + {deprecated, {crypto, hash_init, 1}}; +obsolete_1(crypto, md5_init, 0) -> + {deprecated, {crypto, hash_init, 1}}; +obsolete_1(crypto, sha_init, 0) -> + {deprecated, {crypto, hash_init, 1}}; + +obsolete_1(crypto, md4_update, 2) -> + {deprecated, {crypto, hash_update, 3}}; +obsolete_1(crypto, md5_update, 2) -> + {deprecated, {crypto, hash_update, 3}}; +obsolete_1(crypto, sha_update, 2) -> + {deprecated, {crypto, hash_update, 3}}; + +obsolete_1(crypto, md4_final, 1) -> + {deprecated, {crypto, hash_final, 2}}; +obsolete_1(crypto, md5_final, 1) -> + {deprecated, {crypto, hash_final, 2}}; +obsolete_1(crypto, sha_final, 1) -> + {deprecated, {crypto, hash_final, 2}}; + +obsolete_1(crypto, md5_mac, 2) -> + {deprecated, {crypto, hmac, 3}}; +obsolete_1(crypto, sha_mac, 2) -> + {deprecated, {crypto, hmac, 3}}; +obsolete_1(crypto, sha_mac, 3) -> + {deprecated, {crypto, hmac, 4}}; + +obsolete_1(crypto, sha_mac_96, 2) -> + {deprecated, {crypto, hmac_n, 3}}; +obsolete_1(crypto, md5_mac_96, 2) -> + {deprecated, {crypto, hmac_n, 3}}; + +obsolete_1(crypto, rsa_sign, 2) -> + {deprecated, {crypto, sign, 4}}; +obsolete_1(crypto, rsa_sign, 3) -> + {deprecated, {crypto, sign, 4}}; +obsolete_1(crypto, rsa_verify, 3) -> + {deprecated, {crypto, verify, 5}}; +obsolete_1(crypto, rsa_verify, 4) -> + {deprecated, {crypto, verify, 5}}; + +obsolete_1(crypto, dss_sign, 2) -> + {deprecated, {crypto, sign, 4}}; +obsolete_1(crypto, dss_sign, 3) -> + {deprecated, {crypto, sign, 4}}; + +obsolete_1(crypto, dss_verify, 3) -> + {deprecated, {crypto, verify, 4}}; +obsolete_1(crypto, dss_verify, 4) -> + {deprecated, {crypto, verify, 4}}; + +obsolete_1(crypto, mod_exp, 3) -> + {deprecated, {crypto, mod_pow, 3}}; + +obsolete_1(crypto, dh_compute_key, 3) -> + {deprecated, {crypto, compute_key, 4}}; +obsolete_1(crypto, dh_generate_key, 1) -> + {deprecated, {crypto, generate_key, 3}}; +obsolete_1(crypto, dh_generate_key, 2) -> + {deprecated, {crypto, generate_key, 3}}; + +obsolete_1(crypto, des_cbc_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, des3_cbc_encrypt, 5) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, des_ecb_encrypt, 2) -> + {deprecated, {crypto, block_encrypt, 3}}; +obsolete_1(crypto, des_ede3_cbc_encrypt, 5) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, des_cfb_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, des3_cfb_encrypt, 5) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, blowfish_ecb_encrypt, 2) -> + {deprecated, {crypto, block_encrypt, 3}}; +obsolete_1(crypto, blowfish_cbc_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, blowfish_cfb64_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, blowfish_ofb64_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, aes_cfb_128_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, aes_cbc_128_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto, aes_cbc_256_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto,rc2_cbc_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; +obsolete_1(crypto,rc2_40_cbc_encrypt, 3) -> + {deprecated, {crypto, block_encrypt, 4}}; + +obsolete_1(crypto, des_cbc_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, des3_cbc_decrypt, 5) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, des_ecb_decrypt, 2) -> + {deprecated, {crypto, block_decrypt, 3}}; +obsolete_1(crypto, des_ede3_cbc_decrypt, 5) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, des_cfb_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, des3_cfb_decrypt, 5) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, blowfish_ecb_decrypt, 2) -> + {deprecated, {crypto, block_decrypt, 3}}; +obsolete_1(crypto, blowfish_cbc_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, blowfish_cfb64_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, blowfish_ofb64_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, aes_cfb_128_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, aes_cbc_128_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto, aes_cbc_256_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto,rc2_cbc_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; +obsolete_1(crypto,rc2_40_cbc_decrypt, 3) -> + {deprecated, {crypto, block_decrypt, 4}}; + +obsolete_1(crypto, aes_ctr_stream_decrypt, 2) -> + {deprecated, {crypto, stream_decrypt, 2}}; +obsolete_1(crypto, aes_ctr_stream_encrypt, 2) -> + {deprecated, {crypto, stream_encrypt, 2}}; +obsolete_1(crypto, aes_ctr_decrypt, 3) -> + {deprecated, {crypto, stream_decrypt, 2}}; +obsolete_1(crypto, aes_ctr_encrypt, 3) -> + {deprecated, {crypto, stream_encrypt, 2}}; +obsolete_1(crypto, rc4_encrypt, 2) -> + {deprecated, {crypto, stream_encrypt, 2}}; +obsolete_1(crypto, rc4_encrypt_with_state, 2) -> + {deprecated, {crypto, stream_encrypt, 2}}; +obsolete_1(crypto, aes_ctr_stream_init, 2) -> + {deprecated, {crypto, stream_init, 3}}; +obsolete_1(crypto, rc4_set_key, 1) -> + {deprecated, {crypto, stream_init, 2}}; + +obsolete_1(crypto, rsa_private_decrypt, 3) -> + {deprecated, {crypto, private_decrypt, 4}}; +obsolete_1(crypto, rsa_public_decrypt, 3) -> + {deprecated, {crypto, public_decrypt, 4}}; +obsolete_1(crypto, rsa_private_encrypt, 3) -> + {deprecated, {crypto, private_encrypt, 4}}; +obsolete_1(crypto, rsa_public_encrypt, 3) -> + {deprecated, {crypto, public_encrypt, 4}}; + +obsolete_1(crypto, des_cfb_ivec, 2) -> + {deprecated, {crypto, next_iv, 3}}; +obsolete_1(crypto,des_cbc_ivec, 1) -> + {deprecated, {crypto, next_iv, 2}}; +obsolete_1(crypto, aes_cbc_ivec, 1) -> + {deprecated, {crypto, next_iv, 2}}; + +obsolete_1(crypto,info, 0) -> + {deprecated, {crypto, module_info, 0}}; + +obsolete_1(crypto, strong_rand_mpint, 3) -> + {deprecated, "needed only by deprecated functions"}; +obsolete_1(crypto, erlint, 1) -> + {deprecated, "needed only by deprecated functions"}; +obsolete_1(crypto, mpint, 1) -> + {deprecated, "needed only by deprecated functions"}; + + %% *** SNMP *** obsolete_1(snmp, N, A) -> diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 9f93747c3e..54328cd9ff 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -63,7 +63,9 @@ %%-------------------------------------------------------------------------- -record(child, {% pid is undefined when child is not running - pid = undefined :: child() | {restarting,pid()} | [pid()], + pid = undefined :: child() + | {restarting, pid() | undefined} + | [pid()], name :: child_id(), mfargs :: mfargs(), restart_type :: restart(), @@ -752,6 +754,9 @@ restart(Child, State) -> end, timer:apply_after(0,?MODULE,try_again_restart,[self(),Id]), {ok,NState2}; + {try_again, NState2, #child{name=ChName}} -> + timer:apply_after(0,?MODULE,try_again_restart,[self(),ChName]), + {ok,NState2}; Other -> Other end; @@ -798,10 +803,16 @@ restart(rest_for_one, Child, State) -> case start_children(ChAfter2, State#state.name) of {ok, ChAfter3} -> {ok, State#state{children = ChAfter3 ++ ChBefore}}; - {error, ChAfter3, _Reason} -> + {error, ChAfter3, {failed_to_start_child, ChName, _Reason}} + when ChName =:= Child#child.name -> NChild = Child#child{pid=restarting(Child#child.pid)}, NState = State#state{children = ChAfter3 ++ ChBefore}, - {try_again, replace_child(NChild,NState)} + {try_again, replace_child(NChild,NState)}; + {error, ChAfter3, {failed_to_start_child, ChName, _Reason}} -> + NChild = lists:keyfind(ChName, #child.name, ChAfter3), + NChild2 = NChild#child{pid=?restarting(undefined)}, + NState = State#state{children = ChAfter3 ++ ChBefore}, + {try_again, replace_child(NChild2,NState), NChild2} end; restart(one_for_all, Child, State) -> Children1 = del_child(Child#child.pid, State#state.children), @@ -809,10 +820,16 @@ restart(one_for_all, Child, State) -> case start_children(Children2, State#state.name) of {ok, NChs} -> {ok, State#state{children = NChs}}; - {error, NChs, _Reason} -> + {error, NChs, {failed_to_start_child, ChName, _Reason}} + when ChName =:= Child#child.name -> NChild = Child#child{pid=restarting(Child#child.pid)}, NState = State#state{children = NChs}, - {try_again, replace_child(NChild,NState)} + {try_again, replace_child(NChild,NState)}; + {error, NChs, {failed_to_start_child, ChName, _Reason}} -> + NChild = lists:keyfind(ChName, #child.name, NChs), + NChild2 = NChild#child{pid=?restarting(undefined)}, + NState = State#state{children = NChs}, + {try_again, replace_child(NChild2,NState), NChild2} end. restarting(Pid) when is_pid(Pid) -> ?restarting(Pid); diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl index 2d6287814e..bffeb44179 100644 --- a/lib/stdlib/src/sys.erl +++ b/lib/stdlib/src/sys.erl @@ -21,6 +21,8 @@ %% External exports -export([suspend/1, suspend/2, resume/1, resume/2, get_status/1, get_status/2, + get_state/1, get_state/2, + replace_state/2, replace_state/3, change_code/4, change_code/5, log/2, log/3, trace/2, trace/3, statistics/2, statistics/3, log_to_file/2, log_to_file/3, no_debug/1, no_debug/2, @@ -97,6 +99,32 @@ get_status(Name) -> send_system_msg(Name, get_status). | (Misc :: term()). get_status(Name, Timeout) -> send_system_msg(Name, get_status, Timeout). +-spec get_state(Name) -> State when + Name :: name(), + State :: term(). +get_state(Name) -> send_system_msg(Name, get_state). + +-spec get_state(Name, Timeout) -> State when + Name :: name(), + Timeout :: timeout(), + State :: term(). +get_state(Name, Timeout) -> send_system_msg(Name, get_state, Timeout). + +-spec replace_state(Name, StateFun) -> NewState when + Name :: name(), + StateFun :: fun((State :: term()) -> NewState :: term()), + NewState :: term(). +replace_state(Name, StateFun) -> + send_system_msg(Name, {replace_state, StateFun}). + +-spec replace_state(Name, StateFun, Timeout) -> NewState when + Name :: name(), + StateFun :: fun((State :: term()) -> NewState :: term()), + Timeout :: timeout(), + NewState :: term(). +replace_state(Name, StateFun, Timeout) -> + send_system_msg(Name, {replace_state, StateFun}, Timeout). + -spec change_code(Name, Module, OldVsn, Extra) -> 'ok' | {error, Reason} when Name :: name(), Module :: module(), @@ -362,6 +390,10 @@ do_cmd(_, suspend, _Parent, _Mod, Debug, Misc) -> {suspended, ok, Debug, Misc}; do_cmd(_, resume, _Parent, _Mod, Debug, Misc) -> {running, ok, Debug, Misc}; +do_cmd(SysState, get_state, _Parent, _Mod, Debug, {State, Misc}) -> + {SysState, State, Debug, Misc}; +do_cmd(SysState, replace_state, _Parent, _Mod, Debug, {State, Misc}) -> + {SysState, State, Debug, Misc}; do_cmd(SysState, get_status, Parent, Mod, Debug, Misc) -> Res = get_status(SysState, Parent, Mod, Debug, Misc), {SysState, Res, Debug, Misc}; diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl index 689e42051f..e11fb046e9 100644 --- a/lib/stdlib/src/timer.erl +++ b/lib/stdlib/src/timer.erl @@ -354,7 +354,7 @@ timer_timeout(SysTime) -> '$end_of_table' -> infinity; {Time, _Ref} when Time > SysTime -> - Timeout = (Time - SysTime) div 1000, + Timeout = (Time - SysTime + 999) div 1000, %% Returned timeout must fit in a small int erlang:min(Timeout, ?MAX_TIMEOUT); Key -> @@ -414,7 +414,7 @@ next_timeout() -> '$end_of_table' -> infinity; {Time, _} -> - erlang:min(positive((Time - system_time()) div 1000), ?MAX_TIMEOUT) + erlang:min(positive((Time - system_time() + 999) div 1000), ?MAX_TIMEOUT) end. %% Help functions diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index 6aa09d7bd0..af82f22b21 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -66,6 +66,7 @@ MODULES= \ string_SUITE \ supervisor_1 \ supervisor_2 \ + supervisor_3 \ supervisor_deadlock \ naughty_child \ shell_SUITE \ diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl index 25281365be..8c55b616b9 100644 --- a/lib/stdlib/test/c_SUITE.erl +++ b/lib/stdlib/test/c_SUITE.erl @@ -20,7 +20,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([c_1/1, c_2/1, c_3/1, c_4/1, nc_1/1, nc_2/1, nc_3/1, nc_4/1, - memory/1]). + ls/1, memory/1]). -include_lib("test_server/include/test_server.hrl"). @@ -29,7 +29,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [c_1, c_2, c_3, c_4, nc_1, nc_2, nc_3, nc_4, memory]. + [c_1, c_2, c_3, c_4, nc_1, nc_2, nc_3, nc_4, ls, memory]. groups() -> []. @@ -147,6 +147,13 @@ nc_4(Config) when is_list(Config) -> ?line Result = nc(R,[{outdir,W}]), ?line {ok, m} = Result. +ls(Config) when is_list(Config) -> + Directory = ?config(data_dir, Config), + ok = c:ls(Directory), + File = filename:join(Directory, "m.erl"), + ok = c:ls(File), + ok = c:ls("no_such_file"). + memory(doc) -> ["Checks that c:memory/[0,1] returns consistent results."]; memory(suite) -> diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl index 66799f4d05..8ff7c3ccc9 100644 --- a/lib/stdlib/test/dets_SUITE.erl +++ b/lib/stdlib/test/dets_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% 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 @@ -22,7 +22,6 @@ -ifdef(debug). -define(format(S, A), io:format(S, A)). --define(line, put(line, ?LINE), ). -define(config(X,Y), foo). -define(t, test_server). -define(privdir(_), "./dets_SUITE_priv"). @@ -34,8 +33,6 @@ -define(datadir(Conf), ?config(data_dir, Conf)). -endif. --compile(r13). % OTP-9607 - -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, newly_started/1, basic_v8/1, basic_v9/1, @@ -55,7 +52,7 @@ simultaneous_open/1, insert_new/1, repair_continuation/1, otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1, otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1, - otp_8923/1, otp_9282/1, otp_9607/1]). + otp_8923/1, otp_9282/1]). -export([dets_dirty_loop/0]). @@ -112,7 +109,7 @@ all() -> many_clients, otp_4906, otp_5402, simultaneous_open, insert_new, repair_continuation, otp_5487, otp_6206, otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898, - otp_8899, otp_8903, otp_8923, otp_9282, otp_9607 + otp_8899, otp_8903, otp_8923, otp_9282 ]. groups() -> @@ -135,10 +132,10 @@ newly_started(doc) -> newly_started(suite) -> []; newly_started(Config) when is_list(Config) -> - ?line true = is_alive(), - ?line {ok, Node} = test_server:start_node(slave1, slave, []), - ?line [] = rpc:call(Node, dets, all, []), - ?line test_server:stop_node(Node), + true = is_alive(), + {ok, Node} = test_server:start_node(slave1, slave, []), + [] = rpc:call(Node, dets, all, []), + test_server:stop_node(Node), ok. basic_v8(doc) -> @@ -156,31 +153,31 @@ basic_v9(Config) when is_list(Config) -> basic(Config, 9). basic(Config, Version) -> - ?line Tab = dets_basic_test, - ?line FName = filename(Tab, Config), + Tab = dets_basic_test, + FName = filename(Tab, Config), P0 = pps(), - ?line {ok, _} = dets:open_file(Tab,[{file, FName},{version,Version}]), - ?line ok = dets:insert(Tab,{mazda,japan}), - ?line ok = dets:insert(Tab,{toyota,japan}), - ?line ok = dets:insert(Tab,{suzuki,japan}), - ?line ok = dets:insert(Tab,{honda,japan}), - ?line ok = dets:insert(Tab,{renault,france}), - ?line ok = dets:insert(Tab,{citroen,france}), - ?line ok = dets:insert(Tab,{opel,germany}), - ?line ok = dets:insert(Tab,{saab,sweden}), - ?line ok = dets:insert(Tab,{volvo,sweden}), - ?line [{opel,germany}] = dets:lookup(Tab,opel), - ?line Japs = dets:traverse(Tab, fun(Obj) -> - case Obj of - {_, japan} -> {continue, Obj}; - _ -> continue - end - end), - ?line 4 = length(Japs), - ?line ok = dets:close(Tab), - ?line file:delete(FName), - ?line check_pps(P0), + {ok, _} = dets:open_file(Tab,[{file, FName},{version,Version}]), + ok = dets:insert(Tab,{mazda,japan}), + ok = dets:insert(Tab,{toyota,japan}), + ok = dets:insert(Tab,{suzuki,japan}), + ok = dets:insert(Tab,{honda,japan}), + ok = dets:insert(Tab,{renault,france}), + ok = dets:insert(Tab,{citroen,france}), + ok = dets:insert(Tab,{opel,germany}), + ok = dets:insert(Tab,{saab,sweden}), + ok = dets:insert(Tab,{volvo,sweden}), + [{opel,germany}] = dets:lookup(Tab,opel), + Japs = dets:traverse(Tab, fun(Obj) -> + case Obj of + {_, japan} -> {continue, Obj}; + _ -> continue + end + end), + 4 = length(Japs), + ok = dets:close(Tab), + file:delete(FName), + check_pps(P0), ok. @@ -204,24 +201,24 @@ open(Config, Version) -> %% If this becomes a problem, one should consider running this %% test on a slave node. - ?line {Sets, Bags, Dups} = args(Config), + {Sets, Bags, Dups} = args(Config), - ?line All = Sets ++ Bags ++ Dups, - ?line delete_files(All), + All = Sets ++ Bags ++ Dups, + delete_files(All), - ?line Data = make_data(1), + Data = make_data(1), P0 = pps(), - ?line Tabs = open_files(1, All, Version), - ?line initialize(Tabs, Data), - ?line check(Tabs, Data), + Tabs = open_files(1, All, Version), + initialize(Tabs, Data), + check(Tabs, Data), - ?line foreach(fun(Tab) -> ok = dets:close(Tab) end, Tabs), + foreach(fun(Tab) -> ok = dets:close(Tab) end, Tabs), %% Now reopen the files ?format("Reopening closed files \n", []), - ?line Tabs = open_files(1, All, Version), + Tabs = open_files(1, All, Version), ?format("Checking contents of reopened files \n", []), - ?line check(Tabs, Data), + check(Tabs, Data), %% crash the dets server ?format("Crashing dets server \n", []), @@ -235,25 +232,25 @@ open(Config, Version) -> %% Now reopen the files again ?format("Reopening crashed files \n", []), - ?line open_files(1, All, Version), + open_files(1, All, Version), ?format("Checking contents of repaired files \n", []), - ?line check(Tabs, Data), + check(Tabs, Data), - ?line close_all(Tabs), + close_all(Tabs), - ?line delete_files(All), + delete_files(All), P1 = pps(), {Ports0, Procs0} = P0, {Ports1, Procs1} = P1, - ?line true = Ports1 =:= Ports0, + true = Ports1 =:= Ports0, %% The dets_server process has been restarted: - ?line [_] = Procs0 -- Procs1, - ?line [_] = Procs1 -- Procs0, + [_] = Procs0 -- Procs1, + [_] = Procs1 -- Procs0, ok. check(Tabs, Data) -> foreach(fun(Tab) -> - ?line Kp = dets:info(Tab, keypos), + Kp = dets:info(Tab, keypos), ?format("checking ~p~n", [Tab]), foreach(fun(Item) -> case dets:lookup(Tab, k(Kp,Item)) of @@ -285,31 +282,31 @@ sets_v9(Config) when is_list(Config) -> sets(Config, 9). sets(Config, Version) -> - ?line {Sets, _, _} = args(Config), + {Sets, _, _} = args(Config), - ?line Data = make_data(1), - ?line delete_files(Sets), + Data = make_data(1), + delete_files(Sets), P0 = pps(), - ?line Tabs = open_files(1, Sets, Version), + Tabs = open_files(1, Sets, Version), Bigger = [{17,q,w,w}, {48,q,w,w,w,w,w,w}], % 48 requires a bigger buddy - ?line initialize(Tabs, Data++Bigger++Data), % overwrite - ?line Len = length(Data), - ?line foreach(fun(Tab) -> trav_test(Data, Len, Tab) end, Tabs), - ?line size_test(Len, Tabs), - ?line no_keys_test(Tabs), - ?line foreach(fun(Tab) -> del_test(Tab) end, Tabs), - ?line initialize(Tabs, Data), - ?line foreach(fun(Tab) -> del_obj_test(Tab) end, Tabs), - ?line initialize(Tabs, Data), - ?line foreach(fun(Tab) -> - Len = dets:info(Tab, size) end, - Tabs), - ?line foreach(fun(Tab) -> match_test(Data, Tab) end, Tabs), - ?line foreach(fun(Tab) -> match_del_test(Tab) end, Tabs), + initialize(Tabs, Data++Bigger++Data), % overwrite + Len = length(Data), + foreach(fun(Tab) -> trav_test(Data, Len, Tab) end, Tabs), + size_test(Len, Tabs), + no_keys_test(Tabs), + foreach(fun(Tab) -> del_test(Tab) end, Tabs), + initialize(Tabs, Data), + foreach(fun(Tab) -> del_obj_test(Tab) end, Tabs), + initialize(Tabs, Data), + foreach(fun(Tab) -> + Len = dets:info(Tab, size) end, + Tabs), + foreach(fun(Tab) -> match_test(Data, Tab) end, Tabs), + foreach(fun(Tab) -> match_del_test(Tab) end, Tabs), - ?line close_all(Tabs), - ?line delete_files(Sets), - ?line check_pps(P0), + close_all(Tabs), + delete_files(Sets), + check_pps(P0), ok. bags_v8(doc) -> @@ -328,27 +325,27 @@ bags_v9(Config) when is_list(Config) -> bags(Config, Version) -> {_, Bags, _} = args(Config), - ?line Data = make_data(1, bag), %% gives twice as many objects - ?line delete_files(Bags), + Data = make_data(1, bag), %% gives twice as many objects + delete_files(Bags), P0 = pps(), - ?line Tabs = open_files(1, Bags, Version), - ?line initialize(Tabs, Data++Data), - ?line Len = length(Data), - ?line foreach(fun(Tab) -> trav_test(Data, Len, Tab) end, Tabs), - ?line size_test(Len, Tabs), - ?line no_keys_test(Tabs), - ?line foreach(fun(Tab) -> del_test(Tab) end, Tabs), - ?line initialize(Tabs, Data), - ?line foreach(fun(Tab) -> del_obj_test(Tab) end, Tabs), - ?line initialize(Tabs, Data), - ?line foreach(fun(Tab) -> - Len = dets:info(Tab, size) end, - Tabs), - ?line foreach(fun(Tab) -> match_test(Data, Tab) end, Tabs), - ?line foreach(fun(Tab) -> match_del_test(Tab) end, Tabs), - ?line close_all(Tabs), - ?line delete_files(Bags), - ?line check_pps(P0), + Tabs = open_files(1, Bags, Version), + initialize(Tabs, Data++Data), + Len = length(Data), + foreach(fun(Tab) -> trav_test(Data, Len, Tab) end, Tabs), + size_test(Len, Tabs), + no_keys_test(Tabs), + foreach(fun(Tab) -> del_test(Tab) end, Tabs), + initialize(Tabs, Data), + foreach(fun(Tab) -> del_obj_test(Tab) end, Tabs), + initialize(Tabs, Data), + foreach(fun(Tab) -> + Len = dets:info(Tab, size) end, + Tabs), + foreach(fun(Tab) -> match_test(Data, Tab) end, Tabs), + foreach(fun(Tab) -> match_del_test(Tab) end, Tabs), + close_all(Tabs), + delete_files(Bags), + check_pps(P0), ok. @@ -368,27 +365,27 @@ duplicate_bags_v9(Config) when is_list(Config) -> duplicate_bags(Config, Version) when is_list(Config) -> {_, _, Dups} = args(Config), - ?line Data = make_data(1, duplicate_bag), %% gives twice as many objects - ?line delete_files(Dups), + Data = make_data(1, duplicate_bag), %% gives twice as many objects + delete_files(Dups), P0 = pps(), - ?line Tabs = open_files(1, Dups, Version), - ?line initialize(Tabs, Data), - ?line Len = length(Data), - ?line foreach(fun(Tab) -> trav_test(Data, Len, Tab) end, Tabs), - ?line size_test(Len, Tabs), - ?line no_keys_test(Tabs), - ?line foreach(fun(Tab) -> del_test(Tab) end, Tabs), - ?line initialize(Tabs, Data), - ?line foreach(fun(Tab) -> del_obj_test(Tab) end, Tabs), - ?line initialize(Tabs, Data), - ?line foreach(fun(Tab) -> - Len = dets:info(Tab, size) end, - Tabs), - ?line foreach(fun(Tab) -> match_test(Data, Tab) end, Tabs), - ?line foreach(fun(Tab) -> match_del_test(Tab) end, Tabs), - ?line close_all(Tabs), - ?line delete_files(Dups), - ?line check_pps(P0), + Tabs = open_files(1, Dups, Version), + initialize(Tabs, Data), + Len = length(Data), + foreach(fun(Tab) -> trav_test(Data, Len, Tab) end, Tabs), + size_test(Len, Tabs), + no_keys_test(Tabs), + foreach(fun(Tab) -> del_test(Tab) end, Tabs), + initialize(Tabs, Data), + foreach(fun(Tab) -> del_obj_test(Tab) end, Tabs), + initialize(Tabs, Data), + foreach(fun(Tab) -> + Len = dets:info(Tab, size) end, + Tabs), + foreach(fun(Tab) -> match_test(Data, Tab) end, Tabs), + foreach(fun(Tab) -> match_del_test(Tab) end, Tabs), + close_all(Tabs), + delete_files(Dups), + check_pps(P0), ok. @@ -412,26 +409,26 @@ access(Config, Version) -> Args = [[{ram_file, true}], []], - ?line {Args_acc_1, _, _} = zip_filename(Args_acc, [], [], Config), - ?line delete_files(Args_acc_1), - ?line {Args_1, _, _} = zip_filename(Args, [], [], Config), + {Args_acc_1, _, _} = zip_filename(Args_acc, [], [], Config), + delete_files(Args_acc_1), + {Args_1, _, _} = zip_filename(Args, [], [], Config), P0 = pps(), - ?line {error, {file_error,_,enoent}} = dets:open_file('1', hd(Args_acc_1)), - - ?line Tabs = open_files(1, Args_1, Version), - ?line close_all(Tabs), - ?line Tabs = open_files(1, Args_acc_1, Version), - - ?line foreach(fun(Tab) -> - {error, {access_mode,_}} = dets:insert(Tab, {1,2}), - [] = dets:lookup(Tab, 11), - '$end_of_table' = dets:first(Tab), - {error, {access_mode,_}} = dets:delete(Tab, 22) - end, Tabs), - ?line close_all(Tabs), - ?line delete_files(Args_acc_1), - ?line check_pps(P0), + {error, {file_error,_,enoent}} = dets:open_file('1', hd(Args_acc_1)), + + Tabs = open_files(1, Args_1, Version), + close_all(Tabs), + Tabs = open_files(1, Args_acc_1, Version), + + foreach(fun(Tab) -> + {error, {access_mode,_}} = dets:insert(Tab, {1,2}), + [] = dets:lookup(Tab, 11), + '$end_of_table' = dets:first(Tab), + {error, {access_mode,_}} = dets:delete(Tab, 22) + end, Tabs), + close_all(Tabs), + delete_files(Args_acc_1), + check_pps(P0), ok. @@ -440,23 +437,23 @@ dirty_mark(doc) -> dirty_mark(suite) -> []; dirty_mark(Config) when is_list(Config) -> - ?line true = is_alive(), - ?line Tab = dets_dirty_mark_test, - ?line FName = filename(Tab, Config), + true = is_alive(), + Tab = dets_dirty_mark_test, + FName = filename(Tab, Config), P0 = pps(), - ?line dets:open_file(Tab,[{file, FName}]), - ?line dets:insert(Tab,{mazda,japan}), - ?line dets:insert(Tab,{toyota,japan}), - ?line dets:insert(Tab,{suzuki,japan}), - ?line dets:insert(Tab,{honda,japan}), - ?line dets:insert(Tab,{renault,france}), - ?line dets:insert(Tab,{citroen,france}), - ?line dets:insert(Tab,{opel,germany}), - ?line dets:insert(Tab,{saab,sweden}), - ?line dets:insert(Tab,{volvo,sweden}), - ?line [{opel,germany}] = dets:lookup(Tab,opel), - ?line ok = dets:close(Tab), - ?line Call = fun(P,A) -> + dets:open_file(Tab,[{file, FName}]), + dets:insert(Tab,{mazda,japan}), + dets:insert(Tab,{toyota,japan}), + dets:insert(Tab,{suzuki,japan}), + dets:insert(Tab,{honda,japan}), + dets:insert(Tab,{renault,france}), + dets:insert(Tab,{citroen,france}), + dets:insert(Tab,{opel,germany}), + dets:insert(Tab,{saab,sweden}), + dets:insert(Tab,{volvo,sweden}), + [{opel,germany}] = dets:lookup(Tab,opel), + ok = dets:close(Tab), + Call = fun(P,A) -> P ! {self(), A}, receive {P, Ans} -> @@ -465,26 +462,26 @@ dirty_mark(Config) when is_list(Config) -> exit(other_process_dead) end end, - ?line {ok, Node} = test_server:start_node(dets_dirty_mark, - slave, - [{linked, false}, - {args, "-pa " ++ - filename:dirname + {ok, Node} = test_server:start_node(dets_dirty_mark, + slave, + [{linked, false}, + {args, "-pa " ++ + filename:dirname (code:which(?MODULE))}]), - ?line ok = ensure_node(20, Node), + ok = ensure_node(20, Node), %% io:format("~p~n",[rpc:call(Node, code, get_path, [])]), %% io:format("~p~n",[rpc:call(Node, file, get_cwd, [])]), %% io:format("~p~n",[Config]), - ?line Pid = rpc:call(Node,erlang, spawn, + Pid = rpc:call(Node,erlang, spawn, [?MODULE, dets_dirty_loop, []]), - ?line {ok, Tab} = Call(Pid, [open, Tab, [{file, FName}]]), - ?line [{opel,germany}] = Call(Pid, [read,Tab,opel]), - ?line test_server:stop_node(Node), - ?line {ok, Tab} = dets:open_file(Tab,[{file, FName}, - {repair,false}]), - ?line ok = dets:close(Tab), - ?line file:delete(FName), - ?line check_pps(P0), + {ok, Tab} = Call(Pid, [open, Tab, [{file, FName}]]), + [{opel,germany}] = Call(Pid, [read,Tab,opel]), + test_server:stop_node(Node), + {ok, Tab} = dets:open_file(Tab,[{file, FName}, + {repair,false}]), + ok = dets:close(Tab), + file:delete(FName), + check_pps(P0), ok. dirty_mark2(doc) -> @@ -492,22 +489,22 @@ dirty_mark2(doc) -> dirty_mark2(suite) -> []; dirty_mark2(Config) when is_list(Config) -> - ?line true = is_alive(), - ?line Tab = dets_dirty_mark2_test, - ?line FName = filename(Tab, Config), + true = is_alive(), + Tab = dets_dirty_mark2_test, + FName = filename(Tab, Config), P0 = pps(), - ?line dets:open_file(Tab,[{file, FName}]), - ?line dets:insert(Tab,{toyota,japan}), - ?line dets:insert(Tab,{suzuki,japan}), - ?line dets:insert(Tab,{honda,japan}), - ?line dets:insert(Tab,{renault,france}), - ?line dets:insert(Tab,{citroen,france}), - ?line dets:insert(Tab,{opel,germany}), - ?line dets:insert(Tab,{saab,sweden}), - ?line dets:insert(Tab,{volvo,sweden}), - ?line [{opel,germany}] = dets:lookup(Tab,opel), - ?line ok = dets:close(Tab), - ?line Call = fun(P,A) -> + dets:open_file(Tab,[{file, FName}]), + dets:insert(Tab,{toyota,japan}), + dets:insert(Tab,{suzuki,japan}), + dets:insert(Tab,{honda,japan}), + dets:insert(Tab,{renault,france}), + dets:insert(Tab,{citroen,france}), + dets:insert(Tab,{opel,germany}), + dets:insert(Tab,{saab,sweden}), + dets:insert(Tab,{volvo,sweden}), + [{opel,germany}] = dets:lookup(Tab,opel), + ok = dets:close(Tab), + Call = fun(P,A) -> P ! {self(), A}, receive {P, Ans} -> @@ -516,25 +513,25 @@ dirty_mark2(Config) when is_list(Config) -> exit(other_process_dead) end end, - ?line {ok, Node} = test_server:start_node(dets_dirty_mark2, - slave, - [{linked, false}, - {args, "-pa " ++ - filename:dirname + {ok, Node} = test_server:start_node(dets_dirty_mark2, + slave, + [{linked, false}, + {args, "-pa " ++ + filename:dirname (code:which(?MODULE))}]), - ?line ok = ensure_node(20, Node), - ?line Pid = rpc:call(Node,erlang, spawn, - [?MODULE, dets_dirty_loop, []]), - ?line {ok, Tab} = Call(Pid, [open, Tab, [{file, FName},{auto_save,1000}]]), - ?line ok = Call(Pid, [write,Tab,{mazda,japan}]), - ?line timer:sleep(2100), + ok = ensure_node(20, Node), + Pid = rpc:call(Node,erlang, spawn, + [?MODULE, dets_dirty_loop, []]), + {ok, Tab} = Call(Pid, [open, Tab, [{file, FName},{auto_save,1000}]]), + ok = Call(Pid, [write,Tab,{mazda,japan}]), + timer:sleep(2100), %% Read something, just to give auto save time to finish. - ?line [{opel,germany}] = Call(Pid, [read,Tab,opel]), - ?line test_server:stop_node(Node), - ?line {ok, Tab} = dets:open_file(Tab, [{file, FName}, {repair,false}]), - ?line ok = dets:close(Tab), - ?line file:delete(FName), - ?line check_pps(P0), + [{opel,germany}] = Call(Pid, [read,Tab,opel]), + test_server:stop_node(Node), + {ok, Tab} = dets:open_file(Tab, [{file, FName}, {repair,false}]), + ok = dets:close(Tab), + file:delete(FName), + check_pps(P0), ok. dets_dirty_loop() -> @@ -570,38 +567,38 @@ bag_next_v9(suite) -> bag_next_v9(doc) -> ["Check that bags and next work as expected."]; bag_next_v9(Config) when is_list(Config) -> - ?line Tab = dets_bag_next_test, - ?line FName = filename(Tab, Config), + Tab = dets_bag_next_test, + FName = filename(Tab, Config), %% first and next crash upon error - ?line dets:open_file(Tab,[{file, FName}, {type, bag},{version,9}]), - ?line ok = dets:insert(Tab, [{1,1},{2,2},{3,3},{4,4}]), - ?line FirstKey = dets:first(Tab), - ?line NextKey = dets:next(Tab, FirstKey), - ?line [FirstObj | _] = dets:lookup(Tab, FirstKey), - ?line [NextObj | _] = dets:lookup(Tab, NextKey), - ?line {ok, FirstPos} = dets:where(Tab, FirstObj), - ?line {ok, NextPos} = dets:where(Tab, NextObj), + dets:open_file(Tab,[{file, FName}, {type, bag},{version,9}]), + ok = dets:insert(Tab, [{1,1},{2,2},{3,3},{4,4}]), + FirstKey = dets:first(Tab), + NextKey = dets:next(Tab, FirstKey), + [FirstObj | _] = dets:lookup(Tab, FirstKey), + [NextObj | _] = dets:lookup(Tab, NextKey), + {ok, FirstPos} = dets:where(Tab, FirstObj), + {ok, NextPos} = dets:where(Tab, NextObj), crash(FName, NextPos+12), - ?line {'EXIT',BadObject1} = (catch dets:next(Tab, FirstKey)), - ?line bad_object(BadObject1, FName), + {'EXIT',BadObject1} = (catch dets:next(Tab, FirstKey)), + bad_object(BadObject1, FName), crash(FName, FirstPos+12), - ?line {'EXIT',BadObject2} = (catch dets:first(Tab)), - ?line bad_object(BadObject2, FName), - ?line dets:close(Tab), - ?line file:delete(FName), + {'EXIT',BadObject2} = (catch dets:first(Tab)), + bad_object(BadObject2, FName), + dets:close(Tab), + file:delete(FName), bag_next(Config, 9). bag_next(Config, Version) -> - ?line Tab = dets_bag_next_test, - ?line FName = filename(Tab, Config), + Tab = dets_bag_next_test, + FName = filename(Tab, Config), P0 = pps(), - ?line dets:open_file(Tab,[{file, FName}, {type, bag},{version,Version}]), - ?line dets:insert(Tab,{698,hopp}), - ?line dets:insert(Tab,{186,hopp}), - ?line dets:insert(Tab,{hej,hopp}), - ?line dets:insert(Tab,{186,plopp}), + dets:open_file(Tab,[{file, FName}, {type, bag},{version,Version}]), + dets:insert(Tab,{698,hopp}), + dets:insert(Tab,{186,hopp}), + dets:insert(Tab,{hej,hopp}), + dets:insert(Tab,{186,plopp}), Loop = fun(N, Last, Self) -> case N of 0 -> @@ -615,10 +612,10 @@ bag_next(Config, Version) -> end end end, - ?line ok = Loop(4,dets:first(Tab),Loop), - ?line dets:close(Tab), - ?line file:delete(FName), - ?line check_pps(P0), + ok = Loop(4,dets:first(Tab),Loop), + dets:close(Tab), + file:delete(FName), + check_pps(P0), ok. oldbugs_v8(doc) -> @@ -638,15 +635,15 @@ oldbugs_v9(Config) when is_list(Config) -> oldbugs(Config, Version) -> FName = filename(dets_suite_oldbugs_test, Config), P0 = pps(), - ?line {ok, ob} = dets:open_file(ob, [{version, Version}, + {ok, ob} = dets:open_file(ob, [{version, Version}, {type, bag}, {file, FName}]), - ?line ok = dets:insert(ob, {1, 2}), - ?line ok = dets:insert(ob, {1,3}), - ?line ok = dets:insert(ob, {1, 2}), - ?line 2 = dets:info(ob, size), %% assertion - ?line ok = dets:close(ob), - ?line file:delete(FName), - ?line check_pps(P0), + ok = dets:insert(ob, {1, 2}), + ok = dets:insert(ob, {1,3}), + ok = dets:insert(ob, {1, 2}), + 2 = dets:info(ob, size), %% assertion + ok = dets:close(ob), + file:delete(FName), + check_pps(P0), ok. unsafe_assumptions(suite) -> []; @@ -654,30 +651,30 @@ unsafe_assumptions(doc) -> "Tests that shrinking an object and then expanding it works."; unsafe_assumptions(Config) when is_list(Config) -> FName = filename(dets_suite_unsafe_assumptions_test, Config), - ?line file:delete(FName), + file:delete(FName), P0 = pps(), - ?line {ok, a} = dets:open_file(a, [{version,8},{file, FName}]), + {ok, a} = dets:open_file(a, [{version,8},{file, FName}]), O0 = {2,false}, O1 = {1, false}, O2 = {1, true}, O3 = {1, duplicate(20,false)}, O4 = {1, duplicate(25,false)}, % same 2-log as O3 - ?line ok = dets:insert(a, O1), - ?line ok = dets:insert(a, O0), - ?line true = [O1,O0] =:= sort(get_all_objects(a)), - ?line true = [O1,O0] =:= sort(get_all_objects_fast(a)), - ?line ok = dets:insert(a, O2), - ?line true = [O2,O0] =:= sort(get_all_objects(a)), - ?line true = [O2,O0] =:= sort(get_all_objects_fast(a)), - ?line ok = dets:insert(a, O3), - ?line true = [O3,O0] =:= sort(get_all_objects(a)), - ?line true = [O3,O0] =:= sort(get_all_objects_fast(a)), - ?line ok = dets:insert(a, O4), - ?line true = [O4,O0] =:= sort(get_all_objects(a)), - ?line true = [O4,O0] =:= sort(get_all_objects_fast(a)), - ?line ok = dets:close(a), - ?line file:delete(FName), - ?line check_pps(P0), + ok = dets:insert(a, O1), + ok = dets:insert(a, O0), + true = [O1,O0] =:= sort(get_all_objects(a)), + true = [O1,O0] =:= sort(get_all_objects_fast(a)), + ok = dets:insert(a, O2), + true = [O2,O0] =:= sort(get_all_objects(a)), + true = [O2,O0] =:= sort(get_all_objects_fast(a)), + ok = dets:insert(a, O3), + true = [O3,O0] =:= sort(get_all_objects(a)), + true = [O3,O0] =:= sort(get_all_objects_fast(a)), + ok = dets:insert(a, O4), + true = [O4,O0] =:= sort(get_all_objects(a)), + true = [O4,O0] =:= sort(get_all_objects_fast(a)), + ok = dets:close(a), + file:delete(FName), + check_pps(P0), ok. truncated_segment_array_v8(suite) -> []; @@ -698,22 +695,22 @@ trunc_seg_array(Config, V) -> TabRef = dets_suite_truncated_segment_array_test, Fname = filename(TabRef, Config), %% Create file that needs to be repaired - ?line file:delete(Fname), + file:delete(Fname), P0 = pps(), - ?line {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), - ?line ok = dets:close(TabRef), + {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), + ok = dets:close(TabRef), %% Truncate the file - ?line HeadSize = headsz(V), - ?line truncate(Fname, HeadSize + 10), + HeadSize = headsz(V), + truncate(Fname, HeadSize + 10), %% Open the truncated file - ?line io:format("Expect repair:~n"), - ?line {ok, TabRef} = dets:open_file(TabRef, + io:format("Expect repair:~n"), + {ok, TabRef} = dets:open_file(TabRef, [{file, Fname}, {repair, true}]), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), - ?line check_pps(P0), + ok = dets:close(TabRef), + file:delete(Fname), + check_pps(P0), ok. open_file_v8(doc) -> @@ -730,58 +727,58 @@ open_file_v9(suite) -> open_file_v9(Config) when is_list(Config) -> T = open_v9, Fname = filename(T, Config), - ?line {ok, _} = dets:open_file(T, [{file,Fname},{version,9}]), - ?line 9 = dets:info(T, version), - ?line true = [self()] =:= dets:info(T, users), - ?line {ok, _} = dets:open_file(T, [{file,Fname},{version,9}]), - ?line {error,incompatible_arguments} = + {ok, _} = dets:open_file(T, [{file,Fname},{version,9}]), + 9 = dets:info(T, version), + true = [self()] =:= dets:info(T, users), + {ok, _} = dets:open_file(T, [{file,Fname},{version,9}]), + {error,incompatible_arguments} = dets:open_file(T, [{file,Fname},{version,8}]), - ?line true = [self(),self()] =:= dets:info(T, users), - ?line ok = dets:close(T), - ?line true = [self()] =:= dets:info(T, users), - ?line ok = dets:close(T), - ?line undefined = ets:info(T, users), - ?line file:delete(Fname), + true = [self(),self()] =:= dets:info(T, users), + ok = dets:close(T), + true = [self()] =:= dets:info(T, users), + ok = dets:close(T), + undefined = ets:info(T, users), + file:delete(Fname), open_1(Config, 9). open_1(Config, V) -> TabRef = open_file_1_test, Fname = filename(TabRef, Config), - ?line file:delete(Fname), + file:delete(Fname), P0 = pps(), - ?line {error,{file_error,Fname,enoent}} = dets:open_file(Fname), + {error,{file_error,Fname,enoent}} = dets:open_file(Fname), - ?line ok = file:write_file(Fname, duplicate(100,65)), - ?line {error,{not_a_dets_file,Fname}} = dets:open_file(Fname), - ?line file:delete(Fname), + ok = file:write_file(Fname, duplicate(100,65)), + {error,{not_a_dets_file,Fname}} = dets:open_file(Fname), + file:delete(Fname), HeadSize = headsz(V), - ?line {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), - ?line ok = dets:close(TabRef), - ?line truncate(Fname, HeadSize + 10), - ?line true = dets:is_dets_file(Fname), - ?line io:format("Expect repair:~n"), - ?line {ok, Ref} = dets:open_file(Fname), % repairing - ?line ok = dets:close(Ref), - ?line file:delete(Fname), + {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), + ok = dets:close(TabRef), + truncate(Fname, HeadSize + 10), + true = dets:is_dets_file(Fname), + io:format("Expect repair:~n"), + {ok, Ref} = dets:open_file(Fname), % repairing + ok = dets:close(Ref), + file:delete(Fname), %% truncated file header, invalid type - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = ins(TabRef, 3000), - ?line ok = dets:close(TabRef), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = ins(TabRef, 3000), + ok = dets:close(TabRef), TypePos = 12, crash(Fname, TypePos), - ?line {error, {invalid_type_code,Fname}} = dets:open_file(Fname), - ?line truncate(Fname, HeadSize - 10), - ?line {error, {tooshort,Fname}} = dets:open_file(Fname), - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), - - ?line {error,{file_error,{foo,bar},_}} = dets:is_dets_file({foo,bar}), - ?line check_pps(P0), + {error, {invalid_type_code,Fname}} = dets:open_file(Fname), + truncate(Fname, HeadSize - 10), + {error, {tooshort,Fname}} = dets:open_file(Fname), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = dets:close(TabRef), + file:delete(Fname), + + {error,{file_error,{foo,bar},_}} = dets:is_dets_file({foo,bar}), + check_pps(P0), ok. init_table_v8(doc) -> @@ -799,16 +796,16 @@ init_table_v9(Config) when is_list(Config) -> %% Objects are returned in "time order". T = init_table_v9, Fname = filename(T, Config), - ?line file:delete(Fname), + file:delete(Fname), L = [{1,a},{2,b},{1,c},{2,c},{1,c},{2,a},{1,b}], Input = init([L]), - ?line {ok, _} = dets:open_file(T, [{file,Fname},{version,9}, + {ok, _} = dets:open_file(T, [{file,Fname},{version,9}, {type,duplicate_bag}]), - ?line ok = dets:init_table(T, Input), - ?line [{1,a},{1,c},{1,c},{1,b}] = dets:lookup(T, 1), - ?line [{2,b},{2,c},{2,a}] = dets:lookup(T, 2), - ?line ok = dets:close(T), - ?line file:delete(Fname), + ok = dets:init_table(T, Input), + [{1,a},{1,c},{1,c},{1,b}] = dets:lookup(T, 1), + [{2,b},{2,c},{2,a}] = dets:lookup(T, 2), + ok = dets:close(T), + file:delete(Fname), init_table(Config, 9), fast_init_table(Config). @@ -816,57 +813,57 @@ init_table_v9(Config) when is_list(Config) -> init_table(Config, V) -> TabRef = init_table_test, Fname = filename(TabRef, Config), - ?line file:delete(Fname), + file:delete(Fname), P0 = pps(), Args = [{file,Fname},{version,V},{auto_save,120000}], - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', _} = + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', _} = (catch dets:init_table(TabRef, fun(foo) -> bar end)), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', _} = (catch dets:init_table(TabRef, fun() -> foo end)), + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', _} = (catch dets:init_table(TabRef, fun() -> foo end)), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', {badarg, _}} = (catch dets:init_table(TabRef, nofun)), - ?line {'EXIT', {badarg, _}} = + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', {badarg, _}} = (catch dets:init_table(TabRef, nofun)), + {'EXIT', {badarg, _}} = (catch dets:init_table(TabRef, fun(_X) -> end_of_input end, [{foo,bar}])), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line away = (catch dets:init_table(TabRef, fun(_) -> throw(away) end)), + {ok, _} = dets:open_file(TabRef, Args), + away = (catch dets:init_table(TabRef, fun(_) -> throw(away) end)), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {error, {init_fun, fopp}} = + {ok, _} = dets:open_file(TabRef, Args), + {error, {init_fun, fopp}} = dets:init_table(TabRef, fun(read) -> fopp end), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line dets:safe_fixtable(TabRef, true), - ?line {error, {fixed_table, TabRef}} = dets:init_table(TabRef, init([])), - ?line dets:safe_fixtable(TabRef, false), - ?line ET = ets:new(foo,[]), - ?line ok = dets:from_ets(TabRef, ET), - ?line [] = get_all_objects(TabRef), - ?line [] = get_all_objects_fast(TabRef), - ?line true = ets:insert(ET, {1,a}), - ?line true = ets:insert(ET, {2,b}), - ?line ok = dets:from_ets(TabRef, ET), - ?line [{1,a},{2,b}] = sort(get_all_objects(TabRef)), - ?line [{1,a},{2,b}] = sort(get_all_objects_fast(TabRef)), - ?line true = ets:delete(ET), - ?line 120000 = dets:info(TabRef, auto_save), - ?line ok = dets:close(TabRef), - - ?line {ok, _} = dets:open_file(TabRef, [{access,read} | Args]), - ?line {error, {access_mode, Fname}} = dets:init_table(TabRef, init([])), - ?line ok = dets:close(TabRef), - - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {error, invalid_objects_list} = + {ok, _} = dets:open_file(TabRef, Args), + dets:safe_fixtable(TabRef, true), + {error, {fixed_table, TabRef}} = dets:init_table(TabRef, init([])), + dets:safe_fixtable(TabRef, false), + ET = ets:new(foo,[]), + ok = dets:from_ets(TabRef, ET), + [] = get_all_objects(TabRef), + [] = get_all_objects_fast(TabRef), + true = ets:insert(ET, {1,a}), + true = ets:insert(ET, {2,b}), + ok = dets:from_ets(TabRef, ET), + [{1,a},{2,b}] = sort(get_all_objects(TabRef)), + [{1,a},{2,b}] = sort(get_all_objects_fast(TabRef)), + true = ets:delete(ET), + 120000 = dets:info(TabRef, auto_save), + ok = dets:close(TabRef), + + {ok, _} = dets:open_file(TabRef, [{access,read} | Args]), + {error, {access_mode, Fname}} = dets:init_table(TabRef, init([])), + ok = dets:close(TabRef), + + {ok, _} = dets:open_file(TabRef, Args), + {error, invalid_objects_list} = (catch dets:init_table(TabRef, init([[{1,2},bad,{3,4}]]))), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), L1 = [[{1,a},{2,b}],[],[{3,c}],[{4,d}],[]], bulk_init(L1, set, 4, Config, V), @@ -879,28 +876,28 @@ init_table(Config, V) -> file:delete(Fname), %% Initiate a file that contains a lot of objects. - ?line {ok, _} = dets:open_file(TabRef, [{min_no_slots,10000} | Args]), - ?line ok = ins(TabRef, 6000), + {ok, _} = dets:open_file(TabRef, [{min_no_slots,10000} | Args]), + ok = ins(TabRef, 6000), Fun = init_fun(0, 10000), - ?line ok = dets:init_table(TabRef, Fun,{format,term}), - ?line All = sort(get_all_objects(TabRef)), - ?line FAll = get_all_objects_fast(TabRef), - ?line true = All =:= sort(FAll), - ?line true = length(All) =:= 10000, - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), - - ?line {ok, _} = dets:open_file(TabRef, [{min_no_slots,4000} | Args]), - ?line ok = ins(TabRef, 6000), - ?line FileSize1 = dets:info(TabRef, file_size), + ok = dets:init_table(TabRef, Fun,{format,term}), + All = sort(get_all_objects(TabRef)), + FAll = get_all_objects_fast(TabRef), + true = All =:= sort(FAll), + true = length(All) =:= 10000, + ok = dets:close(TabRef), + file:delete(Fname), + + {ok, _} = dets:open_file(TabRef, [{min_no_slots,4000} | Args]), + ok = ins(TabRef, 6000), + FileSize1 = dets:info(TabRef, file_size), Fun2 = init_fun(0, 4000), - ?line ok = dets:init_table(TabRef, Fun2), - ?line FileSize2 = dets:info(TabRef, file_size), - ?line ok = dets:close(TabRef), - ?line true = FileSize1 > FileSize2, - ?line file:delete(Fname), + ok = dets:init_table(TabRef, Fun2), + FileSize2 = dets:info(TabRef, file_size), + ok = dets:close(TabRef), + true = FileSize1 > FileSize2, + file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. bulk_init(Ls, Type, N, Config, V) -> @@ -909,26 +906,26 @@ bulk_init(Ls, Type, N, Config, V) -> bulk_init(Ls, Type, N, Est, Config, V) -> T = init_table_test, Fname = filename(T, Config), - ?line file:delete(Fname), + file:delete(Fname), Input = init(Ls), Args = [{ram_file,false}, {type,Type},{keypos,1},{file,Fname}, {estimated_no_objects, Est},{version,V}], - ?line {ok, T} = dets:open_file(T, Args), - ?line ok = dets:init_table(T, Input), - ?line All = sort(get_all_objects(T)), - ?line FAll = get_all_objects_fast(T), - ?line true = All =:= sort(FAll), - ?line true = length(All) =:= N, - ?line true = dets:info(T, size) =:= N, - ?line ok = dets:close(T), + {ok, T} = dets:open_file(T, Args), + ok = dets:init_table(T, Input), + All = sort(get_all_objects(T)), + FAll = get_all_objects_fast(T), + true = All =:= sort(FAll), + true = length(All) =:= N, + true = dets:info(T, size) =:= N, + ok = dets:close(T), - ?line {ok, T} = dets:open_file(T, Args), - ?line All2 = sort(get_all_objects(T)), - ?line FAll2 = get_all_objects_fast(T), - ?line true = All =:= All2, - ?line true = All =:= sort(FAll2), - ?line ok = dets:close(T), - ?line file:delete(Fname). + {ok, T} = dets:open_file(T, Args), + All2 = sort(get_all_objects(T)), + FAll2 = get_all_objects_fast(T), + true = All =:= All2, + true = All =:= sort(FAll2), + ok = dets:close(T), + file:delete(Fname). init(L) -> fun(close) -> @@ -954,130 +951,130 @@ fast_init_table(Config) -> V = 9, TabRef = init_table_test, Fname = filename(TabRef, Config), - ?line file:delete(Fname), + file:delete(Fname), P0 = pps(), Args = [{file,Fname},{version,V},{auto_save,120000}], Source = init_table_test_source, SourceFname = filename(Source, Config), - ?line file:delete(SourceFname), + file:delete(SourceFname), SourceArgs = [{file,SourceFname},{version,V},{auto_save,120000}], - ?line {ok, Source} = dets:open_file(Source, SourceArgs), + {ok, Source} = dets:open_file(Source, SourceArgs), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', _} = + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', _} = (catch dets:init_table(TabRef, fun(foo) -> bar end, {format,bchunk})), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', _} = (catch dets:init_table(TabRef, fun() -> foo end, + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', _} = (catch dets:init_table(TabRef, fun() -> foo end, {format,bchunk})), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', {badarg, _}} = + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', {badarg, _}} = (catch dets:init_table(TabRef, nofun, {format,bchunk})), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line away = (catch dets:init_table(TabRef, fun(_) -> throw(away) end, + {ok, _} = dets:open_file(TabRef, Args), + away = (catch dets:init_table(TabRef, fun(_) -> throw(away) end, {format,bchunk})), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {error, {init_fun, fopp}} = + {ok, _} = dets:open_file(TabRef, Args), + {error, {init_fun, fopp}} = dets:init_table(TabRef, fun(read) -> fopp end, {format,bchunk}), dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line dets:safe_fixtable(TabRef, true), - ?line {error, {fixed_table, TabRef}} = + {ok, _} = dets:open_file(TabRef, Args), + dets:safe_fixtable(TabRef, true), + {error, {fixed_table, TabRef}} = dets:init_table(TabRef, init([]), {format,bchunk}), - ?line dets:safe_fixtable(TabRef, false), - ?line ok = dets:close(TabRef), + dets:safe_fixtable(TabRef, false), + ok = dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, [{access,read} | Args]), - ?line {error, {access_mode, Fname}} = + {ok, _} = dets:open_file(TabRef, [{access,read} | Args]), + {error, {access_mode, Fname}} = dets:init_table(TabRef, init([]), {format,bchunk}), - ?line ok = dets:close(TabRef), + ok = dets:close(TabRef), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {error, {init_fun,{1,2}}} = + {ok, _} = dets:open_file(TabRef, Args), + {error, {init_fun,{1,2}}} = dets:init_table(TabRef, init([[{1,2},bad,{3,4}]]), {format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {error, {init_fun, end_of_input}} = + {ok, _} = dets:open_file(TabRef, Args), + {error, {init_fun, end_of_input}} = dets:init_table(TabRef, init([]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line {'EXIT', {badarg, _}} = + {ok, _} = dets:open_file(TabRef, Args), + {'EXIT', {badarg, _}} = (catch dets:init_table(TabRef, init([]),{format,foppla})), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line ok = ins(TabRef, 100), + {ok, _} = dets:open_file(TabRef, Args), + ok = ins(TabRef, 100), - ?line [BParms | Objs] = collect_bchunk(TabRef, init_bchunk(TabRef)), - ?line Parms = binary_to_term(BParms), - ?line {error, {init_fun, <<"foobar">>}} = + [BParms | Objs] = collect_bchunk(TabRef, init_bchunk(TabRef)), + Parms = binary_to_term(BParms), + {error, {init_fun, <<"foobar">>}} = dets:init_table(TabRef, init([[<<"foobar">>]]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line Parms1 = setelement(1, Parms, foobar), + {ok, _} = dets:open_file(TabRef, Args), + Parms1 = setelement(1, Parms, foobar), BParms1 = term_to_binary(Parms1), - ?line {error, {init_fun, BParms1}} = + {error, {init_fun, BParms1}} = dets:init_table(TabRef, init([[BParms1 | Objs]]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), + {ok, _} = dets:open_file(TabRef, Args), [{Sz1,No1} | NoColls17] = element(tuple_size(Parms), Parms), Parms2 = setelement(tuple_size(Parms), Parms, [{Sz1,No1+1} | NoColls17]), BParms2 = term_to_binary(Parms2), - ?line {error, invalid_objects_list} = + {error, invalid_objects_list} = dets:init_table(TabRef, init([[BParms2 | Objs]]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line [{LSize1,Slot1,Obj1} | ObjsRest] = Objs, + {ok, _} = dets:open_file(TabRef, Args), + [{LSize1,Slot1,Obj1} | ObjsRest] = Objs, - ?line BadSize = byte_size(Obj1)-1, - ?line <<BadSizeObj:BadSize/binary,_:1/binary>> = Obj1, - ?line BadObjs = [{LSize1,Slot1,BadSizeObj} | ObjsRest], - ?line {error, invalid_objects_list} = + BadSize = byte_size(Obj1)-1, + <<BadSizeObj:BadSize/binary,_:1/binary>> = Obj1, + BadObjs = [{LSize1,Slot1,BadSizeObj} | ObjsRest], + {error, invalid_objects_list} = dets:init_table(TabRef, init([[BParms | BadObjs]]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), - - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line <<Size:32,BigObj0/binary>> = list_to_binary(lists:duplicate(16,Obj1)), - ?line BigObj = <<(Size*16):32,BigObj0/binary>>, - ?line BadColl = [BParms, {LSize1+4,Slot1,BigObj} | ObjsRest], - ?line {error, invalid_objects_list} = + _ = dets:close(TabRef), + file:delete(Fname), + + {ok, _} = dets:open_file(TabRef, Args), + <<Size:32,BigObj0/binary>> = list_to_binary(lists:duplicate(16,Obj1)), + BigObj = <<(Size*16):32,BigObj0/binary>>, + BadColl = [BParms, {LSize1+4,Slot1,BigObj} | ObjsRest], + {error, invalid_objects_list} = dets:init_table(TabRef, init([BadColl]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, Args), + {ok, _} = dets:open_file(TabRef, Args), BadObj = <<"foobar">>, - ?line {error, invalid_objects_list} = + {error, invalid_objects_list} = dets:init_table(TabRef, init([[BParms, BadObj]]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line {ok, _} = dets:open_file(TabRef, [{type,bag} | Args]), - ?line {error, {init_fun, _}} = + {ok, _} = dets:open_file(TabRef, [{type,bag} | Args]), + {error, {init_fun, _}} = dets:init_table(TabRef, init([[BParms]]),{format,bchunk}), - ?line _ = dets:close(TabRef), - ?line file:delete(Fname), + _ = dets:close(TabRef), + file:delete(Fname), - ?line ok = dets:close(Source), - ?line file:delete(SourceFname), + ok = dets:close(Source), + file:delete(SourceFname), L1 = [{1,a},{2,b},{3,c},{4,d}], fast_bulk_init(L1, set, 4, 4, Config, V), @@ -1090,91 +1087,91 @@ fast_init_table(Config) -> file:delete(Fname), %% Initiate a file that contains a lot of objects. - ?line {ok, _} = dets:open_file(Source, [{min_no_slots,10000} | SourceArgs]), + {ok, _} = dets:open_file(Source, [{min_no_slots,10000} | SourceArgs]), Fun1 = init_fun(0, 10000), - ?line ok = dets:init_table(Source, Fun1, {format,term}), + ok = dets:init_table(Source, Fun1, {format,term}), - ?line {ok, _} = dets:open_file(TabRef, [{min_no_slots,10000} | Args]), - ?line ok = ins(TabRef, 6000), + {ok, _} = dets:open_file(TabRef, [{min_no_slots,10000} | Args]), + ok = ins(TabRef, 6000), Fun2 = init_bchunk(Source), - ?line true = + true = dets:is_compatible_bchunk_format(TabRef, dets:info(Source, bchunk_format)), - ?line false = dets:is_compatible_bchunk_format(TabRef, <<"foobar">>), - ?line ok = dets:init_table(TabRef, Fun2, {format, bchunk}), - ?line ok = dets:close(Source), - ?line file:delete(SourceFname), - ?line All = sort(get_all_objects(TabRef)), - ?line FAll = get_all_objects_fast(TabRef), - ?line true = All =:= sort(FAll), - ?line true = length(All) =:= 10000, - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + false = dets:is_compatible_bchunk_format(TabRef, <<"foobar">>), + ok = dets:init_table(TabRef, Fun2, {format, bchunk}), + ok = dets:close(Source), + file:delete(SourceFname), + All = sort(get_all_objects(TabRef)), + FAll = get_all_objects_fast(TabRef), + true = All =:= sort(FAll), + true = length(All) =:= 10000, + ok = dets:close(TabRef), + file:delete(Fname), %% Initiate inserts fewer objects than the table contains. - ?line {ok, _} = dets:open_file(Source, [{min_no_slots,1000} | SourceArgs]), - ?line ok = ins(Source, 4000), + {ok, _} = dets:open_file(Source, [{min_no_slots,1000} | SourceArgs]), + ok = ins(Source, 4000), - ?line {ok, _} = dets:open_file(TabRef, [{min_no_slots,1000} | Args]), - ?line ok = ins(TabRef, 6000), - ?line FileSize1 = dets:info(TabRef, file_size), + {ok, _} = dets:open_file(TabRef, [{min_no_slots,1000} | Args]), + ok = ins(TabRef, 6000), + FileSize1 = dets:info(TabRef, file_size), Fun4 = init_bchunk(Source), - ?line ok = dets:init_table(TabRef, Fun4, {format, bchunk}), - ?line ok = dets:close(Source), - ?line file:delete(SourceFname), - ?line FileSize2 = dets:info(TabRef, file_size), - ?line All_2 = sort(get_all_objects(TabRef)), - ?line FAll_2 = get_all_objects_fast(TabRef), - ?line true = All_2 =:= sort(FAll_2), - ?line true = length(All_2) =:= 4000, - ?line ok = dets:close(TabRef), - ?line true = FileSize1 > FileSize2, + ok = dets:init_table(TabRef, Fun4, {format, bchunk}), + ok = dets:close(Source), + file:delete(SourceFname), + FileSize2 = dets:info(TabRef, file_size), + All_2 = sort(get_all_objects(TabRef)), + FAll_2 = get_all_objects_fast(TabRef), + true = All_2 =:= sort(FAll_2), + true = length(All_2) =:= 4000, + ok = dets:close(TabRef), + true = FileSize1 > FileSize2, %% Bchunk and fixed table. - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line NoItems = dets:info(TabRef, no_objects), - ?line AllObjects1 = sort(get_all_objects_fast(TabRef)), - ?line dets:safe_fixtable(TabRef, true), - ?line true = dets:info(TabRef, fixed), - ?line Cont1 = init_bchunk(TabRef), - ?line NoDel = + {ok, _} = dets:open_file(TabRef, Args), + NoItems = dets:info(TabRef, no_objects), + AllObjects1 = sort(get_all_objects_fast(TabRef)), + dets:safe_fixtable(TabRef, true), + true = dets:info(TabRef, fixed), + Cont1 = init_bchunk(TabRef), + NoDel = dets:select_delete(TabRef, [{{'_',{item,'_','_'}},[],[true]}]), - ?line true = (NoDel > 0), - ?line AllObjects2 = sort(get_all_objects_fast(TabRef)), - ?line true = dets:info(TabRef, fixed), - ?line Cont2 = init_bchunk(TabRef), - ?line NoItems2 = dets:info(TabRef, no_objects), - ?line true = (NoItems =:= NoItems2 + NoDel), - ?line NoDel2 = dets:select_delete(TabRef, [{'_',[],[true]}]), - ?line true = (NoDel2 > 0), - ?line AllObjects3 = sort(get_all_objects_fast(TabRef)), - ?line NoItems3 = dets:info(TabRef, no_objects), - ?line true = (NoItems3 =:= 0), - ?line true = dets:info(TabRef, fixed), - ?line true = (NoItems2 =:= NoItems3 + NoDel2), - ?line Cont3 = init_bchunk(TabRef), - - ?line BinColl1 = collect_bchunk(TabRef, Cont1), - ?line BinColl2 = collect_bchunk(TabRef, Cont2), - ?line BinColl3 = collect_bchunk(TabRef, Cont3), - ?line dets:safe_fixtable(TabRef, false), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + true = (NoDel > 0), + AllObjects2 = sort(get_all_objects_fast(TabRef)), + true = dets:info(TabRef, fixed), + Cont2 = init_bchunk(TabRef), + NoItems2 = dets:info(TabRef, no_objects), + true = (NoItems =:= NoItems2 + NoDel), + NoDel2 = dets:select_delete(TabRef, [{'_',[],[true]}]), + true = (NoDel2 > 0), + AllObjects3 = sort(get_all_objects_fast(TabRef)), + NoItems3 = dets:info(TabRef, no_objects), + true = (NoItems3 =:= 0), + true = dets:info(TabRef, fixed), + true = (NoItems2 =:= NoItems3 + NoDel2), + Cont3 = init_bchunk(TabRef), + + BinColl1 = collect_bchunk(TabRef, Cont1), + BinColl2 = collect_bchunk(TabRef, Cont2), + BinColl3 = collect_bchunk(TabRef, Cont3), + dets:safe_fixtable(TabRef, false), + ok = dets:close(TabRef), + file:delete(Fname), %% Now check that the above collected binaries are correct. - ?line {ok, _} = dets:open_file(TabRef, Args), - ?line ok = dets:init_table(TabRef, init([BinColl1]),{format,bchunk}), - ?line true = (AllObjects1 =:= sort(get_all_objects_fast(TabRef))), - ?line true = (length(AllObjects1) =:= dets:info(TabRef, no_objects)), - ?line ok = dets:init_table(TabRef, init([BinColl2]),{format,bchunk}), - ?line true = (AllObjects2 =:= sort(get_all_objects_fast(TabRef))), - ?line true = (length(AllObjects2) =:= dets:info(TabRef, no_objects)), - ?line ok = dets:init_table(TabRef, init([BinColl3]),{format,bchunk}), - ?line true = (AllObjects3 =:= sort(get_all_objects_fast(TabRef))), - ?line true = (length(AllObjects3) =:= dets:info(TabRef, no_objects)), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), - ?line check_pps(P0), + {ok, _} = dets:open_file(TabRef, Args), + ok = dets:init_table(TabRef, init([BinColl1]),{format,bchunk}), + true = (AllObjects1 =:= sort(get_all_objects_fast(TabRef))), + true = (length(AllObjects1) =:= dets:info(TabRef, no_objects)), + ok = dets:init_table(TabRef, init([BinColl2]),{format,bchunk}), + true = (AllObjects2 =:= sort(get_all_objects_fast(TabRef))), + true = (length(AllObjects2) =:= dets:info(TabRef, no_objects)), + ok = dets:init_table(TabRef, init([BinColl3]),{format,bchunk}), + true = (AllObjects3 =:= sort(get_all_objects_fast(TabRef))), + true = (length(AllObjects3) =:= dets:info(TabRef, no_objects)), + ok = dets:close(TabRef), + file:delete(Fname), + check_pps(P0), ok. fast_bulk_init(L, Type, N, NoKeys, Config, V) -> @@ -1183,40 +1180,40 @@ fast_bulk_init(L, Type, N, NoKeys, Config, V) -> fast_bulk_init(L, Type, N, NoKeys, Est, Config, V) -> T = init_table_test, Fname = filename(T, Config), - ?line file:delete(Fname), + file:delete(Fname), Args0 = [{ram_file,false}, {type,Type},{keypos,1}, {estimated_no_objects, Est},{version,V}], Args = [{file,Fname} | Args0], S = init_table_test_source, SFname = filename(S, Config), - ?line file:delete(SFname), + file:delete(SFname), SArgs = [{file,SFname} | Args0], - ?line {ok, S} = dets:open_file(S, SArgs), - ?line ok = dets:insert(S, L), + {ok, S} = dets:open_file(S, SArgs), + ok = dets:insert(S, L), Input = init_bchunk(S), - ?line {ok, T} = dets:open_file(T, Args), - ?line ok = dets:init_table(T, Input, [{format,bchunk}]), - ?line All = sort(get_all_objects(T)), - ?line FAll = get_all_objects_fast(T), - ?line true = All =:= sort(FAll), - ?line true = length(All) =:= N, - ?line true = dets:info(T, size) =:= N, - ?line true = dets:info(T, no_keys) =:= NoKeys, - ?line ok = dets:close(T), + {ok, T} = dets:open_file(T, Args), + ok = dets:init_table(T, Input, [{format,bchunk}]), + All = sort(get_all_objects(T)), + FAll = get_all_objects_fast(T), + true = All =:= sort(FAll), + true = length(All) =:= N, + true = dets:info(T, size) =:= N, + true = dets:info(T, no_keys) =:= NoKeys, + ok = dets:close(T), - ?line {ok, T} = dets:open_file(T, Args), - ?line All2 = sort(get_all_objects(T)), - ?line FAll2 = get_all_objects_fast(T), - ?line true = All =:= All2, - ?line true = All =:= sort(FAll2), - ?line ok = dets:close(T), - ?line file:delete(Fname), - - ?line ok = dets:close(S), - ?line file:delete(SFname), + {ok, T} = dets:open_file(T, Args), + All2 = sort(get_all_objects(T)), + FAll2 = get_all_objects_fast(T), + true = All =:= All2, + true = All =:= sort(FAll2), + ok = dets:close(T), + file:delete(Fname), + + ok = dets:close(S), + file:delete(SFname), ok. init_bchunk(T) -> @@ -1268,94 +1265,94 @@ repair_v9(Config) when is_list(Config) -> %% Convert from format 9 to format 8. T = convert_98, Fname = filename(T, Config), - ?line file:delete(Fname), - ?line {ok, _} = dets:open_file(T, [{file,Fname},{version,9}, + file:delete(Fname), + {ok, _} = dets:open_file(T, [{file,Fname},{version,9}, {type,duplicate_bag}]), - ?line 9 = dets:info(T, version), - ?line true = is_binary(dets:info(T, bchunk_format)), - ?line ok = dets:insert(T, [{1,a},{2,b},{1,c},{2,c},{1,c},{2,a},{1,b}]), - ?line dets:close(T), - ?line {error, {version_mismatch, _}} = + 9 = dets:info(T, version), + true = is_binary(dets:info(T, bchunk_format)), + ok = dets:insert(T, [{1,a},{2,b},{1,c},{2,c},{1,c},{2,a},{1,b}]), + dets:close(T), + {error, {version_mismatch, _}} = dets:open_file(T, [{file,Fname},{version,8},{type,duplicate_bag}]), - ?line {ok, _} = dets:open_file(T, [{file,Fname},{version,8}, + {ok, _} = dets:open_file(T, [{file,Fname},{version,8}, {type,duplicate_bag},{repair,force}]), - ?line 8 = dets:info(T, version), - ?line true = undefined =:= dets:info(T, bchunk_format), - ?line [{1,a},{1,b},{1,c},{1,c}] = sort(dets:lookup(T, 1)), - ?line [{2,a},{2,b},{2,c}] = sort(dets:lookup(T, 2)), - ?line 7 = dets:info(T, no_objects), - ?line no_keys_test(T), - ?line _ = histogram(T, silent), - ?line ok = dets:close(T), - ?line file:delete(Fname), + 8 = dets:info(T, version), + true = undefined =:= dets:info(T, bchunk_format), + [{1,a},{1,b},{1,c},{1,c}] = sort(dets:lookup(T, 1)), + [{2,a},{2,b},{2,c}] = sort(dets:lookup(T, 2)), + 7 = dets:info(T, no_objects), + no_keys_test(T), + _ = histogram(T, silent), + ok = dets:close(T), + file:delete(Fname), %% The short lived format 9(a). %% Not very throughly tested here. A9 = a9, - ?line Version9aS = filename:join(?datadir(Config), "version_9a.dets"), - ?line Version9aT = filename('v9a.dets', Config), - ?line {ok, _} = file:copy(Version9aS, Version9aT), - ?line {ok, A9} = dets:open_file(A9, [{file,Version9aT}]), - ?line undefined = dets:info(A9, bchunk_format), - ?line [{1,a},{2,b},{3,c}] = sort(dets:match_object(A9, '_')), - ?line ok = dets:insert(A9, {4,d}), - ?line ok = dets:close(A9), - ?line {ok, A9} = dets:open_file(A9, [{file,Version9aT}]), - ?line {error, old_version} = dets:bchunk(A9, start), - ?line ok = dets:close(A9), - ?line io:format("Expect forced repair:~n"), - ?line {ok, A9} = dets:open_file(A9, [{file,Version9aT},{repair,force}]), - ?line {_, _} = dets:bchunk(A9, start), - ?line ok = dets:close(A9), - ?line file:delete(Version9aT), + Version9aS = filename:join(?datadir(Config), "version_9a.dets"), + Version9aT = filename('v9a.dets', Config), + {ok, _} = file:copy(Version9aS, Version9aT), + {ok, A9} = dets:open_file(A9, [{file,Version9aT}]), + undefined = dets:info(A9, bchunk_format), + [{1,a},{2,b},{3,c}] = sort(dets:match_object(A9, '_')), + ok = dets:insert(A9, {4,d}), + ok = dets:close(A9), + {ok, A9} = dets:open_file(A9, [{file,Version9aT}]), + {error, old_version} = dets:bchunk(A9, start), + ok = dets:close(A9), + io:format("Expect forced repair:~n"), + {ok, A9} = dets:open_file(A9, [{file,Version9aT},{repair,force}]), + {_, _} = dets:bchunk(A9, start), + ok = dets:close(A9), + file:delete(Version9aT), repair(Config, 9). repair(Config, V) -> TabRef = repair_test, Fname = filename(TabRef, Config), - ?line file:delete(Fname), + file:delete(Fname), HeadSize = headsz(V), P0 = pps(), - ?line {'EXIT', {badarg, _}} = + {'EXIT', {badarg, _}} = (catch dets:open_file(TabRef, [{min_no_slots,1000}, {max_no_slots,500}])), - ?line {error,{file_error,hoppla,enoent}} = dets:file_info(hoppla), - ?line {error,{file_error,Fname,enoent}} = + {error,{file_error,hoppla,enoent}} = dets:file_info(hoppla), + {error,{file_error,Fname,enoent}} = dets:open_file(TabRef, [{file, Fname}, {access, read}]), %% compacting, and some kind of test that free lists are saved OK on file - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line 0 = dets:info(TabRef, size), - ?line ok = ins(TabRef, 30000), - ?line ok = del(TabRef, 30000, 3), - ?line ok = dets:close(TabRef), - ?line {error, {access_mode,Fname}} = + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + 0 = dets:info(TabRef, size), + ok = ins(TabRef, 30000), + ok = del(TabRef, 30000, 3), + ok = dets:close(TabRef), + {error, {access_mode,Fname}} = dets:open_file(foo, [{file,Fname},{repair,force},{access,read}]), - ?line {ok, Ref3} = dets:open_file(Fname), % no repair! - ?line 20000 = dets:info(Ref3, size), - ?line 20000 = dets:foldl(fun(_, N) -> N+1 end, 0, Ref3), - ?line 20000 = count_objects_quite_fast(Ref3), % actually a test of match - ?line no_keys_test(Ref3), - ?line ok = dets:close(Ref3), + {ok, Ref3} = dets:open_file(Fname), % no repair! + 20000 = dets:info(Ref3, size), + 20000 = dets:foldl(fun(_, N) -> N+1 end, 0, Ref3), + 20000 = count_objects_quite_fast(Ref3), % actually a test of match + no_keys_test(Ref3), + ok = dets:close(Ref3), if V =:= 8 -> - ?line {ok, TabRef} = dets:open_file(TabRef, + {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V},{access,read}]), - ?line ok = dets:close(TabRef), - ?line io:format("Expect compacting repair:~n"), - ?line {ok, TabRef} = dets:open_file(TabRef, + ok = dets:close(TabRef), + io:format("Expect compacting repair:~n"), + {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), - ?line 20000 = dets:info(TabRef, size), - ?line _ = histogram(TabRef, silent), - ?line ok = dets:close(TabRef); + 20000 = dets:info(TabRef, size), + _ = histogram(TabRef, silent), + ok = dets:close(TabRef); true -> ok end, - ?line {error,{keypos_mismatch,Fname}} = + {error,{keypos_mismatch,Fname}} = dets:open_file(TabRef, [{file, Fname},{keypos,17}]), - ?line {error,{type_mismatch,Fname}} = + {error,{type_mismatch,Fname}} = dets:open_file(TabRef, [{file, Fname},{type,duplicate_bag}]), %% make one of the temporary files unwritable @@ -1364,257 +1361,257 @@ repair(Config, V) -> Fname ++ ".TMP.10000"; true -> Fname ++ ".TMP.1" end, - ?line file:delete(TmpFile), - ?line {ok, TmpFd} = file:open(TmpFile, [read,write]), - ?line ok = file:close(TmpFd), - ?line unwritable(TmpFile), - ?line {error,{file_error,TmpFile,eacces}} = dets:fsck(Fname, V), - ?line {ok, _} = dets:open_file(TabRef, - [{repair,false},{file, Fname},{version,V}]), - ?line 20000 = length(get_all_objects(TabRef)), - ?line _ = histogram(TabRef, silent), - ?line 20000 = length(get_all_objects_fast(TabRef)), - ?line ok = dets:close(TabRef), - ?line writable(TmpFile), - ?line file:delete(TmpFile), - - ?line truncate(Fname, HeadSize + 10), - ?line {error,{not_closed, Fname}} = + file:delete(TmpFile), + {ok, TmpFd} = file:open(TmpFile, [read,write]), + ok = file:close(TmpFd), + unwritable(TmpFile), + {error,{file_error,TmpFile,eacces}} = dets:fsck(Fname, V), + {ok, _} = dets:open_file(TabRef, + [{repair,false},{file, Fname},{version,V}]), + 20000 = length(get_all_objects(TabRef)), + _ = histogram(TabRef, silent), + 20000 = length(get_all_objects_fast(TabRef)), + ok = dets:close(TabRef), + writable(TmpFile), + file:delete(TmpFile), + + truncate(Fname, HeadSize + 10), + {error,{not_closed, Fname}} = dets:open_file(TabRef, [{file, Fname}, {access, read}]), - ?line {error,{not_closed, Fname}} = + {error,{not_closed, Fname}} = dets:open_file(TabRef, [{file, Fname}, {access, read}, {repair,force}]), - ?line {error,{needs_repair, Fname}} = + {error,{needs_repair, Fname}} = dets:open_file(TabRef, [{file, Fname}, {repair, false}]), - ?line file:delete(Fname), + file:delete(Fname), %% truncated file header - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = ins(TabRef, 100), - ?line ok = dets:close(TabRef), - ?line truncate(Fname, HeadSize - 10), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = ins(TabRef, 100), + ok = dets:close(TabRef), + truncate(Fname, HeadSize - 10), %% a new file is created ('tooshort') - ?line {ok, TabRef} = dets:open_file(TabRef, - [{file,Fname},{version,V}, - {min_no_slots,1000}, - {max_no_slots,1000000}]), + {ok, TabRef} = dets:open_file(TabRef, + [{file,Fname},{version,V}, + {min_no_slots,1000}, + {max_no_slots,1000000}]), case dets:info(TabRef, no_slots) of undefined -> ok; {Min1,Slot1,Max1} -> - ?line true = Min1 =< Slot1, true = Slot1 =< Max1, - ?line true = 1000 < Min1, true = 1000+256 > Min1, - ?line true = 1000000 < Max1, true = (1 bsl 20)+256 > Max1 + true = Min1 =< Slot1, true = Slot1 =< Max1, + true = 1000 < Min1, true = 1000+256 > Min1, + true = 1000000 < Max1, true = (1 bsl 20)+256 > Max1 end, - ?line 0 = dets:info(TabRef, size), - ?line no_keys_test(TabRef), - ?line _ = histogram(TabRef, silent), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + 0 = dets:info(TabRef, size), + no_keys_test(TabRef), + _ = histogram(TabRef, silent), + ok = dets:close(TabRef), + file:delete(Fname), %% version bump (v8) - ?line Version7S = filename:join(?datadir(Config), "version_r2d.dets"), - ?line Version7T = filename('v2.dets', Config), - ?line {ok, _} = file:copy(Version7S, Version7T), - ?line {error,{version_bump, Version7T}} = dets:open_file(Version7T), - ?line {error,{version_bump, Version7T}} = + Version7S = filename:join(?datadir(Config), "version_r2d.dets"), + Version7T = filename('v2.dets', Config), + {ok, _} = file:copy(Version7S, Version7T), + {error,{version_bump, Version7T}} = dets:open_file(Version7T), + {error,{version_bump, Version7T}} = dets:open_file(Version7T, [{file,Version7T},{repair,false}]), - ?line {error,{version_bump, Version7T}} = + {error,{version_bump, Version7T}} = dets:open_file(Version7T, [{file, Version7T}, {access, read}]), - ?line io:format("Expect upgrade:~n"), - ?line {ok, _} = dets:open_file(Version7T, + io:format("Expect upgrade:~n"), + {ok, _} = dets:open_file(Version7T, [{file, Version7T},{version, V}]), - ?line [{1,a},{2,b}] = sort(get_all_objects(Version7T)), - ?line [{1,a},{2,b}] = sort(get_all_objects_fast(Version7T)), + [{1,a},{2,b}] = sort(get_all_objects(Version7T)), + [{1,a},{2,b}] = sort(get_all_objects_fast(Version7T)), Phash = if V =:= 8 -> phash; true -> phash2 end, - ?line Phash = dets:info(Version7T, hash), - ?line _ = histogram(Version7T, silent), - ?line ok = dets:close(Version7T), - ?line {ok, _} = dets:open_file(Version7T, [{file, Version7T}]), - ?line Phash = dets:info(Version7T, hash), - ?line ok = dets:close(Version7T), - ?line file:delete(Version7T), + Phash = dets:info(Version7T, hash), + _ = histogram(Version7T, silent), + ok = dets:close(Version7T), + {ok, _} = dets:open_file(Version7T, [{file, Version7T}]), + Phash = dets:info(Version7T, hash), + ok = dets:close(Version7T), + file:delete(Version7T), %% converting free lists - ?line Version8aS = filename:join(?datadir(Config), "version_r3b02.dets"), - ?line Version8aT = filename('v3.dets', Config), - ?line {ok, _} = file:copy(Version8aS, Version8aT), + Version8aS = filename:join(?datadir(Config), "version_r3b02.dets"), + Version8aT = filename('v3.dets', Config), + {ok, _} = file:copy(Version8aS, Version8aT), %% min_no_slots and max_no_slots are ignored - no repair is taking place - ?line {ok, _} = dets:open_file(version_8a, + {ok, _} = dets:open_file(version_8a, [{file, Version8aT},{min_no_slots,1000}, {max_no_slots,100000}]), - ?line [{1,b},{2,a},{a,1},{b,2}] = sort(get_all_objects(version_8a)), - ?line [{1,b},{2,a},{a,1},{b,2}] = sort(get_all_objects_fast(version_8a)), - ?line ok = ins(version_8a, 1000), - ?line 1002 = dets:info(version_8a, size), - ?line no_keys_test(version_8a), - ?line All8a = sort(get_all_objects(version_8a)), - ?line 1002 = length(All8a), - ?line FAll8a = sort(get_all_objects_fast(version_8a)), - ?line true = sort(All8a) =:= sort(FAll8a), - ?line ok = del(version_8a, 300, 3), - ?line 902 = dets:info(version_8a, size), - ?line no_keys_test(version_8a), - ?line All8a2 = sort(get_all_objects(version_8a)), - ?line 902 = length(All8a2), - ?line FAll8a2 = sort(get_all_objects_fast(version_8a)), - ?line true = sort(All8a2) =:= sort(FAll8a2), - ?line _ = histogram(version_8a, silent), - ?line ok = dets:close(version_8a), - ?line file:delete(Version8aT), + [{1,b},{2,a},{a,1},{b,2}] = sort(get_all_objects(version_8a)), + [{1,b},{2,a},{a,1},{b,2}] = sort(get_all_objects_fast(version_8a)), + ok = ins(version_8a, 1000), + 1002 = dets:info(version_8a, size), + no_keys_test(version_8a), + All8a = sort(get_all_objects(version_8a)), + 1002 = length(All8a), + FAll8a = sort(get_all_objects_fast(version_8a)), + true = sort(All8a) =:= sort(FAll8a), + ok = del(version_8a, 300, 3), + 902 = dets:info(version_8a, size), + no_keys_test(version_8a), + All8a2 = sort(get_all_objects(version_8a)), + 902 = length(All8a2), + FAll8a2 = sort(get_all_objects_fast(version_8a)), + true = sort(All8a2) =:= sort(FAll8a2), + _ = histogram(version_8a, silent), + ok = dets:close(version_8a), + file:delete(Version8aT), %% will fail unless the slots are properly sorted when repairing (v8) BArgs = [{file, Fname},{type,duplicate_bag}, {delayed_write,{3000,10000}},{version,V}], - ?line {ok, TabRef} = dets:open_file(TabRef, BArgs), + {ok, TabRef} = dets:open_file(TabRef, BArgs), Seq = seq(1, 500), Small = map(fun(X) -> {X,X} end, Seq), Big = map(fun(X) -> erlang:make_tuple(20, X) end, Seq), - ?line ok = dets:insert(TabRef, Small), - ?line ok = dets:insert(TabRef, Big), - ?line ok = dets:insert(TabRef, Small), - ?line ok = dets:insert(TabRef, Big), - ?line All = sort(safe_get_all_objects(TabRef)), - ?line ok = dets:close(TabRef), - ?line io:format("Expect forced repair:~n"), - ?line {ok, _} = + ok = dets:insert(TabRef, Small), + ok = dets:insert(TabRef, Big), + ok = dets:insert(TabRef, Small), + ok = dets:insert(TabRef, Big), + All = sort(safe_get_all_objects(TabRef)), + ok = dets:close(TabRef), + io:format("Expect forced repair:~n"), + {ok, _} = dets:open_file(TabRef, [{repair,force},{min_no_slots,2000} | BArgs]), if V =:= 9 -> - ?line {MinNoSlots,_,MaxNoSlots} = dets:info(TabRef, no_slots), - ?line ok = dets:close(TabRef), - ?line io:format("Expect compaction:~n"), - ?line {ok, _} = + {MinNoSlots,_,MaxNoSlots} = dets:info(TabRef, no_slots), + ok = dets:close(TabRef), + io:format("Expect compaction:~n"), + {ok, _} = dets:open_file(TabRef, [{repair,force}, {min_no_slots,MinNoSlots}, {max_no_slots,MaxNoSlots} | BArgs]); true -> ok end, - ?line All2 = get_all_objects(TabRef), - ?line true = All =:= sort(All2), - ?line FAll2 = get_all_objects_fast(TabRef), - ?line true = All =:= sort(FAll2), - ?line true = length(All) =:= dets:info(TabRef, size), - ?line no_keys_test(TabRef), + All2 = get_all_objects(TabRef), + true = All =:= sort(All2), + FAll2 = get_all_objects_fast(TabRef), + true = All =:= sort(FAll2), + true = length(All) =:= dets:info(TabRef, size), + no_keys_test(TabRef), Fun = fun(X) -> 4 = length(dets:lookup(TabRef, X)) end, - ?line foreach(Fun, Seq), - ?line _ = histogram(TabRef, silent), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + foreach(Fun, Seq), + _ = histogram(TabRef, silent), + ok = dets:close(TabRef), + file:delete(Fname), %% object bigger than segments, the "hole" is taken care of - ?line {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), + {ok, TabRef} = dets:open_file(TabRef, [{file, Fname},{version,V}]), Tuple = erlang:make_tuple(1000, foobar), % > 2 kB - ?line ok = dets:insert(TabRef, Tuple), + ok = dets:insert(TabRef, Tuple), %% at least one full segment (objects smaller than 2 kB): - ?line ins(TabRef, 2000), - ?line ok = dets:close(TabRef), + ins(TabRef, 2000), + ok = dets:close(TabRef), if V =:= 8 -> %% first estimated number of objects is wrong, repair once more - ?line {ok, Fd} = file:open(Fname, [read,write]), + {ok, Fd} = file:open(Fname, [read,write]), NoPos = HeadSize - 8, % no_objects - ?line file:pwrite(Fd, NoPos, <<0:32>>), % NoItems + file:pwrite(Fd, NoPos, <<0:32>>), % NoItems ok = file:close(Fd), - ?line dets:fsck(Fname, V), - ?line {ok, _} = + dets:fsck(Fname, V), + {ok, _} = dets:open_file(TabRef, [{repair,false},{file, Fname},{version,V}]), - ?line 2001 = length(get_all_objects(TabRef)), - ?line _ = histogram(TabRef, silent), - ?line 2001 = length(get_all_objects_fast(TabRef)), - ?line ok = dets:close(TabRef); + 2001 = length(get_all_objects(TabRef)), + _ = histogram(TabRef, silent), + 2001 = length(get_all_objects_fast(TabRef)), + ok = dets:close(TabRef); true -> ok end, - ?line {ok, _} = + {ok, _} = dets:open_file(TabRef, [{repair,false},{file, Fname},{version,V}]), - ?line {ok, ObjPos} = dets:where(TabRef, {66,{item,number,66}}), - ?line ok = dets:close(TabRef), + {ok, ObjPos} = dets:where(TabRef, {66,{item,number,66}}), + ok = dets:close(TabRef), %% Damaged object. Pos = 12, % v9: compaction fails, proper repair follows crash(Fname, ObjPos+Pos), - ?line io:format( + io:format( "Expect forced repair (possibly after attempted compaction):~n"), - ?line {ok, _} = + {ok, _} = dets:open_file(TabRef, [{repair,force},{file, Fname},{version,V}]), - ?line true = dets:info(TabRef, size) < 2001, - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + true = dets:info(TabRef, size) < 2001, + ok = dets:close(TabRef), + file:delete(Fname), %% The file is smaller than the padded object. - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = dets:insert(TabRef, Tuple), - ?line ok = dets:close(TabRef), - ?line io:format("Expect forced repair or compaction:~n"), - ?line {ok, _} = + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = dets:insert(TabRef, Tuple), + ok = dets:close(TabRef), + io:format("Expect forced repair or compaction:~n"), + {ok, _} = dets:open_file(TabRef, [{repair,force},{file, Fname},{version,V}]), - ?line true = 1 =:= dets:info(TabRef, size), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + true = 1 =:= dets:info(TabRef, size), + ok = dets:close(TabRef), + file:delete(Fname), %% Damaged free lists. - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = ins(TabRef, 300), - ?line ok = dets:sync(TabRef), - ?line ok = del(TabRef, 300, 3), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = ins(TabRef, 300), + ok = dets:sync(TabRef), + ok = del(TabRef, 300, 3), %% FileSize is approximately where the free lists will be written. - ?line FileSize = dets:info(TabRef, memory), - ?line ok = dets:close(TabRef), + FileSize = dets:info(TabRef, memory), + ok = dets:close(TabRef), crash(Fname, FileSize+20), %% Used to return bad_freelists, but that changed in OTP-9622 - ?line {ok, TabRef} = + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + ok = dets:close(TabRef), + file:delete(Fname), %% File not closed, opening with read and read_write access tried. - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = ins(TabRef, 300), - ?line ok = dets:close(TabRef), - ?line crash(Fname, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), - ?line {error, {not_closed, Fname}} = + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = ins(TabRef, 300), + ok = dets:close(TabRef), + crash(Fname, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), + {error, {not_closed, Fname}} = dets:open_file(foo, [{file,Fname},{version,V},{repair,force}, {access,read}]), - ?line {error, {not_closed, Fname}} = + {error, {not_closed, Fname}} = dets:open_file(foo, [{file,Fname},{version,V},{repair,true}, {access,read}]), - ?line io:format("Expect repair:~n"), - ?line {ok, TabRef} = + io:format("Expect repair:~n"), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V},{repair,true}, {access,read_write}]), - ?line ok = dets:close(TabRef), - ?line crash(Fname, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), - ?line io:format("Expect forced repair:~n"), - ?line {ok, TabRef} = + ok = dets:close(TabRef), + crash(Fname, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), + io:format("Expect forced repair:~n"), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V},{repair,force}, {access,read_write}]), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + ok = dets:close(TabRef), + file:delete(Fname), %% The size of an object is huge. - ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), - ?line ok = dets:insert(TabRef, [{1,2,3},{2,3,4}]), - ?line {ok, ObjPos2} = dets:where(TabRef, {1,2,3}), - ?line ok = dets:close(TabRef), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ok = dets:insert(TabRef, [{1,2,3},{2,3,4}]), + {ok, ObjPos2} = dets:where(TabRef, {1,2,3}), + ok = dets:close(TabRef), ObjPos3 = if V =:= 8 -> ObjPos2 + 4; V =:= 9 -> ObjPos2 end, crash(Fname, ObjPos3, 255), - ?line io:format("Expect forced repair:~n"), - ?line {ok, TabRef} = + io:format("Expect forced repair:~n"), + {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V},{repair,force}]), - ?line ok = dets:close(TabRef), - ?line file:delete(Fname), + ok = dets:close(TabRef), + file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. hash_v8b_v8c(doc) -> @@ -1623,77 +1620,77 @@ hash_v8b_v8c(doc) -> hash_v8b_v8c(suite) -> []; hash_v8b_v8c(Config) when is_list(Config) -> - ?line Source = + Source = filename:join(?datadir(Config), "dets_test_v8b.dets"), %% Little endian version of old file (there is an endianess bug in %% the old hash). This is all about version 8 of the dets file format. P0 = pps(), - ?line SourceLE = + SourceLE = filename:join(?datadir(Config), "dets_test_v8b_little_endian.dets"), - ?line Target1 = filename('oldhash1.dets', Config), - ?line Target1LE = filename('oldhash1le.dets', Config), - ?line Target2 = filename('oldhash2.dets', Config), - ?line {ok, Bin} = file:read_file(Source), - ?line {ok, BinLE} = file:read_file(SourceLE), - ?line ok = file:write_file(Target1,Bin), - ?line ok = file:write_file(Target1LE,BinLE), - ?line ok = file:write_file(Target2,Bin), - ?line {ok, d1} = dets:open_file(d1,[{file,Target1}]), - ?line {ok, d1le} = dets:open_file(d1le,[{file,Target1LE}]), - ?line {ok, d2} = dets:open_file(d2,[{file,Target2},{repair,force}, + Target1 = filename('oldhash1.dets', Config), + Target1LE = filename('oldhash1le.dets', Config), + Target2 = filename('oldhash2.dets', Config), + {ok, Bin} = file:read_file(Source), + {ok, BinLE} = file:read_file(SourceLE), + ok = file:write_file(Target1,Bin), + ok = file:write_file(Target1LE,BinLE), + ok = file:write_file(Target2,Bin), + {ok, d1} = dets:open_file(d1,[{file,Target1}]), + {ok, d1le} = dets:open_file(d1le,[{file,Target1LE}]), + {ok, d2} = dets:open_file(d2,[{file,Target2},{repair,force}, {version,8}]), - ?line FF = fun(N,_F,_T) when N > 16#FFFFFFFFFFFFFFFF -> - ok; - (N,F,T) -> - V = integer_to_list(N), - case dets:lookup(T,N) of - [{N,V}] -> - F(N*2,F,T); - _Error -> - exit({failed,{lookup,T,N}}) - end - end, - ?line Mess = case (catch FF(1,FF,d1)) of - {'EXIT', {failed, {lookup,_,_}}} -> - ?line ok = dets:close(d1), - ?line FF(1,FF,d1le), - ?line hash = dets:info(d1le,hash), - ?line dets:insert(d1le,{33333333333,hejsan}), - ?line [{33333333333,hejsan}] = - dets:lookup(d1le,33333333333), - ?line ok = dets:close(d1le), - ?line {ok, d1le} = dets:open_file(d1le, - [{file,Target1LE}]), - ?line [{33333333333,hejsan}] = - dets:lookup(d1le,33333333333), - ?line FF(1,FF,d1le), - ?line ok = dets:close(d1le), - "Seems to be a little endian machine"; - {'EXIT', Fault} -> - exit(Fault); - _ -> - ?line ok = dets:close(d1le), - ?line hash = dets:info(d1,hash), - ?line dets:insert(d1,{33333333333,hejsan}), - ?line [{33333333333,hejsan}] = - dets:lookup(d1,33333333333), - ?line ok = dets:close(d1), - ?line {ok, d1} = dets:open_file(d1,[{file,Target1}]), - ?line [{33333333333,hejsan}] = - dets:lookup(d1,33333333333), - ?line FF(1,FF,d1), - ?line ok = dets:close(d1), - "Seems to be a big endian machine" - end, - ?line FF(1,FF,d2), - ?line phash = dets:info(d2,hash), - ?line ok = dets:close(d2), - ?line file:delete(Target1), - ?line file:delete(Target1LE), - ?line file:delete(Target2), - ?line check_pps(P0), + FF = fun(N,_F,_T) when N > 16#FFFFFFFFFFFFFFFF -> + ok; + (N,F,T) -> + V = integer_to_list(N), + case dets:lookup(T,N) of + [{N,V}] -> + F(N*2,F,T); + _Error -> + exit({failed,{lookup,T,N}}) + end + end, + Mess = case (catch FF(1,FF,d1)) of + {'EXIT', {failed, {lookup,_,_}}} -> + ok = dets:close(d1), + FF(1,FF,d1le), + hash = dets:info(d1le,hash), + dets:insert(d1le,{33333333333,hejsan}), + [{33333333333,hejsan}] = + dets:lookup(d1le,33333333333), + ok = dets:close(d1le), + {ok, d1le} = dets:open_file(d1le, + [{file,Target1LE}]), + [{33333333333,hejsan}] = + dets:lookup(d1le,33333333333), + FF(1,FF,d1le), + ok = dets:close(d1le), + "Seems to be a little endian machine"; + {'EXIT', Fault} -> + exit(Fault); + _ -> + ok = dets:close(d1le), + hash = dets:info(d1,hash), + dets:insert(d1,{33333333333,hejsan}), + [{33333333333,hejsan}] = + dets:lookup(d1,33333333333), + ok = dets:close(d1), + {ok, d1} = dets:open_file(d1,[{file,Target1}]), + [{33333333333,hejsan}] = + dets:lookup(d1,33333333333), + FF(1,FF,d1), + ok = dets:close(d1), + "Seems to be a big endian machine" + end, + FF(1,FF,d2), + phash = dets:info(d2,hash), + ok = dets:close(d2), + file:delete(Target1), + file:delete(Target1LE), + file:delete(Target2), + check_pps(P0), {comment, Mess}. phash(doc) -> @@ -1704,57 +1701,57 @@ phash(Config) when is_list(Config) -> T = phash, Phash_v9bS = filename:join(?datadir(Config), "version_9b_phash.dat"), Fname = filename('v9b.dets', Config), - ?line {ok, _} = file:copy(Phash_v9bS, Fname), + {ok, _} = file:copy(Phash_v9bS, Fname), %% Deleting all objects changes the hash function. %% A feature... (it's for free) - ?line {ok, T} = dets:open_file(T, [{file, Fname}]), - ?line phash = dets:info(T, hash), - ?line dets:delete_all_objects(T), - ?line phash2 = dets:info(T, hash), - ?line [] = get_all_objects(T), - ?line [] = get_all_objects_fast(T), - ?line ok = dets:close(T), + {ok, T} = dets:open_file(T, [{file, Fname}]), + phash = dets:info(T, hash), + dets:delete_all_objects(T), + phash2 = dets:info(T, hash), + [] = get_all_objects(T), + [] = get_all_objects_fast(T), + ok = dets:close(T), %% The hash function is kept when compacting a table. - ?line {ok, _} = file:copy(Phash_v9bS, Fname), - ?line io:format("Expect compaction:~n"), - ?line {ok, T} = dets:open_file(T, [{file, Fname},{repair,force}]), - ?line phash = dets:info(T, hash), - ?line [{1,a},{2,b},{3,c},{4,d},{5,e}] = + {ok, _} = file:copy(Phash_v9bS, Fname), + io:format("Expect compaction:~n"), + {ok, T} = dets:open_file(T, [{file, Fname},{repair,force}]), + phash = dets:info(T, hash), + [{1,a},{2,b},{3,c},{4,d},{5,e}] = lists:sort(dets:lookup_keys(T, [1,2,3,4,5])), - ?line ok = dets:close(T), + ok = dets:close(T), %% The hash function is updated when repairing a table (no cost). - ?line {ok, _} = file:copy(Phash_v9bS, Fname), + {ok, _} = file:copy(Phash_v9bS, Fname), crash(Fname, ?CLOSED_PROPERLY_POS+3, 0), - ?line io:format("Expect repair:~n"), - ?line {ok, T} = dets:open_file(T, [{file, Fname}]), - ?line phash2 = dets:info(T, hash), - ?line [{1,a},{2,b},{3,c},{4,d},{5,e}] = + io:format("Expect repair:~n"), + {ok, T} = dets:open_file(T, [{file, Fname}]), + phash2 = dets:info(T, hash), + [{1,a},{2,b},{3,c},{4,d},{5,e}] = lists:sort(dets:lookup_keys(T, [1,2,3,4,5])), - ?line ok = dets:close(T), + ok = dets:close(T), %% One cannot use the bchunk format when copying between a phash %% table and a phash2 table. (There is no test for the case an R9 %% (or later) node (using phash2) copies a table to an R8 node %% (using phash).) See also the comment on HASH_PARMS in dets_v9.erl. - ?line {ok, _} = file:copy(Phash_v9bS, Fname), - ?line {ok, T} = dets:open_file(T, [{file, Fname}]), - ?line Type = dets:info(T, type), - ?line KeyPos = dets:info(T, keypos), + {ok, _} = file:copy(Phash_v9bS, Fname), + {ok, T} = dets:open_file(T, [{file, Fname}]), + Type = dets:info(T, type), + KeyPos = dets:info(T, keypos), Input = init_bchunk(T), T2 = phash_table, Fname2 = filename(T2, Config), Args = [{type,Type},{keypos,KeyPos},{version,9},{file,Fname2}], - ?line {ok, T2} = dets:open_file(T2, Args), - ?line {error, {init_fun, _}} = + {ok, T2} = dets:open_file(T2, Args), + {error, {init_fun, _}} = dets:init_table(T2, Input, {format,bchunk}), - ?line _ = dets:close(T2), - ?line ok = dets:close(T), - ?line file:delete(Fname2), + _ = dets:close(T2), + ok = dets:close(T), + file:delete(Fname2), - ?line file:delete(Fname), + file:delete(Fname), ok. fold_v8(doc) -> @@ -1774,50 +1771,50 @@ fold_v9(Config) when is_list(Config) -> fold(Config, Version) -> T = test_table, N = 100, - ?line Fname = filename(T, Config), - ?line file:delete(Fname), + Fname = filename(T, Config), + file:delete(Fname), P0 = pps(), Args = [{version, Version}, {file,Fname}, {estimated_no_objects, N}], - ?line {ok, _} = dets:open_file(T, Args), + {ok, _} = dets:open_file(T, Args), - ?line ok = ins(T, N), + ok = ins(T, N), - ?line Ets = ets:new(to_ets, [public]), - ?line dets:to_ets(T, Ets), - ?line true = N =:= ets:info(Ets, size), - ?line ets:delete(Ets), + Ets = ets:new(to_ets, [public]), + dets:to_ets(T, Ets), + true = N =:= ets:info(Ets, size), + ets:delete(Ets), - ?line Ets2 = ets:new(to_ets, [private]), - ?line dets:to_ets(T, Ets2), - ?line true = N =:= ets:info(Ets2, size), - ?line ets:delete(Ets2), + Ets2 = ets:new(to_ets, [private]), + dets:to_ets(T, Ets2), + true = N =:= ets:info(Ets2, size), + ets:delete(Ets2), - ?line {'EXIT', {badarg, _}} = (catch dets:to_ets(T, not_an_ets_table)), + {'EXIT', {badarg, _}} = (catch dets:to_ets(T, not_an_ets_table)), F0 = fun(X, A) -> [X | A] end, - ?line true = N =:= length(dets:foldl(F0, [], T)), - ?line true = N =:= length(dets:foldr(F0, [], T)), + true = N =:= length(dets:foldl(F0, [], T)), + true = N =:= length(dets:foldr(F0, [], T)), F1 = fun(_X, _A) -> throw(away) end, - ?line away = (catch dets:foldl(F1, [], T)), - ?line away = (catch dets:foldr(F1, [], T)), + away = (catch dets:foldl(F1, [], T)), + away = (catch dets:foldr(F1, [], T)), F2 = fun(X, A) -> X + A end, - ?line {'EXIT', _} = (catch dets:foldl(F2, [], T)), - ?line {'EXIT', _} = (catch dets:foldr(F2, [], T)), + {'EXIT', _} = (catch dets:foldl(F2, [], T)), + {'EXIT', _} = (catch dets:foldr(F2, [], T)), F3 = fun(_X) -> throw(away) end, - ?line away = (catch dets:traverse(T, F3)), + away = (catch dets:traverse(T, F3)), F4 = fun(X) -> X + 17 end, - ?line {'EXIT', _} = (catch dets:traverse(T, F4)), + {'EXIT', _} = (catch dets:traverse(T, F4)), - ?line F5 = fun(_X) -> done end, - ?line done = dets:traverse(T, F5), + F5 = fun(_X) -> done end, + done = dets:traverse(T, F5), - ?line {ok, ObjPos} = dets:where(T, {66,{item,number,66}}), - ?line ok = dets:close(T), + {ok, ObjPos} = dets:where(T, {66,{item,number,66}}), + ok = dets:close(T), %% Damaged object. Pos = if @@ -1825,15 +1822,15 @@ fold(Config, Version) -> Version =:= 9 -> 8 end, crash(Fname, ObjPos+Pos), - ?line {ok, _} = dets:open_file(T, Args), - ?line io:format("Expect corrupt table:~n"), - ?line BadObject1 = dets:foldl(F0, [], T), - ?line bad_object(BadObject1, Fname), - ?line BadObject2 = dets:close(T), - ?line bad_object(BadObject2, Fname), - - ?line file:delete(Fname), - ?line check_pps(P0), + {ok, _} = dets:open_file(T, Args), + io:format("Expect corrupt table:~n"), + BadObject1 = dets:foldl(F0, [], T), + bad_object(BadObject1, Fname), + BadObject2 = dets:close(T), + bad_object(BadObject2, Fname), + + file:delete(Fname), + check_pps(P0), ok. fixtable_v8(doc) -> @@ -1852,64 +1849,64 @@ fixtable_v9(Config) when is_list(Config) -> fixtable(Config, Version) when is_list(Config) -> T = fixtable, - ?line Fname = filename(fixtable, Config), - ?line file:delete(Fname), + Fname = filename(fixtable, Config), + file:delete(Fname), Args = [{version,Version},{file,Fname}], P0 = pps(), - ?line {ok, _} = dets:open_file(T, Args), + {ok, _} = dets:open_file(T, Args), %% badarg - ?line check_badarg(catch dets:safe_fixtable(no_table,true), + check_badarg(catch dets:safe_fixtable(no_table,true), dets, safe_fixtable, [no_table,true]), - ?line check_badarg(catch dets:safe_fixtable(T,undefined), + check_badarg(catch dets:safe_fixtable(T,undefined), dets, safe_fixtable, [T,undefined]), %% The table is not allowed to grow while the elements are inserted: - ?line ok = ins(T, 500), - ?line dets:safe_fixtable(T, false), + ok = ins(T, 500), + dets:safe_fixtable(T, false), %% Now the table can grow. At the same time as elements are inserted, %% the table tries to catch up with the previously inserted elements. - ?line ok = ins(T, 1000), - ?line 1000 = dets:info(T, size), - ?line ok = dets:close(T), - ?line file:delete(Fname), + ok = ins(T, 1000), + 1000 = dets:info(T, size), + ok = dets:close(T), + file:delete(Fname), - ?line {ok, _} = dets:open_file(T, [{type, duplicate_bag} | Args]), + {ok, _} = dets:open_file(T, [{type, duplicate_bag} | Args]), %% In a fixed table, delete and re-insert an object. - ?line ok = dets:insert(T, {1, a, b}), - ?line dets:safe_fixtable(T, true), - ?line ok = dets:match_delete(T, {1, a, b}), - ?line ok = dets:insert(T, {1, a, b}), - ?line dets:safe_fixtable(T, false), - ?line 1 = length(dets:match_object(T, '_')), - - ?line ok = dets:match_delete(T, '_'), + ok = dets:insert(T, {1, a, b}), + dets:safe_fixtable(T, true), + ok = dets:match_delete(T, {1, a, b}), + ok = dets:insert(T, {1, a, b}), + dets:safe_fixtable(T, false), + 1 = length(dets:match_object(T, '_')), + + ok = dets:match_delete(T, '_'), %% In a fixed table, delete and insert a smaller object. - ?line ok = dets:insert(T, {1, duplicate(100, e)}), - ?line dets:safe_fixtable(T, true), - ?line ok = dets:match_delete(T, {1, '_'}), - ?line ok = dets:insert(T, {1, a, b}), - ?line dets:safe_fixtable(T, false), - ?line 1 = length(dets:match_object(T, '_')), - - ?line ok = dets:delete_all_objects(T), + ok = dets:insert(T, {1, duplicate(100, e)}), + dets:safe_fixtable(T, true), + ok = dets:match_delete(T, {1, '_'}), + ok = dets:insert(T, {1, a, b}), + dets:safe_fixtable(T, false), + 1 = length(dets:match_object(T, '_')), + + ok = dets:delete_all_objects(T), %% Like the last one, but one extra object. - ?line ok = dets:insert(T, {1, duplicate(100, e)}), - ?line ok = dets:insert(T, {2, duplicate(100, e)}), - ?line dets:safe_fixtable(T, true), - ?line ok = dets:match_delete(T, {1, '_'}), - ?line ok = dets:insert(T, {1, a, b}), - ?line dets:safe_fixtable(T, false), - ?line 2 = length(dets:match_object(T, '_')), - ?line dets:safe_fixtable(T, true), - ?line ok = dets:delete_all_objects(T), - ?line true = dets:info(T, fixed), - ?line 0 = length(dets:match_object(T, '_')), - - ?line ok = dets:close(T), - ?line file:delete(Fname), - ?line check_pps(P0), + ok = dets:insert(T, {1, duplicate(100, e)}), + ok = dets:insert(T, {2, duplicate(100, e)}), + dets:safe_fixtable(T, true), + ok = dets:match_delete(T, {1, '_'}), + ok = dets:insert(T, {1, a, b}), + dets:safe_fixtable(T, false), + 2 = length(dets:match_object(T, '_')), + dets:safe_fixtable(T, true), + ok = dets:delete_all_objects(T), + true = dets:info(T, fixed), + 0 = length(dets:match_object(T, '_')), + + ok = dets:close(T), + file:delete(Fname), + check_pps(P0), ok. match_v8(doc) -> @@ -1928,164 +1925,164 @@ match_v9(Config) when is_list(Config) -> match(Config, Version) -> T = match, - ?line Fname = filename(match, Config), - ?line file:delete(Fname), + Fname = filename(match, Config), + file:delete(Fname), P0 = pps(), Args = [{version, Version}, {file,Fname}, {type, duplicate_bag}, {estimated_no_objects,550}], - ?line {ok, _} = dets:open_file(T, Args), - ?line ok = dets:insert(T, {1, a, b}), - ?line ok = dets:insert(T, {1, b, a}), - ?line ok = dets:insert(T, {2, a, b}), - ?line ok = dets:insert(T, {2, b, a}), + {ok, _} = dets:open_file(T, Args), + ok = dets:insert(T, {1, a, b}), + ok = dets:insert(T, {1, b, a}), + ok = dets:insert(T, {2, a, b}), + ok = dets:insert(T, {2, b, a}), %% match, badarg MSpec = [{'_',[],['$_']}], - ?line check_badarg(catch dets:match(no_table, '_'), - dets, match, [no_table,'_']), - ?line check_badarg(catch dets:match(T, '_', not_a_number), - dets, match, [T,'_',not_a_number]), - ?line {EC1, _} = dets:select(T, MSpec, 1), - ?line check_badarg(catch dets:match(EC1), - dets, match, [EC1]), + check_badarg(catch dets:match(no_table, '_'), + dets, match, [no_table,'_']), + check_badarg(catch dets:match(T, '_', not_a_number), + dets, match, [T,'_',not_a_number]), + {EC1, _} = dets:select(T, MSpec, 1), + check_badarg(catch dets:match(EC1), + dets, match, [EC1]), %% match_object, badarg - ?line check_badarg(catch dets:match_object(no_table, '_'), - dets, match_object, [no_table,'_']), - ?line check_badarg(catch dets:match_object(T, '_', not_a_number), - dets, match_object, [T,'_',not_a_number]), - ?line {EC2, _} = dets:select(T, MSpec, 1), - ?line check_badarg(catch dets:match_object(EC2), - dets, match_object, [EC2]), + check_badarg(catch dets:match_object(no_table, '_'), + dets, match_object, [no_table,'_']), + check_badarg(catch dets:match_object(T, '_', not_a_number), + dets, match_object, [T,'_',not_a_number]), + {EC2, _} = dets:select(T, MSpec, 1), + check_badarg(catch dets:match_object(EC2), + dets, match_object, [EC2]), dets:safe_fixtable(T, true), - ?line {[_, _], C1} = dets:match_object(T, '_', 2), - ?line {[_, _], C2} = dets:match_object(C1), - ?line '$end_of_table' = dets:match_object(C2), - ?line {[_, _], C3} = dets:match_object(T, {1, '_', '_'}, 100), - ?line '$end_of_table' = dets:match_object(C3), - ?line '$end_of_table' = dets:match_object(T, {'_'}, default), - ?line dets:safe_fixtable(T, false), - - ?line dets:safe_fixtable(T, true), - ?line {[_, _], C30} = dets:match(T, '$1', 2), - ?line {[_, _], C31} = dets:match(C30), - ?line '$end_of_table' = dets:match(C31), - ?line {[_, _], C32} = dets:match(T, {1, '$1', '_'}, 100), - ?line '$end_of_table' = dets:match(C32), - ?line '$end_of_table' = dets:match(T, {'_'}, default), - ?line dets:safe_fixtable(T, false), - ?line [[1],[1],[2],[2]] = sort(dets:match(T, {'$1','_','_'})), + {[_, _], C1} = dets:match_object(T, '_', 2), + {[_, _], C2} = dets:match_object(C1), + '$end_of_table' = dets:match_object(C2), + {[_, _], C3} = dets:match_object(T, {1, '_', '_'}, 100), + '$end_of_table' = dets:match_object(C3), + '$end_of_table' = dets:match_object(T, {'_'}, default), + dets:safe_fixtable(T, false), + + dets:safe_fixtable(T, true), + {[_, _], C30} = dets:match(T, '$1', 2), + {[_, _], C31} = dets:match(C30), + '$end_of_table' = dets:match(C31), + {[_, _], C32} = dets:match(T, {1, '$1', '_'}, 100), + '$end_of_table' = dets:match(C32), + '$end_of_table' = dets:match(T, {'_'}, default), + dets:safe_fixtable(T, false), + [[1],[1],[2],[2]] = sort(dets:match(T, {'$1','_','_'})), %% delete and insert while chunking %% (this case almost worthless after changes in OTP-5232) - ?line ok = dets:match_delete(T, '_'), + ok = dets:match_delete(T, '_'), L500 = seq(1, 500), Fun = fun(X) -> ok = dets:insert(T, {X, a, b, c, d}) end, - ?line foreach(Fun, L500), + foreach(Fun, L500), %% Select one object DI in L3 below to be deleted. - ?line {_, TmpCont} = dets:match_object(T, '_', 200), - ?line {_, TmpCont1} = dets:match_object(TmpCont), - ?line {TTL, _} = dets:match_object(TmpCont1), - ?line DI = if Version =:= 8 -> last(TTL); Version =:= 9 -> hd(TTL) end, - ?line dets:safe_fixtable(T, true), - ?line {L1, C20} = dets:match_object(T, '_', 200), - ?line true = 200 =< length(L1), - ?line ok = dets:match_delete(T, {'2','_','_'}), % no match - ?line ok = dets:match_delete(T, DI), % last object + {_, TmpCont} = dets:match_object(T, '_', 200), + {_, TmpCont1} = dets:match_object(TmpCont), + {TTL, _} = dets:match_object(TmpCont1), + DI = if Version =:= 8 -> last(TTL); Version =:= 9 -> hd(TTL) end, + dets:safe_fixtable(T, true), + {L1, C20} = dets:match_object(T, '_', 200), + true = 200 =< length(L1), + ok = dets:match_delete(T, {'2','_','_'}), % no match + ok = dets:match_delete(T, DI), % last object Tiny = {1050}, - ?line ok = dets:insert(T, Tiny), - ?line true = member(Tiny, dets:match_object(T, '_')), - ?line {_L2, C21} = dets:match_object(C20), - ?line {_L3, _C22} = dets:match_object(C21), + ok = dets:insert(T, Tiny), + true = member(Tiny, dets:match_object(T, '_')), + {_L2, C21} = dets:match_object(C20), + {_L3, _C22} = dets:match_object(C21), %% It used to be that Tiny was not visible here, but since the %% scanning of files was changed to inspect the free lists every %% now and then it may very well be visible here. - %% ?line false = member(Tiny, _L3), + %% false = member(Tiny, _L3), %% DI used to visible here, but the above mentioned modification %% has changed that; it may or may not be visible. - %% ?line true = member(DI, _L3), - ?line dets:safe_fixtable(T, false), - ?line true = dets:member(T, 1050), - ?line true = member(Tiny, dets:match_object(T, '_')), - ?line false = member(DI, dets:match_object(T, '_')), + %% true = member(DI, _L3), + dets:safe_fixtable(T, false), + true = dets:member(T, 1050), + true = member(Tiny, dets:match_object(T, '_')), + false = member(DI, dets:match_object(T, '_')), - ?line ok = dets:close(T), - ?line file:delete(Fname), + ok = dets:close(T), + file:delete(Fname), N = 100, - ?line {ok, _} = dets:open_file(T, [{estimated_no_objects,N} | Args]), - ?line ok = ins(T, N), + {ok, _} = dets:open_file(T, [{estimated_no_objects,N} | Args]), + ok = ins(T, N), Obj = {66,{item,number,66}}, Spec = {'_','_'}, - ?line {ok, ObjPos} = dets:where(T, Obj), - ?line ok = dets:close(T), + {ok, ObjPos} = dets:where(T, Obj), + ok = dets:close(T), %% Damaged object. crash(Fname, ObjPos+12), - ?line {ok, _} = dets:open_file(T, Args), - ?line io:format("Expect corrupt table:~n"), - ?line case ins(T, N) of + {ok, _} = dets:open_file(T, Args), + io:format("Expect corrupt table:~n"), + case ins(T, N) of ok -> - ?line bad_object(dets:sync(T), Fname); + bad_object(dets:sync(T), Fname); Else -> - ?line bad_object(Else, Fname) + bad_object(Else, Fname) end, - ?line io:format("Expect corrupt table:~n"), - ?line bad_object(dets:match(T, Spec), Fname), - ?line io:format("Expect corrupt table:~n"), - ?line bad_object(dets:match_delete(T, Spec), Fname), - ?line bad_object(dets:close(T), Fname), - ?line file:delete(Fname), - - ?line {ok, _} = dets:open_file(T, [{estimated_no_objects,N} | Args]), - ?line ok = ins(T, N), - ?line {ok, ObjPos2} = dets:where(T, Obj), - ?line ok = dets:close(T), + io:format("Expect corrupt table:~n"), + bad_object(dets:match(T, Spec), Fname), + io:format("Expect corrupt table:~n"), + bad_object(dets:match_delete(T, Spec), Fname), + bad_object(dets:close(T), Fname), + file:delete(Fname), + + {ok, _} = dets:open_file(T, [{estimated_no_objects,N} | Args]), + ok = ins(T, N), + {ok, ObjPos2} = dets:where(T, Obj), + ok = dets:close(T), %% Damaged size of object. %% In v8, there is a next pointer before the size. CrashPos = if Version =:= 8 -> 5; Version =:= 9 -> 1 end, crash(Fname, ObjPos2+CrashPos), - ?line {ok, _} = dets:open_file(T, Args), - ?line io:format("Expect corrupt table:~n"), - ?line case ins(T, N) of - ok -> - ?line bad_object(dets:sync(T), Fname); - Else2 -> - ?line bad_object(Else2, Fname) - end, + {ok, _} = dets:open_file(T, Args), + io:format("Expect corrupt table:~n"), + case ins(T, N) of + ok -> + bad_object(dets:sync(T), Fname); + Else2 -> + bad_object(Else2, Fname) + end, %% Just echoes... - ?line bad_object(dets:match(T, Spec), Fname), - ?line bad_object(dets:match_delete(T, Spec), Fname), - ?line bad_object(dets:close(T), Fname), - ?line file:delete(Fname), + bad_object(dets:match(T, Spec), Fname), + bad_object(dets:match_delete(T, Spec), Fname), + bad_object(dets:close(T), Fname), + file:delete(Fname), - ?line {ok, _} = dets:open_file(T, [{estimated_no_objects,N} | Args]), - ?line ok = ins(T, N), - ?line {ok, ObjPos3} = dets:where(T, Obj), - ?line ok = dets:close(T), + {ok, _} = dets:open_file(T, [{estimated_no_objects,N} | Args]), + ok = ins(T, N), + {ok, ObjPos3} = dets:where(T, Obj), + ok = dets:close(T), %% match_delete finds an error CrashPos3 = if Version =:= 8 -> 12; Version =:= 9 -> 16 end, crash(Fname, ObjPos3+CrashPos3), - ?line {ok, _} = dets:open_file(T, Args), - ?line bad_object(dets:match_delete(T, Spec), Fname), - ?line bad_object(dets:close(T), Fname), - ?line file:delete(Fname), + {ok, _} = dets:open_file(T, Args), + bad_object(dets:match_delete(T, Spec), Fname), + bad_object(dets:close(T), Fname), + file:delete(Fname), %% The key is not fixed, but not all objects with the key are removed. - ?line {ok, _} = dets:open_file(T, Args), - ?line ok = dets:insert(T, [{1,a},{1,b},{1,c},{1,a},{1,b},{1,c}]), - ?line 6 = dets:info(T, size), - ?line ok = dets:match_delete(T, {'_',a}), - ?line 4 = dets:info(T, size), - ?line [{1,b},{1,b},{1,c},{1,c}] = + {ok, _} = dets:open_file(T, Args), + ok = dets:insert(T, [{1,a},{1,b},{1,c},{1,a},{1,b},{1,c}]), + 6 = dets:info(T, size), + ok = dets:match_delete(T, {'_',a}), + 4 = dets:info(T, size), + [{1,b},{1,b},{1,c},{1,c}] = sort(dets:match_object(T,{'_','_'})), - ?line ok = dets:close(T), - ?line file:delete(Fname), + ok = dets:close(T), + file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. select_v8(doc) -> @@ -2104,102 +2101,102 @@ select_v9(Config) when is_list(Config) -> select(Config, Version) -> T = select, - ?line Fname = filename(select, Config), - ?line file:delete(Fname), + Fname = filename(select, Config), + file:delete(Fname), P0 = pps(), - ?line Args = [{version,Version}, {file,Fname}, {type, duplicate_bag}, - {estimated_no_objects,550}], - ?line {ok, _} = dets:open_file(T, Args), - ?line ok = dets:insert(T, {1, a, b}), - ?line ok = dets:insert(T, {1, b, a}), - ?line ok = dets:insert(T, {2, a, b}), - ?line ok = dets:insert(T, {2, b, a}), - ?line ok = dets:insert(T, {3, a, b}), - ?line ok = dets:insert(T, {3, b, a}), + Args = [{version,Version}, {file,Fname}, {type, duplicate_bag}, + {estimated_no_objects,550}], + {ok, _} = dets:open_file(T, Args), + ok = dets:insert(T, {1, a, b}), + ok = dets:insert(T, {1, b, a}), + ok = dets:insert(T, {2, a, b}), + ok = dets:insert(T, {2, b, a}), + ok = dets:insert(T, {3, a, b}), + ok = dets:insert(T, {3, b, a}), %% badarg MSpec = [{'_',[],['$_']}], - ?line check_badarg(catch dets:select(no_table, MSpec), - dets, select, [no_table,MSpec]), - ?line check_badarg(catch dets:select(T, <<17>>), - dets, select, [T,<<17>>]), - ?line check_badarg(catch dets:select(T, []), - dets, select, [T,[]]), - ?line check_badarg(catch dets:select(T, MSpec, not_a_number), - dets, select, [T,MSpec,not_a_number]), - ?line {EC, _} = dets:match(T, '_', 1), - ?line check_badarg(catch dets:select(EC), - dets, select, [EC]), + check_badarg(catch dets:select(no_table, MSpec), + dets, select, [no_table,MSpec]), + check_badarg(catch dets:select(T, <<17>>), + dets, select, [T,<<17>>]), + check_badarg(catch dets:select(T, []), + dets, select, [T,[]]), + check_badarg(catch dets:select(T, MSpec, not_a_number), + dets, select, [T,MSpec,not_a_number]), + {EC, _} = dets:match(T, '_', 1), + check_badarg(catch dets:select(EC), + dets, select, [EC]), AllSpec = [{'_',[],['$_']}], - ?line dets:safe_fixtable(T, true), - ?line {[_, _], C1} = dets:select(T, AllSpec, 2), - ?line {[_, _], C2} = dets:select(C1), - ?line {[_, _], C2a} = dets:select(C2), - ?line '$end_of_table' = dets:select(C2a), - ?line {[_, _], C3} = dets:select(T, [{{1,'_','_'},[],['$_']}], 100), - ?line '$end_of_table' = dets:select(C3), - ?line '$end_of_table' = dets:select(T, [{{'_'},[],['$_']}], default), - ?line dets:safe_fixtable(T, false), + dets:safe_fixtable(T, true), + {[_, _], C1} = dets:select(T, AllSpec, 2), + {[_, _], C2} = dets:select(C1), + {[_, _], C2a} = dets:select(C2), + '$end_of_table' = dets:select(C2a), + {[_, _], C3} = dets:select(T, [{{1,'_','_'},[],['$_']}], 100), + '$end_of_table' = dets:select(C3), + '$end_of_table' = dets:select(T, [{{'_'},[],['$_']}], default), + dets:safe_fixtable(T, false), Sp1 = [{{1,'_','_'},[],['$_']},{{1,'_','_'},[],['$_']}, {{2,'_','_'},[],['$_']}], - ?line [_,_,_,_] = dets:select(T, Sp1), + [_,_,_,_] = dets:select(T, Sp1), Sp2 = [{{1,'_','_'},[],['$_']},{{1,'_','_'},[],['$_']}, {{'_','_','_'},[],['$_']}], - ?line [_,_,_,_,_,_] = dets:select(T, Sp2), + [_,_,_,_,_,_] = dets:select(T, Sp2), AllDeleteSpec = [{'_',[],[true]}], %% delete and insert while chunking %% (this case almost worthless after changes in OTP-5232) - ?line 6 = dets:select_delete(T, AllDeleteSpec), + 6 = dets:select_delete(T, AllDeleteSpec), L500 = seq(1, 500), Fun = fun(X) -> ok = dets:insert(T, {X, a, b, c, d}) end, - ?line foreach(Fun, L500), + foreach(Fun, L500), %% Select one object DI in L3 below to be deleted. - ?line {_, TmpCont} = dets:match_object(T, '_', 200), - ?line {_, TmpCont1} = dets:match_object(TmpCont), - ?line {TTL, _} = dets:match_object(TmpCont1), - ?line DI = if Version =:= 8 -> last(TTL); Version =:= 9 -> hd(TTL) end, - ?line dets:safe_fixtable(T, true), - ?line {L1, C20} = dets:select(T, AllSpec, 200), - ?line true = 200 =< length(L1), - ?line 0 = dets:select_delete(T, [{{2,'_','_'},[],[true]}]), - ?line 1 = dets:select_delete(T, [{DI,[],[true]}]), % last object + {_, TmpCont} = dets:match_object(T, '_', 200), + {_, TmpCont1} = dets:match_object(TmpCont), + {TTL, _} = dets:match_object(TmpCont1), + DI = if Version =:= 8 -> last(TTL); Version =:= 9 -> hd(TTL) end, + dets:safe_fixtable(T, true), + {L1, C20} = dets:select(T, AllSpec, 200), + true = 200 =< length(L1), + 0 = dets:select_delete(T, [{{2,'_','_'},[],[true]}]), + 1 = dets:select_delete(T, [{DI,[],[true]}]), % last object Tiny = {1050}, - ?line ok = dets:insert(T, Tiny), - ?line true = member(Tiny, dets:select(T, AllSpec)), - ?line {_L2, C21} = dets:select(C20), - ?line {_L3, _C22} = dets:select(C21), + ok = dets:insert(T, Tiny), + true = member(Tiny, dets:select(T, AllSpec)), + {_L2, C21} = dets:select(C20), + {_L3, _C22} = dets:select(C21), %% It used to be that Tiny was not visible here, but since the %% scanning of files was changed to inspect the free lists every %% now and then it may very well be visible here. - %% ?line false = member(Tiny, _L3), + %% false = member(Tiny, _L3), %% DI used to visible here, but the above mentioned modification %% has changed that; it may or may not be visible. - %% ?line true = member(DI, _L3), - ?line true = dets:member(T, 1050), - ?line true = member(Tiny, dets:select(T, AllSpec)), - ?line false = member(DI, dets:select(T, AllSpec)), - ?line dets:safe_fixtable(T, false), - ?line true = dets:member(T, 1050), - ?line true = member(Tiny, dets:select(T, AllSpec)), - ?line false = member(DI, dets:select(T, AllSpec)), - ?line ok = dets:close(T), - ?line file:delete(Fname), + %% true = member(DI, _L3), + true = dets:member(T, 1050), + true = member(Tiny, dets:select(T, AllSpec)), + false = member(DI, dets:select(T, AllSpec)), + dets:safe_fixtable(T, false), + true = dets:member(T, 1050), + true = member(Tiny, dets:select(T, AllSpec)), + false = member(DI, dets:select(T, AllSpec)), + ok = dets:close(T), + file:delete(Fname), %% The key is not fixed, but not all objects with the key are removed. - ?line {ok, _} = dets:open_file(T, Args), - ?line ok = dets:insert(T, [{1,a},{1,b},{1,c},{1,a},{1,b},{1,c}]), - ?line 6 = dets:info(T, size), - ?line 2 = dets:select_delete(T, [{{'_',a},[],[true]}]), - ?line 4 = dets:info(T, size), - ?line [{1,b},{1,b},{1,c},{1,c}] = sort(dets:select(T, AllSpec)), - ?line ok = dets:close(T), - ?line file:delete(Fname), - - ?line check_pps(P0), + {ok, _} = dets:open_file(T, Args), + ok = dets:insert(T, [{1,a},{1,b},{1,c},{1,a},{1,b},{1,c}]), + 6 = dets:info(T, size), + 2 = dets:select_delete(T, [{{'_',a},[],[true]}]), + 4 = dets:info(T, size), + [{1,b},{1,b},{1,c},{1,c}] = sort(dets:select(T, AllSpec)), + ok = dets:close(T), + file:delete(Fname), + + check_pps(P0), ok. update_counter(doc) -> @@ -2208,34 +2205,34 @@ update_counter(suite) -> []; update_counter(Config) when is_list(Config) -> T = update_counter, - ?line Fname = filename(select, Config), - ?line file:delete(Fname), + Fname = filename(select, Config), + file:delete(Fname), P0 = pps(), - ?line check_badarg(catch dets:update_counter(no_table, 1, 1), - dets, update_counter, [no_table,1,1]), + check_badarg(catch dets:update_counter(no_table, 1, 1), + dets, update_counter, [no_table,1,1]), Args = [{file,Fname},{keypos,2}], - ?line {ok, _} = dets:open_file(T, [{type,set} | Args]), - ?line {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), - ?line ok = dets:insert(T, {1,a}), - ?line {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), - ?line ok = dets:insert(T, {0,1}), - ?line {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), - ?line ok = dets:insert(T, {0,1,0}), - ?line 1 = dets:update_counter(T, 1, 1), - ?line 2 = dets:update_counter(T, 1, 1), - ?line 6 = dets:update_counter(T, 1, {3,4}), - ?line {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, {0,3})), - ?line ok = dets:close(T), - ?line file:delete(Fname), - - ?line {ok, _} = dets:open_file(T, [{type,bag} | Args]), - ?line ok = dets:insert(T, {0,1,0}), - ?line {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), - ?line ok = dets:close(T), - ?line file:delete(Fname), - ?line check_pps(P0), + {ok, _} = dets:open_file(T, [{type,set} | Args]), + {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), + ok = dets:insert(T, {1,a}), + {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), + ok = dets:insert(T, {0,1}), + {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), + ok = dets:insert(T, {0,1,0}), + 1 = dets:update_counter(T, 1, 1), + 2 = dets:update_counter(T, 1, 1), + 6 = dets:update_counter(T, 1, {3,4}), + {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, {0,3})), + ok = dets:close(T), + file:delete(Fname), + + {ok, _} = dets:open_file(T, [{type,bag} | Args]), + ok = dets:insert(T, {0,1,0}), + {'EXIT', {badarg, _}} = (catch dets:update_counter(T, 1, 1)), + ok = dets:close(T), + file:delete(Fname), + check_pps(P0), ok. @@ -2245,133 +2242,133 @@ badarg(suite) -> []; badarg(Config) when is_list(Config) -> T = badarg, - ?line Fname = filename(select, Config), - ?line file:delete(Fname), + Fname = filename(select, Config), + file:delete(Fname), P0 = pps(), Args = [{file,Fname},{keypos,3}], - ?line {ok, _} = dets:open_file(T, [{type,set} | Args]), - % ?line dets:verbose(), + {ok, _} = dets:open_file(T, [{type,set} | Args]), + % dets:verbose(), %% badargs are tested in match, select and fixtable too. %% open - ?line check_badarg(catch dets:open_file({a,tuple},[]), - dets, open_file, [{a,tuple},[]]), - ?line check_badarg(catch dets:open_file({a,tuple}), - dets, open_file,[{a,tuple}]), - ?line check_badarg(catch dets:open_file(file,[foo]), - dets, open_file, [file,[foo]]), - ?line check_badarg(catch dets:open_file({hej,san},[{type,set}|3]), - dets, open_file, [{hej,san},[{type,set}|3]]), + check_badarg(catch dets:open_file({a,tuple},[]), + dets, open_file, [{a,tuple},[]]), + check_badarg(catch dets:open_file({a,tuple}), + dets, open_file,[{a,tuple}]), + check_badarg(catch dets:open_file(file,[foo]), + dets, open_file, [file,[foo]]), + check_badarg(catch dets:open_file({hej,san},[{type,set}|3]), + dets, open_file, [{hej,san},[{type,set}|3]]), %% insert - ?line check_badarg(catch dets:insert(no_table, {1,2}), - dets, insert, [no_table,{1,2}]), - ?line check_badarg(catch dets:insert(no_table, [{1,2}]), - dets, insert, [no_table,[{1,2}]]), - ?line check_badarg(catch dets:insert(T, {1,2}), - dets, insert, [T,{1,2}]), - ?line check_badarg(catch dets:insert(T, [{1,2}]), - dets, insert, [T,[{1,2}]]), - ?line check_badarg(catch dets:insert(T, [{1,2,3} | 3]), - dets, insert, [T,[{1,2,3}|3]]), + check_badarg(catch dets:insert(no_table, {1,2}), + dets, insert, [no_table,{1,2}]), + check_badarg(catch dets:insert(no_table, [{1,2}]), + dets, insert, [no_table,[{1,2}]]), + check_badarg(catch dets:insert(T, {1,2}), + dets, insert, [T,{1,2}]), + check_badarg(catch dets:insert(T, [{1,2}]), + dets, insert, [T,[{1,2}]]), + check_badarg(catch dets:insert(T, [{1,2,3} | 3]), + dets, insert, [T,[{1,2,3}|3]]), %% lookup{_keys} - ?line check_badarg(catch dets:lookup_keys(T, []), - dets, lookup_keys, [badarg,[]]), - ?line check_badarg(catch dets:lookup(no_table, 1), - dets, lookup, [no_table,1]), - ?line check_badarg(catch dets:lookup_keys(T, [1 | 2]), - dets, lookup_keys, [T,[1|2]]), + check_badarg(catch dets:lookup_keys(T, []), + dets, lookup_keys, [badarg,[]]), + check_badarg(catch dets:lookup(no_table, 1), + dets, lookup, [no_table,1]), + check_badarg(catch dets:lookup_keys(T, [1 | 2]), + dets, lookup_keys, [T,[1|2]]), %% member - ?line check_badarg(catch dets:member(no_table, 1), - dets, member, [no_table,1]), + check_badarg(catch dets:member(no_table, 1), + dets, member, [no_table,1]), %% sync - ?line check_badarg(catch dets:sync(no_table), - dets, sync, [no_table]), + check_badarg(catch dets:sync(no_table), + dets, sync, [no_table]), %% delete{_keys} - ?line check_badarg(catch dets:delete(no_table, 1), - dets, delete, [no_table,1]), + check_badarg(catch dets:delete(no_table, 1), + dets, delete, [no_table,1]), %% delete_object - ?line check_badarg(catch dets:delete_object(no_table, {1,2,3}), - dets, delete_object, [no_table,{1,2,3}]), - ?line check_badarg(catch dets:delete_object(T, {1,2}), - dets, delete_object, [T,{1,2}]), - ?line check_badarg(catch dets:delete_object(no_table, [{1,2,3}]), - dets, delete_object, [no_table,[{1,2,3}]]), - ?line check_badarg(catch dets:delete_object(T, [{1,2}]), - dets, delete_object, [T,[{1,2}]]), - ?line check_badarg(catch dets:delete_object(T, [{1,2,3} | 3]), - dets, delete_object, [T,[{1,2,3}|3]]), + check_badarg(catch dets:delete_object(no_table, {1,2,3}), + dets, delete_object, [no_table,{1,2,3}]), + check_badarg(catch dets:delete_object(T, {1,2}), + dets, delete_object, [T,{1,2}]), + check_badarg(catch dets:delete_object(no_table, [{1,2,3}]), + dets, delete_object, [no_table,[{1,2,3}]]), + check_badarg(catch dets:delete_object(T, [{1,2}]), + dets, delete_object, [T,[{1,2}]]), + check_badarg(catch dets:delete_object(T, [{1,2,3} | 3]), + dets, delete_object, [T,[{1,2,3}|3]]), %% first,next,slot - ?line check_badarg(catch dets:first(no_table), - dets, first, [no_table]), - ?line check_badarg(catch dets:next(no_table, 1), - dets, next, [no_table,1]), - ?line check_badarg(catch dets:slot(no_table, 0), - dets, slot, [no_table,0]), + check_badarg(catch dets:first(no_table), + dets, first, [no_table]), + check_badarg(catch dets:next(no_table, 1), + dets, next, [no_table,1]), + check_badarg(catch dets:slot(no_table, 0), + dets, slot, [no_table,0]), %% info - ?line undefined = dets:info(no_table), - ?line undefined = dets:info(no_table, foo), - ?line undefined = dets:info(T, foo), + undefined = dets:info(no_table), + undefined = dets:info(no_table, foo), + undefined = dets:info(T, foo), %% match_delete - ?line check_badarg(catch dets:match_delete(no_table, '_'), + check_badarg(catch dets:match_delete(no_table, '_'), dets, match_delete, [no_table,'_']), %% delete_all_objects - ?line check_badarg(catch dets:delete_all_objects(no_table), - dets, delete_all_objects, [no_table]), + check_badarg(catch dets:delete_all_objects(no_table), + dets, delete_all_objects, [no_table]), %% select_delete MSpec = [{'_',[],['$_']}], - ?line check_badarg(catch dets:select_delete(no_table, MSpec), - dets, select_delete, [no_table,MSpec]), - ?line check_badarg(catch dets:select_delete(T, <<17>>), - dets, select_delete, [T, <<17>>]), + check_badarg(catch dets:select_delete(no_table, MSpec), + dets, select_delete, [no_table,MSpec]), + check_badarg(catch dets:select_delete(T, <<17>>), + dets, select_delete, [T, <<17>>]), %% traverse, fold TF = fun(_) -> continue end, - ?line check_badarg(catch dets:traverse(no_table, TF), - dets, traverse, [no_table,TF]), + check_badarg(catch dets:traverse(no_table, TF), + dets, traverse, [no_table,TF]), FF = fun(_, A) -> A end, - ?line check_badarg(catch dets:foldl(FF, [], no_table), - dets, foldl, [FF,[],no_table]), - ?line check_badarg(catch dets:foldr(FF, [], no_table), - dets, foldl, [FF,[],no_table]), + check_badarg(catch dets:foldl(FF, [], no_table), + dets, foldl, [FF,[],no_table]), + check_badarg(catch dets:foldr(FF, [], no_table), + dets, foldl, [FF,[],no_table]), %% close - ?line ok = dets:close(T), - ?line {error, not_owner} = dets:close(T), - ?line {error, not_owner} = dets:close(T), + ok = dets:close(T), + {error, not_owner} = dets:close(T), + {error, not_owner} = dets:close(T), %% init_table IF = fun(X) -> X end, - ?line check_badarg(catch dets:init_table(no_table, IF), - dets, init_table, [no_table,IF,[]]), - ?line check_badarg(catch dets:init_table(no_table, IF, []), - dets, init_table, [no_table,IF,[]]), + check_badarg(catch dets:init_table(no_table, IF), + dets, init_table, [no_table,IF,[]]), + check_badarg(catch dets:init_table(no_table, IF, []), + dets, init_table, [no_table,IF,[]]), %% from_ets Ets = ets:new(ets,[]), - ?line check_badarg(catch dets:from_ets(no_table, Ets), - dets, from_ets, [no_table,Ets]), + check_badarg(catch dets:from_ets(no_table, Ets), + dets, from_ets, [no_table,Ets]), ets:delete(Ets), - ?line {ok, T} = dets:open_file(T, Args), - ?line {error,incompatible_arguments} = + {ok, T} = dets:open_file(T, Args), + {error,incompatible_arguments} = dets:open_file(T, [{type,bag} | Args]), - ?line ok = dets:close(T), + ok = dets:close(T), file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. cache_sets_v8(doc) -> @@ -2407,11 +2404,11 @@ cache_sets(Config, DelayedWrite, Extra, Sz, Version) -> %% Sz = integer(). Size of the inserted tuples. T = cache, - ?line Fname = filename(cache, Config), - ?line file:delete(Fname), + Fname = filename(cache, Config), + file:delete(Fname), P0 = pps(), - ?line {ok, _} = + {ok, _} = dets:open_file(T,[{version, Version}, {file,Fname}, {type,set}, {delayed_write, DelayedWrite}]), @@ -2420,48 +2417,48 @@ cache_sets(Config, DelayedWrite, Extra, Sz, Version) -> if Extra -> %% Insert enough to get three keys in some slot. - ?line dets:safe_fixtable(T, true), + dets:safe_fixtable(T, true), insert_objs(T, 1, Sz, Dups); true -> {1,[]} end, Tuple = erlang:make_tuple(Sz, Key), - ?line ok = dets:delete(T, Key), - ?line ok = dets:sync(T), + ok = dets:delete(T, Key), + ok = dets:sync(T), %% The values of keys in the same slot as Key are checked. - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), + OtherValues = sort(lookup_keys(T, OtherKeys)), - ?line ok = dets:insert(T, Tuple), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:insert(T, [Tuple,Tuple]), + ok = dets:insert(T, Tuple), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:insert(T, [Tuple,Tuple]), %% If no delay, the cache gets filled immediately, and written. - ?line [Tuple] = dets:lookup_keys(T, [Key,a,b,c,d,e,f]), - ?line true = dets:member(T, Key), + [Tuple] = dets:lookup_keys(T, [Key,a,b,c,d,e,f]), + true = dets:member(T, Key), %% If delay, this happens without file access. - ?line ok = dets:delete(T,Key), - ?line ok = dets:insert(T,Tuple), - ?line ok = dets:insert(T,Tuple), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:sync(T), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), + ok = dets:delete(T,Key), + ok = dets:insert(T,Tuple), + ok = dets:insert(T,Tuple), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:sync(T), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), %% Key's objects are is on file only, %% key 'toto' in the cache (if there is one). - ?line ok = dets:delete(T,toto), - ?line ok = dets:insert(T,[{toto,b},{toto,b}]), - ?line true = sort([Tuple,{toto,b}]) =:= - sort(dets:lookup_keys(T, [Key,toto])), - ?line true = dets:member(T, toto), + ok = dets:delete(T,toto), + ok = dets:insert(T,[{toto,b},{toto,b}]), + true = sort([Tuple,{toto,b}]) =:= + sort(dets:lookup_keys(T, [Key,toto])), + true = dets:member(T, toto), - ?line ok = dets:delete(T, Key), - ?line ok = dets:sync(T), - ?line false = dets:member(T, Key), - ?line Size = dets:info(T, size), + ok = dets:delete(T, Key), + ok = dets:sync(T), + false = dets:member(T, Key), + Size = dets:info(T, size), %% No object with the key on the file. %% Delete, add one object. @@ -2483,37 +2480,37 @@ cache_sets(Config, DelayedWrite, Extra, Sz, Version) -> E -> E + 1 end, Tuple2 = setelement(2, Tuple, Element), - ?line ok = dets:sync(T), - ?line ok = dets:insert(T, Tuple2), - ?line [Tuple2] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:sync(T), - ?line [Tuple2] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - - ?line ok = dets:insert(T, {3,a}), - ?line ok = dets:insert(T, {3,b}), - ?line ok = dets:delete_object(T, {3,c}), - ?line ok = dets:delete_object(T, {3,d}), - ?line [{3,b}] = dets:lookup(T, 3), - - ?line ok = dets:delete(T, 3), - ?line ok = dets:delete_object(T, {3,c}), - ?line ok = dets:delete_object(T, {3,d}), - ?line [] = dets:lookup(T, 3), - - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), + ok = dets:sync(T), + ok = dets:insert(T, Tuple2), + [Tuple2] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:sync(T), + [Tuple2] = dets:lookup(T, Key), + true = dets:member(T, Key), + + ok = dets:insert(T, {3,a}), + ok = dets:insert(T, {3,b}), + ok = dets:delete_object(T, {3,c}), + ok = dets:delete_object(T, {3,d}), + [{3,b}] = dets:lookup(T, 3), + + ok = dets:delete(T, 3), + ok = dets:delete_object(T, {3,c}), + ok = dets:delete_object(T, {3,d}), + [] = dets:lookup(T, 3), + + OtherValues = sort(lookup_keys(T, OtherKeys)), if Extra -> %% Let the table grow a while, if it needs to. - ?line All1 = get_all_objects(T), - ?line dets:safe_fixtable(T, false), - ?line timer:sleep(1000), - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), - ?line dets:safe_fixtable(T, true), - ?line All2 = get_all_objects(T), - ?line FAll2 = get_all_objects_fast(T), - ?line true = sort(All2) =:= sort(FAll2), + All1 = get_all_objects(T), + dets:safe_fixtable(T, false), + timer:sleep(1000), + OtherValues = sort(lookup_keys(T, OtherKeys)), + dets:safe_fixtable(T, true), + All2 = get_all_objects(T), + FAll2 = get_all_objects_fast(T), + true = sort(All2) =:= sort(FAll2), case symdiff(All1, All2) of {[],[]} -> ok; {X,Y} -> @@ -2523,10 +2520,10 @@ cache_sets(Config, DelayedWrite, Extra, Sz, Version) -> true -> ok end, - ?line ok = dets:close(T), + ok = dets:close(T), file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. cache_bags_v8(doc) -> @@ -2562,11 +2559,11 @@ cache_bags(Config, DelayedWrite, Extra, Sz, Version) -> %% Sz = integer(). Size of the inserted tuples. T = cache, - ?line Fname = filename(cache, Config), - ?line file:delete(Fname), + Fname = filename(cache, Config), + file:delete(Fname), P0 = pps(), - ?line {ok, _} = + {ok, _} = dets:open_file(T,[{version, Version}, {file,Fname}, {type,bag}, {delayed_write, DelayedWrite}]), @@ -2575,49 +2572,49 @@ cache_bags(Config, DelayedWrite, Extra, Sz, Version) -> if Extra -> %% Insert enough to get three keys in some slot. - ?line dets:safe_fixtable(T, true), + dets:safe_fixtable(T, true), insert_objs(T, 1, Sz, Dups); true -> {1,[]} end, Tuple = erlang:make_tuple(Sz, Key), - ?line ok = dets:delete(T, Key), - ?line ok = dets:sync(T), + ok = dets:delete(T, Key), + ok = dets:sync(T), %% The values of keys in the same slot as Key are checked. - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), + OtherValues = sort(lookup_keys(T, OtherKeys)), - ?line ok = dets:insert(T, Tuple), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:insert(T, [Tuple,Tuple]), + ok = dets:insert(T, Tuple), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:insert(T, [Tuple,Tuple]), %% If no delay, the cache gets filled immediately, and written. - ?line [Tuple] = dets:lookup_keys(T, [Key,a,b,c,d,e,f]), - ?line true = dets:member(T, Key), + [Tuple] = dets:lookup_keys(T, [Key,a,b,c,d,e,f]), + true = dets:member(T, Key), %% If delay, this happens without file access. %% (This is no longer true; cache lookup has been simplified.) - ?line ok = dets:delete(T,Key), - ?line ok = dets:insert(T,Tuple), - ?line ok = dets:insert(T,Tuple), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:sync(T), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), + ok = dets:delete(T,Key), + ok = dets:insert(T,Tuple), + ok = dets:insert(T,Tuple), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:sync(T), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), %% Key's objects are is on file only, %% key toto in the cache (if there is one). - ?line ok = dets:delete(T,toto), - ?line false = dets:member(T, toto), - ?line ok = dets:insert(T,[{toto,b},{toto,b}]), - ?line true = sort([Tuple,{toto,b}]) =:= - sort(dets:lookup_keys(T, [Key,toto])), - ?line true = dets:member(T, toto), + ok = dets:delete(T,toto), + false = dets:member(T, toto), + ok = dets:insert(T,[{toto,b},{toto,b}]), + true = sort([Tuple,{toto,b}]) =:= + sort(dets:lookup_keys(T, [Key,toto])), + true = dets:member(T, toto), - ?line ok = dets:delete(T, Key), - ?line ok = dets:sync(T), - ?line Size = dets:info(T, size), + ok = dets:delete(T, Key), + ok = dets:sync(T), + Size = dets:info(T, size), %% No object with the key on the file. %% Delete, add one object. @@ -2634,50 +2631,50 @@ cache_bags(Config, DelayedWrite, Extra, Sz, Version) -> del_and_ins(both, T, Size2, Tuple, Key, 1), %% Overwrite an objekt on file with the same object. - ?line ok = dets:insert(T, Tuple), - ?line ok = dets:sync(T), - ?line [Tuple2] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:insert(T, Tuple), - ?line ok = dets:sync(T), - ?line [Tuple2] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), + ok = dets:insert(T, Tuple), + ok = dets:sync(T), + [Tuple2] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:insert(T, Tuple), + ok = dets:sync(T), + [Tuple2] = dets:lookup(T, Key), + true = dets:member(T, Key), %% A mix of insert and delete. - ?line ok = dets:delete(T, Key), - ?line ok = dets:sync(T), - ?line ok = dets:delete(T, Key), - ?line ok = dets:insert(T, {Key,foo}), - ?line ok = dets:insert(T, {Key,bar}), - ?line [{Key,bar},{Key,foo}] = sort(dets:lookup(T, Key)), - ?line true = dets:member(T, Key), - ?line ok = dets:delete_object(T, {Key,foo}), - ?line ok = dets:insert(T, {Key,kar}), - ?line [{Key,bar},{Key,kar}] = sort(dets:lookup(T, Key)), - ?line true = dets:member(T, Key), - ?line ok = dets:insert(T, [{Key,kar},{Key,kar}]), - ?line [{Key,bar},{Key,kar}] = sort(dets:lookup(T, Key)), - ?line true = dets:member(T, Key), - ?line ok = dets:delete_object(T, {Key,bar}), - ?line ok = dets:delete_object(T, {Key,kar}), - ?line [] = dets:lookup(T, Key), - ?line false = dets:member(T, Key), - ?line ok = dets:sync(T), - ?line [] = dets:lookup(T, Key), - ?line false = dets:member(T, Key), - - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), + ok = dets:delete(T, Key), + ok = dets:sync(T), + ok = dets:delete(T, Key), + ok = dets:insert(T, {Key,foo}), + ok = dets:insert(T, {Key,bar}), + [{Key,bar},{Key,foo}] = sort(dets:lookup(T, Key)), + true = dets:member(T, Key), + ok = dets:delete_object(T, {Key,foo}), + ok = dets:insert(T, {Key,kar}), + [{Key,bar},{Key,kar}] = sort(dets:lookup(T, Key)), + true = dets:member(T, Key), + ok = dets:insert(T, [{Key,kar},{Key,kar}]), + [{Key,bar},{Key,kar}] = sort(dets:lookup(T, Key)), + true = dets:member(T, Key), + ok = dets:delete_object(T, {Key,bar}), + ok = dets:delete_object(T, {Key,kar}), + [] = dets:lookup(T, Key), + false = dets:member(T, Key), + ok = dets:sync(T), + [] = dets:lookup(T, Key), + false = dets:member(T, Key), + + OtherValues = sort(lookup_keys(T, OtherKeys)), if Extra -> %% Let the table grow for a while, if it needs to. - ?line All1 = get_all_objects(T), - ?line dets:safe_fixtable(T, false), - ?line timer:sleep(1200), - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), - ?line dets:safe_fixtable(T, true), - ?line All2 = get_all_objects(T), - ?line FAll2 = get_all_objects_fast(T), - ?line true = sort(All2) =:= sort(FAll2), + All1 = get_all_objects(T), + dets:safe_fixtable(T, false), + timer:sleep(1200), + OtherValues = sort(lookup_keys(T, OtherKeys)), + dets:safe_fixtable(T, true), + All2 = get_all_objects(T), + FAll2 = get_all_objects_fast(T), + true = sort(All2) =:= sort(FAll2), case symdiff(All1, All2) of {[],[]} -> ok; {X,Y} -> @@ -2687,28 +2684,28 @@ cache_bags(Config, DelayedWrite, Extra, Sz, Version) -> true -> ok end, - ?line ok = dets:close(T), + ok = dets:close(T), file:delete(Fname), %% Second object of a key added and looked up simultaneously. R1 = {index_test,1,2,3,4}, R2 = {index_test,2,2,13,14}, R3 = {index_test,1,12,13,14}, - ?line {ok, _} = dets:open_file(T,[{version,Version},{type,bag}, - {keypos,2},{file,Fname}]), - ?line ok = dets:insert(T,R1), - ?line ok = dets:sync(T), - ?line ok = dets:insert(T,R2), - ?line ok = dets:sync(T), - ?line ok = dets:insert(T,R3), - ?line [R1,R3] = sort(dets:lookup(T,1)), - ?line true = dets:member(T, 1), - ?line [R1,R3] = sort(dets:lookup(T,1)), - ?line true = dets:member(T, 1), - ?line ok = dets:close(T), + {ok, _} = dets:open_file(T,[{version,Version},{type,bag}, + {keypos,2},{file,Fname}]), + ok = dets:insert(T,R1), + ok = dets:sync(T), + ok = dets:insert(T,R2), + ok = dets:sync(T), + ok = dets:insert(T,R3), + [R1,R3] = sort(dets:lookup(T,1)), + true = dets:member(T, 1), + [R1,R3] = sort(dets:lookup(T,1)), + true = dets:member(T, 1), + ok = dets:close(T), file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. cache_duplicate_bags_v8(doc) -> @@ -2743,11 +2740,11 @@ cache_dup_bags(Config, DelayedWrite, Extra, Sz, Version) -> %% Sz = integer(). Size of the inserted tuples. T = cache, - ?line Fname = filename(cache, Config), - ?line file:delete(Fname), + Fname = filename(cache, Config), + file:delete(Fname), P0 = pps(), - ?line {ok, _} = + {ok, _} = dets:open_file(T,[{version, Version}, {file,Fname}, {type,duplicate_bag}, {delayed_write, DelayedWrite}]), @@ -2757,53 +2754,53 @@ cache_dup_bags(Config, DelayedWrite, Extra, Sz, Version) -> if Extra -> %% Insert enough to get three keys in some slot. - ?line dets:safe_fixtable(T, true), + dets:safe_fixtable(T, true), insert_objs(T, 1, Sz, Dups); true -> {1,[]} end, Tuple = erlang:make_tuple(Sz, Key), - ?line ok = dets:delete(T, Key), - ?line ok = dets:sync(T), - ?line false = dets:member(T, Key), + ok = dets:delete(T, Key), + ok = dets:sync(T), + false = dets:member(T, Key), %% The values of keys in the same slot as Key are checked. - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), + OtherValues = sort(lookup_keys(T, OtherKeys)), - ?line ok = dets:insert(T, Tuple), - ?line [Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:insert(T, [Tuple,Tuple]), + ok = dets:insert(T, Tuple), + [Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:insert(T, [Tuple,Tuple]), %% If no delay, the cache gets filled immediately, and written. - ?line [Tuple,Tuple,Tuple] = dets:lookup_keys(T, [Key,a,b,c,d,e,f]), - ?line true = dets:member(T, Key), + [Tuple,Tuple,Tuple] = dets:lookup_keys(T, [Key,a,b,c,d,e,f]), + true = dets:member(T, Key), %% If delay, this happens without file access. %% (This is no longer true; cache lookup has been simplified.) - ?line ok = dets:delete(T,Key), - ?line ok = dets:insert(T,Tuple), - ?line ok = dets:insert(T,Tuple), - ?line [Tuple,Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), - ?line ok = dets:sync(T), - ?line [Tuple,Tuple] = dets:lookup(T, Key), - ?line true = dets:member(T, Key), + ok = dets:delete(T,Key), + ok = dets:insert(T,Tuple), + ok = dets:insert(T,Tuple), + [Tuple,Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), + ok = dets:sync(T), + [Tuple,Tuple] = dets:lookup(T, Key), + true = dets:member(T, Key), %% One object in the cache, one on the file. - ?line ok = dets:delete(T,Key), - ?line ok = dets:insert(T,Tuple), - ?line ok = dets:sync(T), - ?line ok = dets:insert(T,Tuple), - ?line true = dets:member(T, Key), % should not read the file, but it does.. + ok = dets:delete(T,Key), + ok = dets:insert(T,Tuple), + ok = dets:sync(T), + ok = dets:insert(T,Tuple), + true = dets:member(T, Key), % should not read the file, but it does.. %% Key's objects are is on file only, %% key toto in the cache (if there is one). - ?line ok = dets:delete(T,toto), - ?line ok = dets:insert(T,[{toto,b},{toto,b}]), - ?line true = sort([Tuple,Tuple,{toto,b},{toto,b}]) =:= + ok = dets:delete(T,toto), + ok = dets:insert(T,[{toto,b},{toto,b}]), + true = sort([Tuple,Tuple,{toto,b},{toto,b}]) =:= sort(dets:lookup_keys(T, [Key,toto])), - ?line true = dets:member(T, toto), - ?line Size = dets:info(T, size), + true = dets:member(T, toto), + Size = dets:info(T, size), %% Two objects with the same key on the file. %% Delete them, add two objects. @@ -2824,18 +2821,18 @@ cache_dup_bags(Config, DelayedWrite, Extra, Sz, Version) -> del_and_ins(object, T, Size, Tuple, Key, 1), del_and_ins(both, T, Size, Tuple, Key, 1), - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), + OtherValues = sort(lookup_keys(T, OtherKeys)), if Extra -> %% Let the table grow for a while, if it needs to. - ?line All1 = get_all_objects(T), - ?line dets:safe_fixtable(T, false), - ?line timer:sleep(1200), - ?line OtherValues = sort(lookup_keys(T, OtherKeys)), - ?line dets:safe_fixtable(T, true), - ?line All2 = get_all_objects(T), - ?line FAll2 = get_all_objects_fast(T), - ?line true = sort(All2) =:= sort(FAll2), + All1 = get_all_objects(T), + dets:safe_fixtable(T, false), + timer:sleep(1200), + OtherValues = sort(lookup_keys(T, OtherKeys)), + dets:safe_fixtable(T, true), + All2 = get_all_objects(T), + FAll2 = get_all_objects_fast(T), + true = sort(All2) =:= sort(FAll2), case symdiff(All1, All2) of {[],[]} -> ok; {X,Y} -> @@ -2845,10 +2842,10 @@ cache_dup_bags(Config, DelayedWrite, Extra, Sz, Version) -> true -> ok end, - ?line ok = dets:close(T), + ok = dets:close(T), file:delete(Fname), - ?line check_pps(P0), + check_pps(P0), ok. lookup_keys(_T, []) -> @@ -2859,47 +2856,47 @@ lookup_keys(T, Keys) -> del_and_ins(W, T, Size, Obj, Key, N) -> case W of object -> - ?line ok = dets:delete_object(T, Obj); + ok = dets:delete_object(T, Obj); key -> - ?line ok = dets:delete(T, Key); + ok = dets:delete(T, Key); both -> - ?line ok = dets:delete(T, Key), - ?line ok = dets:delete_object(T, Obj) + ok = dets:delete(T, Key), + ok = dets:delete_object(T, Obj) end, Objs = duplicate(N, Obj), - ?line [] = dets:lookup(T, Key), - ?line ok = dets:insert(T, Objs), - ?line Objs = dets:lookup_keys(T, [snurrespratt,Key]), - ?line true = Size + length(Objs)-2 =:= dets:info(T, size), - ?line Objs = dets:lookup(T, Key). + [] = dets:lookup(T, Key), + ok = dets:insert(T, Objs), + Objs = dets:lookup_keys(T, [snurrespratt,Key]), + true = Size + length(Objs)-2 =:= dets:info(T, size), + Objs = dets:lookup(T, Key). insert_objs(T, N, Sz, Dups) -> Seq = seq(N,N+255), L0 = map(fun(I) -> erlang:make_tuple(Sz, I) end, Seq), L = append(duplicate(Dups, L0)), - ?line ok = dets:insert(T, L), - ?line case search_slot(T, 0) of - false -> - insert_objs(T, N+256, Sz, Dups); - Keys -> - Keys - end. + ok = dets:insert(T, L), + case search_slot(T, 0) of + false -> + insert_objs(T, N+256, Sz, Dups); + Keys -> + Keys + end. search_slot(T, I) -> - ?line case dets:slot(T, I) of - '$end_of_table' -> - false; - Objs -> - case usort(map(fun(X) -> element(1, X) end, Objs)) of - [_, Key, _ | _] = Keys0 -> - Keys = delete(Key, Keys0), - {Key, Keys}; - _ -> - search_slot(T, I+1) - end - end. + case dets:slot(T, I) of + '$end_of_table' -> + false; + Objs -> + case usort(map(fun(X) -> element(1, X) end, Objs)) of + [_, Key, _ | _] = Keys0 -> + Keys = delete(Key, Keys0), + {Key, Keys}; + _ -> + search_slot(T, I+1) + end + end. symdiff(L1, L2) -> {X, _, Y} = @@ -2912,18 +2909,18 @@ otp_4208(suite) -> []; otp_4208(Config) when is_list(Config) -> Tab = otp_4208, - ?line FName = filename(Tab, Config), + FName = filename(Tab, Config), Expected = sort([{3,ghi,12},{1,abc,10},{4,jkl,13},{2,def,11}]), file:delete(FName), - ?line {ok, Tab} = dets:open_file(Tab, [{file,FName}]), - ?line ok = dets:insert(Tab, [{1,abc,10},{2,def,11},{3,ghi,12},{4,jkl,13}]), - ?line Expected = sort(dets:traverse(Tab, fun(X) -> {continue, X} end)), - ?line ok = dets:close(Tab), - - ?line {ok, Tab} = dets:open_file(Tab, [{access, read},{file,FName}]), - ?line Expected = sort(dets:traverse(Tab, fun(X) -> {continue, X} end)), - ?line ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, [{file,FName}]), + ok = dets:insert(Tab, [{1,abc,10},{2,def,11},{3,ghi,12},{4,jkl,13}]), + Expected = sort(dets:traverse(Tab, fun(X) -> {continue, X} end)), + ok = dets:close(Tab), + + {ok, Tab} = dets:open_file(Tab, [{access, read},{file,FName}]), + Expected = sort(dets:traverse(Tab, fun(X) -> {continue, X} end)), + ok = dets:close(Tab), file:delete(FName), ok. @@ -2934,21 +2931,21 @@ otp_4989(suite) -> []; otp_4989(Config) when is_list(Config) -> Tab = otp_4989, - ?line FName = filename(Tab, Config), + FName = filename(Tab, Config), %% Do exactly as in the error report. - ?line _Ets = ets:new(Tab, [named_table]), + _Ets = ets:new(Tab, [named_table]), ets_init(Tab, 100000), - ?line {ok, Tab} = + {ok, Tab} = dets:open_file(Tab, [{access, read_write}, {file,FName}, {keypos,2}]), - ?line ok = dets:from_ets(Tab, Tab), - ?line ok = dets:close(Tab), + ok = dets:from_ets(Tab, Tab), + ok = dets:close(Tab), %% Restore. - ?line {ok, Tab} = + {ok, Tab} = dets:open_file(Tab, [{access, read}, {keypos, 2}, {file, FName}]), - ?line true = ets:delete_all_objects(Tab), - ?line true = ets:from_dets(Tab, Tab), - ?line ok = dets:close(Tab), + true = ets:delete_all_objects(Tab), + true = ets:from_dets(Tab, Tab), + ok = dets:close(Tab), ets:delete(Tab), file:delete(FName), ok. @@ -2965,20 +2962,20 @@ otp_8898(suite) -> []; otp_8898(Config) when is_list(Config) -> Tab = otp_8898, - ?line FName = filename(Tab, Config), + FName = filename(Tab, Config), Server = self(), - ?line file:delete(FName), - ?line {ok, _} = dets:open_file(Tab,[{file, FName}]), - ?line [P1,P2,P3] = new_clients(3, Tab), + file:delete(FName), + {ok, _} = dets:open_file(Tab,[{file, FName}]), + [P1,P2,P3] = new_clients(3, Tab), Seq = [{P1,[sync]},{P2,[{lookup,1,[]}]},{P3,[{insert,{1,b}}]}], - ?line atomic_requests(Server, Tab, [[]], Seq), - ?line true = get_replies([{P1,ok},{P2,ok},{P3,ok}]), - ?line ok = dets:close(Tab), - ?line {ok, _} = dets:open_file(Tab,[{file, FName}]), - ?line file:delete(FName), + atomic_requests(Server, Tab, [[]], Seq), + true = get_replies([{P1,ok},{P2,ok},{P3,ok}]), + ok = dets:close(Tab), + {ok, _} = dets:open_file(Tab,[{file, FName}]), + file:delete(FName), ok. @@ -2988,25 +2985,25 @@ otp_8899(suite) -> []; otp_8899(Config) when is_list(Config) -> Tab = many_clients, - ?line FName = filename(Tab, Config), + FName = filename(Tab, Config), Server = self(), - ?line file:delete(FName), - ?line {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), - ?line [P1,P2,P3,P4] = new_clients(4, Tab), + file:delete(FName), + {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), + [P1,P2,P3,P4] = new_clients(4, Tab), MC = [Tab], Seq6a = [{P1,[{insert,[{used_to_be_skipped_by,match}]}, {lookup,1,[{1,a}]}]}, {P2,[{verbose,true,MC}]}, {P3,[{lookup,1,[{1,a}]}]}, {P4,[{verbose,true,MC}]}], - ?line atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq6a), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), - ?line [{1,a},{2,b},{3,c},{used_to_be_skipped_by,match}] = + atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq6a), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + [{1,a},{2,b},{3,c},{used_to_be_skipped_by,match}] = lists:sort(dets:match_object(Tab, '_')), - ?line _ = dets:close(Tab), - ?line file:delete(FName), + _ = dets:close(Tab), + file:delete(FName), ok. @@ -3016,14 +3013,14 @@ many_clients(suite) -> []; many_clients(Config) when is_list(Config) -> Tab = many_clients, - ?line FName = filename(Tab, Config), + FName = filename(Tab, Config), Server = self(), - ?line file:delete(FName), + file:delete(FName), P0 = pps(), - ?line {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), - ?line [P1,P2,P3,P4] = new_clients(4, Tab), + {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), + [P1,P2,P3,P4] = new_clients(4, Tab), %% dets:init_table/2 is used for making sure that all processes %% start sending requests before the Dets process begins to handle @@ -3034,67 +3031,67 @@ many_clients(Config) when is_list(Config) -> %% One key is read, updated, and read again. Seq1 = [{P1,[{lookup,1,[{1,a}]}]}, {P2,[{insert,{1,b}}]}, {P3,[{lookup,1,[{1,b}]}]}, {P4,[{lookup,1,[{1,b}]}]}], - ?line atomic_requests(Server, Tab, [[{1,a}]], Seq1), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [[{1,a}]], Seq1), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), %% Different keys read by different processes Seq2 = [{P1,[{member,1,true}]}, {P2,[{lookup,2,[{2,b}]}]}, {P3,[{lookup,1,[{1,a}]}]}, {P4,[{lookup,3,[{3,c}]}]}], - ?line atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq2), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq2), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), %% Reading deleted key. Seq3 = [{P1,[{delete_key,2}]}, {P2,[{lookup,1,[{1,a}]}]}, {P3,[{lookup,1,[{1,a}]}]}, {P4,[{member,2,false}]}], - ?line atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq3), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq3), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), %% Inserting objects. Seq4 = [{P1,[{insert,[{1,a},{2,b}]}]}, {P2,[{insert,[{2,c},{3,a}]}]}, {P3,[{insert,[{3,b},{4,d}]}]}, {P4,[{lookup_keys,[1,2,3,4],[{1,a},{2,c},{3,b},{4,d}]}]}], - ?line atomic_requests(Server, Tab, [], Seq4), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [], Seq4), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), %% Deleting objects. Seq5 = [{P1,[{delete_object,{1,a}}]}, {P2,[{delete_object,{1,a}}]}, {P3,[{delete_object,{3,c}}]}, {P4,[{lookup_keys,[1,2,3,4],[{2,b}]}]}], - ?line atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq5), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq5), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), %% Some request not streamed. Seq6 = [{P1,[{lookup,1,[{1,a}]}]}, {P2,[{info,size,3}]}, {P3,[{lookup,1,[{1,a}]}]}, {P4,[{info,size,3}]}], - ?line atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq6), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq6), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), %% Some request not streamed. Seq7 = [{P1,[{insert,[{3,a}]}]}, {P2,[{insert,[{3,b}]}]}, {P3,[{delete_object,{3,c}}]}, {P4,[{lookup,3,[{3,b}]}]}], - ?line atomic_requests(Server, Tab, [[{3,c}]], Seq7), - ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), + atomic_requests(Server, Tab, [[{3,c}]], Seq7), + true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]), - ?line put_requests(Server, [{P1,stop},{P2,stop},{P3,stop},{P4,stop}]), - ?line ok = dets:close(Tab), - ?line file:delete(FName), + put_requests(Server, [{P1,stop},{P2,stop},{P3,stop},{P4,stop}]), + ok = dets:close(Tab), + file:delete(FName), %% Check that errors are handled correctly by the streaming operators. - ?line {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), - ?line ok = ins(Tab, 100), + {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), + ok = ins(Tab, 100), Obj = {66,{item,number,66}}, - ?line {ok, ObjPos} = dets:where(Tab, Obj), - ?line ok = dets:close(Tab), + {ok, ObjPos} = dets:where(Tab, Obj), + ok = dets:close(Tab), %% Damaged object. crash(FName, ObjPos+12), - ?line {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), - ?line BadObject1 = dets:lookup_keys(Tab, [65,66,67,68,69]), - ?line bad_object(BadObject1, FName), - ?line _Error = dets:close(Tab), - ?line file:delete(FName), + {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]), + BadObject1 = dets:lookup_keys(Tab, [65,66,67,68,69]), + bad_object(BadObject1, FName), + _Error = dets:close(Tab), + file:delete(FName), - ?line check_pps(P0), + check_pps(P0), ok. @@ -3120,7 +3117,7 @@ get_replies(L) -> lists:all(fun({Pid,Reply}) -> Reply =:= get_reply(Pid) end, L). get_reply(Pid) -> - ?line receive {Pid, Reply} -> Reply end. + receive {Pid, Reply} -> Reply end. new_clients(0, _Tab) -> []; @@ -3135,7 +3132,7 @@ client(S, Tab) -> {S, stop} -> exit(normal); {S, ToDo} -> - ?line Reply = eval(ToDo, Tab), + Reply = eval(ToDo, Tab), case Reply of {error, _} -> io:format("~p: ~p~n", [self(), Reply]); _ -> ok @@ -3147,55 +3144,55 @@ client(S, Tab) -> eval([], _Tab) -> ok; eval([{verbose,Bool,Expected} | L], Tab) -> - ?line case dets:verbose(Bool) of - Expected -> eval(L, Tab); - Error -> {error, {verbose,Error}} - end; + case dets:verbose(Bool) of + Expected -> eval(L, Tab); + Error -> {error, {verbose,Error}} + end; eval([sync | L], Tab) -> - ?line case dets:sync(Tab) of - ok -> eval(L, Tab); - Error -> {error, {sync,Error}} - end; + case dets:sync(Tab) of + ok -> eval(L, Tab); + Error -> {error, {sync,Error}} + end; eval([{insert,Stuff} | L], Tab) -> - ?line case dets:insert(Tab, Stuff) of - ok -> eval(L, Tab); - Error -> {error, {insert,Stuff,Error}} - end; + case dets:insert(Tab, Stuff) of + ok -> eval(L, Tab); + Error -> {error, {insert,Stuff,Error}} + end; eval([{lookup,Key,Expected} | L], Tab) -> - ?line case dets:lookup(Tab, Key) of - Expected -> eval(L, Tab); - Else -> {error, {lookup,Key,Expected,Else}} - end; + case dets:lookup(Tab, Key) of + Expected -> eval(L, Tab); + Else -> {error, {lookup,Key,Expected,Else}} + end; eval([{lookup_keys,Keys,Expected} | L], Tab) -> %% Time order is destroyed... - ?line case dets:lookup_keys(Tab, Keys) of - R when is_list(R) -> - case lists:sort(Expected) =:= lists:sort(R) of - true -> eval(L, Tab); - false -> {error, {lookup_keys,Keys,Expected,R}} - end; - Else -> {error, {lookup_keys,Keys,Expected,Else}} - end; + case dets:lookup_keys(Tab, Keys) of + R when is_list(R) -> + case lists:sort(Expected) =:= lists:sort(R) of + true -> eval(L, Tab); + false -> {error, {lookup_keys,Keys,Expected,R}} + end; + Else -> {error, {lookup_keys,Keys,Expected,Else}} + end; eval([{member,Key,Expected} | L], Tab) -> - ?line case dets:member(Tab, Key) of - Expected -> eval(L, Tab); - Else -> {error, {member,Key,Expected,Else}} - end; + case dets:member(Tab, Key) of + Expected -> eval(L, Tab); + Else -> {error, {member,Key,Expected,Else}} + end; eval([{delete_key,Key} | L], Tab) -> - ?line case dets:delete(Tab, Key) of - ok -> eval(L, Tab); - Else -> {error, {delete_key,Key,Else}} - end; + case dets:delete(Tab, Key) of + ok -> eval(L, Tab); + Else -> {error, {delete_key,Key,Else}} + end; eval([{delete_object,Object} | L], Tab) -> - ?line case dets:delete_object(Tab, Object) of - ok -> eval(L, Tab); - Else -> {error, {delete_object,Object,Else}} - end; + case dets:delete_object(Tab, Object) of + ok -> eval(L, Tab); + Else -> {error, {delete_object,Object,Else}} + end; eval([{info,Tag,Expected} | L], Tab) -> - ?line case dets:info(Tab, Tag) of - Expected -> eval(L, Tab); - Else -> {error, {info,Tag,Else,Expected}} - end; + case dets:info(Tab, Tag) of + Expected -> eval(L, Tab); + Else -> {error, {info,Tag,Else,Expected}} + end; eval(Else, _Tab) -> {error, {bad_request,Else}}. @@ -3206,44 +3203,44 @@ otp_4906(suite) -> otp_4906(Config) when is_list(Config) -> N = 256*512 + 400, Tab = otp_4906, - ?line FName = filename(Tab, Config), + FName = filename(Tab, Config), file:delete(FName), - ?line {ok, Tab} = dets:open_file(Tab, [{file, FName}]), - ?line ok = ins_small(Tab, 0, N), - ?line ok = dets:close(Tab), - ?line {ok, Tab} = dets:open_file(Tab, [{file, FName}]), - ?line ok = read_4906(Tab, N-1), - ?line ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, [{file, FName}]), + ok = ins_small(Tab, 0, N), + ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, [{file, FName}]), + ok = read_4906(Tab, N-1), + ok = dets:close(Tab), file:delete(FName), %% If the (only) process fixing a table updates the table, the %% process will no longer be punished with a 1 ms delay (hm, the %% server is delayed, it should be the client...). In this example %% the writing process *is* delayed. - ?line {ok,Tab} = dets:open_file(Tab, [{file,FName}]), + {ok,Tab} = dets:open_file(Tab, [{file,FName}]), Parent = self(), FixPid = spawn_link(fun() -> dets:safe_fixtable(Tab, true), receive {Parent, stop} -> ok end end), - ?line ok = ins_small(Tab, 0, 1000), + ok = ins_small(Tab, 0, 1000), FixPid ! {Parent, stop}, timer:sleep(1), - ?line ok = dets:close(Tab), + ok = dets:close(Tab), file:delete(FName), ok. read_4906(_T, N) when N < 0 -> ok; read_4906(T, N) -> - ?line [_] = dets:lookup(T, N), + [_] = dets:lookup(T, N), read_4906(T, N-1). ins_small(_T, I, N) when I =:= N -> ok; ins_small(T, I, N) -> - ?line ok = dets:insert(T, {I}), + ok = dets:insert(T, {I}), ins_small(T, I+1, N). otp_5402(doc) -> @@ -3252,28 +3249,28 @@ otp_5402(suite) -> []; otp_5402(Config) when is_list(Config) -> Tab = otp_5402, - ?line File = filename:join(["cannot", "write", "this", "file"]), + File = filename:join(["cannot", "write", "this", "file"]), %% close - ?line{ok, T} = dets:open_file(Tab, [{ram_file,true}, - {file, File}]), - ?line ok = dets:insert(T, {1,a}), - ?line {error,{file_error,_,_}} = dets:close(T), + {ok, T} = dets:open_file(Tab, [{ram_file,true}, + {file, File}]), + ok = dets:insert(T, {1,a}), + {error,{file_error,_,_}} = dets:close(T), %% sync - ?line {ok, T} = dets:open_file(Tab, [{ram_file,true}, - {file, File}]), - ?line ok = dets:insert(T, {1,a}), - ?line {error,{file_error,_,_}} = dets:sync(T), - ?line {error,{file_error,_,_}} = dets:close(T), + {ok, T} = dets:open_file(Tab, [{ram_file,true}, + {file, File}]), + ok = dets:insert(T, {1,a}), + {error,{file_error,_,_}} = dets:sync(T), + {error,{file_error,_,_}} = dets:close(T), %% auto_save - ?line {ok, T} = dets:open_file(Tab, [{ram_file,true}, - {auto_save, 2000}, - {file, File}]), - ?line ok = dets:insert(T, {1,a}), - ?line timer:sleep(5000), - ?line {error,{file_error,_,_}} = dets:close(T), + {ok, T} = dets:open_file(Tab, [{ram_file,true}, + {auto_save, 2000}, + {file, File}]), + ok = dets:insert(T, {1,a}), + timer:sleep(5000), + {error,{file_error,_,_}} = dets:close(T), ok. simultaneous_open(doc) -> @@ -3284,12 +3281,12 @@ simultaneous_open(Config) -> Tab = sim_open, File = filename(Tab, Config), - ?line ok = monit(Tab, File), - ?line ok = kill_while_repairing(Tab, File), - ?line ok = kill_while_init(Tab, File), - ?line ok = open_ro(Tab, File), - ?line ok = open_w(Tab, File, 0, Config), - ?line ok = open_w(Tab, File, 100, Config), + ok = monit(Tab, File), + ok = kill_while_repairing(Tab, File), + ok = kill_while_init(Tab, File), + ok = open_ro(Tab, File), + ok = open_w(Tab, File, 0, Config), + ok = open_w(Tab, File, 100, Config), ok. %% One process logs and another process closes the log. Before @@ -3303,8 +3300,7 @@ monit(Tab, File) -> timer:sleep(100), spawn(F1), dets:close(Tab), - file:delete(File), - ok. + ok = file:delete(File). do_log(Tab) -> case catch dets:insert(Tab, {hej,san,sa}) of @@ -3314,7 +3310,7 @@ do_log(Tab) -> %% Kill the Dets process while repair is in progress. kill_while_repairing(Tab, File) -> - ?line create_opened_log(File), + create_opened_log(File), Delay = 1000, dets:start(), Parent = self(), @@ -3324,16 +3320,22 @@ kill_while_repairing(Tab, File) -> timer:sleep(Delay), Parent ! {self(), R} end, - ?line P1 = spawn(F), % will repair - timer:sleep(100), - ?line P2 = spawn(F), % pending... - ?line P3 = spawn(F), % pending... - ?line DetsPid = find_dets_pid([P1, P2, P3 | Ps]), + %% One of these will open the file, the other will be pending + %% until the file has been repaired: + P1 = spawn(F), + P2 = spawn(F), + P3 = spawn(F), + DetsPid = find_dets_pid([P1, P2, P3 | Ps]), exit(DetsPid, kill), - ?line receive {P1,R1} -> {'EXIT', {dets_process_died, _}} = R1 end, - ?line receive {P2,R2} -> {ok, _} = R2 end, - ?line receive {P3,R3} -> {ok, _} = R3 end, + receive {P1,R1} -> R1 end, + receive {P2,R2} -> R2 end, + receive {P3,R3} -> R3 end, + io:format("Killed pid: ~p~n", [DetsPid]), + io:format("Remaining Dets-pids (should be nil): ~p~n", + [find_dets_pids()]), + {replies,[{'EXIT', {dets_process_died, _}}, {ok,_}, {ok, _}]} = + {replies,lists:sort([R1, R2, R3])}, timer:sleep(200), case dets:info(Tab) of @@ -3341,7 +3343,7 @@ kill_while_repairing(Tab, File) -> ok; _Info -> timer:sleep(5000), - ?line undefined = dets:info(Tab) + undefined = dets:info(Tab) end, file:delete(File), @@ -3353,6 +3355,19 @@ find_dets_pid(P0) -> _ -> timer:sleep(100), find_dets_pid(P0) end. +find_dets_pid() -> + case find_dets_pids() of + [] -> + timer:sleep(100), + find_dets_pid(); + [Pid] -> + Pid + end. + +find_dets_pids() -> + lists:filter(fun(P) -> dets:pid2name(P) =/= undefined end, + erlang:processes()). + %% Kill the Dets process when there are users and an on-going %% initiailization. kill_while_init(Tab, File) -> @@ -3364,9 +3379,9 @@ kill_while_init(Tab, File) -> receive {Parent, die} -> ok end, {error, not_owner} = dets:close(Tab) end, - ?line P1 = spawn(F), - ?line P2 = spawn(F), - ?line P3 = spawn(F), + P1 = spawn(F), + P2 = spawn(F), + P3 = spawn(F), IF = fun() -> R = dets:open_file(Tab, [{file,File}]), Parent ! {self(), R}, @@ -3374,29 +3389,27 @@ kill_while_init(Tab, File) -> {'EXIT', {badarg, _}} = (catch dets:init_table(Tab, Fun)), receive {Parent, die} -> ok end end, - ?line P4 = spawn(IF), - ?line receive {P1,R1} -> {ok, _} = R1 end, - ?line receive {P2,R2} -> {ok, _} = R2 end, - ?line receive {P3,R3} -> {ok, _} = R3 end, - ?line receive {P4,R4} -> {ok, _} = R4 end, - ?line [DetsPid] = - lists:filter(fun(P) -> dets:pid2name(P) =/= undefined end, - erlang:processes()), + P4 = spawn(IF), + receive {P1,R1} -> {ok, _} = R1 end, + receive {P2,R2} -> {ok, _} = R2 end, + receive {P3,R3} -> {ok, _} = R3 end, + receive {P4,R4} -> {ok, _} = R4 end, + DetsPid = find_dets_pid(), exit(DetsPid, kill), timer:sleep(1000), - ?line undefined = dets:info(Tab), - ?line P1 ! {Parent, die}, - ?line P2 ! {Parent, die}, - ?line P3 ! {Parent, die}, - ?line P4 ! {Parent, die}, + undefined = dets:info(Tab), + P1 ! {Parent, die}, + P2 ! {Parent, die}, + P3 ! {Parent, die}, + P4 ! {Parent, die}, file:delete(File), timer:sleep(100), ok. open_ro(Tab, File) -> - ?line create_opened_log(File), + create_opened_log(File), Delay = 1000, Parent = self(), F = fun() -> @@ -3404,47 +3417,47 @@ open_ro(Tab, File) -> timer:sleep(Delay), Parent ! {self(), R} end, - ?line P1 = spawn(F), - ?line P2 = spawn(F), - ?line P3 = spawn(F), + P1 = spawn(F), + P2 = spawn(F), + P3 = spawn(F), - ?line receive {P1,R1} -> {error,{not_closed,_}} = R1 end, - ?line receive {P2,R2} -> {error,{not_closed,_}} = R2 end, - ?line receive {P3,R3} -> {error,{not_closed,_}} = R3 end, + receive {P1,R1} -> {error,{not_closed,_}} = R1 end, + receive {P2,R2} -> {error,{not_closed,_}} = R2 end, + receive {P3,R3} -> {error,{not_closed,_}} = R3 end, ok. open_w(Tab, File, Delay, Config) -> - ?line create_opened_log(File), + create_opened_log(File), Parent = self(), F = fun() -> R = dets:open_file(Tab, [{file,File}]), timer:sleep(Delay), Parent ! {self(), R} end, - ?line Pid1 = spawn(F), - ?line Pid2 = spawn(F), - ?line Pid3 = spawn(F), - ?line undefined = dets:info(Tab), % is repairing now - ?line 0 = qlen(), + Pid1 = spawn(F), + Pid2 = spawn(F), + Pid3 = spawn(F), + undefined = dets:info(Tab), % is repairing now + 0 = qlen(), Tab2 = t2, File2 = filename(Tab2, Config), - ?line file:delete(File2), - ?line {ok,Tab2} = dets:open_file(Tab2, [{file,File2}]), - ?line ok = dets:close(Tab2), - ?line file:delete(File2), - ?line 0 = qlen(), % still repairing - - ?line receive {Pid1,R1} -> {ok, Tab} = R1 end, - ?line receive {Pid2,R2} -> {ok, Tab} = R2 end, - ?line receive {Pid3,R3} -> {ok, Tab} = R3 end, + file:delete(File2), + {ok,Tab2} = dets:open_file(Tab2, [{file,File2}]), + ok = dets:close(Tab2), + file:delete(File2), + 0 = qlen(), % still repairing + + receive {Pid1,R1} -> {ok, Tab} = R1 end, + receive {Pid2,R2} -> {ok, Tab} = R2 end, + receive {Pid3,R3} -> {ok, Tab} = R3 end, timer:sleep(200), case dets:info(Tab) of undefined -> ok; _Info -> timer:sleep(5000), - ?line undefined = dets:info(Tab) + undefined = dets:info(Tab) end, file:delete(File), @@ -3457,10 +3470,10 @@ qlen() -> create_opened_log(File) -> Tab = t, file:delete(File), - ?line {ok, Tab} = dets:open_file(Tab, [{file,File}]), - ?line ok = ins(Tab, 60000), - ?line ok = dets:close(Tab), - ?line crash(File, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), + {ok, Tab} = dets:open_file(Tab, [{file,File}]), + ok = ins(Tab, 60000), + ok = dets:close(Tab), + crash(File, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), ok. insert_new(doc) -> @@ -3471,24 +3484,24 @@ insert_new(Config) -> Tab = insert_new, File = filename(Tab, Config), file:delete(File), - ?line {ok, T} = dets:open_file(Tab, [{file,File}]), - ?line {'EXIT', {badarg, _}} = (catch dets:insert_new(Tab, 14)), - ?line {'EXIT', {badarg, _}} = (catch dets:insert_new(Tab, {})), - ?line true = dets:insert_new(Tab, {1,a}), - ?line false = dets:insert_new(Tab, {1,a}), - ?line true = dets:insert_new(Tab, [{2,b}, {3,c}]), - ?line false = dets:insert_new(Tab, [{2,b}, {3,c}]), - ?line false = dets:insert_new(Tab, [{1,a}, {4,d}]), - ?line ok = dets:close(Tab), + {ok, T} = dets:open_file(Tab, [{file,File}]), + {'EXIT', {badarg, _}} = (catch dets:insert_new(Tab, 14)), + {'EXIT', {badarg, _}} = (catch dets:insert_new(Tab, {})), + true = dets:insert_new(Tab, {1,a}), + false = dets:insert_new(Tab, {1,a}), + true = dets:insert_new(Tab, [{2,b}, {3,c}]), + false = dets:insert_new(Tab, [{2,b}, {3,c}]), + false = dets:insert_new(Tab, [{1,a}, {4,d}]), + ok = dets:close(Tab), file:delete(File), - ?line {ok, T} = dets:open_file(Tab, [{file,File},{type,bag}]), - ?line true = dets:insert_new(Tab, {1,a}), - ?line false = dets:insert_new(Tab, {1,b}), - ?line true = dets:insert_new(Tab, [{2,b}, {3,c}]), - ?line false = dets:insert_new(Tab, [{2,a}, {3,d}]), - ?line false = dets:insert_new(Tab, [{1,a}, {4,d}]), - ?line ok = dets:close(Tab), + {ok, T} = dets:open_file(Tab, [{file,File},{type,bag}]), + true = dets:insert_new(Tab, {1,a}), + false = dets:insert_new(Tab, {1,b}), + true = dets:insert_new(Tab, [{2,b}, {3,c}]), + false = dets:insert_new(Tab, [{2,a}, {3,d}]), + false = dets:insert_new(Tab, [{1,a}, {4,d}]), + ok = dets:close(Tab), file:delete(File), @@ -3500,24 +3513,24 @@ repair_continuation(suite) -> []; repair_continuation(Config) -> Tab = repair_continuation_table, - ?line Fname = filename(repair_cont, Config), - ?line file:delete(Fname), - ?line {ok, _} = dets:open_file(Tab, [{file,Fname}]), - ?line ok = dets:insert(Tab, [{1,a},{2,b},{3,c}]), - - ?line MS = [{'_',[],[true]}], - - ?line {[true], C1} = dets:select(Tab, MS, 1), - ?line C2 = binary_to_term(term_to_binary(C1)), - ?line {'EXIT', {badarg, _}} = (catch dets:select(C2)), - ?line C3 = dets:repair_continuation(C2, MS), - ?line {[true], C4} = dets:select(C3), - ?line C5 = dets:repair_continuation(C4, MS), - ?line {[true], _} = dets:select(C5), - ?line {'EXIT', {badarg, _}} = (catch dets:repair_continuation(Tab, bu)), - - ?line ok = dets:close(Tab), - ?line file:delete(Fname), + Fname = filename(repair_cont, Config), + file:delete(Fname), + {ok, _} = dets:open_file(Tab, [{file,Fname}]), + ok = dets:insert(Tab, [{1,a},{2,b},{3,c}]), + + MS = [{'_',[],[true]}], + + {[true], C1} = dets:select(Tab, MS, 1), + C2 = binary_to_term(term_to_binary(C1)), + {'EXIT', {badarg, _}} = (catch dets:select(C2)), + C3 = dets:repair_continuation(C2, MS), + {[true], C4} = dets:select(C3), + C5 = dets:repair_continuation(C4, MS), + {[true], _} = dets:select(C5), + {'EXIT', {badarg, _}} = (catch dets:repair_continuation(Tab, bu)), + + ok = dets:close(Tab), + file:delete(Fname), ok. otp_5487(doc) -> @@ -3531,20 +3544,20 @@ otp_5487(Config) -> otp_5487(Config, Version) -> Tab = otp_5487, - ?line Fname = filename(otp_5487, Config), - ?line file:delete(Fname), - ?line Ets = ets:new(otp_5487, [public, set]), - ?line lists:foreach(fun(I) -> ets:insert(Ets, {I,I+1}) end, - lists:seq(0,1000)), - ?line {ok, _} = dets:open_file(Tab, [{file,Fname},{version,Version}]), - ?line ok = dets:from_ets(Tab, Ets), - ?line ok = dets:sync(Tab), - ?line ok = dets:close(Tab), - ?line {ok, _} = dets:open_file(Tab, [{file,Fname},{access,read}]), - ?line [{1,2}] = dets:lookup(Tab, 1), - ?line ok = dets:close(Tab), - ?line ets:delete(Ets), - ?line file:delete(Fname). + Fname = filename(otp_5487, Config), + file:delete(Fname), + Ets = ets:new(otp_5487, [public, set]), + lists:foreach(fun(I) -> ets:insert(Ets, {I,I+1}) end, + lists:seq(0,1000)), + {ok, _} = dets:open_file(Tab, [{file,Fname},{version,Version}]), + ok = dets:from_ets(Tab, Ets), + ok = dets:sync(Tab), + ok = dets:close(Tab), + {ok, _} = dets:open_file(Tab, [{file,Fname},{access,read}]), + [{1,2}] = dets:lookup(Tab, 1), + ok = dets:close(Tab), + ets:delete(Ets), + file:delete(Fname). otp_6206(doc) -> ["OTP-6206. Badly formed free lists."]; @@ -3556,15 +3569,15 @@ otp_6206(Config) -> file:delete(File), Options = [{file,File}], - ?line {ok, Tab} = dets:open_file(Tab, Options), + {ok, Tab} = dets:open_file(Tab, Options), NObjs = 13006, - ?line ok = ins(Tab, NObjs), - ?line ok = del(Tab, NObjs, 2), - ?line ok = dets:close(Tab), + ok = ins(Tab, NObjs), + ok = del(Tab, NObjs, 2), + ok = dets:close(Tab), %% Used to return {badmatch,{error,{bad_freelists,File}}. - ?line {ok, Tab} = dets:open_file(Tab, [{repair,false}|Options]), - ?line ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, [{repair,false}|Options]), + ok = dets:close(Tab), file:delete(File), ok. @@ -3577,10 +3590,10 @@ otp_6359(Config) -> File = filename(Tab, Config), file:delete(File), - ?line {ok, _} = dets:open_file(Tab, [{file, File}]), + {ok, _} = dets:open_file(Tab, [{file, File}]), %% Used to return {[], Cont}: - ?line '$end_of_table' = dets:match(Tab, '_', 100), - ?line ok = dets:close(Tab), + '$end_of_table' = dets:match(Tab, '_', 100), + ok = dets:close(Tab), file:delete(File), ok. @@ -3605,47 +3618,47 @@ otp_4738_dupbag(Version, Config) -> One = 1, FOne = float(One), Args = [{file,File},{type,duplicate_bag},{version,Version}], - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), - ?line ok = dets:sync(Tab), - ?line [{F,One},{F,FOne}] = dets:lookup(Tab, F), - ?line [{I,One},{I,FOne}] = dets:lookup(Tab, I), - ?line ok = dets:insert(Tab, [{F,One},{F,FOne}]), - ?line [{I,One},{I,FOne},{F,One},{F,FOne},{F,One},{F,FOne}] = + {ok, Tab} = dets:open_file(Tab, Args), + ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), + ok = dets:sync(Tab), + [{F,One},{F,FOne}] = dets:lookup(Tab, F), + [{I,One},{I,FOne}] = dets:lookup(Tab, I), + ok = dets:insert(Tab, [{F,One},{F,FOne}]), + [{I,One},{I,FOne},{F,One},{F,FOne},{F,One},{F,FOne}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:insert(Tab, [{F,FOne},{F,One}]), - ?line [{I,One},{I,FOne},{F,One},{F,FOne},{F,One}, + ok = dets:insert(Tab, [{F,FOne},{F,One}]), + [{I,One},{I,FOne},{F,One},{F,FOne},{F,One}, {F,FOne},{F,FOne},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:delete_object(Tab, {I,FOne}), - ?line [{I,One},{F,One},{F,FOne},{F,One},{F,FOne},{F,FOne},{F,One}] = + ok = dets:delete_object(Tab, {I,FOne}), + [{I,One},{F,One},{F,FOne},{F,One},{F,FOne},{F,FOne},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:insert(Tab, {I,FOne}), - ?line [{I,One},{I,FOne},{F,One},{F,FOne},{F,One}, + ok = dets:insert(Tab, {I,FOne}), + [{I,One},{I,FOne},{F,One},{F,FOne},{F,One}, {F,FOne},{F,FOne},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:delete_object(Tab, {F,FOne}), - ?line [{I,One},{I,FOne},{F,One},{F,One},{F,One}] = + ok = dets:delete_object(Tab, {F,FOne}), + [{I,One},{I,FOne},{F,One},{F,One},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:delete(Tab, F), - ?line [{I,One},{I,FOne}] = dets:match_object(Tab, '_'), - ?line ok = dets:close(Tab), + ok = dets:delete(Tab, F), + [{I,One},{I,FOne}] = dets:match_object(Tab, '_'), + ok = dets:close(Tab), file:delete(File), Zero = 0, FZero = float(Zero), - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), - ?line ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), - ?line ok = dets:insert(Tab, [{I,Zero},{F,Zero},{I,FZero},{I,FZero}]), - ?line Objs0 = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, Args), + ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), + ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), + ok = dets:insert(Tab, [{I,Zero},{F,Zero},{I,FZero},{I,FZero}]), + Objs0 = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), crash(File, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED), io:format("Expect repair:~n"), - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line Objs1 = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), - ?line Objs1 = Objs0, + {ok, Tab} = dets:open_file(Tab, Args), + Objs1 = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), + Objs1 = Objs0, file:delete(File), ok. @@ -3658,26 +3671,26 @@ otp_4738_bag(Version, Config) -> One = 1, FOne = float(One), Args = [{file,File},{type,bag},{version,Version}], - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), - ?line ok = dets:sync(Tab), - ?line [{F,One},{F,FOne}] = dets:lookup(Tab, F), - ?line [{I,One},{I,FOne}] = dets:lookup(Tab, I), - ?line ok = dets:insert(Tab, [{F,One},{F,FOne}]), - ?line [{I,One},{I,FOne},{F,One},{F,FOne}] = + {ok, Tab} = dets:open_file(Tab, Args), + ok = dets:insert(Tab, [{I,One},{F,One},{I,FOne},{F,FOne}]), + ok = dets:sync(Tab), + [{F,One},{F,FOne}] = dets:lookup(Tab, F), + [{I,One},{I,FOne}] = dets:lookup(Tab, I), + ok = dets:insert(Tab, [{F,One},{F,FOne}]), + [{I,One},{I,FOne},{F,One},{F,FOne}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:insert(Tab, [{F,FOne},{F,One}]), - ?line [{I,One},{I,FOne},{F,FOne},{F,One}] = + ok = dets:insert(Tab, [{F,FOne},{F,One}]), + [{I,One},{I,FOne},{F,FOne},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:delete_object(Tab, {I,FOne}), - ?line [{I,One},{F,FOne},{F,One}] = + ok = dets:delete_object(Tab, {I,FOne}), + [{I,One},{F,FOne},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:insert(Tab, {I,FOne}), - ?line [{I,One},{I,FOne},{F,FOne},{F,One}] = + ok = dets:insert(Tab, {I,FOne}), + [{I,One},{I,FOne},{F,FOne},{F,One}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:delete(Tab, F), - ?line [{I,One},{I,FOne}] = dets:match_object(Tab, '_'), - ?line ok = dets:close(Tab), + ok = dets:delete(Tab, F), + [{I,One},{I,FOne}] = dets:match_object(Tab, '_'), + ok = dets:close(Tab), file:delete(File). otp_4738_set(Version, Config) -> @@ -3689,53 +3702,53 @@ otp_4738_set(Version, Config) -> %% I and F share the same slot. I = -12857447, F = float(I), - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line ok = dets:insert(Tab, [{I},{F}]), - ?line ok = dets:sync(Tab), - ?line [{F}] = dets:lookup(Tab, F), - ?line [{I}] = dets:lookup(Tab, I), - ?line ok = dets:insert(Tab, [{F}]), - ?line [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, Args), + ok = dets:insert(Tab, [{I},{F}]), + ok = dets:sync(Tab), + [{F}] = dets:lookup(Tab, F), + [{I}] = dets:lookup(Tab, I), + ok = dets:insert(Tab, [{F}]), + [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), file:delete(File), - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line ok = dets:insert(Tab, [{I}]), - ?line ok = dets:sync(Tab), - ?line [] = dets:lookup(Tab, F), - ?line [{I}] = dets:lookup(Tab, I), - ?line ok = dets:insert(Tab, [{F}]), - ?line [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), + {ok, Tab} = dets:open_file(Tab, Args), + ok = dets:insert(Tab, [{I}]), + ok = dets:sync(Tab), + [] = dets:lookup(Tab, F), + [{I}] = dets:lookup(Tab, I), + ok = dets:insert(Tab, [{F}]), + [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), file:delete(File), - ?line {ok, Tab} = dets:open_file(Tab, Args), + {ok, Tab} = dets:open_file(Tab, Args), ok = dets:insert(Tab, [{I},{F}]), %% {insert, ...} in the cache, try lookup: - ?line [{F}] = dets:lookup(Tab, F), - ?line [{I}] = dets:lookup(Tab, I), + [{F}] = dets:lookup(Tab, F), + [{I}] = dets:lookup(Tab, I), %% Both were found, but that cannot be verified. - ?line [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), + [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), file:delete(File), - ?line {ok, Tab} = dets:open_file(Tab, Args), - ?line ok = dets:insert(Tab, [{I}]), - ?line ok = dets:sync(Tab), - ?line ok = dets:insert(Tab, [{F}]), + {ok, Tab} = dets:open_file(Tab, Args), + ok = dets:insert(Tab, [{I}]), + ok = dets:sync(Tab), + ok = dets:insert(Tab, [{F}]), %% {insert, ...} in the cache, try lookup: - ?line [{F}] = dets:lookup(Tab, F), - ?line [{I}] = dets:lookup(Tab, I), - ?line [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), + [{F}] = dets:lookup(Tab, F), + [{I}] = dets:lookup(Tab, I), + [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), file:delete(File), - ?line {ok, Tab} = dets:open_file(Tab, Args), + {ok, Tab} = dets:open_file(Tab, Args), %% Both operations in the cache: - ?line ok = dets:insert(Tab, [{I}]), - ?line ok = dets:insert(Tab, [{F}]), - ?line [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), - ?line ok = dets:close(Tab), + ok = dets:insert(Tab, [{I}]), + ok = dets:insert(Tab, [{F}]), + [{I},{F}] = dets_utils:mkeysort(1, dets:match_object(Tab, '_')), + ok = dets:close(Tab), file:delete(File), ok. @@ -3749,9 +3762,9 @@ otp_7146(Config) -> file:delete(File), Max = 2048, - ?line {ok, Tab} = dets:open_file(Tab, [{max_no_slots,Max}, {file,File}]), + {ok, Tab} = dets:open_file(Tab, [{max_no_slots,Max}, {file,File}]), write_dets(Tab, Max), - ?line ok = dets:close(Tab), + ok = dets:close(Tab), file:delete(File), ok. @@ -3773,11 +3786,11 @@ otp_8070(Config) when is_list(Config) -> Tab = otp_8070, File = filename(Tab, Config), file:delete(File), - ?line {ok, _} = dets:open_file(Tab, [{file,File},{type, duplicate_bag}]), - ?line ok = dets:insert(Tab, [{3,0}]), - ?line false = dets:insert_new(Tab, [{3,1},{3,1}]), - ?line [{3,0}] = dets:lookup(Tab, 3), - ?line ok = dets:close(Tab), + {ok, _} = dets:open_file(Tab, [{file,File},{type, duplicate_bag}]), + ok = dets:insert(Tab, [{3,0}]), + false = dets:insert_new(Tab, [{3,1},{3,1}]), + [{3,0}] = dets:lookup(Tab, 3), + ok = dets:close(Tab), file:delete(File), ok. @@ -3790,19 +3803,19 @@ otp_8856(Config) when is_list(Config) -> File = filename(Tab, Config), file:delete(File), Me = self(), - ?line {ok, _} = dets:open_file(Tab, [{type, bag}, {file, File}]), + {ok, _} = dets:open_file(Tab, [{type, bag}, {file, File}]), spawn(fun()-> Me ! {1, dets:insert(Tab, [])} end), spawn(fun()-> Me ! {2, dets:insert_new(Tab, [])} end), - ?line ok = dets:close(Tab), - ?line receive {1, ok} -> ok end, - ?line receive {2, true} -> ok end, + ok = dets:close(Tab), + receive {1, ok} -> ok end, + receive {2, true} -> ok end, file:delete(File), - ?line {ok, _} = dets:open_file(Tab, [{type, set}, {file, File}]), + {ok, _} = dets:open_file(Tab, [{type, set}, {file, File}]), spawn(fun() -> dets:delete(Tab, 0) end), spawn(fun() -> Me ! {3, dets:insert_new(Tab, {0,0})} end), - ?line ok = dets:close(Tab), - ?line receive {3, true} -> ok end, + ok = dets:close(Tab), + receive {3, true} -> ok end, file:delete(File), ok. @@ -3813,19 +3826,19 @@ otp_8903(suite) -> otp_8903(Config) when is_list(Config) -> Tab = otp_8903, File = filename(Tab, Config), - ?line {ok,T} = dets:open_file(bug, [{file,File}]), - ?line ok = dets:insert(T, [{1,a},{2,b},{3,c}]), - ?line dets:safe_fixtable(T, true), - ?line {[_],C1} = dets:match_object(T, '_', 1), - ?line {BC1,_D} = dets:bchunk(T, start), - ?line ok = dets:close(T), - ?line {'EXIT', {badarg, _}} = (catch {foo,dets:match_object(C1)}), - ?line {'EXIT', {badarg, _}} = (catch {foo,dets:bchunk(T, BC1)}), - ?line {ok,T} = dets:open_file(bug, [{file,File}]), - ?line false = dets:info(T, safe_fixed), - ?line {'EXIT', {badarg, _}} = (catch {foo,dets:match_object(C1)}), - ?line {'EXIT', {badarg, _}} = (catch {foo,dets:bchunk(T, BC1)}), - ?line ok = dets:close(T), + {ok,T} = dets:open_file(bug, [{file,File}]), + ok = dets:insert(T, [{1,a},{2,b},{3,c}]), + dets:safe_fixtable(T, true), + {[_],C1} = dets:match_object(T, '_', 1), + {BC1,_D} = dets:bchunk(T, start), + ok = dets:close(T), + {'EXIT', {badarg, _}} = (catch {foo,dets:match_object(C1)}), + {'EXIT', {badarg, _}} = (catch {foo,dets:bchunk(T, BC1)}), + {ok,T} = dets:open_file(bug, [{file,File}]), + false = dets:info(T, safe_fixed), + {'EXIT', {badarg, _}} = (catch {foo,dets:match_object(C1)}), + {'EXIT', {badarg, _}} = (catch {foo,dets:bchunk(T, BC1)}), + ok = dets:close(T), file:delete(File), ok. @@ -3841,23 +3854,23 @@ otp_8923(Config) when is_list(Config) -> Bin = list_to_binary([ 0 || _ <- lists:seq(1, 400) ]), BigBin = list_to_binary([ 0 ||_ <- lists:seq(1, 4000)]), Ets = ets:new(temp, [{keypos,1}]), - ?line [ true = ets:insert(Ets, {C,Bin}) || C <- lists:seq(1, 700) ], - ?line true = ets:insert(Ets, {helper_data,BigBin}), - ?line true = ets:insert(Ets, {prim_btree,BigBin}), - ?line true = ets:insert(Ets, {sec_btree,BigBin}), + [ true = ets:insert(Ets, {C,Bin}) || C <- lists:seq(1, 700) ], + true = ets:insert(Ets, {helper_data,BigBin}), + true = ets:insert(Ets, {prim_btree,BigBin}), + true = ets:insert(Ets, {sec_btree,BigBin}), %% Note: too few slots; re-hash will take place - ?line {ok, Tab} = dets:open_file(Tab, [{file,File}]), - ?line Tab = ets:to_dets(Ets, Tab), - ?line ok = dets:close(Tab), - ?line true = ets:delete(Ets), + {ok, Tab} = dets:open_file(Tab, [{file,File}]), + Tab = ets:to_dets(Ets, Tab), + ok = dets:close(Tab), + true = ets:delete(Ets), - ?line {ok,Ref} = dets:open_file(File), - ?line [{1,_}] = dets:lookup(Ref, 1), - ?line ok = dets:close(Ref), + {ok,Ref} = dets:open_file(File), + [{1,_}] = dets:lookup(Ref, 1), + ok = dets:close(Ref), - ?line {ok,Ref2} = dets:open_file(File), - ?line [{helper_data,_}] = dets:lookup(Ref2, helper_data), - ?line ok = dets:close(Ref2), + {ok,Ref2} = dets:open_file(File), + [{helper_data,_}] = dets:lookup(Ref2, helper_data), + ok = dets:close(Ref2), file:delete(File), ok. @@ -3874,87 +3887,16 @@ otp_9282(Config) when is_list(Config) -> some_calls(Tab, Config) -> File = filename(ref, Config), - ?line {ok,T} = dets:open_file(Tab, [{file,File}]), - ?line T = Tab, - ?line false = dets:info(T, safe_fixed), - ?line File = dets:info(T, filename), - ?line ok = dets:insert(Tab, [{3,0}]), - ?line [{3,0}] = dets:lookup(Tab, 3), - ?line [{3,0}] = dets:traverse(Tab, fun(X) -> {continue, X} end), - ?line ok = dets:close(T), + {ok,T} = dets:open_file(Tab, [{file,File}]), + T = Tab, + false = dets:info(T, safe_fixed), + File = dets:info(T, filename), + ok = dets:insert(Tab, [{3,0}]), + [{3,0}] = dets:lookup(Tab, 3), + [{3,0}] = dets:traverse(Tab, fun(X) -> {continue, X} end), + ok = dets:close(T), file:delete(File). -otp_9607(doc) -> - ["OTP-9607. Test downgrading the slightly changed format."]; -otp_9607(suite) -> - []; -otp_9607(Config) when is_list(Config) -> - %% Note: the bug is about almost full tables. The fix of that - %% problem is *not* tested here. - Version = r13b, - case ?t:is_release_available(atom_to_list(Version)) of - true -> - T = otp_9607, - File = filename(T, Config), - Key = a, - Value = 1, - Args = [{file,File}], - ?line {ok, T} = dets:open_file(T, Args), - ?line ok = dets:insert(T, {Key, Value}), - ?line ok = dets:close(T), - - ?line Call = fun(P, A) -> - P ! {self(), A}, - receive - {P, Ans} -> - Ans - after 5000 -> - exit(other_process_dead) - end - end, - %% Create a file on the modified format, read the file - %% with an emulator that doesn't know about the modified - %% format. - ?line {ok, Node} = start_node_rel(Version, Version, slave), - ?line Pid = rpc:call(Node, erlang, spawn, - [?MODULE, dets_dirty_loop, []]), - ?line {error,{needs_repair, File}} = - Call(Pid, [open, T, Args++[{repair,false}]]), - io:format("Expect repair:~n"), - ?line {ok, T} = Call(Pid, [open, T, Args]), - ?line [{Key,Value}] = Call(Pid, [read, T, Key]), - ?line ok = Call(Pid, [close, T]), - file:delete(File), - - %% Create a file on the unmodified format. Modify the file - %% using an emulator that must not turn the file into the - %% modified format. Read the file and make sure it is not - %% repaired. - ?line {ok, T} = Call(Pid, [open, T, Args]), - ?line ok = Call(Pid, [write, T, {Key,Value}]), - ?line [{Key,Value}] = Call(Pid, [read, T, Key]), - ?line ok = Call(Pid, [close, T]), - - Key2 = b, - Value2 = 2, - - ?line {ok, T} = dets:open_file(T, Args), - ?line [{Key,Value}] = dets:lookup(T, Key), - ?line ok = dets:insert(T, {Key2,Value2}), - ?line ok = dets:close(T), - - ?line {ok, T} = Call(Pid, [open, T, Args++[{repair,false}]]), - ?line [{Key2,Value2}] = Call(Pid, [read, T, Key2]), - ?line ok = Call(Pid, [close, T]), - - ?t:stop_node(Node), - file:delete(File), - ok; - false -> - {skipped, "No support for old node"} - end. - - %% %% Parts common to several test cases @@ -3962,21 +3904,21 @@ otp_9607(Config) when is_list(Config) -> start_node_rel(Name, Rel, How) -> Release = [{release, atom_to_list(Rel)}], - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line test_server:start_node(Name, How, - [{args, - " -kernel net_setuptime 100 " - " -pa " ++ Pa}, - {erl, Release}]). + Pa = filename:dirname(code:which(?MODULE)), + test_server:start_node(Name, How, + [{args, + " -kernel net_setuptime 100 " + " -pa " ++ Pa}, + {erl, Release}]). crash(File, Where) -> crash(File, Where, 10). crash(File, Where, What) when is_integer(What) -> - ?line {ok, Fd} = file:open(File, [read,write]), - ?line file:position(Fd, Where), - ?line ok = file:write(Fd, [What]), - ?line ok = file:close(Fd). + {ok, Fd} = file:open(File, [read,write]), + file:position(Fd, Where), + ok = file:write(Fd, [What]), + ok = file:close(Fd). args(Config) -> {Sets, Bags, Dups} = @@ -4031,56 +3973,56 @@ zip_filename([], [], [], S1, B1, D1, _, _Conf) -> del_test(Tab) -> ?format("Deltest on ~p~n", [Tab]), - ?line Objs = safe_get_all_objects(Tab), - ?line Keys = map(fun(X) -> element(1, X) end, Objs), - ?line foreach(fun(Key) -> dets:delete(Tab, Key) end, Keys), - ?line 0 = length(get_all_objects(Tab)), - ?line [] = get_all_objects_fast(Tab), - ?line 0 = dets:info(Tab, size). + Objs = safe_get_all_objects(Tab), + Keys = map(fun(X) -> element(1, X) end, Objs), + foreach(fun(Key) -> dets:delete(Tab, Key) end, Keys), + 0 = length(get_all_objects(Tab)), + [] = get_all_objects_fast(Tab), + 0 = dets:info(Tab, size). del_obj_test(Tab) -> ?format("Delobjtest on ~p~n", [Tab]), - ?line Objs = safe_get_all_objects(Tab), - ?line LL = length(Objs), - ?line LL = dets:info(Tab, size), - ?line foreach(fun(Obj) -> dets:delete_object(Tab, Obj) end, Objs), - ?line 0 = length(get_all_objects(Tab)), - ?line [] = get_all_objects_fast(Tab), - ?line 0 = dets:info(Tab, size). + Objs = safe_get_all_objects(Tab), + LL = length(Objs), + LL = dets:info(Tab, size), + foreach(fun(Obj) -> dets:delete_object(Tab, Obj) end, Objs), + 0 = length(get_all_objects(Tab)), + [] = get_all_objects_fast(Tab), + 0 = dets:info(Tab, size). match_del_test(Tab) -> - ?line ?format("Match delete test on ~p~n", [Tab]), - ?line ok = dets:match_delete(Tab, {'_','_','_'}), - ?line Sz = dets:info(Tab, size), - ?line true = Sz =:= length(dets:match_object(Tab, '_')), - ?line ok = dets:match_delete(Tab, '_'), - ?line 0 = dets:info(Tab, size), - ?line 0 = length(get_all_objects(Tab)), - ?line [] = get_all_objects_fast(Tab). + ?format("Match delete test on ~p~n", [Tab]), + ok = dets:match_delete(Tab, {'_','_','_'}), + Sz = dets:info(Tab, size), + true = Sz =:= length(dets:match_object(Tab, '_')), + ok = dets:match_delete(Tab, '_'), + 0 = dets:info(Tab, size), + 0 = length(get_all_objects(Tab)), + [] = get_all_objects_fast(Tab). trav_test(_Data, Len, Tab) -> ?format("Travtest on ~p~n", [Tab]), - ?line _X0 = dets:traverse(Tab, fun(_X) -> continue end), - ?line XX = dets:traverse(Tab, fun(X) -> {continue, X} end), - ?line case Len =:= length(XX) of + _X0 = dets:traverse(Tab, fun(_X) -> continue end), + XX = dets:traverse(Tab, fun(X) -> {continue, X} end), + case Len =:= length(XX) of false -> ?format("DIFF ~p~n", [XX -- _Data]); true -> ok end, - ?line 1 = length(dets:traverse(Tab, fun(X) -> {done, X} end)). + 1 = length(dets:traverse(Tab, fun(X) -> {done, X} end)). match_test(Data, Tab) -> - ?line ?format("Match test on ~p~n", [Tab]), - ?line Data1 = sort(filter(fun(X) when tuple_size(X) =:= 3 -> true; - (_X) -> false - end, Data)), - ?line Data1 = sort(dets:match_object(Tab, {'$1', '$2', '$3'})), - - ?line Len = length(Data), - ?line Len = length(dets:match(Tab, '_')), - ?line Len2 = length(Data1), - ?line Len2 = length(dets:match(Tab, {'$1', '_', '_'})), + ?format("Match test on ~p~n", [Tab]), + Data1 = sort(filter(fun(X) when tuple_size(X) =:= 3 -> true; + (_X) -> false + end, Data)), + Data1 = sort(dets:match_object(Tab, {'$1', '$2', '$3'})), + + Len = length(Data), + Len = length(dets:match(Tab, '_')), + Len2 = length(Data1), + Len2 = length(dets:match(Tab, {'$1', '_', '_'})), - ?line Data3 = + Data3 = filter(fun(X) -> K = element(1, X), if @@ -4088,14 +4030,14 @@ match_test(Data, Tab) -> true -> false end end, Data), - ?line Len3 = length(Data3), - ?line Len3 = length(dets:match(Tab, {{'$1', '$2'}, '_', '_'})), - ?line Len3 = length(dets:match_object(Tab, {{'$1', '$2'}, '_', '_'})), + Len3 = length(Data3), + Len3 = length(dets:match(Tab, {{'$1', '$2'}, '_', '_'})), + Len3 = length(dets:match_object(Tab, {{'$1', '$2'}, '_', '_'})), - ?line R = make_ref(), - ?line dets:insert(Tab, {{R, R}, 33 ,44}), - ?line 1 = length(dets:match(Tab, {{R, R}, '_', '_'})), - ?line 1 = length(dets:match_object(Tab, {{R, R}, '_', '_'})). + R = make_ref(), + dets:insert(Tab, {{R, R}, 33 ,44}), + 1 = length(dets:match(Tab, {{R, R}, '_', '_'})), + 1 = length(dets:match_object(Tab, {{R, R}, '_', '_'})). %% %% Utilities @@ -4107,20 +4049,20 @@ headsz(_) -> ?HEADSZ_v9. unwritable(Fname) -> - ?line {ok, Info} = file:read_file_info(Fname), + {ok, Info} = file:read_file_info(Fname), Mode = Info#file_info.mode - 8#00200, - ?line file:write_file_info(Fname, Info#file_info{mode = Mode}). + file:write_file_info(Fname, Info#file_info{mode = Mode}). writable(Fname) -> - ?line {ok, Info} = file:read_file_info(Fname), + {ok, Info} = file:read_file_info(Fname), Mode = Info#file_info.mode bor 8#00200, - ?line file:write_file_info(Fname, Info#file_info{mode = Mode}). + file:write_file_info(Fname, Info#file_info{mode = Mode}). truncate(File, Where) -> - ?line {ok, Fd} = file:open(File, [read,write]), - ?line file:position(Fd, Where), - ?line ok = file:truncate(Fd), - ?line ok = file:close(Fd). + {ok, Fd} = file:open(File, [read,write]), + file:position(Fd, Where), + ok = file:truncate(Fd), + ok = file:close(Fd). new_filename(Name, _Config) when is_integer(Name) -> filename:join(?privdir(_Config), @@ -4135,8 +4077,8 @@ open_files(_Name, [], _Version) -> []; open_files(Name0, [Args | Tail], Version) -> ?format("init ~p~n", [Args]), - ?line Name = list_to_atom(integer_to_list(Name0)), - ?line {ok, Name} = dets:open_file(Name, [{version,Version} | Args]), + Name = list_to_atom(integer_to_list(Name0)), + {ok, Name} = dets:open_file(Name, [{version,Version} | Args]), [Name | open_files(Name0+1, Tail, Version)]. close_all(Tabs) -> foreach(fun(Tab) -> ok = dets:close(Tab) end, Tabs). @@ -4151,11 +4093,11 @@ delete_files(Args) -> %% Initialize all tables initialize(Tabs, Data) -> - ?line foreach(fun(Tab) -> - Fun = fun(Obj) -> ok = dets:insert(Tab, Obj) end, - foreach(Fun, Data), - dets:sync(Tab) - end, Tabs). + foreach(fun(Tab) -> + Fun = fun(Obj) -> ok = dets:insert(Tab, Obj) end, + foreach(Fun, Data), + dets:sync(Tab) + end, Tabs). %% need more than 512 objects to really trig overflow make_data(Kp) -> @@ -4228,9 +4170,9 @@ ensure_node(N, Node) -> end. size_test(Len, Tabs) -> - ?line foreach(fun(Tab) -> - Len = dets:info(Tab, size) - end, Tabs). + foreach(fun(Tab) -> + Len = dets:info(Tab, size) + end, Tabs). no_keys_test([T | Ts]) -> no_keys_test(T), @@ -4243,15 +4185,15 @@ no_keys_test(T) -> ok; 9 -> Kp = dets:info(T, keypos), - ?line All = dets:match_object(T, '_'), - ?line L = lists:map(fun(X) -> element(Kp, X) end, All), - ?line NoKeys = length(lists:usort(L)), - ?line case {dets:info(T, no_keys), NoKeys} of - {N, N} -> - ok; - {N1, N2} -> - exit({no_keys_test, N1, N2}) - end + All = dets:match_object(T, '_'), + L = lists:map(fun(X) -> element(Kp, X) end, All), + NoKeys = length(lists:usort(L)), + case {dets:info(T, no_keys), NoKeys} of + {N, N} -> + ok; + {N1, N2} -> + exit({no_keys_test, N1, N2}) + end end. safe_get_all_objects(Tab) -> @@ -4266,13 +4208,13 @@ get_all_objects(Tab) -> get_all_objects(dets:first(Tab), Tab, []). %% Assuming no key matches {error, Reason}... get_all_objects('$end_of_table', _Tab, L) -> L; get_all_objects({error, Reason}, _Tab, _L) -> - exit({get_all_objects, get(line), {error, Reason}}); + exit({get_all_objects, {error, Reason}}); get_all_objects(Key, Tab, L) -> Objs = dets:lookup(Tab, Key), - ?line get_all_objects(dets:next(Tab, Key), Tab, Objs ++ L). + get_all_objects(dets:next(Tab, Key), Tab, Objs ++ L). count_objects_quite_fast(Tab) -> - ?line R1 = dets:match_object(Tab, '_', 1), + R1 = dets:match_object(Tab, '_', 1), count_objs_1(R1, 0). count_objs_1('$end_of_table', N) -> @@ -4292,42 +4234,42 @@ histogram(Tab) -> histogram(Tab, OnePercent). histogram(Tab, OnePercent) -> - ?line E = ets:new(histo, []), - ?line dets:safe_fixtable(Tab, true), - ?line Hist = histo(Tab, E, 0, OnePercent, OnePercent), - ?line dets:safe_fixtable(Tab, false), - ?line case Hist of - ok -> - ?line H = ets:tab2list(E), - ?line true = ets:delete(E), - sort(H); - Error -> - ets:delete(E), - Error - end. + E = ets:new(histo, []), + dets:safe_fixtable(Tab, true), + Hist = histo(Tab, E, 0, OnePercent, OnePercent), + dets:safe_fixtable(Tab, false), + case Hist of + ok -> + H = ets:tab2list(E), + true = ets:delete(E), + sort(H); + Error -> + ets:delete(E), + Error + end. histo(T, E, I, One, Count) when is_number(Count), I > Count -> io:format("."), histo(T, E, I, One, Count+One); histo(T, E, I, One, Count) -> - ?line case dets:slot(T, I) of - '$end_of_table' when is_number(Count) -> - io:format("~n"), - ok; - '$end_of_table' -> - ok; - Objs when is_list(Objs) -> - L = length(Objs), - case catch ets:update_counter(E, L, 1) of - {'EXIT', _} -> - ets:insert(E, {L, 1}); - _ -> - ok - end, - histo(T, E, I+1, One, Count); - Error -> - Error - end. + case dets:slot(T, I) of + '$end_of_table' when is_number(Count) -> + io:format("~n"), + ok; + '$end_of_table' -> + ok; + Objs when is_list(Objs) -> + L = length(Objs), + case catch ets:update_counter(E, L, 1) of + {'EXIT', _} -> + ets:insert(E, {L, 1}); + _ -> + ok + end, + histo(T, E, I+1, One, Count); + Error -> + Error + end. sum_histogram(H) -> sum_histogram(H, 0). diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index b2f1aa955a..0cbdf76270 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -104,6 +104,8 @@ include_local(suite) -> include_local(Config) when is_list(Config) -> ?line DataDir = ?config(data_dir, Config), ?line File = filename:join(DataDir, "include_local.erl"), + FooHrl = filename:join([DataDir,"include","foo.hrl"]), + BarHrl = filename:join([DataDir,"include","bar.hrl"]), %% include_local.erl includes include/foo.hrl which %% includes bar.hrl (also in include/) without requiring %% any additional include path, and overriding any file @@ -111,6 +113,8 @@ include_local(Config) when is_list(Config) -> ?line {ok, List} = epp:parse_file(File, [DataDir], []), ?line {value, {attribute,_,a,{true,true}}} = lists:keysearch(a,3,List), + [{File,1},{FooHrl,1},{BarHrl,1},{FooHrl,5},{File,5}] = + [ FileLine || {attribute,_,file,FileLine} <- List ], ok. %%% Here is a little reimplementation of epp:parse_file, which times out diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 7ff4c81ea6..18ec17a4bf 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -992,7 +993,7 @@ otp_10622(Config) when is_list(Config) -> <<0>>), check(fun() -> <<"\x{aa}ff"/utf8>> = <<"\x{aa}ff"/utf8>> end, "<<\"\\x{aa}ff\"/utf8>> = <<\"\\x{aa}ff\"/utf8>>. ", - <<"�\xaaff">>), + <<"Â\xaaff">>), %% The same bug as last example: check(fun() -> case <<"foo"/utf8>> of <<"foo"/utf8>> -> true diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 9c0a43abcc..ff3470349e 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -49,7 +49,7 @@ otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1, otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1, - otp_10302/1, otp_10820/1]). + otp_10302/1, otp_10820/1, otp_11100/1]). %% Internal export. -export([ehook/6]). @@ -81,7 +81,7 @@ groups() -> {tickets, [], [otp_6321, otp_6911, otp_6914, otp_8150, otp_8238, otp_8473, otp_8522, otp_8567, otp_8664, otp_9147, - otp_10302, otp_10820]}]. + otp_10302, otp_10820, otp_11100]}]. init_per_suite(Config) -> Config. @@ -1103,6 +1103,45 @@ file_attr_is_string("-file(\"" ++ _) -> true; file_attr_is_string([_ | L]) -> file_attr_is_string(L). +otp_11100(doc) -> + "OTP-11100. Fix printing of invalid forms."; +otp_11100(suite) -> []; +otp_11100(Config) when is_list(Config) -> + %% There are a few places where the added code ("options(none)") + %% doesn't make a difference (pp:bit_elem_type/1 is an example). + + %% Cannot trigger the use of the hook function with export/import. + "-export([{fy,a}/b]).\n" = + pf({attribute,1,export,[{{fy,a},b}]}), + "-type foo() :: integer(INVALID-FORM:{foo,bar}:).\n" = + pf({attribute,1,type,{foo,{type,1,integer,[{foo,bar}]},[]}}), + pf({attribute,1,type, + {a,{type,1,range,[{integer,1,1},{foo,bar}]},[]}}), + "-type foo(INVALID-FORM:{foo,bar}:) :: A.\n" = + pf({attribute,1,type,{foo,{var,1,'A'},[{foo,bar}]}}), + "-type foo() :: (INVALID-FORM:{foo,bar}: :: []).\n" = + pf({attribute,1,type, + {foo,{paren_type,1, + [{ann_type,1,[{foo,bar},{type,1,nil,[]}]}]}, + []}}), + "-type foo() :: <<_:INVALID-FORM:{foo,bar}:>>.\n" = + pf({attribute,1,type, + {foo,{type,1,binary,[{foo,bar},{integer,1,0}]},[]}}), + "-type foo() :: <<_:10, _:_*INVALID-FORM:{foo,bar}:>>.\n" = + pf({attribute,1,type, + {foo,{type,1,binary,[{integer,1,10},{foo,bar}]},[]}}), + "-type foo() :: #r{INVALID-FORM:{foo,bar}: :: integer()}.\n" = + pf({attribute,1,type, + {foo,{type,1,record, + [{atom,1,r}, + {type,1,field_type, + [{foo,bar},{type,1,integer,[]}]}]}, + []}}), + ok. + +pf(Form) -> + lists:flatten(erl_pp:form(Form,none)). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% compile(Config, Tests) -> diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl index ecd181e87c..361abbb771 100644 --- a/lib/stdlib/test/erl_scan_SUITE.erl +++ b/lib/stdlib/test/erl_scan_SUITE.erl @@ -21,7 +21,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). --export([ error_1/1, error_2/1, iso88591/1, otp_7810/1, otp_10302/1]). +-export([ error_1/1, error_2/1, iso88591/1, otp_7810/1, otp_10302/1, + otp_10990/1, otp_10992/1]). -import(lists, [nth/2,flatten/1]). -import(io_lib, [print/1]). @@ -60,7 +61,7 @@ end_per_testcase(_Case, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [{group, error}, iso88591, otp_7810, otp_10302]. + [{group, error}, iso88591, otp_7810, otp_10302, otp_10990, otp_10992]. groups() -> [{error, [], [error_1, error_2]}]. @@ -1121,6 +1122,29 @@ otp_10302(Config) when is_list(Config) -> erl_parse:abstract("a"++[1024]++"c", [{encoding,latin1}]), ok. +otp_10990(doc) -> + "OTP-10990. Floating point number in input string."; +otp_10990(suite) -> + []; +otp_10990(Config) when is_list(Config) -> + {'EXIT',_} = (catch {foo, erl_scan:string([$",42.0,$"],1)}), + ok. + +otp_10992(doc) -> + "OTP-10992. List of floats to abstract format."; +otp_10992(suite) -> + []; +otp_10992(Config) when is_list(Config) -> + {cons,0,{float,0,42.0},{nil,0}} = + erl_parse:abstract([42.0], [{encoding,unicode}]), + {cons,0,{float,0,42.0},{nil,0}} = + erl_parse:abstract([42.0], [{encoding,utf8}]), + {cons,0,{integer,0,65},{cons,0,{float,0,42.0},{nil,0}}} = + erl_parse:abstract([$A,42.0], [{encoding,unicode}]), + {cons,0,{integer,0,65},{cons,0,{float,0,42.0},{nil,0}}} = + erl_parse:abstract([$A,42.0], [{encoding,utf8}]), + ok. + test_string(String, Expected) -> {ok, Expected, _End} = erl_scan:string(String), test(String). diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl index cf5fb12686..eebfec3336 100644 --- a/lib/stdlib/test/escript_SUITE.erl +++ b/lib/stdlib/test/escript_SUITE.erl @@ -615,7 +615,7 @@ archive_script_file_access(Config) when is_list(Config) -> %% 3. If symlinks are supported, run one of the scripts via a symlink. %% %% This is in order to test error b) described above this test case. - case file:read_link(Symlink2) of + case element(1,os:type()) =:= win32 orelse file:read_link(Symlink2) of {ok,_} -> run(PrivDir, "./" ++ SymlinkName2 ++ " " ++ ScriptName2, [<<"ExitCode:0">>]); @@ -919,6 +919,9 @@ unicode(Config) when is_list(Config) -> " an arithmetic expression\n in operator '/'/2\n " "called as <<\"\xaa\">> / <<\"\xaa\">>\nExitCode:127">>]), run(Dir, "unicode3", [<<"ExitCode:0">>]), + run(Dir, "unicode4", [<<"ExitCode:0">>]), + run(Dir, "unicode5", [<<"ExitCode:0">>]), + run(Dir, "unicode6", [<<"ExitCode:0">>]), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl index b03c8ba70d..523621e4f3 100644 --- a/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl +++ b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% 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 @@ -56,7 +56,7 @@ main([RelArchiveFile]) -> %% If symlinks are supported on this platform... RelSymlinkArchiveFile = "symlink_to_" ++ RelArchiveFile, - case file:read_link(RelSymlinkArchiveFile) of + case element(1,os:type()) =:= win32 orelse file:read_link(RelSymlinkArchiveFile) of {ok,_} -> DotSlashSymlinkArchiveFile = "./" ++ RelSymlinkArchiveFile, AbsSymlinkArchiveFile=filename:join(filename:dirname(AbsArchiveFile), diff --git a/lib/stdlib/test/escript_SUITE_data/unicode3 b/lib/stdlib/test/escript_SUITE_data/unicode3 index 944487dcae..0702ecf309 100755 --- a/lib/stdlib/test/escript_SUITE_data/unicode3 +++ b/lib/stdlib/test/escript_SUITE_data/unicode3 @@ -1,5 +1,5 @@ #!/usr/bin/env escript -%% -*- erlang; coding: utf-8 -*- +%% -*- erlang; coding: latin-1 -*- -export([main/1]). diff --git a/lib/stdlib/test/escript_SUITE_data/unicode4 b/lib/stdlib/test/escript_SUITE_data/unicode4 new file mode 100755 index 0000000000..a7563a613a --- /dev/null +++ b/lib/stdlib/test/escript_SUITE_data/unicode4 @@ -0,0 +1,12 @@ +#!/usr/bin/env escript +%% -*- erlang; encoding:utf-8 -*- + +-export([main/1]). + +main(_) -> + ok = io:setopts([{encoding,unicode}]), + Bin1 = <<"örn_Рש×××-ש×××+×©× æ¥æ¬èª">>, + L = [246,114,110,95,1024,32,1513,1500,1493,1501,45,1513,1500,1493, + 1501,43,1513,1500,32,26085,26412,35486], + L = unicode:characters_to_list(Bin1, utf8), + ok. diff --git a/lib/stdlib/test/escript_SUITE_data/unicode5 b/lib/stdlib/test/escript_SUITE_data/unicode5 new file mode 100755 index 0000000000..e95da3361d --- /dev/null +++ b/lib/stdlib/test/escript_SUITE_data/unicode5 @@ -0,0 +1,12 @@ +#!/usr/bin/env escript +%% -*- erlang -*- +-export([main/1]). +%% -*- encoding:latin-1 -*- + +main(_) -> + ok = io:setopts([{encoding,unicode}]), + Bin1 = <<"örn_Ѐ שלום-שלום+של 日本語">>, + L = [246,114,110,95,1024,32,1513,1500,1493,1501,45,1513,1500,1493, + 1501,43,1513,1500,32,26085,26412,35486], + L = unicode:characters_to_list(Bin1, utf8), + ok. diff --git a/lib/stdlib/test/escript_SUITE_data/unicode6 b/lib/stdlib/test/escript_SUITE_data/unicode6 new file mode 100755 index 0000000000..8027a2a08c --- /dev/null +++ b/lib/stdlib/test/escript_SUITE_data/unicode6 @@ -0,0 +1,13 @@ +#!/usr/bin/env escript +%% -*- erlang -*- +%%! +pc unicode +-export([main/1]). +%% -*- encoding:utf-8 -*- + +main(_) -> + ok = io:setopts([{encoding,unicode}]), + Bin1 = <<"örn_Рש×××-ש×××+×©× æ¥æ¬èª">>, + L = [246,114,110,95,1024,32,1513,1500,1493,1501,45,1513,1500,1493, + 1501,43,1513,1500,32,26085,26412,35486], + L = unicode:characters_to_list(Bin1, utf8), + ok. diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index b6c94a6f6d..bd69019892 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -75,6 +75,7 @@ -export([otp_9932/1]). -export([otp_9423/1]). -export([otp_10182/1]). +-export([memory_check_summary/1]). -export([init_per_testcase/2, end_per_testcase/2]). %% Convenience for manual testing @@ -149,7 +150,9 @@ all() -> give_away, setopts, bad_table, types, otp_10182, otp_9932, - otp_9423]. + otp_9423, + + memory_check_summary]. % MUST BE LAST groups() -> [{new, [], @@ -185,7 +188,8 @@ init_per_suite(Config) -> end_per_suite(_Config) -> stop_spawn_logger(), - catch erts_debug:set_internal_state(available_internal_state, false). + catch erts_debug:set_internal_state(available_internal_state, false), + ok. init_per_group(_GroupName, Config) -> Config. @@ -193,6 +197,26 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +%% Test that we did not have "too many" failed verify_etsmem()'s +%% in the test suite. +%% verify_etsmem() may give a low number of false positives +%% as concurrent activities, such as lingering processes +%% from earlier test suites, may do unrelated ets (de)allocations. +memory_check_summary(_Config) -> + case whereis(ets_test_spawn_logger) of + undefined -> + ?t:fail("No spawn logger exist"); + _ -> + ets_test_spawn_logger ! {self(), get_failed_memchecks}, + receive {get_failed_memchecks, FailedMemchecks} -> ok end, + io:format("Failed memchecks: ~p\n",[FailedMemchecks]), + if FailedMemchecks > 3 -> + ct:fail("Too many failed (~p) memchecks", [FailedMemchecks]); + true -> + ok + end + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -3218,6 +3242,7 @@ delete_large_tab_1(Name, Flags, Data, Fix) -> end end, 0), + SchedTracerMon = monitor(process, SchedTracer), ?line Loopers = start_loopers(erlang:system_info(schedulers), Prio, fun (_) -> erlang:yield() end, @@ -3237,12 +3262,14 @@ delete_large_tab_1(Name, Flags, Data, Fix) -> N >= 5 -> ?line ok; true -> ?line ?t:fail() end - end. + end, + receive {'DOWN',SchedTracerMon,process,SchedTracer,_} -> ok end, + ok. delete_large_named_table(doc) -> "Delete a large name table and try to create a new table with the same name in another process."; delete_large_named_table(Config) when is_list(Config) -> - ?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)], + ?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 200000)], ?line EtsMem = etsmem(), repeat_for_opts(fun(Opts) -> delete_large_named_table_do(Opts,Data) end), ?line verify_etsmem(EtsMem), @@ -3264,16 +3291,16 @@ delete_large_named_table_1(Name, Flags, Data, Fix) -> ?line lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data) end, Parent = self(), - Pid = my_spawn_link(fun() -> - receive - {trace,Parent,call,_} -> - ets_new(Name, [named_table]) - end - end), - ?line erlang:trace(self(), true, [call,{tracer,Pid}]), - ?line erlang:trace_pattern({ets,delete,1}, true, [global]), - ?line erlang:yield(), true = ets:delete(Tab), - ?line erlang:trace_pattern({ets,delete,1}, false, [global]), + {Pid, MRef} = my_spawn_opt(fun() -> + receive + ets_new -> + ets_new(Name, [named_table]) + end + end, + [link, monitor]), + true = ets:delete(Tab), + Pid ! ets_new, + receive {'DOWN',MRef,process,Pid,_} -> ok end, ok. evil_delete(doc) -> @@ -5632,7 +5659,8 @@ verify_etsmem({MemInfo,AllTabs}) -> io:format("Actual: ~p", [MemInfo2]), io:format("Changed tables before: ~p\n",[AllTabs -- AllTabs2]), io:format("Changed tables after: ~p\n", [AllTabs2 -- AllTabs]), - ?t:fail() + ets_test_spawn_logger ! failed_memcheck, + {comment, "Failed memory check"} end. @@ -5654,10 +5682,10 @@ stop_loopers(Loopers) -> looper(Fun, State) -> looper(Fun, Fun(State)). -spawn_logger(Procs) -> +spawn_logger(Procs, FailedMemchecks) -> receive {new_test_proc, Proc} -> - spawn_logger([Proc|Procs]); + spawn_logger([Proc|Procs], FailedMemchecks); {sync_test_procs, Kill, From} -> lists:foreach(fun (Proc) when From == Proc -> ok; @@ -5680,7 +5708,14 @@ spawn_logger(Procs) -> end end, Procs), From ! test_procs_synced, - spawn_logger([From]) + spawn_logger([From], FailedMemchecks); + + failed_memcheck -> + spawn_logger(Procs, FailedMemchecks+1); + + {Pid, get_failed_memchecks} -> + Pid ! {get_failed_memchecks, FailedMemchecks}, + spawn_logger(Procs, FailedMemchecks) end. pid_status(Pid) -> @@ -5696,7 +5731,7 @@ start_spawn_logger() -> case whereis(ets_test_spawn_logger) of Pid when is_pid(Pid) -> true; _ -> register(ets_test_spawn_logger, - spawn_opt(fun () -> spawn_logger([]) end, + spawn_opt(fun () -> spawn_logger([], 0) end, [{priority, max}])) end. @@ -5707,8 +5742,7 @@ start_spawn_logger() -> stop_spawn_logger() -> Mon = erlang:monitor(process, ets_test_spawn_logger), (catch exit(whereis(ets_test_spawn_logger), kill)), - receive {'DOWN', Mon, _, _, _} -> ok end, - ok. + receive {'DOWN', Mon, _, _, _} -> ok end. wait_for_test_procs() -> wait_for_test_procs(false). @@ -5808,7 +5842,7 @@ spawn_monitor_with_pid(Pid, Fun, N) -> end) of Pid -> {Pid, erlang:monitor(process, Pid)}; - Other -> + _Other -> spawn_monitor_with_pid(Pid,Fun,N-1) end. @@ -6114,11 +6148,18 @@ repeat_for_opts(F, OptGenList) -> repeat_for_opts(F, OptGenList, []). repeat_for_opts(F, [], Acc) -> - lists:map(fun(Opts) -> - OptList = lists:filter(fun(E) -> E =/= void end, Opts), - io:format("Calling with options ~p\n",[OptList]), - F(OptList) - end, Acc); + lists:foldl(fun(Opts, RV_Acc) -> + OptList = lists:filter(fun(E) -> E =/= void end, Opts), + io:format("Calling with options ~p\n",[OptList]), + RV = F(OptList), + case RV_Acc of + {comment,_} -> RV_Acc; + _ -> case RV of + {comment,_} -> RV; + _ -> [RV | RV_Acc] + end + end + end, [], Acc); repeat_for_opts(F, [OptList | Tail], []) when is_list(OptList) -> repeat_for_opts(F, Tail, [[Opt] || Opt <- OptList]); repeat_for_opts(F, [OptList | Tail], AccList) when is_list(OptList) -> diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl index 5c51e12e35..6be5a299b6 100644 --- a/lib/stdlib/test/gen_event_SUITE.erl +++ b/lib/stdlib/test/gen_event_SUITE.erl @@ -26,13 +26,14 @@ delete_handler/1, swap_handler/1, swap_sup_handler/1, notify/1, sync_notify/1, call/1, info/1, hibernate/1, call_format_status/1, call_format_status_anon/1, - error_format_status/1]). + error_format_status/1, get_state/1, replace_state/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [start, {group, test_all}, hibernate, - call_format_status, call_format_status_anon, error_format_status]. + call_format_status, call_format_status_anon, error_format_status, + get_state, replace_state]. groups() -> [{test_all, [], @@ -956,3 +957,45 @@ error_format_status(Config) when is_list(Config) -> ?line ok = gen_event:stop(Pid), process_flag(trap_exit, OldFl), ok. + +get_state(suite) -> + []; +get_state(doc) -> + ["Test that sys:get_state/1,2 return the gen_event state"]; +get_state(Config) when is_list(Config) -> + {ok, Pid} = gen_event:start({local, my_dummy_handler}), + State1 = self(), + ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State1]), + [{dummy1_h,false,State1}] = sys:get_state(Pid), + [{dummy1_h,false,State1}] = sys:get_state(Pid, 5000), + State2 = {?MODULE, self()}, + ok = gen_event:add_handler(my_dummy_handler, {dummy1_h,id}, [State2]), + Result1 = sys:get_state(Pid), + [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result1), + Result2 = sys:get_state(Pid, 5000), + [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result2), + ok = gen_event:stop(Pid), + ok. + +replace_state(suite) -> + []; +replace_state(doc) -> + ["Test that replace_state/2,3 replace the gen_event state"]; +replace_state(Config) when is_list(Config) -> + {ok, Pid} = gen_event:start({local, my_dummy_handler}), + State1 = self(), + ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State1]), + [{dummy1_h,false,State1}] = sys:get_state(Pid), + NState1 = "replaced", + Replace1 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState1) end, + [{dummy1_h,false,NState1}] = sys:replace_state(Pid, Replace1), + [{dummy1_h,false,NState1}] = sys:get_state(Pid), + NState2 = "replaced again", + Replace2 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState2) end, + [{dummy1_h,false,NState2}] = sys:replace_state(Pid, Replace2, 5000), + [{dummy1_h,false,NState2}] = sys:get_state(Pid), + %% verify no change in state if replace function crashes + Replace3 = fun(_) -> exit(fail) end, + [{dummy1_h,false,NState2}] = sys:replace_state(Pid, Replace3), + [{dummy1_h,false,NState2}] = sys:get_state(Pid), + ok. diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl index a637a8543b..fd15838b7d 100644 --- a/lib/stdlib/test/gen_fsm_SUITE.erl +++ b/lib/stdlib/test/gen_fsm_SUITE.erl @@ -31,7 +31,7 @@ -export([shutdown/1]). --export([ sys1/1, call_format_status/1, error_format_status/1]). +-export([ sys1/1, call_format_status/1, error_format_status/1, get_state/1, replace_state/1]). -export([hibernate/1,hiber_idle/3,hiber_wakeup/3,hiber_idle/2,hiber_wakeup/2]). @@ -66,7 +66,7 @@ groups() -> start8, start9, start10, start11, start12]}, {abnormal, [], [abnormal1, abnormal2]}, {sys, [], - [sys1, call_format_status, error_format_status]}]. + [sys1, call_format_status, error_format_status, get_state, replace_state]}]. init_per_suite(Config) -> Config. @@ -413,6 +413,40 @@ error_format_status(Config) when is_list(Config) -> process_flag(trap_exit, OldFl), ok. +get_state(Config) when is_list(Config) -> + State = self(), + {ok, Pid} = gen_fsm:start(?MODULE, {state_data, State}, []), + {idle, State} = sys:get_state(Pid), + {idle, State} = sys:get_state(Pid, 5000), + stop_it(Pid), + + %% check that get_state can handle a name being an atom (pid is + %% already checked by the previous test) + {ok, Pid2} = gen_fsm:start({local, gfsm}, gen_fsm_SUITE, {state_data, State}, []), + {idle, State} = sys:get_state(gfsm), + {idle, State} = sys:get_state(gfsm, 5000), + stop_it(Pid2), + ok. + +replace_state(Config) when is_list(Config) -> + State = self(), + {ok, Pid} = gen_fsm:start(?MODULE, {state_data, State}, []), + {idle, State} = sys:get_state(Pid), + NState1 = "replaced", + Replace1 = fun({StateName, _}) -> {StateName, NState1} end, + {idle, NState1} = sys:replace_state(Pid, Replace1), + {idle, NState1} = sys:get_state(Pid), + NState2 = "replaced again", + Replace2 = fun({idle, _}) -> {state0, NState2} end, + {state0, NState2} = sys:replace_state(Pid, Replace2, 5000), + {state0, NState2} = sys:get_state(Pid), + %% verify no change in state if replace function crashes + Replace3 = fun(_) -> error(fail) end, + {state0, NState2} = sys:replace_state(Pid, Replace3), + {state0, NState2} = sys:get_state(Pid), + stop_it(Pid), + ok. + %% Hibernation hibernate(suite) -> []; hibernate(Config) when is_list(Config) -> diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl index dffeadb423..a360a0809b 100644 --- a/lib/stdlib/test/gen_server_SUITE.erl +++ b/lib/stdlib/test/gen_server_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% 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 @@ -32,7 +32,7 @@ spec_init_local_registered_parent/1, spec_init_global_registered_parent/1, otp_5854/1, hibernate/1, otp_7669/1, call_format_status/1, - error_format_status/1, call_with_huge_message_queue/1 + error_format_status/1, get_state/1, replace_state/1, call_with_huge_message_queue/1 ]). % spawn export @@ -57,6 +57,7 @@ all() -> spec_init_local_registered_parent, spec_init_global_registered_parent, otp_5854, hibernate, otp_7669, call_format_status, error_format_status, + get_state, replace_state, call_with_huge_message_queue]. groups() -> @@ -1033,16 +1034,71 @@ error_format_status(Config) when is_list(Config) -> process_flag(trap_exit, OldFl), ok. +%% Verify that sys:get_state correctly returns gen_server state +%% +get_state(suite) -> + []; +get_state(doc) -> + ["Test that sys:get_state/1,2 return the gen_server state"]; +get_state(Config) when is_list(Config) -> + State = self(), + {ok, _Pid} = gen_server:start_link({local, get_state}, + ?MODULE, {state,State}, []), + State = sys:get_state(get_state), + State = sys:get_state(get_state, 5000), + {ok, Pid} = gen_server:start_link(?MODULE, {state,State}, []), + State = sys:get_state(Pid), + State = sys:get_state(Pid, 5000), + ok. + +%% Verify that sys:replace_state correctly replaces gen_server state +%% +replace_state(suite) -> + []; +replace_state(doc) -> + ["Test that sys:replace_state/1,2 replace the gen_server state"]; +replace_state(Config) when is_list(Config) -> + State = self(), + {ok, _Pid} = gen_server:start_link({local, replace_state}, + ?MODULE, {state,State}, []), + State = sys:get_state(replace_state), + NState1 = "replaced", + Replace1 = fun(_) -> NState1 end, + NState1 = sys:replace_state(replace_state, Replace1), + NState1 = sys:get_state(replace_state), + {ok, Pid} = gen_server:start_link(?MODULE, {state,NState1}, []), + NState1 = sys:get_state(Pid), + Suffix = " again", + NState2 = NState1 ++ Suffix, + Replace2 = fun(S) -> S ++ Suffix end, + NState2 = sys:replace_state(Pid, Replace2, 5000), + NState2 = sys:get_state(Pid, 5000), + %% verify no change in state if replace function crashes + Replace3 = fun(_) -> throw(fail) end, + NState2 = sys:replace_state(Pid, Replace3), + NState2 = sys:get_state(Pid, 5000), + ok. + %% Test that the time for a huge message queue is not %% significantly slower than with an empty message queue. call_with_huge_message_queue(Config) when is_list(Config) -> + case test_server:is_native(gen) of + true -> + {skip, + "gen is native - huge message queue optimization " + "is not implemented"}; + false -> + do_call_with_huge_message_queue() + end. + +do_call_with_huge_message_queue() -> ?line Pid = spawn_link(fun echo_loop/0), - ?line {Time,ok} = tc(fun() -> calls(10, Pid) end), + ?line {Time,ok} = tc(fun() -> calls(10000, Pid) end), ?line [self() ! {msg,N} || N <- lists:seq(1, 500000)], erlang:garbage_collect(), - ?line {NewTime,ok} = tc(fun() -> calls(10, Pid) end), + ?line {NewTime,ok} = tc(fun() -> calls(10000, Pid) end), io:format("Time for empty message queue: ~p", [Time]), io:format("Time for huge message queue: ~p", [NewTime]), diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl index 4ca8680fc9..76a8109a8d 100644 --- a/lib/stdlib/test/io_proto_SUITE.erl +++ b/lib/stdlib/test/io_proto_SUITE.erl @@ -147,8 +147,7 @@ unicode_prompt(Config) when is_list(Config) -> %% And one with oldshell ?line rtnode([{putline,""}, {putline, "2."}, - {getline_re, ".*2."}, - {getline, "2"}, + {getline_re, ".*2$"}, {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."}, {getline_re, ".*default"}, {putline, "io:get_line('')."}, @@ -263,8 +262,7 @@ setopts_getopts(Config) when is_list(Config) -> %% And one with oldshell ?line rtnode([{putline,""}, {putline, "2."}, - {getline_re, ".*2."}, - {getline, "2"}, + {getline_re, ".*2$"}, {putline, "lists:keyfind(binary,1,io:getopts())."}, {getline_re, ".*{binary,false}"}, {putline, "io:get_line('')."}, @@ -467,8 +465,7 @@ unicode_options(Config) when is_list(Config) -> end, ?line rtnode([{putline,""}, {putline, "2."}, - {getline_re, ".*2."}, - {getline, "2"}, + {getline_re, ".*2$"}, {putline, "lists:keyfind(encoding,1,io:getopts())."}, {getline_re, ".*{encoding,latin1}"}, {putline, "io:format(\"~ts~n\",[[1024]])."}, @@ -701,8 +698,7 @@ binary_options(Config) when is_list(Config) -> old -> ok; new -> - ?line rtnode([{putline,""}, - {putline, "2."}, + ?line rtnode([{putline, "2."}, {getline, "2"}, {putline, "lists:keyfind(binary,1,io:getopts())."}, {getline, "{binary,false}"}, @@ -720,10 +716,8 @@ binary_options(Config) when is_list(Config) -> ],[]) end, %% And one with oldshell - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline_re, ".*2."}, - {getline, "2"}, + ?line rtnode([{putline, "2."}, + {getline_re, ".*2$"}, {putline, "lists:keyfind(binary,1,io:getopts())."}, {getline_re, ".*{binary,false}"}, {putline, "io:get_line('')."}, @@ -935,8 +929,8 @@ bc_with_r12_gl_1(_Config,Machine) -> TestDataLine1BinUtf = unicode:characters_to_binary(TestDataLine1), TestDataLine1BinLatin = list_to_binary(TestDataLine1), - N2List = create_nodename(), - MyNodeList = atom_to_list(node()), + {ok,N2List} = create_nodename(), + MyNodeList = atom2list(node()), register(io_proto_suite,self()), AM1 = spawn(?MODULE,Machine, [MyNodeList, "io_proto_suite", N2List]), @@ -1182,8 +1176,8 @@ read_modes_gl_1(_Config,Machine) -> TestDataLine1BinUtf = unicode:characters_to_binary(TestDataLine1), TestDataLine1BinLatin = list_to_binary(TestDataLine1), - N2List = create_nodename(), - MyNodeList = atom_to_list(node()), + {ok,N2List} = create_nodename(), + MyNodeList = atom2list(node()), register(io_proto_suite,self()), AM1 = spawn(?MODULE,Machine, [MyNodeList, "io_proto_suite", N2List]), @@ -1609,7 +1603,7 @@ create_nodename(X) -> case file:read_file_info(filename:join(["/tmp",NN])) of {error,enoent} -> Host = lists:nth(2,string:tokens(atom_to_list(node()),"@")), - NN++"@"++Host; + {ok,NN++"@"++Host}; _ -> create_nodename(X+1) end. @@ -1925,6 +1919,9 @@ from(H, [H | T]) -> T; from(H, [_ | T]) -> from(H, T); from(_, []) -> []. +atom2list(A) -> + lists:flatten(io_lib:format("~w", [A])). + chomp([]) -> []; chomp([$\n]) -> diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index b56f0b39d8..cd7210f8ec 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -2532,8 +2532,8 @@ otp_5939(Config) when is_list(Config) -> ?line [] = lists:filter(Pred, []), ?line {'EXIT', _} = (catch lists:partition(func, [])), ?line {[],[]} = lists:partition(Pred, []), - ?line {'EXIT', _} = (catch lists:zf(func, [])), - ?line [] = lists:zf(Fun1, []), + ?line {'EXIT', _} = (catch lists:filtermap(func, [])), + ?line [] = lists:filtermap(Fun1, []), ?line {'EXIT', _} = (catch lists:foreach(func, [])), ?line ok = lists:foreach(Fun1, []), ?line {'EXIT', _} = (catch lists:mapfoldl(func, [], [])), diff --git a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl index e0db132c47..b93b907392 100644 --- a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl +++ b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -515,7 +516,7 @@ create_handle() -> $.:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -523,16 +524,16 @@ create_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -541,19 +542,19 @@ create_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $r:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¥:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $F:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ :8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, $":8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $³:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $þ:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $É:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -562,7 +563,7 @@ create_handle() -> $<:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -570,16 +571,16 @@ create_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Î:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -588,22 +589,22 @@ create_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $r:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¥:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $::8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¡:8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, $":8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ñ:8/integer-unit:1-unsigned-big, $Y:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ª:8/integer-unit:1-unsigned-big, $9:8/integer-unit:1-unsigned-big, $\r:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $ý:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -612,51 +613,51 @@ create_handle() -> $I:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, + $²:8/integer-unit:1-unsigned-big, + $Í:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $e:8/integer-unit:1-unsigned-big, $\211:8/integer-unit:1-unsigned-big, $E:8/integer-unit:1-unsigned-big, $\s:8/integer-unit:1-unsigned-big, $>:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $£:8/integer-unit:1-unsigned-big, $\023:8/integer-unit:1-unsigned-big, $\210:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ç:8/integer-unit:1-unsigned-big, $\232:8/integer-unit:1-unsigned-big, $\226:8/integer-unit:1-unsigned-big, $\223:8/integer-unit:1-unsigned-big, $\237:8/integer-unit:1-unsigned-big, $X:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $\235:8/integer-unit:1-unsigned-big, $l:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¨:8/integer-unit:1-unsigned-big, $g:8/integer-unit:1-unsigned-big, $i:8/integer-unit:1-unsigned-big, $d:8/integer-unit:1-unsigned-big, $\200:8/integer-unit:1-unsigned-big, $\001:8/integer-unit:1-unsigned-big, $R:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, $\r:8/integer-unit:1-unsigned-big, $\214:8/integer-unit:1-unsigned-big, $\030:8/integer-unit:1-unsigned-big, @@ -664,7 +665,7 @@ create_handle() -> $\000:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $c:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ö:8/integer-unit:1-unsigned-big, $\017:8/integer-unit:1-unsigned-big, $=:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, @@ -708,24 +709,24 @@ create_handle() -> $*:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, $\005:8/integer-unit:1-unsigned-big, $R:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, $\031:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $\f:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $e:8/integer-unit:1-unsigned-big, $\211:8/integer-unit:1-unsigned-big, $E:8/integer-unit:1-unsigned-big, @@ -737,7 +738,7 @@ create_handle() -> $/:8/integer-unit:1-unsigned-big, $\022:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $\205:8/integer-unit:1-unsigned-big, $\t:8/integer-unit:1-unsigned-big, $\216:8/integer-unit:1-unsigned-big>>, @@ -749,33 +750,33 @@ create_handle() -> $j:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Î:8/integer-unit:1-unsigned-big, + $Ï:8/integer-unit:1-unsigned-big, $+:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ú:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $·:8/integer-unit:1-unsigned-big, $\f:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $æ:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ö:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $\202:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ô:8/integer-unit:1-unsigned-big, $D:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $®:8/integer-unit:1-unsigned-big, $\034:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, @@ -791,7 +792,7 @@ create_handle() -> $W:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $£:8/integer-unit:1-unsigned-big, $\023:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, @@ -800,18 +801,18 @@ create_handle() -> $\027:8/integer-unit:1-unsigned-big, $\237:8/integer-unit:1-unsigned-big, $\205:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¤:8/integer-unit:1-unsigned-big, $\227:8/integer-unit:1-unsigned-big, $\007:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¤:8/integer-unit:1-unsigned-big, $\227:8/integer-unit:1-unsigned-big, $\021:8/integer-unit:1-unsigned-big, $.:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ï:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, $\224:8/integer-unit:1-unsigned-big, $\217:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $\002:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\203:8/integer-unit:1-unsigned-big, @@ -1398,7 +1399,7 @@ lookup_handle() -> $.:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -1406,16 +1407,16 @@ lookup_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -1424,19 +1425,19 @@ lookup_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¦:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $F:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ :8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, $":8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $³:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\206:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $Þ:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -1445,7 +1446,7 @@ lookup_handle() -> $.:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -1453,16 +1454,16 @@ lookup_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -1471,19 +1472,19 @@ lookup_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¦:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $F:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ :8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, + $â:8/integer-unit:1-unsigned-big, + $³:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $ä:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $h:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, @@ -1525,25 +1526,25 @@ lookup_handle() -> $+:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, + $²:8/integer-unit:1-unsigned-big, + $Í:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $e:8/integer-unit:1-unsigned-big, $\211:8/integer-unit:1-unsigned-big, $E:8/integer-unit:1-unsigned-big, @@ -1555,10 +1556,10 @@ lookup_handle() -> $/:8/integer-unit:1-unsigned-big, $\022:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $×:8/integer-unit:1-unsigned-big, $\227:8/integer-unit:1-unsigned-big, $\t:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $Û:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -1567,33 +1568,33 @@ lookup_handle() -> $\\:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Î:8/integer-unit:1-unsigned-big, + $Ï:8/integer-unit:1-unsigned-big, $+:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ú:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $û:8/integer-unit:1-unsigned-big, $\f:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $æ:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ö:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $\202:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ô:8/integer-unit:1-unsigned-big, $D:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Á:8/integer-unit:1-unsigned-big, $\034:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, @@ -1605,7 +1606,7 @@ lookup_handle() -> $Y:8/integer-unit:1-unsigned-big, $b:8/integer-unit:1-unsigned-big, $Q:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¢:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, @@ -1616,7 +1617,7 @@ lookup_handle() -> $>:8/integer-unit:1-unsigned-big, $\v:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, $\020:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, $5:8/integer-unit:1-unsigned-big, @@ -1630,7 +1631,7 @@ lookup_handle() -> $\005:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ù:8/integer-unit:1-unsigned-big, $\031:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big>>} end, diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl index 990b1f5eb2..3c49aaa103 100644 --- a/lib/stdlib/test/shell_SUITE.erl +++ b/lib/stdlib/test/shell_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -122,7 +123,7 @@ start_restricted_from_shell(Config) when is_list(Config) -> "test_restricted.erl"), Contents = <<"-module(test_restricted). -export([local_allowed/3, non_local_allowed/3]). - local_allowed(i,[],State) -> + local_allowed(m,[],State) -> {true,State}; local_allowed(ugly,[],_State) -> non_conforming_reply; @@ -146,7 +147,7 @@ start_restricted_from_shell(Config) when is_list(Config) -> "test_restricted) end.">>), ?line {ok, test_restricted} = application:get_env(stdlib, restricted_shell), - ?line "Pid" ++ _ = t(<<"begin i() end.">>), + ?line "Module" ++ _ = t(<<"begin m() end.">>), ?line "exception exit: restricted shell does not allow c(foo)" = comm_err(<<"begin c(foo) end.">>), ?line "exception exit: restricted shell does not allow init:stop()" = @@ -199,9 +200,9 @@ start_restricted_on_command_line(Config) when is_list(Config) -> "-pa "++?config(priv_dir,Config)++ " -stdlib restricted_shell foo"), ?line "Warning! Restricted shell module foo not found: nofile"++_ = - t({Node, <<"begin i() end.">>}), - ?line "exception exit: restricted shell does not allow i()" = - comm_err({Node, <<"begin i() end.">>}), + t({Node, <<"begin m() end.">>}), + ?line "exception exit: restricted shell does not allow m()" = + comm_err({Node, <<"begin m() end.">>}), ?line [ok] = (catch scan({Node, <<"begin q() end.">>})), ?line test_server:stop_node(Node), @@ -209,7 +210,7 @@ start_restricted_on_command_line(Config) when is_list(Config) -> "test_restricted2.erl"), Contents = <<"-module(test_restricted2). -export([local_allowed/3, non_local_allowed/3]). - local_allowed(i,[],State) -> + local_allowed(m,[],State) -> {true,State}; local_allowed(_,_,State) -> {false,State}. @@ -225,7 +226,7 @@ start_restricted_on_command_line(Config) when is_list(Config) -> ?line {ok,Node2} = start_node(shell_suite_helper_2, "-pa "++?config(priv_dir,Config)++ " -stdlib restricted_shell test_restricted2"), - ?line "Pid" ++ _ = t({Node2,<<"begin i() end.">>}), + ?line "Module" ++ _ = t({Node2,<<"begin m() end.">>}), ?line "exception exit: restricted shell does not allow c(foo)" = comm_err({Node2,<<"begin c(foo) end.">>}), ?line "exception exit: restricted shell does not allow init:stop()" = @@ -254,7 +255,7 @@ restricted_local(Config) when is_list(Config) -> "test_restricted_local.erl"), Contents = <<"-module(test_restricted_local). -export([local_allowed/3, non_local_allowed/3]). - local_allowed(i,[],State) -> + local_allowed(m,[],State) -> {true,State}; local_allowed(banan,_,State) -> {true,State}; @@ -2820,7 +2821,7 @@ otp_10302(Config) when is_list(Config) -> "ok.\n** exception error: an error occurred when evaluating" " an arithmetic expression\n in operator '/'/2\n" - " called as <<\"�\">> / <<\"�\">>.\n" = t({Node,Test7}), + " called as <<\"ª\">> / <<\"ª\">>.\n" = t({Node,Test7}), Test8 = <<"begin A = [1089], diff --git a/lib/stdlib/test/supervisor_3.erl b/lib/stdlib/test/supervisor_3.erl new file mode 100644 index 0000000000..31b3037d6f --- /dev/null +++ b/lib/stdlib/test/supervisor_3.erl @@ -0,0 +1,45 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% +%% 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 online 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. +%% +%% %CopyrightEnd% +%% +%% Description: Simulates the behaviour that a child process may have. +%% Is used by the supervisor_SUITE test suite. +-module(supervisor_3). + +-export([start_child/2, init/1]). + +-export([handle_call/3, handle_info/2, terminate/2]). + +start_child(Name, Caller) -> + gen_server:start_link(?MODULE, [Name, Caller], []). + +init([Name, Caller]) -> + Caller ! {Name, self()}, + receive + {Result, Caller} -> + Result + end. + +handle_call(Req, _From, State) -> + {reply, Req, State}. + +handle_info(_, State) -> + {noreply, State}. + +terminate(_Reason, Time) -> + timer:sleep(Time), + ok. diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index 569c66959e..ff5be6bb95 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -53,9 +53,10 @@ %% Restart strategy tests -export([ one_for_one/1, one_for_one_escalation/1, one_for_all/1, - one_for_all_escalation/1, + one_for_all_escalation/1, one_for_all_other_child_fails_restart/1, simple_one_for_one/1, simple_one_for_one_escalation/1, rest_for_one/1, rest_for_one_escalation/1, + rest_for_one_other_child_fails_restart/1, simple_one_for_one_extra/1, simple_one_for_one_shutdown/1]). %% Misc tests @@ -107,12 +108,14 @@ groups() -> {restart_one_for_one, [], [one_for_one, one_for_one_escalation]}, {restart_one_for_all, [], - [one_for_all, one_for_all_escalation]}, + [one_for_all, one_for_all_escalation, + one_for_all_other_child_fails_restart]}, {restart_simple_one_for_one, [], [simple_one_for_one, simple_one_for_one_shutdown, simple_one_for_one_extra, simple_one_for_one_escalation]}, {restart_rest_for_one, [], - [rest_for_one, rest_for_one_escalation]}]. + [rest_for_one, rest_for_one_escalation, + rest_for_one_other_child_fails_restart]}]. init_per_suite(Config) -> Config. @@ -879,6 +882,57 @@ one_for_all_escalation(Config) when is_list(Config) -> %%------------------------------------------------------------------------- +%% Test that the supervisor terminates a restarted child when a different +%% child fails to start. +one_for_all_other_child_fails_restart(Config) when is_list(Config) -> + process_flag(trap_exit, true), + Self = self(), + Child1 = {child1, {supervisor_3, start_child, [child1, Self]}, + permanent, 1000, worker, []}, + Child2 = {child2, {supervisor_3, start_child, [child2, Self]}, + permanent, 1000, worker, []}, + Children = [Child1, Child2], + StarterFun = fun() -> + {ok, SupPid} = start_link({ok, {{one_for_all, 3, 3600}, Children}}), + Self ! {sup_pid, SupPid}, + receive {stop, Self} -> ok end + end, + StarterPid = spawn_link(StarterFun), + Ok = {{ok, undefined}, Self}, + %% Let the children start. + Child1Pid = receive {child1, Pid1} -> Pid1 end, + Child1Pid ! Ok, + Child2Pid = receive {child2, Pid2} -> Pid2 end, + Child2Pid ! Ok, + %% Supervisor started. + SupPid = receive {sup_pid, Pid} -> Pid end, + link(SupPid), + exit(Child1Pid, die), + %% Let child1 restart but don't let child2. + Child1Pid2 = receive {child1, Pid3} -> Pid3 end, + Child1Pid2Ref = erlang:monitor(process, Child1Pid2), + Child1Pid2 ! Ok, + Child2Pid2 = receive {child2, Pid4} -> Pid4 end, + Child2Pid2 ! {{stop, normal}, Self}, + %% Check child1 is terminated. + receive + {'DOWN', Child1Pid2Ref, _, _, shutdown} -> + ok; + {_childName, _Pid} -> + exit(SupPid, kill), + check_exit([StarterPid, SupPid]), + test_server:fail({restarting_child_not_terminated, Child1Pid2}) + end, + %% Let the restart complete. + Child1Pid3 = receive {child1, Pid5} -> Pid5 end, + Child1Pid3 ! Ok, + Child2Pid3 = receive {child2, Pid6} -> Pid6 end, + Child2Pid3 ! Ok, + StarterPid ! {stop, Self}, + check_exit([StarterPid, SupPid]). + + +%%------------------------------------------------------------------------- %% Test the simple_one_for_one base case. simple_one_for_one(Config) when is_list(Config) -> process_flag(trap_exit, true), @@ -1044,6 +1098,52 @@ rest_for_one_escalation(Config) when is_list(Config) -> terminate(SupPid, CPid1, child1, abnormal), check_exit([CPid2, SupPid]). + +%%------------------------------------------------------------------------- +%% Test that the supervisor terminates a restarted child when a different +%% child fails to start. +rest_for_one_other_child_fails_restart(Config) when is_list(Config) -> + process_flag(trap_exit, true), + Self = self(), + Child1 = {child1, {supervisor_3, start_child, [child1, Self]}, + permanent, 1000, worker, []}, + Child2 = {child2, {supervisor_3, start_child, [child2, Self]}, + permanent, 1000, worker, []}, + Children = [Child1, Child2], + StarterFun = fun() -> + {ok, SupPid} = start_link({ok, {{rest_for_one, 3, 3600}, Children}}), + Self ! {sup_pid, SupPid}, + receive {stop, Self} -> ok end + end, + StarterPid = spawn_link(StarterFun), + Ok = {{ok, undefined}, Self}, + %% Let the children start. + Child1Pid = receive {child1, Pid1} -> Pid1 end, + Child1Pid ! Ok, + Child2Pid = receive {child2, Pid2} -> Pid2 end, + Child2Pid ! Ok, + %% Supervisor started. + SupPid = receive {sup_pid, Pid} -> Pid end, + link(SupPid), + exit(Child1Pid, die), + %% Let child1 restart but don't let child2. + Child1Pid2 = receive {child1, Pid3} -> Pid3 end, + Child1Pid2 ! Ok, + Child2Pid2 = receive {child2, Pid4} -> Pid4 end, + Child2Pid2 ! {{stop, normal}, Self}, + %% Let child2 restart. + receive + {child2, Child2Pid3} -> + Child2Pid3 ! Ok; + {child1, _Child1Pid3} -> + exit(SupPid, kill), + check_exit([StarterPid, SupPid]), + test_server:fail({restarting_started_child, Child1Pid2}) + end, + StarterPid ! {stop, Self}, + check_exit([StarterPid, SupPid]). + + %%------------------------------------------------------------------------- %% Test that the supervisor does not hang forever if the child unliks %% and then is terminated by the supervisor. diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl index 7233c061ef..a57641ef62 100644 --- a/lib/stdlib/test/zip_SUITE.erl +++ b/lib/stdlib/test/zip_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% 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 @@ -109,13 +109,32 @@ borderline_test(Size, TempDir) -> ok. unzip_list(Archive, Name) -> - case os:find_executable("unzip") of - Unzip when is_list(Unzip) -> + case unix_unzip_exists() of + true -> unzip_list1(Archive, Name); _ -> ok end. +%% Used to do os:find_executable() to check if unzip exists, but on +%% some hosts that would give an unzip program which did not take the +%% "-Z" option. +%% Here we check that "unzip -Z" (which should display usage) and +%% check that it exists with status 0. +unix_unzip_exists() -> + case os:type() of + {unix,_} -> + Port = open_port({spawn,"unzip -Z > /dev/null"}, [exit_status]), + receive + {Port,{exit_status,0}} -> + true; + {Port,{exit_status,_Fail}} -> + false + end; + _ -> + false + end. + unzip_list1(Archive, Name) -> Expect = Name ++ "\n", cmd_expect("unzip -Z -1 " ++ Archive, Expect). |