Skip to content

Commit

Permalink
Fix hashmap tests
Browse files Browse the repository at this point in the history
  • Loading branch information
garazdawi committed Oct 6, 2023
1 parent 0e77342 commit c3636ad
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions lib/stdlib/test/ets_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1956,7 +1956,7 @@ t_select_hashmap_term_copy_bug(_Config) ->
_ -> {250, 32}
end,

LM = maps:from_list([{V,1} || V <- lists:seq(1,LargeMapSize)]),
LM = maps:from_keys(lists:seq(1,LargeMapSize), 1),

lists:foreach(
fun(Key) ->
Expand All @@ -1968,21 +1968,23 @@ t_select_hashmap_term_copy_bug(_Config) ->
V = [LM#{ Key => Dollar1 }]
end, maps:keys(LM)),

LMWithDollar = LM#{ '$1' => a },
%% Create a hashmap with enough keys before and after the '$1' for it to
%% remain a hashmap when we remove those keys.
LMWithDollar = make_lm_with_dollar(LM#{ '$1' => a }, LargeMapSize, FlatmapSize),

%% Test that hashmap with '$1' in first position works
%% We rely on that fact that maps:keys return the keys
%% in iteration order.
lists:foldl(
fun
(Key, M = #{ '$1' := _ }) ->
(Key, M = #{ '$1' := A }) when map_size(M) > FlatmapSize ->

V = ets:select(T, [{{'$1'},[], [M]}]),
erlang:garbage_collect(),
V = ets:select(T, [{{'$1'},[], [M]}]),
erlang:garbage_collect(),

V = [(maps:remove('$1',M))#{ Dollar1 => a }],
V = [(maps:remove('$1',M))#{ Dollar1 => A }],

maps:remove(Key, M);
(_, M) when map_size(M) > FlatmapSize ->
Expand All @@ -1994,14 +1996,14 @@ t_select_hashmap_term_copy_bug(_Config) ->
%% in iteration order.
lists:foldl(
fun
(Key, M = #{ '$1' := _ }) ->
(Key, M = #{ '$1' := A }) ->

V = ets:select(T, [{{'$1'},[], [M]}]),
erlang:garbage_collect(),
V = ets:select(T, [{{'$1'},[], [M]}]),
erlang:garbage_collect(),

V = [(maps:remove('$1',M))#{ Dollar1 => a }],
V = [(maps:remove('$1',M))#{ Dollar1 => A }],

maps:remove(Key, M);
(_, M) when map_size(M) > FlatmapSize ->
Expand All @@ -2027,6 +2029,20 @@ t_select_hashmap_term_copy_bug(_Config) ->
ets:delete(T),
ok.

%% Create a hashmap that always has FlatmapSize keys before and after '$1'.
%% Since the atom index of '$1' is used as hash, we cannot know before the
%% code is run where exactly it will be placed, so in the rare cases when
%% there isn't enough keys in the map, we insert more until there are enough.
make_lm_with_dollar(Map, LargeMapSize, FlatmapSize) ->
{KeysBefore, KeysAfter} = lists:splitwith(fun erlang:is_integer/1, maps:keys(Map)),
if length(KeysBefore) =< FlatmapSize;
length(KeysAfter) - 1 =< FlatmapSize ->
NewMap = maps:from_keys(lists:seq(LargeMapSize, LargeMapSize*2), 1),
make_lm_with_dollar(maps:merge(Map, NewMap), LargeMapSize*2, FlatmapSize);
true ->
Map
end.

%% Test that partly bound keys gives faster matches.
partly_bound(Config) when is_list(Config) ->
case os:type() of
Expand Down

0 comments on commit c3636ad

Please sign in to comment.