aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/test/pdict_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/test/pdict_SUITE.erl')
-rw-r--r--lib/kernel/test/pdict_SUITE.erl189
1 files changed, 165 insertions, 24 deletions
diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl
index 6de4ff9f77..3685e51c10 100644
--- a/lib/kernel/test/pdict_SUITE.erl
+++ b/lib/kernel/test/pdict_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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.
@@ -18,10 +18,9 @@
%% %CopyrightEnd%
%%
-module(pdict_SUITE).
-%% NB: The ?line macro cannot be used when testing the dictionary.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(M(A,B),m(A,B,?MODULE,?LINE)).
-ifdef(DEBUG).
@@ -32,22 +31,30 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
+ mixed/1,
+ literals/1,
+ destructive/1,
simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
-export([other_process/2]).
+-export([put_do/2, get_do/1, erase_do/1]).
+
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(test_server:minutes(10)),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
- [simple, complicated, heavy, simple_all_keys, info].
+ [simple, complicated, heavy, simple_all_keys, info,
+ literals,
+ destructive,
+ mixed].
groups() ->
[].
@@ -65,10 +72,7 @@ end_per_group(_GroupName, Config) ->
Config.
-simple(doc) ->
- ["Tests simple functionality in process dictionary."];
-simple(suite) ->
- [];
+%% Tests simple functionality in process dictionary.
simple(Config) when is_list(Config) ->
XX = get(),
ok = match_keys(XX),
@@ -109,7 +113,7 @@ complicated(Config) when is_list(Config) ->
Previous = get(),
ok = match_keys(Previous),
Previous = erase(),
- N = case ?t:is_debug() of
+ N = case test_server:is_debug() of
false -> 500000;
true -> 5000
end,
@@ -143,10 +147,7 @@ comp_4([{{key,_}=K,{value,_}=Val}|T]) ->
comp_4(T);
comp_4([]) -> ok.
-heavy(doc) ->
- ["Tests heavy usage of the process dictionary"];
-heavy(suite) ->
- [];
+%% Tests heavy usage of the process dictionary.
heavy(Config) when is_list(Config) ->
XX = get(),
erase(),
@@ -156,7 +157,7 @@ heavy(Config) when is_list(Config) ->
?M([],get()),
time(5000),
?M([],get()),
- case {os:type(),?t:is_debug()} of
+ case {os:type(),test_server:is_debug()} of
{_,true} -> ok;
_ ->
time(50000),
@@ -185,10 +186,7 @@ simple_all_keys_del_loop([K|Ks]) ->
ok = match_keys(get()),
simple_all_keys_del_loop(Ks).
-info(doc) ->
- ["Tests process_info(Pid, dictionary)"];
-info(suite) ->
- [];
+%% Tests process_info(Pid, dictionary).
info(Config) when is_list(Config) ->
L = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,
q,r,s,t,u,v,x,y,z,'A','B','C','D'],
@@ -369,3 +367,146 @@ match_keys(All) ->
Ks = lists:sort([K||{K,_}<-All]),
Ks = lists:sort(erlang:get_keys()),
ok.
+
+
+%% Test destructive put optimization of immed values
+%% does not affect get/0 or process_info.
+destructive(_Config) ->
+ Keys = lists:seq(1,100),
+ [put(Key, 17) || Key <- Keys],
+ Get1 = get(),
+ {dictionary,PI1} = process_info(self(), dictionary),
+
+ [begin
+ {Key, 17} = lists:keyfind(Key, 1, Get1),
+ {Key, 17} = lists:keyfind(Key, 1, PI1)
+ end
+ || Key <- Keys],
+
+ [17 = put(Key, 42) || Key <- Keys], % Mutate
+
+ Get2 = get(),
+ {dictionary,PI2} = process_info(self(), dictionary),
+
+ [begin
+ {Key, 17} = lists:keyfind(Key, 1, Get1),
+ {Key, 17} = lists:keyfind(Key, 1, PI1),
+ {Key, 42} = lists:keyfind(Key, 1, Get2),
+ {Key, 42} = lists:keyfind(Key, 1, PI2)
+
+ end
+ || Key <- Keys],
+
+ ok.
+
+%% Do random mixed put/erase to test grow/shrink
+%% Written for a temporary bug in gc during shrink
+mixed(_Config) ->
+ Rand0 = rand:seed_s(exsplus),
+ io:format("Random seed = ~p\n\n", [rand:export_seed_s(Rand0)]),
+
+ erts_debug:set_internal_state(available_internal_state, true),
+ try
+ C = do_mixed([10,0,100,50,1000,500,600,100,150,1,11,2,30,0],
+ 0,
+ array:new(),
+ 1,
+ Rand0),
+ io:format("\nDid total of ~p operations\n", [C])
+ after
+ erts_debug:set_internal_state(available_internal_state, false)
+ end.
+
+do_mixed([], _, _, C, _) ->
+ C;
+do_mixed([GoalN | Tail], GoalN, Array, C, Rand0) ->
+ io:format("Reached goal of ~p keys in dict after ~p mixed ops\n",[GoalN, C]),
+ GoalN = array:size(Array),
+ do_mixed(Tail, GoalN, Array, C, Rand0);
+do_mixed([GoalN | _]=Goals, CurrN, Array0, C, Rand0) ->
+ CurrN = array:size(Array0),
+ GrowPercent = case GoalN > CurrN of
+ true when CurrN == 0 -> 100;
+ true -> 75;
+ false -> 25
+ end,
+ {R, Rand1} = rand:uniform_s(100, Rand0),
+ case R of
+ _ when R =< GrowPercent -> %%%%%%%%%%%%% GROW
+ {Key, Rand2} = rand:uniform_s(10000, Rand1),
+ case put(Key, {Key,C}) of
+ undefined ->
+ Array1 = array:set(CurrN, Key, Array0),
+ do_mixed(Goals, CurrN+1, Array1, C+1, Rand2);
+ _ ->
+ do_mixed(Goals, CurrN, Array0, C+1, Rand2)
+ end;
+
+ _ -> %%%%%%%%%% SHRINK
+ {Kix, Rand2} = rand:uniform_s(CurrN, Rand1),
+ Key = array:get(Kix-1, Array0),
+
+ %% provoke GC during shrink
+ erts_debug:set_internal_state(fill_heap, true),
+
+ {Key, _} = erase(Key),
+ Array1 = array:set(Kix-1, array:get(CurrN-1, Array0), Array0),
+ Array2 = array:resize(CurrN-1, Array1),
+ do_mixed(Goals, CurrN-1, Array2, C+1, Rand2)
+ end.
+
+%% Test hash precalculation of literal keys
+literals(_Config) ->
+ %% Put literal -> get variable
+ put(1742, "1742"),
+ "1742" = ?MODULE:get_do(1742),
+ "1742" = ?MODULE:erase_do(1742),
+
+ put(-1742, "-1742"),
+ "-1742" = ?MODULE:get_do(-1742),
+ "-1742" = ?MODULE:erase_do(-1742),
+
+ put([], "NIL"),
+ "NIL" = ?MODULE:get_do([]),
+ "NIL" = ?MODULE:erase_do([]),
+
+ put(<<"binary">>, "binary"),
+ "binary" = ?MODULE:get_do(<<"binary">>),
+ "binary" = ?MODULE:erase_do(<<"binary">>),
+
+ BigBin = <<"A large binary with a lot of bytes to make it go off heap as shared and reference counted">>,
+ put(BigBin, "bigbin"),
+ "bigbin" = ?MODULE:get_do(BigBin),
+ "bigbin" = ?MODULE:erase_do(BigBin),
+
+ %% Put variable -> get literal
+ ?MODULE:put_do(4217, "4217"),
+ "4217" = get(4217),
+ "4217" = erase(4217),
+
+ ?MODULE:put_do(-4217, "-4217"),
+ "-4217" = get(-4217),
+ "-4217" = erase(-4217),
+
+ ?MODULE:put_do([], "NIL"),
+ "NIL" = get([]),
+ "NIL" = erase([]),
+
+ ?MODULE:put_do(<<"bytes">>, "bytes"),
+ "bytes" = get(<<"bytes">>),
+ "bytes" = erase(<<"bytes">>),
+
+ ?MODULE:put_do(BigBin, "BigBin"),
+ "BigBin" = get(BigBin),
+ "BigBin" = erase(BigBin),
+
+ ok.
+
+put_do(K, V) ->
+ put(K, V).
+
+get_do(K) ->
+ get(K).
+
+erase_do(K) ->
+ erase(K).