aboutsummaryrefslogblamecommitdiffstats
path: root/lib/tools/test/lcnt_SUITE.erl
blob: a79572a742b717be8e3f6bd3f01c6309c5c4e99f (plain) (tree)
1
2
3
4
5
6
7
8
9


                   
                                                        
  


                                                                   
  






                                                                           




                    
                                           

                               
                          


                                                   


                       
                       
                            
                                  
                        

                                   
           
 
                                   
                      

       


                                 
 
        
                                                                     
                                         




                                                                        
                       
                                      
                                                 


                                                        

       






                            
                 
                                           
                                                 









                                                        
                    

                                                                                 
                                                                                                                    

                                                                    



                                                                                                                             



                                   


                                  
                             

                              
                 
                                           
                                                 









                                                        
                         

                                                                                 

                                                                                                                 
                                  



                                                                                                                             


                                   


                                  
                             

                              
                                                
                                           
                                                 


                                                        

       








                                 
 




                                                                              



                                                      

                                                           
                     

                                                   







































































                                                                              
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2010-2017. 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(lcnt_SUITE).
-include_lib("common_test/include/ct.hrl").

%% Test server specific exports
-export([all/0, suite/0]).
-export([init_per_testcase/2, end_per_testcase/2]).

%% Test cases
-export([t_load/1,
         t_conflicts/1,
         t_locations/1,
         t_swap_keys/1,
         t_implicit_start/1,
         t_crash_before_collect/1,
         smoke_lcnt/1]).

init_per_testcase(_Case, Config) ->
    Config.

end_per_testcase(_Case, _Config) ->
    catch lcnt:stop(),
    ok.

suite() ->
    [{ct_hooks,[ts_install_cth]},
     {timetrap,{minutes,4}}].

all() ->
    [t_load, t_conflicts, t_locations, t_swap_keys, t_implicit_start,
     t_crash_before_collect, smoke_lcnt].

%%----------------------------------------------------------------------
%% Tests
%%----------------------------------------------------------------------

%% Load data from file.
t_load(Config) when is_list(Config) ->
    Path = proplists:get_value(data_dir, Config),
    Files = [filename:join([Path,"big_bang_40.lcnt"]),
	     filename:join([Path,"ehb_3_3_hist.lcnt"])],
    ok = t_load_file(Files),
    ok.

t_load_file([]) -> ok;
t_load_file([File|Files]) ->
    {ok, _} = lcnt:start(),
    ok = lcnt:load(File),
    ok = lcnt:stop(),
    t_load_file(Files).

%% API: conflicts
t_conflicts(Config) when is_list(Config) ->
    Path = proplists:get_value(data_dir, Config),
    Files = [filename:join([Path,"big_bang_40.lcnt"]),
	     filename:join([Path,"ehb_3_3_hist.lcnt"])],
    ok = t_conflicts_file(Files),
    ok.

t_conflicts_file([]) -> ok;
t_conflicts_file([File|Files]) ->
    {ok, _} = lcnt:start(),
    ok = lcnt:load(File),
    ok = lcnt:conflicts(),
    THs   = [-1, 5],
    Print = [name , id , type , entry , tries , colls , ratio , time , duration],
    Opts  = [
	[{sort, Sort}, {reverse, Rev}, {max_locks, ML}, {combine, Combine}, {thresholds, [TH]}, {print, [Print]}] ||
	    Sort    <- [name , type , tries , colls , ratio , time],
	    ML      <- [none, 32],
	    Combine <- [true, false],
	    TH      <- [{tries, Tries} || Tries <- THs] ++ [{colls, Colls} || Colls <- THs] ++ [{time, Time} || Time <- THs],
	    Rev     <- [true, false]
	],
    ok = test_conflicts_opts(Opts),
    ok = lcnt:stop(),
    t_conflicts_file(Files).


test_conflicts_opts([]) -> ok;
test_conflicts_opts([Opt|Opts]) ->
    ok = lcnt:conflicts(Opt),
    test_conflicts_opts(Opts).

%% API: locations
t_locations(Config) when is_list(Config) ->
    Path = proplists:get_value(data_dir, Config),
    Files = [filename:join([Path,"big_bang_40.lcnt"]),
	     filename:join([Path,"ehb_3_3_hist.lcnt"])],
    ok = t_locations_file(Files),
    ok.

