diff options
Diffstat (limited to 'lib/stdlib')
| -rw-r--r-- | lib/stdlib/doc/src/epp.xml | 8 | ||||
| -rw-r--r-- | lib/stdlib/src/epp.erl | 13 | ||||
| -rw-r--r-- | lib/stdlib/src/ms_transform.erl | 1 | ||||
| -rw-r--r-- | lib/stdlib/src/stdlib.appup.src | 6 | ||||
| -rw-r--r-- | lib/stdlib/test/epp_SUITE.erl | 16 | ||||
| -rw-r--r-- | lib/stdlib/test/epp_SUITE_data/source_name.erl | 27 | ||||
| -rw-r--r-- | lib/stdlib/test/ets_SUITE.erl | 186 | ||||
| -rw-r--r-- | lib/stdlib/test/rand_SUITE.erl | 3 | 
8 files changed, 206 insertions, 54 deletions
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml index 1dc0161398..d803d259aa 100644 --- a/lib/stdlib/doc/src/epp.xml +++ b/lib/stdlib/doc/src/epp.xml @@ -124,6 +124,10 @@        <fsummary>Open a file for preprocessing.</fsummary>        <desc>          <p>Opens a file for preprocessing.</p> +        <p>If you want to change the file name of the implicit -file() +          attributes inserted during preprocessing, you can do with +          <c>{source_name, <anno>SourceName</anno>}</c>. If unset it will +          default to the name of the opened file.</p>          <p>If <c>extra</c> is specified in            <c><anno>Options</anno></c>, the return value is            <c>{ok, <anno>Epp</anno>, <anno>Extra</anno>}</c> instead @@ -169,6 +173,10 @@          <p>Preprocesses and parses an Erlang source file.            Notice that tuple <c>{eof, <anno>Line</anno>}</c> returned at the            end of the file is included as a "form".</p> +        <p>If you want to change the file name of the implicit -file() +          attributes inserted during preprocessing, you can do with +          <c>{source_name, <anno>SourceName</anno>}</c>. If unset it will +          default to the name of the opened file.</p>          <p>If <c>extra</c> is specified in           <c><anno>Options</anno></c>, the return value is           <c>{ok, [<anno>Form</anno>], <anno>Extra</anno>}</c> instead diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index cc34d4bdd3..181a524db6 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -117,6 +117,7 @@ open(Name, File, StartLocation, Path, Pdm) ->  		  {'ok', Epp} | {'ok', Epp, Extra} | {'error', ErrorDescriptor} when        Options :: [{'default_encoding', DefEncoding :: source_encoding()} |  		  {'includes', IncludePath :: [DirectoryName :: file:name()]} | +		  {'source_name', SourceName :: file:name()} |  		  {'macros', PredefMacros :: macros()} |  		  {'name',FileName :: file:name()} |  		  'extra'], @@ -248,6 +249,7 @@ parse_file(Ifile, Path, Predefs) ->          {'ok', [Form]} | {'ok', [Form], Extra} | {error, OpenError} when        FileName :: file:name(),        Options :: [{'includes', IncludePath :: [DirectoryName :: file:name()]} | +		  {'source_name', SourceName :: file:name()} |  		  {'macros', PredefMacros :: macros()} |  		  {'default_encoding', DefEncoding :: source_encoding()} |  		  'extra'], @@ -540,9 +542,10 @@ server(Pid, Name, Options, #epp{pre_opened=PreOpened}=St) ->              init_server(Pid, Name, Options, St)      end. -init_server(Pid, Name, Options, St0) -> +init_server(Pid, FileName, Options, St0) -> +    SourceName = proplists:get_value(source_name, Options, FileName),      Pdm = proplists:get_value(macros, Options, []), -    Ms0 = predef_macros(Name), +    Ms0 = predef_macros(FileName),      case user_predef(Pdm, Ms0) of  	{ok,Ms1} ->  	    #epp{file = File, location = AtLocation} = St0, @@ -552,14 +555,14 @@ init_server(Pid, Name, Options, St0) ->              epp_reply(Pid, {ok,self(),Encoding}),              %% ensure directory of current source file is              %% first in path -            Path = [filename:dirname(Name) | +            Path = [filename:dirname(FileName) |                      proplists:get_value(includes, Options, [])], -            St = St0#epp{delta=0, name=Name, name2=Name, +            St = St0#epp{delta=0, name=SourceName, name2=SourceName,  			 path=Path, macs=Ms1,  			 default_encoding=DefEncoding},              From = wait_request(St),              Anno = erl_anno:new(AtLocation), -            enter_file_reply(From, file_name(Name), Anno, +            enter_file_reply(From, file_name(SourceName), Anno,  			     AtLocation, code),              wait_req_scan(St);  	{error,E} -> diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl index 3845e35e9b..6d243e1bec 100644 --- a/lib/stdlib/src/ms_transform.erl +++ b/lib/stdlib/src/ms_transform.erl @@ -946,6 +946,7 @@ real_guard_function(node,0) -> true;  real_guard_function(node,1) -> true;  real_guard_function(round,1) -> true;  real_guard_function(size,1) -> true; +real_guard_function(bit_size,1) -> true;  real_guard_function(map_size,1) -> true;  real_guard_function(map_get,2) -> true;  real_guard_function(tl,1) -> true; diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 8d1cc09a8b..8c0b186288 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -19,8 +19,10 @@  {"%VSN%",   %% Up from - max one major revision back   [{<<"3\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.* -  {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}],% OTP-21.* +  {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-21.0 +  {<<"3\\.6(\\.[0-9]+)*">>,[restart_new_emulator]}],% OTP-21.1   %% Down to - max one major revision back   [{<<"3\\.4(\\.[0-9]+)*">>,[restart_new_emulator]},  % OTP-20.* -  {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}]  % OTP-20.* +  {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]},  % OTP-21.0 +  {<<"3\\.6(\\.[0-9]+)*">>,[restart_new_emulator]}]  % OTP-21.1  }. diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 10e1b75e0f..a90beed4f3 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -29,7 +29,7 @@           otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,           otp_11728/1, encoding/1, extends/1,  function_macro/1,  	 test_error/1, test_warning/1, otp_14285/1, -	 test_if/1]). +	 test_if/1,source_name/1]).  -export([epp_parse_erl_form/2]). @@ -70,7 +70,7 @@ all() ->       overload_mac, otp_8388, otp_8470, otp_8562,       otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,       encoding, extends, function_macro, test_error, test_warning, -     otp_14285, test_if]. +     otp_14285, test_if, source_name].  groups() ->       [{upcase_mac, [], [upcase_mac_1, upcase_mac_2]}, @@ -1702,6 +1702,18 @@ function_macro(Config) ->      ok. +source_name(Config) when is_list(Config) -> +    DataDir = proplists:get_value(data_dir, Config), +    File = filename:join(DataDir, "source_name.erl"), + +    source_name_1(File, "/test/gurka.erl"), +    source_name_1(File, "gaffel.erl"), + +    ok. + +source_name_1(File, Expected) -> +    Res = epp:parse_file(File, [{source_name, Expected}]), +    {ok, [{attribute,_,file,{Expected,_}} | _Forms]} = Res.  check(Config, Tests) ->      eval_tests(Config, fun check_test/2, Tests). diff --git a/lib/stdlib/test/epp_SUITE_data/source_name.erl b/lib/stdlib/test/epp_SUITE_data/source_name.erl new file mode 100644 index 0000000000..71ad2dddb9 --- /dev/null +++ b/lib/stdlib/test/epp_SUITE_data/source_name.erl @@ -0,0 +1,27 @@ +%% +%% %CopyrightBegin% +%%  +%% Copyright Ericsson AB 2018. All Rights Reserved. +%%  +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%%     http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%  +%% %CopyrightEnd% +%% + +-module(source_name). +-export([ok/0]). + +%% Changing source name should not affect headers +-include("bar.hrl"). + +ok() -> ok. diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 8940f0b58c..0014793588 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -3457,6 +3457,13 @@ delete_large_tab_do(Opts,Data) ->  delete_large_tab_1(Name, Flags, Data, Fix) -> +    case is_redundant_opts_combo(Flags) of +        true -> skip; +        false -> +            delete_large_tab_2(Name, Flags, Data, Fix) +    end. + +delete_large_tab_2(Name, Flags, Data, Fix) ->      Tab = ets_new(Name, Flags),      ets:insert(Tab, Data), @@ -3528,6 +3535,13 @@ delete_large_named_table_do(Opts,Data) ->      delete_large_named_table_1(foo_hash, [named_table | Opts], Data, true).  delete_large_named_table_1(Name, Flags, Data, Fix) -> +    case is_redundant_opts_combo(Flags) of +        true -> skip; +        false -> +            delete_large_named_table_2(Name, Flags, Data, Fix) +    end. + +delete_large_named_table_2(Name, Flags, Data, Fix) ->      Tab = ets_new(Name, Flags),      ets:insert(Tab, Data), @@ -3576,6 +3590,13 @@ evil_delete_do(Opts,Data) ->  		  [TabA,TabB,TabC,TabD]).  evil_delete_not_owner(Name, Flags, Data, Fix) -> +    case is_redundant_opts_combo(Flags) of +        true -> skip; +        false -> +            evil_delete_not_owner_1(Name, Flags, Data, Fix) +    end. + +evil_delete_not_owner_1(Name, Flags, Data, Fix) ->      io:format("Not owner: ~p, fix = ~p", [Name,Fix]),      Tab = ets_new(Name, [public|Flags]),      ets:insert(Tab, Data), @@ -3601,6 +3622,13 @@ evil_delete_not_owner(Name, Flags, Data, Fix) ->      Tab.  evil_delete_owner(Name, Flags, Data, Fix) -> +    case is_redundant_opts_combo(Flags) of +        true -> skip; +        false -> +            evil_delete_owner_1(Name, Flags, Data, Fix) +    end. + +evil_delete_owner_1(Name, Flags, Data, Fix) ->      Fun = fun() ->  		  Tab = ets_new(Name, [public|Flags]),  		  ets:insert(Tab, Data), @@ -5299,7 +5327,7 @@ otp_7665_act(Tab,Min,Max,DelNr) ->  %% Whitebox testing of meta name table hashing.  meta_wb(Config) when is_list(Config) ->      EtsMem = etsmem(), -    repeat_for_opts_all_table_types(fun meta_wb_do/1), +    repeat_for_opts_all_non_stim_table_types(fun meta_wb_do/1),      verify_etsmem(EtsMem). @@ -5586,25 +5614,28 @@ meta_newdel_named(Config) when is_list(Config) ->  %% Concurrent insert's on same table.  smp_insert(Config) when is_list(Config) -> -    repeat_for_all_set_table_types( -      fun(Opts) -> -              ets_new(smp_insert,[named_table,public,{write_concurrency,true}|Opts]), -              InitF = fun(_) -> ok end, -              ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)}) -                      end, -              FiniF = fun(_) -> ok end, -              run_smp_workers(InitF,ExecF,FiniF,100000), -              verify_table_load(smp_insert), -              ets:delete(smp_insert) -      end). +    repeat_for_opts(fun smp_insert_do/1, +                    [[set,ordered_set,stim_cat_ord_set]]). + +smp_insert_do(Opts) -> +    ets_new(smp_insert,[named_table,public,{write_concurrency,true}|Opts]), +    InitF = fun(_) -> ok end, +    ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)}) +            end, +    FiniF = fun(_) -> ok end, +    run_smp_workers(InitF,ExecF,FiniF,100000), +    verify_table_load(smp_insert), +    ets:delete(smp_insert).  %% Concurrent deletes on same fixated table.  smp_fixed_delete(Config) when is_list(Config) -> -    only_if_smp(fun()->smp_fixed_delete_do() end). +    only_if_smp(fun()-> +                        repeat_for_opts(fun smp_fixed_delete_do/1, +                                        [[set,ordered_set,stim_cat_ord_set]]) +                end). -smp_fixed_delete_do() -> -    repeat_for_opts_all_set_table_types( -      fun(Opts) -> +smp_fixed_delete_do(Opts) -> +    begin                T = ets_new(foo,[public,{write_concurrency,true}|Opts]),                %%Mem = ets:info(T,memory),                NumOfObjs = 100000, @@ -5632,7 +5663,7 @@ smp_fixed_delete_do() ->                %%Mem = ets:info(T,memory),                %%verify_table_load(T),                ets:delete(T) -      end). +      end.  %% ERL-720  %% Provoke race between ets:delete and table unfix (by select_count) @@ -5887,8 +5918,11 @@ otp_8732(Config) when is_list(Config) ->  %% Run concurrent select_delete (and inserts) on same table.  smp_select_delete(Config) when is_list(Config) -> -    repeat_for_opts_all_set_table_types( -      fun(Opts) -> +    repeat_for_opts(fun smp_select_delete_do/1, +                    [[set,ordered_set,stim_cat_ord_set], read_concurrency, compressed]). + +smp_select_delete_do(Opts) -> +    begin % indentation                T = ets_new(smp_select_delete,[named_table,public,{write_concurrency,true}|Opts]),                Mod = 17,                Zeros = erlang:make_tuple(Mod,0), @@ -5942,7 +5976,7 @@ smp_select_delete(Config) when is_list(Config) ->                0 = ets:info(T,size),                false = ets:info(T,fixed),                ets:delete(T) -      end), +    end, % indentation      ok.  smp_select_replace(Config) when is_list(Config) -> @@ -6253,6 +6287,19 @@ do_work(WorksDoneSoFar, Table, ProbHelpTab, Range, Operations) ->               do_work(WorksDoneSoFar + 1, Table, ProbHelpTab, Range, Operations)      end. +prefill_table(T, KeyRange, Num) -> +    Seed = rand:uniform(KeyRange), +    %%io:format("prefill_table: Seed = ~p\n", [Seed]), +    RState = unique_rand_start(KeyRange, Seed), +    prefill_table_loop(T, RState, Num), +    Num = ets:info(T, size). + +prefill_table_loop(_, _, 0) -> +    ok; +prefill_table_loop(T, RS0, N) -> +    {Key, RS1} = unique_rand_next(RS0), +    ets:insert(T, {Key}), +    prefill_table_loop(T, RS1, N-1).  throughput_benchmark() ->       throughput_benchmark(false, not_set, not_set). @@ -6337,14 +6384,6 @@ throughput_benchmark(TestMode, BenchmarkRunMs, RecoverTimeMs) ->                                          false -> Calculate([Count*2,Count|Rest])                                      end                              end, -    PrefillTable = fun Prefill(T, KeyRange) -> -                           Size = ets:info(T, size), -                           case Size > KeyRange / 2 of -                               true -> ok; -                               false -> ets:insert(T, {rand:uniform(KeyRange)}), -                                        Prefill(T, KeyRange) -                           end -                   end,      CalculateOpsProbHelpTab =          fun Calculate([{_, OpName}], _) ->                  [{1.0, OpName}]; @@ -6386,7 +6425,7 @@ throughput_benchmark(TestMode, BenchmarkRunMs, RecoverTimeMs) ->              Range, Duration, RecoverTime) ->                  ProbHelpTab = CalculateOpsProbHelpTab(Scenario, 0),                  Table = ets:new(t, TableConfig), -                PrefillTable(Table, Range), +                prefill_table(Table, Range, Range div 2),                  SafeFixTableIfRequired(Table, Scenario, true),                  ParentPid = self(),                  ChildPids = @@ -6426,7 +6465,7 @@ throughput_benchmark(TestMode, BenchmarkRunMs, RecoverTimeMs) ->          end,      KeyRanges = % Sizes of the key ranges          case TestMode of -            true -> [100000]; +            true -> [50000];              false -> [1000000]          end,      Duration =  @@ -7225,16 +7264,22 @@ repeat_for_opts(F, OptGenList) when is_function(F, 1) ->  repeat_for_opts(F, [], 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); +                        case is_redundant_opts_combo(OptList) of +                            true -> +                                %%io:format("Ignoring redundant options ~p\n",[OptList]), +                                ok; +                            false -> +                                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 +                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) -> @@ -7242,15 +7287,22 @@ repeat_for_opts(F, [OptList | Tail], AccList) when is_list(OptList) ->  repeat_for_opts(F, [Atom | Tail], AccList) when is_atom(Atom) ->      repeat_for_opts(F, [repeat_for_opts_atom2list(Atom) | Tail ], AccList). -repeat_for_opts_atom2list(set_types) -> [void,set,ordered_set,stim_cat_ord_set,cat_ord_set]; +repeat_for_opts_atom2list(set_types) -> [set,ordered_set,stim_cat_ord_set,cat_ord_set];  repeat_for_opts_atom2list(ord_set_types) -> [ordered_set,stim_cat_ord_set,cat_ord_set]; -repeat_for_opts_atom2list(all_types) -> [void,set,ordered_set,stim_cat_ord_set,cat_ord_set,bag,duplicate_bag]; -repeat_for_opts_atom2list(all_non_stim_types) -> [void,set,ordered_set,cat_ord_set,bag,duplicate_bag]; -repeat_for_opts_atom2list(all_non_stim_set_types) -> [void,set,ordered_set,cat_ord_set]; +repeat_for_opts_atom2list(all_types) -> [set,ordered_set,stim_cat_ord_set,cat_ord_set,bag,duplicate_bag]; +repeat_for_opts_atom2list(all_non_stim_types) -> [set,ordered_set,cat_ord_set,bag,duplicate_bag]; +repeat_for_opts_atom2list(all_non_stim_set_types) -> [set,ordered_set,cat_ord_set];  repeat_for_opts_atom2list(write_concurrency) -> [{write_concurrency,false},{write_concurrency,true}];  repeat_for_opts_atom2list(read_concurrency) -> [{read_concurrency,false},{read_concurrency,true}];  repeat_for_opts_atom2list(compressed) -> [compressed,void]. +is_redundant_opts_combo(Opts) -> +    (lists:member(stim_cat_ord_set, Opts) orelse +     lists:member(cat_ord_set, Opts)) +        andalso +    (lists:member({write_concurrency, false}, Opts) orelse +     lists:member(private, Opts) orelse +     lists:member(protected, Opts)).  ets_new(Name, Opts) ->      ReplaceStimOrdSetHelper = @@ -7361,3 +7413,49 @@ syrup_factor() ->          valgrind -> 20;          _ -> 1      end. + + +%% +%% This is a pseudo random number generator for UNIQUE integers. +%% All integers between 1 and Max will be generated before it repeat itself. +%% It's a variant of this one using quadratic residues by Jeff Preshing: +%% http://preshing.com/20121224/how-to-generate-a-sequence-of-unique-random-integers/ +%% +unique_rand_start(Max, Seed) -> +    L = lists:dropwhile(fun(P) -> P < Max end, +                        primes_3mod4()), +    [P | _] = case L of +                      [] -> +                          error("Random range too large"); +                      _ -> +                          L +                  end, +    3 = P rem 4, +    {0, {Max, P, Seed}}. + +unique_rand_next({N, {Max, P, Seed}=Const}) -> +    case dquad(P, N, Seed) + 1 of +        RND when RND > Max ->  % Too large, skip +            unique_rand_next({N+1, Const}); +        RND -> +            {RND, {N+1, Const}} +    end. + +%% A one-to-one relation between all integers 0 =< X < Prime +%% if Prime rem 4 == 3. +quad(Prime, X) -> +    Rem = X*X rem Prime, +    case 2*X < Prime of +        true -> +            Rem; +        false -> +            Prime - Rem +    end. + +dquad(Prime, X, Seed) -> +    quad(Prime, (quad(Prime, X) + Seed) rem Prime). + +%% Primes where P rem 4 == 3. +primes_3mod4() -> +    [103, 211, 503, 1019, 2003, 5003, 10007, 20011, 50023, +     100003, 200003, 500083, 1000003, 2000003]. diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl index 4cb1c0b13d..6c9fab51dc 100644 --- a/lib/stdlib/test/rand_SUITE.erl +++ b/lib/stdlib/test/rand_SUITE.erl @@ -471,10 +471,11 @@ stats_standard_normal_box_muller_2(Config) when is_list(Config) ->  stats_standard_normal(Config) when is_list(Config) -> +    Retries = 7,      try math:erfc(1.0) of          _ ->              stats_standard_normal( -              fun rand:normal_s/1, rand:seed_s(exrop), 3) +              fun rand:normal_s/1, rand:seed_s(exrop), Retries)      catch error:_ ->              {skip, "math:erfc/1 not supported"}      end.  | 