t_locations_file([]) -> ok;
t_locations_file([File|Files]) ->
    {ok, _} = lcnt:start(),
    ok = lcnt:load(File),
    ok = lcnt:locations(),
    THs   = [-1, 0, 100],
    Print = [name , id , type , entry , tries , colls , ratio , time , duration],
    Opts  = [
	[{full_id, Id}, {sort, Sort}, {max_locks, ML}, {combine, Combine}, {thresholds, [TH]}, {print, Print}] ||
	    Sort    <- [name , id , type , tries , colls , ratio , time , entry],
	    ML      <- [none, 64],
	    Combine <- [true, false],
	    TH      <- [{tries, Tries} || Tries <- THs] ++ [{colls, Colls} || Colls <- THs] ++ [{time, Time} || Time <- THs],
	    Id      <- [true, false]
	],
    ok = test_locations_opts(Opts),
    ok = lcnt:stop(),
    t_locations_file(Files).

test_locations_opts([]) -> ok;
test_locations_opts([Opt|Opts]) ->
    ok = lcnt:locations(Opt),
    test_locations_opts(Opts).

%% Test interchanging port/process id with class
t_swap_keys(Config) when is_list(Config) ->
    Path = proplists:get_value(data_dir, Config),
    Files = [filename:join([Path,"big_bang_40.lcnt"]),
	     filename:join([Path,"ehb_3_3_hist.lcnt"])],
    ok = t_swap_keys_file(Files),
    ok.

t_swap_keys_file([]) -> ok;
t_swap_keys_file([File|Files]) ->
    {ok, _} = lcnt:start(),
    ok = lcnt:load(File),
    ok = lcnt:conflicts(),
    ok = lcnt:swap_pid_keys(),
    ok = lcnt:conflicts(),
    ok = lcnt:stop(),
    t_swap_keys_file(Files).

%% Prior to OTP-14913 this would crash with 'noproc' as the lcnt server hadn't
%% been started yet.
t_implicit_start(Config) when is_list(Config) ->
    ok = lcnt:conflicts().

t_crash_before_collect(Config) when is_list(Config) ->
    {ok, _} = lcnt:start(),
    ok = lcnt:information().

%% Simple smoke test of actual lock-counting, if running on
%% a run-time with lock-counting enabled.
smoke_lcnt(Config) ->
    case catch erlang:system_info(lock_counting) of
        true ->
            do_smoke_lcnt(Config);
        _ ->
            {skip,"Lock counting is not enabled"}
    end.

do_smoke_lcnt(Config) ->
    PrivDir = proplists:get_value(priv_dir, Config),
    SaveFile = filename:join(PrivDir, atom_to_list(?FUNCTION_NAME)),
    {Time,ok} = timer:tc(fun() -> lcnt:apply(fun() -> big_bang(200) end) end),
    io:format("~p ms\n", [Time]),
    ok = lcnt:conflicts(),
    ok = lcnt:save(SaveFile),
    ok = lcnt:load(SaveFile),
    ok = lcnt:conflicts(),
    lcnt:stop().


%%%
%%% A slightly modified version of Rickard Green's Big Bang benchmark.
%%%

big_bang(N) when is_integer(N) ->
    Procs = spawn_procs(N),
    RMsgs = lists:map(fun (P) -> {done, P} end, Procs),
    send_procs(Procs, {procs, Procs, self()}),
    receive_msgs(RMsgs),
    lists:foreach(fun (P) -> exit(P, normal) end, Procs).

pinger([], [], true) ->
    receive
        {procs, Procs, ReportTo} ->
            pinger(Procs, [], ReportTo)
    end;
pinger([], [], false) ->
    receive {ping, From} -> From ! {pong, self()} end,
    pinger([],[],false);
pinger([], [], ReportTo) ->
    ReportTo ! {done, self()},
    pinger([],[],false);
pinger([],[Po|Pos] = Pongers, ReportTo) ->
    receive
        {ping, From} ->
            From ! {pong, self()},
            pinger([], Pongers, ReportTo);
        {pong, Po} ->
            pinger([], Pos, ReportTo)
    end;
pinger([Pi|Pis], Pongers, ReportTo) ->
    receive {ping, From} -> From ! {pong, self()}
    after 0 -> ok
    end,
    Pi ! {ping, self()},
    pinger(Pis, [Pi|Pongers], ReportTo).

spawn_procs(N) when N =< 0 ->
    [];
spawn_procs(N) ->
    [spawn_link(fun () -> pinger([], [], true) end) | spawn_procs(N-1)].

send_procs([], Msg) ->
    Msg;
send_procs([P|Ps], Msg) ->
    P ! Msg,
    send_procs(Ps, Msg).

receive_msgs([]) ->
    ok;
receive_msgs([M|Ms]) ->
    receive
        M ->
            receive_msgs(Ms)
    end.