%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2013. 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(map_SUITE).
%% Copied from map_SUITE in erts.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2
]).
-export([
t_build_and_match_literals/1, t_build_and_match_literals_large/1,
t_update_literals/1, t_update_literals_large/1,
t_match_and_update_literals/1, t_match_and_update_literals_large/1,
t_update_map_expressions/1,
t_update_assoc/1, t_update_assoc_large/1,
t_update_exact/1, t_update_exact_large/1,
t_guard_bifs/1,
t_guard_sequence/1, t_guard_sequence_large/1,
t_guard_update/1, t_guard_update_large/1,
t_guard_receive/1, t_guard_receive_large/1,
t_guard_fun/1,
t_list_comprehension/1,
t_map_sort_literals/1,
t_map_size/1,
t_build_and_match_aliasing/1,
%% variables
t_build_and_match_variables/1,
t_update_assoc_variables/1,t_update_exact_variables/1,
t_nested_pattern_expressions/1,
t_guard_update_variables/1,
t_guard_sequence_variables/1,
t_guard_sequence_mixed/1,
t_frequency_table/1,
%% not covered in 17.0-rc1
t_build_and_match_over_alloc/1,
t_build_and_match_empty_val/1,
t_build_and_match_val/1,
t_build_and_match_nil/1,
t_build_and_match_structure/1,
%% errors in 17.0-rc1
t_update_values/1,
t_expand_map_update/1,
t_export/1,
%% Specific Map BIFs
t_bif_map_get/1,
t_bif_map_find/1,
t_bif_map_is_key/1,
t_bif_map_keys/1,
t_bif_map_merge/1,
t_bif_map_new/1,
t_bif_map_put/1,
t_bif_map_remove/1,
t_bif_map_update/1,
t_bif_map_values/1,
t_bif_map_to_list/1,
t_bif_map_from_list/1,
%% erlang
t_erlang_hash/1,
t_map_encode_decode/1,
%% maps module not bifs
t_maps_fold/1,
t_maps_map/1,
t_maps_size/1,
t_maps_without/1,
%% misc
t_pdict/1,
t_ets/1
]).
-include_lib("stdlib/include/ms_transform.hrl").
suite() -> [].
all() -> [
t_build_and_match_literals, t_build_and_match_literals_large,
t_update_literals, t_update_literals_large,
t_match_and_update_literals, t_match_and_update_literals_large,
t_update_map_expressions,
t_update_assoc, t_update_assoc_large,
t_update_exact, t_update_exact_large,
t_guard_bifs,
t_guard_sequence, t_guard_sequence_large,
t_guard_update, t_guard_update_large,
t_guard_receive, t_guard_receive_large,
t_guard_fun, t_list_comprehension,
t_map_sort_literals,
t_build_and_match_aliasing,
%% variables
t_build_and_match_variables,
t_update_assoc_variables,t_update_exact_variables,
t_nested_pattern_expressions,
t_guard_update_variables,
t_guard_sequence_variables,
t_guard_sequence_mixed,
t_frequency_table,
%% not covered in 17.0-rc1
t_build_and_match_over_alloc,
t_build_and_match_empty_val,
t_build_and_match_val,
t_build_and_match_nil,
t_build_and_match_structure,
%% errors in 17.0-rc1
t_update_values,
t_expand_map_update,
t_export,
%% Specific Map BIFs
t_bif_map_get,t_bif_map_find,t_bif_map_is_key,
t_bif_map_keys, t_bif_map_merge, t_bif_map_new,
t_bif_map_put,
t_bif_map_remove, t_bif_map_update,
t_bif_map_values,
t_bif_map_to_list, t_bif_map_from_list,
%% erlang
t_erlang_hash, t_map_encode_decode,
t_map_size,
%% maps module
t_maps_fold, t_maps_map,
t_maps_size, t_maps_without,
%% Other functions
t_pdict,
t_ets
].
groups() -> [].
init_per_suite(Config) ->
test_lib:interpret(?MODULE),
Config.
end_per_suite(_Config) -> ok.
init_per_group(_GroupName, Config) -> Config.
end_per_group(_GroupName, Config) -> Config.
%% tests
t_build_and_match_literals(Config) when is_list(Config) ->
#{} = id(#{}),
#{1:=a} = id(#{1=>a}),
#{1:=a,2:=b} = id(#{1=>a,2=>b}),
#{1:=a,2:=b,3:="c"} = id(#{1=>a,2=>b,3=>"c"}),
#{1:=a,2:=b,3:="c","4":="d"} = id(#{1=>a,2=>b,3=>"c","4"=>"d"}),
#{1:=a,2:=b,3:="c","4":="d",<<"5">>:=<<"e">>} =
id(#{1=>a,2=>b,3=>"c","4"=>"d",<<"5">>=><<"e">>}),
#{1:=a,2:=b,3:="c","4":="d",<<"5">>:=<<"e">>,{"6",7}:="f"} =
id(#{1=>a,2=>b,3=>"c","4"=>"d",<<"5">>=><<"e">>,{"6",7}=>"f"}),
#{1:=a,2:=b,3:="c","4":="d",<<"5">>:=<<"e">>,{"6",7}:="f",8:=g} =
id(#{1=>a,2=>b,3=>"c","4"=>"d",<<"5">>=><<"e">>,{"6",7}=>"f",8=>g}),
#{<<"hi all">> := 1} = id(#{<<"hi",32,"all">> => 1}),
#{a:=X,a:=X=3,b:=4} = id(#{a=>3,b=>4}), % weird but ok =)
#{ a:=#{ b:=#{c := third, b:=second}}, b:=first} =
id(#{ b=>first, a=>#{ b=>#{c => third, b=> second}}}),
M = #{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first},
M = #{ map_1:=#{ map_2:=#{value_3 := third}, value_2:= second}, value_1:=first} =
id(#{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first}),
%% error case
%% V = 32,
%%{'EXIT',{{badmatch,_},_}} = (catch (#{<<"hi all">> => 1} = id(#{<<"hi",V,"all">> => 1}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=3,x:=2} = id(#{x=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=2} = id(#{x=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id({a,b,c}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{y=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{x=>"three"}))),
ok.
t_build_and_match_literals_large(Config) when is_list(Config) ->
%% normal non-repeating
M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" }),
#{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M0,
#{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M0,
#{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M0,
#{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M0,
#{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M0,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M0,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M0,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M0,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M0,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M0,
60 = map_size(M0),
60 = maps:size(M0),
%% with repeating
M1 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
10=>na0,20=>nb0,30=>"nc0","40"=>"nd0",<<"50">>=>"ne0",{["00"]}=>"n10",
11=>na1,21=>nb1,31=>"nc1","41"=>"nd1",<<"51">>=>"ne1",{["01"]}=>"n11",
12=>na2,22=>nb2,32=>"nc2","42"=>"nd2",<<"52">>=>"ne2",{["02"]}=>"n12",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
13=>na3,23=>nb3,33=>"nc3","43"=>"nd3",<<"53">>=>"ne3",{["03"]}=>"n13",
14=>na4,24=>nb4,34=>"nc4","44"=>"nd4",<<"54">>=>"ne4",{["04"]}=>"n14",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" }),
#{10:=na0,20:=nb0,30:="nc0","40":="nd0",<<"50">>:="ne0",{["00"]}:="n10"} = M1,
#{11:=na1,21:=nb1,31:="nc1","41":="nd1",<<"51">>:="ne1",{["01"]}:="n11"} = M1,
#{12:=na2,22:=nb2,32:="nc2","42":="nd2",<<"52">>:="ne2",{["02"]}:="n12"} = M1,
#{13:=na3,23:=nb3,33:="nc3","43":="nd3",<<"53">>:="ne3",{["03"]}:="n13"} = M1,
#{14:=na4,24:=nb4,34:="nc4","44":="nd4",<<"54">>:="ne4",{["04"]}:="n14"} = M1,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M1,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M1,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M1,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M1,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M1,
60 = map_size(M1),
60 = maps:size(M1),
%% with floats
M2 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
10.0=>fa0,20.0=>fb0,30.0=>"fc0",
11.0=>fa1,21.0=>fb1,31.0=>"fc1",
12.0=>fa2,22.0=>fb2,32.0=>"fc2",
13.0=>fa3,23.0=>fb3,33.0=>"fc3",
14.0=>fa4,24.0=>fb4,34.0=>"fc4",
15.0=>fa5,25.0=>fb5,35.0=>"fc5",
16.0=>fa6,26.0=>fb6,36.0=>"fc6",
17.0=>fa7,27.0=>fb7,37.0=>"fc7",
18.0=>fa8,28.0=>fb8,38.0=>"fc8",
19.0=>fa9,29.0=>fb9,39.0=>"fc9"}),
#{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M2,
#{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M2,
#{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M2,
#{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M2,
#{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M2,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M2,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M2,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M2,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M2,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M2,
#{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M2,
#{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M2,
#{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M2,
#{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M2,
#{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M2,
#{15.0:=fa5,25.0:=fb5,35.0:="fc5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M2,
#{16.0:=fa6,26.0:=fb6,36.0:="fc6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M2,
#{17.0:=fa7,27.0:=fb7,37.0:="fc7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M2,
#{18.0:=fa8,28.0:=fb8,38.0:="fc8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M2,
#{19.0:=fa9,29.0:=fb9,39.0:="fc9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M2,
90 = map_size(M2),
90 = maps:size(M2),
%% with bignums
M3 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
10.0=>fa0,20.0=>fb0,30.0=>"fc0",
11.0=>fa1,21.0=>fb1,31.0=>"fc1",
12.0=>fa2,22.0=>fb2,32.0=>"fc2",
13.0=>fa3,23.0=>fb3,33.0=>"fc3",
14.0=>fa4,24.0=>fb4,34.0=>"fc4",
15.0=>fa5,25.0=>fb5,35.0=>"fc5",
16.0=>fa6,26.0=>fb6,36.0=>"fc6",
17.0=>fa7,27.0=>fb7,37.0=>"fc7",
18.0=>fa8,28.0=>fb8,38.0=>"fc8",
19.0=>fa9,29.0=>fb9,39.0=>"fc9",
36893488147419103232=>big1, 73786976294838206464=>big2,
147573952589676412928=>big3, 18446744073709551616=>big4,
4294967296=>big5, 8589934592=>big6,
4294967295=>big7, 67108863=>big8
}),
#{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M3,
#{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M3,
#{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M3,
#{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M3,
#{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M3,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
#{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M3,
#{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M3,
#{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M3,
#{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M3,
#{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M3,
#{15.0:=fa5,25.0:=fb5,35.0:="fc5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
#{16.0:=fa6,26.0:=fb6,36.0:="fc6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
#{17.0:=fa7,27.0:=fb7,37.0:="fc7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
#{18.0:=fa8,28.0:=fb8,38.0:="fc8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
#{19.0:=fa9,29.0:=fb9,39.0:="fc9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
#{36893488147419103232:=big1,67108863:=big8,"45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
#{147573952589676412928:=big3,8589934592:=big6,"46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
#{4294967296:=big5,18446744073709551616:=big4,"47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
#{4294967295:=big7,73786976294838206464:=big2,"48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
98 = map_size(M3),
98 = maps:size(M3),
%% with maps
M4 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
10.0=>fa0,20.0=>fb0,30.0=>"fc0",
11.0=>fa1,21.0=>fb1,31.0=>"fc1",
12.0=>fa2,22.0=>fb2,32.0=>"fc2",
13.0=>fa3,23.0=>fb3,33.0=>"fc3",
14.0=>fa4,24.0=>fb4,34.0=>"fc4",
15.0=>fa5,25.0=>fb5,35.0=>"fc5",
16.0=>fa6,26.0=>fb6,36.0=>"fc6",
17.0=>fa7,27.0=>fb7,37.0=>"fc7",
18.0=>fa8,28.0=>fb8,38.0=>"fc8",
19.0=>fa9,29.0=>fb9,39.0=>"fc9",
#{ one => small, map => key } => "small map key 1",
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
#{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M4,
#{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M4,
#{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M4,
#{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M4,
#{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M4,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M4,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M4,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M4,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M4,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M4,
#{ #{ one => small, map => key } := "small map key 1",
#{ second => small, map => key } := "small map key 2",
#{ third => small, map => key } := "small map key 3" } = M4,
#{ #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 2" } = M4,
#{ 15:=V1,25:=b5,35:=V2,"45":="d5",<<"55">>:=V3,{["05"]}:="15",
#{ one => small, map => key } := "small map key 1",
#{ second => small, map => key } := V4,
#{ third => small, map => key } := "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := V5 } = M4,
a5 = V1,
"c5" = V2,
"e5" = V3,
"small map key 2" = V4,
"large map key 1" = V5,
95 = map_size(M4),
95 = maps:size(M4),
%% call for value
M5 = id(#{ 10=>id(a0),20=>b0,30=>id("c0"),"40"=>"d0",<<"50">>=>id("e0"),{["00"]}=>"10",
11=>id(a1),21=>b1,31=>id("c1"),"41"=>"d1",<<"51">>=>id("e1"),{["01"]}=>"11",
12=>id(a2),22=>b2,32=>id("c2"),"42"=>"d2",<<"52">>=>id("e2"),{["02"]}=>"12",
13=>id(a3),23=>b3,33=>id("c3"),"43"=>"d3",<<"53">>=>id("e3"),{["03"]}=>"13",
14=>id(a4),24=>b4,34=>id("c4"),"44"=>"d4",<<"54">>=>id("e4"),{["04"]}=>"14",
15=>id(a5),25=>b5,35=>id("c5"),"45"=>"d5",<<"55">>=>id("e5"),{["05"]}=>"15",
16=>id(a6),26=>b6,36=>id("c6"),"46"=>"d6",<<"56">>=>id("e6"),{["06"]}=>"16",
17=>id(a7),27=>b7,37=>id("c7"),"47"=>"d7",<<"57">>=>id("e7"),{["07"]}=>"17",
18=>id(a8),28=>b8,38=>id("c8"),"48"=>"d8",<<"58">>=>id("e8"),{["08"]}=>"18",
19=>id(a9),29=>b9,39=>id("c9"),"49"=>"d9",<<"59">>=>id("e9"),{["09"]}=>"19",
10.0=>fa0,20.0=>id(fb0),30.0=>id("fc0"),
11.0=>fa1,21.0=>id(fb1),31.0=>id("fc1"),
12.0=>fa2,22.0=>id(fb2),32.0=>id("fc2"),
13.0=>fa3,23.0=>id(fb3),33.0=>id("fc3"),
14.0=>fa4,24.0=>id(fb4),34.0=>id("fc4"),
15.0=>fa5,25.0=>id(fb5),35.0=>id("fc5"),
16.0=>fa6,26.0=>id(fb6),36.0=>id("fc6"),
17.0=>fa7,27.0=>id(fb7),37.0=>id("fc7"),
18.0=>fa8,28.0=>id(fb8),38.0=>id("fc8"),
19.0=>fa9,29.0=>id(fb9),39.0=>id("fc9"),
#{ one => small, map => key } => id("small map key 1"),
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => id("large map key 2") }),
#{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M5,
#{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M5,
#{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M5,
#{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M5,
#{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M5,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M5,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M5,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M5,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M5,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M5,
#{ #{ one => small, map => key } := "small map key 1",
#{ second => small, map => key } := "small map key 2",
#{ third => small, map => key } := "small map key 3" } = M5,
#{ #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 2" } = M5,
95 = map_size(M5),
95 = maps:size(M5),
%% remember
#{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M0,
#{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M0,
#{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M0,
#{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M0,
#{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M0,
#{10:=na0,20:=nb0,30:="nc0","40":="nd0",<<"50">>:="ne0",{["00"]}:="n10"} = M1,
#{11:=na1,21:=nb1,31:="nc1","41":="nd1",<<"51">>:="ne1",{["01"]}:="n11"} = M1,
#{12:=na2,22:=nb2,32:="nc2","42":="nd2",<<"52">>:="ne2",{["02"]}:="n12"} = M1,
#{13:=na3,23:=nb3,33:="nc3","43":="nd3",<<"53">>:="ne3",{["03"]}:="n13"} = M1,
#{14:=na4,24:=nb4,34:="nc4","44":="nd4",<<"54">>:="ne4",{["04"]}:="n14"} = M1,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M1,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M1,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M1,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M1,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M1,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M2,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M2,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M2,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M2,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M2,
#{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M2,
#{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M2,
#{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M2,
#{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M2,
#{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M2,
#{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
#{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
#{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
#{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
#{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
#{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M3,
#{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M3,
#{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M3,
#{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M3,
#{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M3,
#{15.0:=fa5,25.0:=fb5,35.0:="fc5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
#{16.0:=fa6,26.0:=fb6,36.0:="fc6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
#{17.0:=fa7,27.0:=fb7,37.0:="fc7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
#{18.0:=fa8,28.0:=fb8,38.0:="fc8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
#{19.0:=fa9,29.0:=fb9,39.0:="fc9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
#{36893488147419103232:=big1,67108863:=big8,"45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
#{147573952589676412928:=big3,8589934592:=big6,"46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
#{4294967296:=big5,18446744073709551616:=big4,"47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
#{4294967295:=big7,73786976294838206464:=big2,"48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
ok.
t_map_size(Config) when is_list(Config) ->
0 = map_size(id(#{})),
1 = map_size(id(#{a=>1})),
1 = map_size(id(#{a=>"wat"})),
2 = map_size(id(#{a=>1, b=>2})),
3 = map_size(id(#{a=>1, b=>2, b=>"3","33"=><<"n">>})),
true = map_is_size(#{a=>1}, 1),
true = map_is_size(#{a=>1, a=>2}, 1),
M = #{ "a" => 1, "b" => 2},
true = map_is_size(M, 2),
false = map_is_size(M, 3),
true = map_is_size(M#{ "a" => 2}, 2),
false = map_is_size(M#{ "c" => 2}, 2),
%% Error cases.
do_badmap(fun(T) ->
{'EXIT',{{badmap,T},_}} =
(catch map_size(T))
end),
ok.
map_is_size(M,N) when map_size(M) =:= N -> true;
map_is_size(_,_) -> false.
%% test map updates without matching
t_update_literals(Config) when is_list(Config) ->
Map = #{x=>1,y=>2,z=>3,q=>4},
#{x:="d",q:="4"} = loop_update_literals_x_q(Map, [
{"a","1"},{"b","2"},{"c","3"},{"d","4"}
]),
ok.
t_update_literals_large(Config) when is_list(Config) ->
Map = id(#{ 10=>id(a0),20=>b0,30=>id("c0"),"40"=>"d0",<<"50">>=>id("e0"),{["00"]}=>"10",
11=>id(a1),21=>b1,31=>id("c1"),"41"=>"d1",<<"51">>=>id("e1"),{["01"]}=>"11",
12=>id(a2),22=>b2,32=>id("c2"),"42"=>"d2",<<"52">>=>id("e2"),{["02"]}=>"12",
13=>id(a3),23=>b3,33=>id("c3"),"43"=>"d3",<<"53">>=>id("e3"),{["03"]}=>"13",
14=>id(a4),24=>b4,34=>id("c4"),"44"=>"d4",<<"54">>=>id("e4"),{["04"]}=>"14",
15=>id(a5),25=>b5,35=>id("c5"),"45"=>"d5",<<"55">>=>id("e5"),{["05"]}=>"15",
16=>id(a6),26=>b6,36=>id("c6"),"46"=>"d6",<<"56">>=>id("e6"),{["06"]}=>"16",
17=>id(a7),27=>b7,37=>id("c7"),"47"=>"d7",<<"57">>=>id("e7"),{["07"]}=>"17",
18=>id(a8),28=>b8,38=>id("c8"),"48"=>"d8",<<"58">>=>id("e8"),{["08"]}=>"18",
19=>id(a9),29=>b9,39=>id("c9"),"49"=>"d9",<<"59">>=>id("e9"),{["09"]}=>"19",
10.0=>fa0,20.0=>id(fb0),30.0=>id("fc0"),
11.0=>fa1,21.0=>id(fb1),31.0=>id("fc1"),
12.0=>fa2,22.0=>id(fb2),32.0=>id("fc2"),
13.0=>fa3,23.0=>id(fb3),33.0=>id("fc3"),
14.0=>fa4,24.0=>id(fb4),34.0=>id("fc4"),
15.0=>fa5,25.0=>id(fb5),35.0=>id("fc5"),
16.0=>fa6,26.0=>id(fb6),36.0=>id("fc6"),
17.0=>fa7,27.0=>id(fb7),37.0=>id("fc7"),
18.0=>fa8,28.0=>id(fb8),38.0=>id("fc8"),
19.0=>fa9,29.0=>id(fb9),39.0=>id("fc9"),
#{ one => small, map => key } => id("small map key 1"),
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => id("large map key 2") }),
#{x:="d",q:="4"} = loop_update_literals_x_q(Map, [
{"a","1"},{"b","2"},{"c","3"},{"d","4"}
]),
ok.
loop_update_literals_x_q(Map, []) -> Map;
loop_update_literals_x_q(Map, [{X,Q}|Vs]) ->
loop_update_literals_x_q(Map#{q=>Q,x=>X},Vs).
%% test map updates with matching
t_match_and_update_literals(Config) when is_list(Config) ->
Map = #{ x=>0,y=>"untouched",z=>"also untouched",q=>1,
#{ "one" => small, map => key } => "small map key 1" },
#{x:=16,q:=21,y:="untouched",z:="also untouched"} = loop_match_and_update_literals_x_q(Map, [
{1,2},{3,4},{5,6},{7,8}
]),
M0 = id(#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat}),
M1 = id(#{}),
M2 = M1#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat},
M0 = M2,
#{ 4 := another_number, int := 3 } = M2#{ 4 => another_number },
ok.
t_match_and_update_literals_large(Config) when is_list(Config) ->
Map = id(#{ 10=>id(a0),20=>b0,30=>id("c0"),"40"=>"d0",<<"50">>=>id("e0"),{["00"]}=>"10",
11=>id(a1),21=>b1,31=>id("c1"),"41"=>"d1",<<"51">>=>id("e1"),{["01"]}=>"11",
12=>id(a2),22=>b2,32=>id("c2"),"42"=>"d2",<<"52">>=>id("e2"),{["02"]}=>"12",
13=>id(a3),23=>b3,33=>id("c3"),"43"=>"d3",<<"53">>=>id("e3"),{["03"]}=>"13",
14=>id(a4),24=>b4,34=>id("c4"),"44"=>"d4",<<"54">>=>id("e4"),{["04"]}=>"14",
15=>id(a5),25=>b5,35=>id("c5"),"45"=>"d5",<<"55">>=>id("e5"),{["05"]}=>"15",
16=>id(a6),26=>b6,36=>id("c6"),"46"=>"d6",<<"56">>=>id("e6"),{["06"]}=>"16",
17=>id(a7),27=>b7,37=>id("c7"),"47"=>"d7",<<"57">>=>id("e7"),{["07"]}=>"17",
18=>id(a8),28=>b8,38=>id("c8"),"48"=>"d8",<<"58">>=>id("e8"),{["08"]}=>"18",
19=>id(a9),29=>b9,39=>id("c9"),"49"=>"d9",<<"59">>=>id("e9"),{["09"]}=>"19",
10.0=>fa0,20.0=>id(fb0),30.0=>id("fc0"),
11.0=>fa1,21.0=>id(fb1),31.0=>id("fc1"),
12.0=>fa2,22.0=>id(fb2),32.0=>id("fc2"),
13.0=>fa3,23.0=>id(fb3),33.0=>id("fc3"),
14.0=>fa4,24.0=>id(fb4),34.0=>id("fc4"),
15.0=>fa5,25.0=>id(fb5),35.0=>id("fc5"),
16.0=>fa6,26.0=>id(fb6),36.0=>id("fc6"),
17.0=>fa7,27.0=>id(fb7),37.0=>id("fc7"),
18.0=>fa8,28.0=>id(fb8),38.0=>id("fc8"),
19.0=>fa9,29.0=>id(fb9),39.0=>id("fc9"),
x=>0,y=>"untouched",z=>"also untouched",q=>1,
#{ "one" => small, map => key } => id("small map key 1"),
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => id("large map key 2") }),
#{x:=16,q:=21,y:="untouched",z:="also untouched"} = loop_match_and_update_literals_x_q(Map, [
{1,2},{3,4},{5,6},{7,8}
]),
M0 = id(Map#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat}),
M1 = id(Map#{}),
M2 = M1#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat},
M0 = M2,
#{ 4 := another_number, int := 3 } = M2#{ 4 => another_number },
ok.
loop_match_and_update_literals_x_q(Map, []) -> Map;
loop_match_and_update_literals_x_q(#{ q:=Q0, x:=X0,
#{ "one" => small, map => key } := "small map key 1" } = Map, [{X,Q}|Vs]) ->
loop_match_and_update_literals_x_q(Map#{q=>Q0+Q,x=>X0+X},Vs).
t_update_map_expressions(Config) when is_list(Config) ->
M = maps:new(),
#{ a := 1 } = M#{a => 1},
#{ b := 2 } = (maps:new())#{ b => 2 },
#{ a :=42, b:=42, c:=42 } = (maps:from_list([{a,1},{b,2},{c,3}]))#{ a := 42, b := 42, c := 42 },
#{ "a" :=1, "b":=42, "c":=42 } = (maps:from_list([{"a",1},{"b",2}]))#{ "b" := 42, "c" => 42 },
%% Error cases.
{'EXIT',{{badmap,<<>>},_}} = (catch (id(<<>>))#{ a := 42, b => 2 }),
{'EXIT',{{badmap,[]},_}} = (catch (id([]))#{ a := 42, b => 2 }),
ok.
t_update_assoc(Config) when is_list(Config) ->
M0 = id(#{1=>a,2=>b,3.0=>c,4=>d,5=>e}),
M1 = M0#{1=>42,2=>100,4=>[a,b,c]},
#{1:=42,2:=100,3.0:=c,4:=[a,b,c],5:=e} = M1,
#{1:=42,2:=b,4:=d,5:=e,2.0:=100,3.0:=c,4.0:=[a,b,c]} = M0#{1.0=>float,1:=42,2.0=>wrong,2.0=>100,4.0=>[a,b,c]},
M2 = M0#{3.0=>new},
#{1:=a,2:=b,3.0:=new,4:=d,5:=e} = M2,
M2 = M0#{3.0:=wrong,3.0=>new},
%% Errors cases.
BadMap = id(not_a_good_map),
{'EXIT',{{badmap,BadMap},_}} = (catch BadMap#{nonexisting=>val}),
ok.
t_update_assoc_large(Config) when is_list(Config) ->
M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
10.0=>fa0,20.0=>fb0,30.0=>"fc0",
11.0=>fa1,21.0=>fb1,31.0=>"fc1",
12.0=>fa2,22.0=>fb2,32.0=>"fc2",
13.0=>fa3,23.0=>fb3,33.0=>"fc3",
14.0=>fa4,24.0=>fb4,34.0=>"fc4",
15.0=>fa5,25.0=>fb5,35.0=>"fc5",
16.0=>fa6,26.0=>fb6,36.0=>"fc6",
17.0=>fa7,27.0=>fb7,37.0=>"fc7",
18.0=>fa8,28.0=>fb8,38.0=>"fc8",
19.0=>fa9,29.0=>fb9,39.0=>"fc9",
#{ one => small, map => key } => "small map key 1",
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
M1 = M0#{1=>42,2=>100,4=>[a,b,c]},
#{1:=42,2:=100,10.0:=fa0,4:=[a,b,c],25:=b5} = M1,
#{ 10:=43, 24:=b4, 15:=a5, 35:="c5", 2.0:=100, 13.0:=fa3, 4.0:=[a,b,c]} =
M0#{1.0=>float,10:=43,2.0=>wrong,2.0=>100,4.0=>[a,b,c]},
M2 = M0#{13.0=>new},
#{10:=a0,20:=b0,13.0:=new,"40":="d0",<<"50">>:="e0"} = M2,
M2 = M0#{13.0:=wrong,13.0=>new},
%% Errors cases.
BadMap = id(a_bad_map),
{'EXIT',{{badmap,BadMap},_}} = (catch BadMap#{nonexisting=>M0}),
ok.
t_update_exact(Config) when is_list(Config) ->
M0 = id(#{1=>a,2=>b,3.0=>c,4=>d,5=>e}),
M1 = M0#{1:=42,2:=100,4:=[a,b,c]},
#{1:=42,2:=100,3.0:=c,4:=[a,b,c],5:=e} = M1,
M1 = M0#{1:=wrong,1=>42,2=>wrong,2:=100,4:=[a,b,c]},
M2 = M0#{3.0:=new},
#{1:=a,2:=b,3.0:=new,4:=d,5:=e} = M2,
M2 = M0#{3.0=>wrong,3.0:=new},
%% M2 = M0#{3=>wrong,3.0:=new}, %% FIXME
%% Errors cases.
do_badmap(fun(T) ->
{'EXIT',{{badmap,T},_}} =
(catch T#{nonexisting=>val})
end),
Empty = id(#{}),
{'EXIT',{{badkey,nonexisting},_}} = (catch Empty#{nonexisting:=val}),
{'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
{'EXIT',{{badkey,1.0},_}} = (catch M0#{1.0:=v,1.0=>v2}),
{'EXIT',{{badkey,_},_}} = (catch M0#{42.0:=v,42:=v2}),
{'EXIT',{{badkey,_},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
%% Evaluation order.
BadMap = id([no,map]),
{'EXIT',{blurf,_}} =
(catch BadMap#{whatever:=id(error(blurf))}),
{'EXIT',{blurf,_}} =
(catch BadMap#{id(error(blurf)):=whatever}),
{'EXIT',{{badmap,BadMap},_}} =
(catch BadMap#{nonexisting:=whatever}),
ok.
t_update_exact_large(Config) when is_list(Config) ->
M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
10.0=>fa0,20.0=>fb0,30.0=>"fc0",
11.0=>fa1,21.0=>fb1,31.0=>"fc1",
12.0=>fa2,22.0=>fb2,32.0=>"fc2",
13.0=>fa3,23.0=>fb3,33.0=>"fc3",
14.0=>fa4,24.0=>fb4,34.0=>"fc4",
15.0=>fa5,25.0=>fb5,35.0=>"fc5",
16.0=>fa6,26.0=>fb6,36.0=>"fc6",
17.0=>fa7,27.0=>fb7,37.0=>"fc7",
18.0=>fa8,28.0=>fb8,38.0=>"fc8",
19.0=>fa9,29.0=>fb9,39.0=>"fc9",
#{ one => small, map => key } => "small map key 1",
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
M1 = M0#{10:=42,<<"55">>:=100,10.0:=[a,b,c]},
#{ 10:=42,<<"55">>:=100,{["05"]}:="15",10.0:=[a,b,c],
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 1" } = M1,
M1 = M0#{10:=wrong,10=>42,<<"55">>=>wrong,<<"55">>:=100,10.0:=[a,b,c]},
M2 = M0#{13.0:=new},
#{10:=a0,20:=b0,13.0:=new} = M2,
M2 = M0#{13.0=>wrong,13.0:=new},
%% Errors cases.
{'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
{'EXIT',{{badkey,1.0},_}} = (catch M0#{1.0:=v,1.0=>v2}),
{'EXIT',{{badkey,_},_}} = (catch M0#{42.0:=v,42:=v2}),
{'EXIT',{{badkey,_},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
ok.
t_update_values(Config) when is_list(Config) ->
V0 = id(1337),
M0 = #{ a => 1, val => V0},
V1 = get_val(M0),
M1 = id(M0#{ val := [V0,V1], "wazzup" => 42 }),
[1337, {some_val, 1337}] = get_val(M1),
M2 = id(M1#{ <<42:333>> => 1337 }),
{bin_key,1337} = get_val(M2),
N = 110,
List = [{[I,1,2,3,I],{1,2,3,"wat",I}}|| I <- lists:seq(1,N)],
{_,_,#{val2 := {1,2,3,"wat",N}, val1 := [N,1,2,3,N]}} = lists:foldl(fun
({V2,V3},{Old2,Old3,Mi}) ->
ok = check_val(Mi,Old2,Old3),
#{ val1 := Old2, val2 := Old3 } = Mi,
{V2,V3, Mi#{ val1 := id(V2), val2 := V1, val2 => id(V3)}}
end, {none, none, #{val1=>none,val2=>none}},List),
ok.
t_expand_map_update(Config) when is_list(Config) ->
M = #{<<"hello">> => <<"world">>}#{<<"hello">> := <<"les gens">>},
#{<<"hello">> := <<"les gens">>} = M,
ok.
t_export(Config) when is_list(Config) ->
Raclette = id(#{}),
case brie of brie -> Fromage = Raclette end,
Raclette = Fromage#{},
ok.
check_val(#{val1:=V1, val2:=V2},V1,V2) -> ok.
get_val(#{ <<42:333>> := V }) -> {bin_key, V};
get_val(#{ "wazzup" := _, val := V}) -> V;
get_val(#{ val := V }) -> {some_val, V}.
t_guard_bifs(Config) when is_list(Config) ->
true = map_guard_head(#{a=>1}),
false = map_guard_head([]),
true = map_guard_body(#{a=>1}),
false = map_guard_body({}),
true = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }),
false = map_guard_pattern("list"),
ok.
map_guard_head(M) when is_map(M) -> true;
map_guard_head(_) -> false.
map_guard_body(M) -> is_map(M).
map_guard_pattern(#{}) -> true;
map_guard_pattern(_) -> false.
t_guard_sequence(Config) when is_list(Config) ->
{1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}),
{2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}),
{3, "c"} = map_guard_sequence_1(#{seq=>3,val=>id("c")}),
{4, "d"} = map_guard_sequence_1(#{seq=>4,val=>id("d")}),
{5, "e"} = map_guard_sequence_1(#{seq=>5,val=>id("e")}),
{1,M1} = map_guard_sequence_2(M1 = id(#{a=>3})),
{2,M2} = map_guard_sequence_2(M2 = id(#{a=>4, b=>4})),
{3,gg,M3} = map_guard_sequence_2(M3 = id(#{a=>gg, b=>4})),
{4,sc,sc,M4} = map_guard_sequence_2(M4 = id(#{a=>sc, b=>3, c=>sc2})),
{5,kk,kk,M5} = map_guard_sequence_2(M5 = id(#{a=>kk, b=>other, c=>sc2})),
%% error case
{'EXIT',{function_clause,_}} = (catch map_guard_sequence_1(#{seq=>6,val=>id("e")})),
{'EXIT',{function_clause,_}} = (catch map_guard_sequence_2(#{b=>5})),
ok.
t_guard_sequence_large(Config) when is_list(Config) ->
M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00",03]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01",03]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02",03]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03",03]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04",03]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05",03]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06",03]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07",03]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08",03]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09",03]}=>"19",
10.0=>fa0,20.0=>fb0,30.0=>"fc0",
11.0=>fa1,21.0=>fb1,31.0=>"fc1",
12.0=>fa2,22.0=>fb2,32.0=>"fc2",
13.0=>fa3,23.0=>fb3,33.0=>"fc3",
14.0=>fa4,24.0=>fb4,34.0=>"fc4",
15.0=>fa5,25.0=>fb5,35.0=>"fc5",
16.0=>fa6,26.0=>fb6,36.0=>"fc6",
17.0=>fa7,27.0=>fb7,37.0=>"fc7",
18.0=>fa8,28.0=>fb8,38.0=>"fc8",
19.0=>fa9,29.0=>fb9,39.0=>"fc9",
#{ one => small, map => key } => "small map key 1",
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
{1, "a"} = map_guard_sequence_1(M0#{seq=>1,val=>id("a")}),
{2, "b"} = map_guard_sequence_1(M0#{seq=>2,val=>id("b")}),
{3, "c"} = map_guard_sequence_1(M0#{seq=>3,val=>id("c")}),
{4, "d"} = map_guard_sequence_1(M0#{seq=>4,val=>id("d")}),
{5, "e"} = map_guard_sequence_1(M0#{seq=>5,val=>id("e")}),
{1,M1} = map_guard_sequence_2(M1 = id(M0#{a=>3})),
{2,M2} = map_guard_sequence_2(M2 = id(M0#{a=>4, b=>4})),
{3,gg,M3} = map_guard_sequence_2(M3 = id(M0#{a=>gg, b=>4})),
{4,sc,sc,M4} = map_guard_sequence_2(M4 = id(M0#{a=>sc, b=>3, c=>sc2})),
{5,kk,kk,M5} = map_guard_sequence_2(M5 = id(M0#{a=>kk, b=>other, c=>sc2})),
{'EXIT',{function_clause,_}} = (catch map_guard_sequence_1(M0#{seq=>6,val=>id("e")})),
{'EXIT',{function_clause,_}} = (catch map_guard_sequence_2(M0#{b=>5})),
ok.
map_guard_sequence_1(#{seq:=1=Seq, val:=Val}) -> {Seq,Val};
map_guard_sequence_1(#{seq:=2=Seq, val:=Val}) -> {Seq,Val};
map_guard_sequence_1(#{seq:=3=Seq, val:=Val}) -> {Seq,Val};
map_guard_sequence_1(#{seq:=4=Seq, val:=Val}) -> {Seq,Val};
map_guard_sequence_1(#{seq:=5=Seq, val:=Val}) -> {Seq,Val}.
map_guard_sequence_2(#{ a:=3 }=M) -> {1, M};
map_guard_sequence_2(#{ a:=4 }=M) -> {2, M};
map_guard_sequence_2(#{ a:=X, a:=X, b:=4 }=M) -> {3,X,M};
map_guard_sequence_2(#{ a:=X, a:=Y, b:=3 }=M) when X =:= Y -> {4,X,Y,M};
map_guard_sequence_2(#{ a:=X, a:=Y }=M) when X =:= Y -> {5,X,Y,M}.
t_guard_update(Config) when is_list(Config) ->
error = map_guard_update(#{},#{}),
first = map_guard_update(#{}, #{x=>first}),
second = map_guard_update(#{y=>old}, #{x=>second,y=>old}),
ok.
t_guard_update_large(Config) when is_list(Config) ->
M0 = id(#{ 70=>a0,80=>b0,90=>"c0","40"=>"d0",<<"50">>=>"e0",{["00",03]}=>"10",
71=>a1,81=>b1,91=>"c1","41"=>"d1",<<"51">>=>"e1",{["01",03]}=>"11",
72=>a2,82=>b2,92=>"c2","42"=>"d2",<<"52">>=>"e2",{["02",03]}=>"12",
73=>a3,83=>b3,93=>"c3","43"=>"d3",<<"53">>=>"e3",{["03",03]}=>"13",
74=>a4,84=>b4,94=>"c4","44"=>"d4",<<"54">>=>"e4",{["04",03]}=>"14",
75=>a5,85=>b5,95=>"c5","45"=>"d5",<<"55">>=>"e5",{["05",03]}=>"15",
76=>a6,86=>b6,96=>"c6","46"=>"d6",<<"56">>=>"e6",{["06",03]}=>"16",
77=>a7,87=>b7,97=>"c7","47"=>"d7",<<"57">>=>"e7",{["07",03]}=>"17",
78=>a8,88=>b8,98=>"c8","48"=>"d8",<<"58">>=>"e8",{["08",03]}=>"18",
79=>a9,89=>b9,99=>"c9","49"=>"d9",<<"59">>=>"e9",{["09",03]}=>"19",
70.0=>fa0,80.0=>fb0,90.0=>"fc0",
71.0=>fa1,81.0=>fb1,91.0=>"fc1",
72.0=>fa2,82.0=>fb2,92.0=>"fc2",
73.0=>fa3,83.0=>fb3,93.0=>"fc3",
74.0=>fa4,84.0=>fb4,94.0=>"fc4",
75.0=>fa5,85.0=>fb5,95.0=>"fc5",
76.0=>fa6,86.0=>fb6,96.0=>"fc6",
77.0=>fa7,87.0=>fb7,97.0=>"fc7",
78.0=>fa8,88.0=>fb8,98.0=>"fc8",
79.0=>fa9,89.0=>fb9,99.0=>"fc9",
#{ one => small, map => key } => "small map key 1",
#{ second => small, map => key } => "small map key 2",
#{ third => small, map => key } => "small map key 3",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
error = map_guard_update(M0#{},M0#{}),
first = map_guard_update(M0#{},M0#{x=>first}),
second = map_guard_update(M0#{y=>old}, M0#{x=>second,y=>old}),
ok.
map_guard_update(M1, M2) when M1#{x=>first} =:= M2 -> first;
map_guard_update(M1, M2) when M1#{x=>second} =:= M2 -> second;
map_guard_update(_, _) -> error.
t_guard_receive(Config) when is_list(Config) ->
M0 = #{ id => 0 },
Pid = spawn_link(fun() -> guard_receive_loop() end),
Big = 36893488147419103229,
B1 = <<"some text">>,
B2 = <<"was appended">>,
B3 = <<B1/binary, B2/binary>>,
#{id:=1, res:=Big} = M1 = call(Pid, M0#{op=>sub,in=>{1 bsl 65, 3}}),
#{id:=2, res:=26} = M2 = call(Pid, M1#{op=>idiv,in=>{53,2}}),
#{id:=3, res:=832} = M3 = call(Pid, M2#{op=>imul,in=>{26,32}}),
#{id:=4, res:=4} = M4 = call(Pid, M3#{op=>add,in=>{1,3}}),
#{id:=5, res:=Big} = M5 = call(Pid, M4#{op=>sub,in=>{1 bsl 65, 3}}),
#{id:=6, res:=B3} = M6 = call(Pid, M5#{op=>"append",in=>{B1,B2}}),
#{id:=7, res:=4} = _ = call(Pid, M6#{op=>add,in=>{1,3}}),
%% update old maps and check id update
#{id:=2, res:=B3} = call(Pid, M1#{op=>"append",in=>{B1,B2}}),
#{id:=5, res:=99} = call(Pid, M4#{op=>add,in=>{33, 66}}),
%% cleanup
done = call(Pid, done),
ok.
-define(t_guard_receive_large_procs, 50).
t_guard_receive_large(Config) when is_list(Config) ->
M = lists:foldl(fun(_,#{procs := Ps } = M) ->
M#{ procs := Ps#{ spawn_link(fun() -> grecv_loop() end) => 0 }}
end, #{procs => #{}, done => 0}, lists:seq(1,?t_guard_receive_large_procs)),
lists:foreach(fun(Pid) ->
Pid ! {self(), hello}
end, maps:keys(maps:get(procs,M))),
ok = guard_receive_large_loop(M),
ok.
guard_receive_large_loop(#{done := ?t_guard_receive_large_procs}) ->
ok;
guard_receive_large_loop(M) ->
receive
#{pid := Pid, msg := hello} ->
case M of
#{done := Count, procs := #{Pid := 15}} ->
Pid ! {self(), done},
guard_receive_large_loop(M#{done := Count + 1});
#{procs := #{Pid := Count} = Ps} ->
Pid ! {self(), hello},
guard_receive_large_loop(M#{procs := Ps#{Pid := Count + 1}})
end
end.
grecv_loop() ->
receive
{_, done} ->
ok;
{Pid, hello} ->
Pid ! #{pid=>self(), msg=>hello},
grecv_loop()
end.
call(Pid, M) ->
Pid ! {self(), M}, receive {Pid, Res} -> Res end.
guard_receive_loop() ->
receive
{Pid, #{ id:=Id, op:="append", in:={X,Y}}=M} when is_binary(X), is_binary(Y) ->
Pid ! {self(), M#{ id=>Id+1, res=><<X/binary,Y/binary>>}},
guard_receive_loop();
{Pid, #{ id:=Id, op:=add, in:={X,Y}}} ->
Pid ! {self(), #{ id=>Id+1, res=>X+Y}},
guard_receive_loop();
{Pid, #{ id:=Id, op:=sub, in:={X,Y}}=M} ->
Pid ! {self(), M#{ id=>Id+1, res=>X-Y}},
guard_receive_loop();
{Pid, #{ id:=Id, op:=idiv, in:={X,Y}}=M} ->
Pid ! {self(), M#{ id=>Id+1, res=>X div Y}},
guard_receive_loop();
{Pid, #{ id:=Id, op:=imul, in:={X,Y}}=M} ->
Pid ! {self(), M#{ id=>Id+1, res=>X * Y}},
guard_receive_loop();
{Pid, done} ->
Pid ! {self(), done};
{Pid, Other} ->
Pid ! {error, Other},
guard_receive_loop()
end.
t_list_comprehension(Config) when is_list(Config) ->
[#{k:=1},#{k:=2},#{k:=3}] = [#{k=>I} || I <- [1,2,3]],
Ls = id([#{<<2:301>> => I, "wat" => I + 1} || I <- [1,2,3]]),
[#{<<2:301>>:=1,"wat":=2},#{<<2:301>>:=2,"wat":=3},#{<<2:301>>:=3,"wat":=4}] = Ls,
[{1,2},{2,3},{3,4}] = id([{I2,I1} || #{"wat" := I1, <<2:301>> := I2} <- Ls]),
Ks = lists:seq($a,$z),
Ms = [#{[K1,K2]=>{K1,K2}} || K1 <- Ks, K2 <- Ks],
[#{"aa" := {$a,$a}},#{"ab":={$a,$b}}|_] = Ms,
[#{"zz" := {$z,$z}},#{"zy":={$z,$y}}|_] = lists:reverse(Ms),
ok.
t_guard_fun(Config) when is_list(Config) ->
F1 = fun
(#{s:=v,v:=V}) -> {v,V};
(#{s:=t,v:={V,V}}) -> {t,V};
(#{s:=l,v:=[V,V]}) -> {l,V}
end,
F2 = fun
(#{s:=T,v:={V,V}}) -> {T,V};
(#{s:=T,v:=[V,V]}) -> {T,V};
(#{s:=T,v:=V}) -> {T,V}
end,
V = <<"hi">>,
{v,V} = F1(#{s=>v,v=>V}),
{t,V} = F1(#{s=>t,v=>{V,V}}),
{l,V} = F1(#{s=>l,v=>[V,V]}),
{v,V} = F2(#{s=>v,v=>V}),
{t,V} = F2(#{s=>t,v=>{V,V}}),
{l,V} = F2(#{s=>l,v=>[V,V]}),
%% error case
{'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} = (catch F1(#{s=>none,v=>none})),
ok.
t_map_sort_literals(Config) when is_list(Config) ->
%% test relation
%% size order
true = #{ a => 1, b => 2} < id(#{ a => 1, b => 1, c => 1}),
true = #{ b => 1, a => 1} < id(#{ c => 1, a => 1, b => 1}),
false = #{ c => 1, b => 1, a => 1} < id(#{ c => 1, a => 1}),
%% key order
true = #{ a => 1 } < id(#{ b => 1}),
false = #{ b => 1 } < id(#{ a => 1}),
true = #{ a => 1, b => 1, c => 1 } < id(#{ b => 1, c => 1, d => 1}),
true = #{ b => 1, c => 1, d => 1 } > id(#{ a => 1, b => 1, c => 1}),
true = #{ c => 1, b => 1, a => 1 } < id(#{ b => 1, c => 1, d => 1}),
true = #{ "a" => 1 } < id(#{ <<"a">> => 1}),
false = #{ <<"a">> => 1 } < id(#{ "a" => 1}),
true = #{ 1 => 1 } < id(#{ 1.0 => 1}),
false = #{ 1.0 => 1 } < id(#{ 1 => 1}),
%% value order
true = #{ a => 1 } < id(#{ a => 2}),
false = #{ a => 2 } < id(#{ a => 1}),
false = #{ a => 2, b => 1 } < id(#{ a => 1, b => 3}),
true = #{ a => 1, b => 1 } < id(#{ a => 1, b => 3}),
true = #{ "a" => "hi", b => 134 } == id(#{ b => 134,"a" => "hi"}),
%% lists:sort
SortVs = [#{"a"=>1},#{a=>2},#{1=>3},#{<<"a">>=>4}],
[#{1:=ok},#{a:=ok},#{"a":=ok},#{<<"a">>:=ok}] = lists:sort([#{"a"=>ok},#{a=>ok},#{1=>ok},#{<<"a">>=>ok}]),
[#{1:=3},#{a:=2},#{"a":=1},#{<<"a">>:=4}] = lists:sort(SortVs),
[#{1:=3},#{a:=2},#{"a":=1},#{<<"a">>:=4}] = lists:sort(lists:reverse(SortVs)),
ok.
%% BIFs
t_bif_map_get(Config) when is_list(Config) ->
1 = maps:get(a, #{ a=> 1}),
2 = maps:get(b, #{ a=> 1, b => 2}),
"hi" = maps:get("hello", #{ a=>1, "hello" => "hi"}),
"tuple hi" = maps:get({1,1.0}, #{ a=>a, {1,1.0} => "tuple hi"}),
M = id(#{ k1=>"v1", <<"k2">> => <<"v3">> }),
"v4" = maps:get(<<"k2">>, M#{ <<"k2">> => "v4" }),
%% error case
{'EXIT',{{badmap,[]},[{maps,get,_,_}|_]}} = (catch maps:get(a, [])),
{'EXIT',{{badmap,<<>>},[{maps,get,_,_}|_]}} = (catch maps:get(a, <<>>)),
{'EXIT',{{badkey,{1,1}},[{maps,get,_,_}|_]}} = (catch maps:get({1,1}, #{{1,1.0} => "tuple"})),
{'EXIT',{{badkey,a},[{maps,get,_,_}|_]}} = (catch maps:get(a, #{})),
{'EXIT',{{badkey,a},[{maps,get,_,_}|_]}} = (catch maps:get(a, #{ b=>1, c=>2})),
ok.
t_bif_map_find(Config) when is_list(Config) ->
{ok, 1} = maps:find(a, #{ a=> 1}),
{ok, 2} = maps:find(b, #{ a=> 1, b => 2}),
{ok, "int"} = maps:find(1, #{ 1 => "int"}),
{ok, "float"} = maps:find(1.0, #{ 1.0=> "float"}),
{ok, "hi"} = maps:find("hello", #{ a=>1, "hello" => "hi"}),
{ok, "tuple hi"} = maps:find({1,1.0}, #{ a=>a, {1,1.0} => "tuple hi"}),
M = id(#{ k1=>"v1", <<"k2">> => <<"v3">> }),
{ok, "v4"} = maps:find(<<"k2">>, M#{ <<"k2">> => "v4" }),
%% error case
error = maps:find(a,#{}),
error = maps:find(a,#{b=>1, c=>2}),
error = maps:find(1.0, #{ 1 => "int"}),
error = maps:find(1, #{ 1.0 => "float"}),
error = maps:find({1.0,1}, #{ a=>a, {1,1.0} => "tuple hi"}), % reverse types in tuple key
{'EXIT',{{badmap,[]},[{maps,find,_,_}|_]}} =
(catch maps:find(a, id([]))),
{'EXIT',{{badmap,<<>>},[{maps,find,_,_}|_]}} =
(catch maps:find(a, id(<<>>))),
ok.
t_bif_map_is_key(Config) when is_list(Config) ->
M1 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>, 4 => number},
true = maps:is_key("hi", M1),
true = maps:is_key(int, M1),
true = maps:is_key(<<"key">>, M1),
true = maps:is_key(4, M1),
false = maps:is_key(5, M1),
false = maps:is_key(<<"key2">>, M1),
false = maps:is_key("h", M1),
false = maps:is_key("hello", M1),
false = maps:is_key(atom, M1),
false = maps:is_key(any, id(#{})),
false = maps:is_key("hi", maps:remove("hi", M1)),
true = maps:is_key("hi", M1),
true = maps:is_key(1, maps:put(1, "number", M1)),
false = maps:is_key(1.0, maps:put(1, "number", M1)),
%% error case
{'EXIT',{{badmap,[]},[{maps,is_key,_,_}|_]}} = (catch maps:is_key(a, id([]))),
{'EXIT',{{badmap,<<>>},[{maps,is_key,_,_}|_]}} = (catch maps:is_key(a, id(<<>>))),
ok.
t_bif_map_keys(Config) when is_list(Config) ->
[] = maps:keys(#{}),
[1,2,3,4,5] = lists:sort(maps:keys(#{ 1 => a, 2 => b, 3 => c, 4 => d, 5 => e})),
[1,2,3,4,5] = lists:sort(maps:keys(#{ 4 => d, 5 => e, 1 => a, 2 => b, 3 => c})),
M1 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>, 4 => number},
[4,int,"hi",<<"key">>] = lists:sort(maps:keys(M1)),
%% error case
BigNum = 1 bsl 65 + 3,
{'EXIT',{{badmap,BigNum},[{maps,keys,_,_}|_]}} = (catch maps:keys(BigNum)),
{'EXIT',{{badmap,154},[{maps,keys,_,_}|_]}} = (catch maps:keys(154)),
{'EXIT',{{badmap,atom},[{maps,keys,_,_}|_]}} = (catch maps:keys(atom)),
{'EXIT',{{badmap,[]},[{maps,keys,_,_}|_]}} = (catch maps:keys([])),
{'EXIT',{{badmap,<<>>},[{maps,keys,_,_}|_]}} = (catch maps:keys(<<>>)),
ok.
t_bif_map_new(Config) when is_list(Config) ->
#{} = maps:new(),
0 = erlang:map_size(maps:new()),
ok.
t_bif_map_merge(Config) when is_list(Config) ->
0 = erlang:map_size(maps:merge(#{},#{})),
M0 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat},
#{ "hi" := "hello", int := 3, <<"key">> := <<"value">>,
4 := number, 18446744073709551629 := wat} = maps:merge(#{}, M0),
#{ "hi" := "hello", int := 3, <<"key">> := <<"value">>,
4 := number, 18446744073709551629 := wat} = maps:merge(M0, #{}),
M1 = #{ "hi" => "hello again", float => 3.3, {1,2} => "tuple", 4 => integer },
#{4 := number, 18446744073709551629 := wat, float := 3.3, int := 3,
{1,2} := "tuple", "hi" := "hello", <<"key">> := <<"value">>} = maps:merge(M1,M0),
#{4 := integer, 18446744073709551629 := wat, float := 3.3, int := 3,
{1,2} := "tuple", "hi" := "hello again", <<"key">> := <<"value">>} = maps:merge(M0,M1),
%% error case
BigNum = 1 bsl 65 + 3,
{'EXIT',{{badmap,BigNum},[{maps,merge,_,_}|_]}} = (catch maps:merge(BigNum, <<>>)),
{'EXIT',{{badmap,<<>>},[{maps,merge,_,_}|_]}} = (catch maps:merge(<<>>, id(#{ a => 1}))),
{'EXIT',{{badmap,<<>>},[{maps,merge,_,_}|_]}} = (catch maps:merge(id(#{ a => 2}), <<>> )),
ok.
t_bif_map_put(Config) when is_list(Config) ->
M0 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat},
M1 = #{ "hi" := "hello"} = maps:put("hi", "hello", #{}),
true = is_members(["hi"],maps:keys(M1)),
true = is_members(["hello"],maps:values(M1)),
M2 = #{ int := 3 } = maps:put(int, 3, M1),
true = is_members([int,"hi"],maps:keys(M2)),
true = is_members([3,"hello"],maps:values(M2)),
M3 = #{ <<"key">> := <<"value">> } = maps:put(<<"key">>, <<"value">>, M2),
true = is_members([int,"hi",<<"key">>],maps:keys(M3)),
true = is_members([3,"hello",<<"value">>],maps:values(M3)),
M4 = #{ 18446744073709551629 := wat } = maps:put(18446744073709551629, wat, M3),
true = is_members([18446744073709551629,int,"hi",<<"key">>],maps:keys(M4)),
true = is_members([wat,3,"hello",<<"value">>],maps:values(M4)),
M0 = #{ 4 := number } = M5 = maps:put(4, number, M4),
true = is_members([4,18446744073709551629,int,"hi",<<"key">>],maps:keys(M5)),
true = is_members([number,wat,3,"hello",<<"value">>],maps:values(M5)),
M6 = #{ <<"key">> := <<"other value">> } = maps:put(<<"key">>, <<"other value">>, M5),
true = is_members([4,18446744073709551629,int,"hi",<<"key">>],maps:keys(M6)),
true = is_members([number,wat,3,"hello",<<"other value">>],maps:values(M6)),
%% error case
BigNum = 1 bsl 65 + 3,
{'EXIT',{{badmap,BigNum},[{maps,put,_,_}|_]}} = (catch maps:put(1, a, BigNum)),
{'EXIT',{{badmap,154},[{maps,put,_,_}|_]}} = (catch maps:put(1, a, 154)),
{'EXIT',{{badmap,atom},[{maps,put,_,_}|_]}} = (catch maps:put(1, a, atom)),
{'EXIT',{{badmap,[]},[{maps,put,_,_}|_]}} = (catch maps:put(1, a, [])),
{'EXIT',{{badmap,<<>>},[{maps,put,_,_}|_]}} = (catch maps:put(1, a, <<>>)),
ok.
is_members(Ks,Ls) when length(Ks) =/= length(Ls) -> false;
is_members(Ks,Ls) -> is_members_do(Ks,Ls).
is_members_do([],[]) -> true;
is_members_do([],_) -> false;
is_members_do([K|Ks],Ls) ->
is_members_do(Ks, lists:delete(K,Ls)).
t_bif_map_update(Config) when is_list(Config) ->
M0 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat},
#{ "hi" := "hello again", int := 3, <<"key">> := <<"value">>,
4 := number, 18446744073709551629 := wat} = maps:update("hi", "hello again", M0),
#{ "hi" := "hello", int := 1337, <<"key">> := <<"value">>,
4 := number, 18446744073709551629 := wat} = maps:update(int, 1337, M0),
#{ "hi" := "hello", int := 3, <<"key">> := <<"new value">>,
4 := number, 18446744073709551629 := wat} = maps:update(<<"key">>, <<"new value">>, M0),
#{ "hi" := "hello", int := 3, <<"key">> := <<"value">>,
4 := integer, 18446744073709551629 := wat} = maps:update(4, integer, M0),
#{ "hi" := "hello", int := 3, <<"key">> := <<"value">>,
4 := number, 18446744073709551629 := wazzup} = maps:update(18446744073709551629, wazzup, M0),
%% error case
{'EXIT',{{badmap,{}},[{maps,update,_,_}|_]}} = (catch maps:update(1, none, {})),
{'EXIT',{{badmap,<<"value">>},[{maps,update,_,_}|_]}} =
(catch maps:update(1, none, <<"value">>)),
{'EXIT',{{badkey,5},[{maps,update,_,_}|_]}} = (catch maps:update(5, none, M0)),
ok.
t_bif_map_remove(Config) when is_list(Config) ->
0 = erlang:map_size(maps:remove(some_key, #{})),
M0 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
4 => number, 18446744073709551629 => wat},
M1 = maps:remove("hi", M0),
true = is_members([4,18446744073709551629,int,<<"key">>],maps:keys(M1)),
true = is_members([number,wat,3,<<"value">>],maps:values(M1)),
M2 = maps:remove(int, M1),
true = is_members([4,18446744073709551629,<<"key">>],maps:keys(M2)),
true = is_members([number,wat,<<"value">>],maps:values(M2)),
M3 = maps:remove(<<"key">>, M2),
true = is_members([4,18446744073709551629],maps:keys(M3)),
true = is_members([number,wat],maps:values(M3)),
M4 = maps:remove(18446744073709551629, M3),
true = is_members([4],maps:keys(M4)),
true = is_members([number],maps:values(M4)),
M5 = maps:remove(4, M4),
[] = maps:keys(M5),
[] = maps:values(M5),
M0 = maps:remove(5,M0),
M0 = maps:remove("hi there",M0),
#{ "hi" := "hello", int := 3, 4 := number} = maps:remove(18446744073709551629,maps:remove(<<"key">>,M0)),
%% error case
BigNum = 1 bsl 65 + 3,
{'EXIT',{{badmap,BigNum},[{maps,remove,_,_}|_]}} = (catch maps:remove(a, BigNum)),
{'EXIT',{{badmap,154},[{maps,remove,_,_}|_]}} = (catch maps:remove(1, 154)),
{'EXIT',{{badmap,atom},[{maps,remove,_,_}|_]}} = (catch maps:remove(a, atom)),
{'EXIT',{{badmap,[]},[{maps,remove,_,_}|_]}} = (catch maps:remove(1, [])),
{'EXIT',{{badmap,<<>>},[{maps,remove,_,_}|_]}} = (catch maps:remove(a, <<>>)),
ok.
t_bif_map_values(Config) when is_list(Config) ->
[] = maps:values(#{}),
[1] = maps:values(#{a=>1}),
true = is_members([a,b,c,d,e],maps:values(#{ 1 => a, 2 => b, 3 => c, 4 => d, 5 => e})),
true = is_members([a,b,c,d,e],maps:values(#{ 4 => d, 5 => e, 1 => a, 2 => b, 3 => c})),
M1 = #{ "hi" => "hello", int => 3, <<"key">> => <<"value">>, 4 => number},
M2 = M1#{ "hi" => "hello2", <<"key">> => <<"value2">> },
true = is_members([number,3,"hello2",<<"value2">>],maps:values(M2)),
true = is_members([number,3,"hello",<<"value">>],maps:values(M1)),
%% error case
BigNum = 1 bsl 65 + 3,
{'EXIT',{{badmap,BigNum},[{maps,values,_,_}|_]}} = (catch maps:values(BigNum)),
{'EXIT',{{badmap,atom},[{maps,values,_,_}|_]}} = (catch maps:values(atom)),
{'EXIT',{{badmap,[]},[{maps,values,_,_}|_]}} = (catch maps:values([])),
{'EXIT',{{badmap,<<>>},[{maps,values,_,_}|_]}} = (catch maps:values(<<>>)),
ok.
t_erlang_hash(Config) when is_list(Config) ->
ok = t_bif_erlang_phash2(),
ok = t_bif_erlang_phash(),
ok.
t_bif_erlang_phash2() ->
39679005 = erlang:phash2(#{}),
33667975 = erlang:phash2(#{ a => 1, "a" => 2, <<"a">> => 3, {a,b} => 4 }), % 78942764
95332690 = erlang:phash2(#{ 1 => a, 2 => "a", 3 => <<"a">>, 4 => {a,b} }), % 37338230
108954384 = erlang:phash2(#{ 1 => a }), % 14363616
59617982 = erlang:phash2(#{ a => 1 }), % 51612236
42770201 = erlang:phash2(#{{} => <<>>}), % 37468437
71687700 = erlang:phash2(#{<<>> => {}}), % 44049159
M0 = #{ a => 1, "key" => <<"value">> },
M1 = maps:remove("key",M0),
M2 = M1#{ "key" => <<"value">> },
70249457 = erlang:phash2(M0), % 118679416
59617982 = erlang:phash2(M1), % 51612236
70249457 = erlang:phash2(M2), % 118679416
ok.
t_bif_erlang_phash() ->
Sz = 1 bsl 32,
1113425985 = erlang:phash(#{},Sz), % 268440612
1510068139 = erlang:phash(#{ a => 1, "a" => 2, <<"a">> => 3, {a,b} => 4 },Sz), % 1196461908
3182345590 = erlang:phash(#{ 1 => a, 2 => "a", 3 => <<"a">>, 4 => {a,b} },Sz), % 3944426064
2927531828 = erlang:phash(#{ 1 => a },Sz), % 1394238263
1670235874 = erlang:phash(#{ a => 1 },Sz), % 4066388227
3935089469 = erlang:phash(#{{} => <<>>},Sz), % 1578050717
71692856 = erlang:phash(#{<<>> => {}},Sz), % 1578050717
M0 = #{ a => 1, "key" => <<"value">> },
M1 = maps:remove("key",M0),
M2 = M1#{ "key" => <<"value">> },
2620391445 = erlang:phash(M0,Sz), % 3590546636
1670235874 = erlang:phash(M1,Sz), % 4066388227
2620391445 = erlang:phash(M2,Sz), % 3590546636
ok.
t_map_encode_decode(Config) when is_list(Config) ->
<<131,116,0,0,0,0>> = erlang:term_to_binary(#{}),
Pairs = [
{a,b},{"key","values"},{<<"key">>,<<"value">>},
{1,b},{[atom,1],{<<"wat">>,1,2,3}},
{aa,"values"},
{1 bsl 64 + (1 bsl 50 - 1), sc1},
{99, sc2},
{1 bsl 65 + (1 bsl 51 - 1), sc3},
{88, sc4},
{1 bsl 66 + (1 bsl 52 - 1), sc5},
{77, sc6},
{1 bsl 67 + (1 bsl 53 - 1), sc3},
{75, sc6}, {-10,sc8},
{<<>>, sc9}, {3.14158, sc10},
{[3.14158], sc11}, {more_atoms, sc12},
{{more_tuples}, sc13}, {self(), sc14},
{{},{}},{[],[]}
],
ok = map_encode_decode_and_match(Pairs,[],#{}),
%% check sorting
%% literally #{ b=>2, a=>1 } in the internal order
#{ a:=1, b:=2 } =
erlang:binary_to_term(<<131,116,0,0,0,2,100,0,1,98,97,2,100,0,1,97,97,1>>),
%% literally #{ "hi" => "value", a=>33, b=>55 } in the internal order
#{ a:=33, b:=55, "hi" := "value"} = erlang:binary_to_term(<<131,116,0,0,0,3,
107,0,2,104,105, % "hi" :: list()
107,0,5,118,97,108,117,101, % "value" :: list()
100,0,1,97, % a :: atom()
97,33, % 33 :: integer()
100,0,1,98, % b :: atom()
97,55 % 55 :: integer()
>>),
%% error cases
%% template: <<131,116,0,0,0,2,100,0,1,97,100,0,1,98,97,1,97,1>>
%% which is: #{ a=>1, b=>1 }
%% uniqueness violation
%% literally #{ a=>1, "hi"=>"value", a=>2 }
{'EXIT',{badarg,[{_,_,_,_}|_]}} = (catch
erlang:binary_to_term(<<131,116,0,0,0,3,100,0,1,97,107,0,2,104,105,100,0,1,97,97,1,107,0,5,118,97,108,117,101,97,2>>)),
%% bad size (too large)
{'EXIT',{badarg,[{_,_,_,_}|_]}} = (catch
erlang:binary_to_term(<<131,116,0,0,0,12,100,0,1,97,100,0,1,98,97,1,97,1>>)),
%% bad size (too small) .. should fail just truncate it .. weird.
%% possibly change external format so truncated will be #{a:=1}
#{ a:=b } =
erlang:binary_to_term(<<131,116,0,0,0,1,100,0,1,97,100,0,1,98,97,1,97,1>>),
ok.
map_encode_decode_and_match([{K,V}|Pairs], EncodedPairs, M0) ->
M1 = maps:put(K,V,M0),
B0 = erlang:term_to_binary(M1),
Ls = [{erlang:term_to_binary(K), erlang:term_to_binary(V)}|EncodedPairs],
ok = match_encoded_map(B0, length(Ls), Ls),
%% decode and match it
M1 = erlang:binary_to_term(B0),
map_encode_decode_and_match(Pairs,Ls,M1);
map_encode_decode_and_match([],_,_) -> ok.
match_encoded_map(<<131,116,Size:32,Encoded/binary>>,Size,Items) ->
match_encoded_map_stripped_size(Encoded,Items,Items);
match_encoded_map(_,_,_) -> no_match_size.
match_encoded_map_stripped_size(<<>>,_,_) -> ok;
match_encoded_map_stripped_size(B0,[{<<131,K/binary>>,<<131,V/binary>>}|Items],Ls) ->
Ksz = byte_size(K),
Vsz = byte_size(V),
case B0 of
<<K:Ksz/binary,V:Vsz/binary,B1/binary>> ->
match_encoded_map_stripped_size(B1,Ls,Ls);
_ ->
match_encoded_map_stripped_size(B0,Items,Ls)
end;
match_encoded_map_stripped_size(_,[],_) -> fail.
t_bif_map_to_list(Config) when is_list(Config) ->
[] = maps:to_list(#{}),
[{a,1},{b,2}] = lists:sort(maps:to_list(#{a=>1,b=>2})),
[{a,1},{b,2},{c,3}] = lists:sort(maps:to_list(#{c=>3,a=>1,b=>2})),
[{a,1},{b,2},{g,3}] = lists:sort(maps:to_list(#{g=>3,a=>1,b=>2})),
[{a,1},{b,2},{g,3},{"c",4}] = lists:sort(maps:to_list(#{g=>3,a=>1,b=>2,"c"=>4})),
[{3,v2},{hi,v4},{{hi,3},v5},{"hi",v3},{<<"hi">>,v1}] =
lists:sort(maps:to_list(#{<<"hi">>=>v1,3=>v2,"hi"=>v3,hi=>v4,{hi,3}=>v5})),
[{3,v7},{hi,v9},{{hi,3},v10},{"hi",v8},{<<"hi">>,v6}] =
lists:sort(maps:to_list(#{<<"hi">>=>v1,3=>v2,"hi"=>v3,hi=>v4,{hi,3}=>v5,
<<"hi">>=>v6,3=>v7,"hi"=>v8,hi=>v9,{hi,3}=>v10})),
%% error cases
{'EXIT', {{badmap,a},_}} = (catch maps:to_list(id(a))),
{'EXIT', {{badmap,42},_}} = (catch maps:to_list(id(42))),
ok.
t_bif_map_from_list(Config) when is_list(Config) ->
#{} = maps:from_list([]),
A = maps:from_list([]),
0 = erlang:map_size(A),
#{a:=1,b:=2} = maps:from_list([{a,1},{b,2}]),
#{c:=3,a:=1,b:=2} = maps:from_list([{a,1},{b,2},{c,3}]),
#{g:=3,a:=1,b:=2} = maps:from_list([{a,1},{b,2},{g,3}]),
#{a:=2} = maps:from_list([{a,1},{a,3},{a,2}]),
#{ <<"hi">>:=v1,3:=v3,"hi":=v6,hi:=v4,{hi,3}:=v5} =
maps:from_list([{3,v3},{"hi",v6},{hi,v4},{{hi,3},v5},{<<"hi">>,v1}]),
#{<<"hi">>:=v6,3:=v8,"hi":=v11,hi:=v9,{hi,3}:=v10} =
maps:from_list([ {{hi,3},v3}, {"hi",v0},{3,v1}, {<<"hi">>,v4}, {hi,v2},
{<<"hi">>,v6}, {{hi,3},v10},{"hi",v11}, {hi,v9}, {3,v8}]),
%% error cases
{'EXIT', {badarg,_}} = (catch maps:from_list(id([{a,b},b]))),
{'EXIT', {badarg,_}} = (catch maps:from_list(id([{a,b},{b,b,3}]))),
{'EXIT', {badarg,_}} = (catch maps:from_list(id([{a,b},<<>>]))),
{'EXIT', {badarg,_}} = (catch maps:from_list(id([{a,b}|{b,a}]))),
{'EXIT', {badarg,_}} = (catch maps:from_list(id(a))),
{'EXIT', {badarg,_}} = (catch maps:from_list(id(42))),
ok.
%% Maps module, not BIFs
t_maps_fold(_Config) ->
Vs = lists:seq(1,100),
M = maps:from_list([{{k,I},{v,I}}||I<-Vs]),
%% fold
5050 = maps:fold(fun({k,_},{v,V},A) -> V + A end, 0, M),
ok.
t_maps_map(_Config) ->
Vs = lists:seq(1,100),
M1 = maps:from_list([{I,I}||I<-Vs]),
M2 = maps:from_list([{I,{token,I}}||I<-Vs]),
M2 = maps:map(fun(_K,V) -> {token,V} end, M1),
ok.
t_maps_size(_Config) ->
Vs = lists:seq(1,100),
lists:foldl(fun(I,M) ->
M1 = maps:put(I,I,M),
I = maps:size(M1),
M1
end, #{}, Vs),
ok.
t_maps_without(_Config) ->
Ki = [11,22,33,44,55,66,77,88,99],
M0 = maps:from_list([{{k,I},{v,I}}||I<-lists:seq(1,100)]),
M1 = maps:from_list([{{k,I},{v,I}}||I<-lists:seq(1,100) -- Ki]),
M1 = maps:without([{k,I}||I <- Ki],M0),
ok.
%% MISC
t_pdict(_Config) ->
put(#{ a => b, b => a},#{ c => d}),
put(get(#{ a => b, b => a}),1),
1 = get(#{ c => d}),
#{ c := d } = get(#{ a => b, b => a}).
t_ets(_Config) ->
Tid = ets:new(map_table,[]),
[ets:insert(Tid,{maps:from_list([{I,-I}]),I}) || I <- lists:seq(1,100)],
[{#{ 2 := -2},2}] = ets:lookup(Tid,#{ 2 => -2 }),
%% Test equal
[3,4] = lists:sort(
ets:select(Tid,[{{'$1','$2'},
[{'or',{'==','$1',#{ 3 => -3 }},
{'==','$1',#{ 4 => -4 }}}],
['$2']}])),
%% Test match
[30,50] = lists:sort(
ets:select(Tid,
[{{#{ 30 => -30}, '$1'},[],['$1']},
{{#{ 50 => -50}, '$1'},[],['$1']}]
)),
ets:insert(Tid,{#{ a => b, b => c, c => a},transitivity}),
%% Test equal with map of different size
[] = ets:select(Tid,[{{'$1','_'},[{'==','$1',#{ b => c }}],['$_']}]),
%% Test match with map of different size
%%[{#{ a := b },_}] = ets:select(Tid,[{{#{ b => c },'_'},[],['$_']}]),
%%% Test match with don't care value
%%[{#{ a := b },_}] = ets:select(Tid,[{{#{ b => '_' },'_'},[],['$_']}]),
%% Test is_map bif
101 = length(ets:select(Tid,[{'$1',[{is_map,{element,1,'$1'}}],['$1']}])),
ets:insert(Tid,{not_a_map,2}),
101 = length(ets:select(Tid,[{'$1',[{is_map,{element,1,'$1'}}],['$1']}])),
ets:insert(Tid,{{nope,a,tuple},2}),
101 = length(ets:select(Tid,[{'$1',[{is_map,{element,1,'$1'}}],['$1']}])),
%% Test map_size bif
[3] = ets:select(Tid,[{{'$1','_'},[{'==',{map_size,'$1'},3}],
[{map_size,'$1'}]}]),
true = ets:delete(Tid,#{50 => -50}),
[] = ets:lookup(Tid,#{50 => -50}),
ets:delete(Tid),
ok.
t_build_and_match_aliasing(Config) when is_list(Config) ->
M1 = id(#{a=>1,b=>2,c=>3,d=>4}),
#{c:=C1=_=_=C2} = M1,
true = C1 =:= C2,
#{a:=A,a:=A,a:=A,b:=B,b:=B} = M1,
#{a:=A,a:=A,a:=A,b:=B,b:=B,b:=2} = M1,
#{a:=A=1,a:=A,a:=A,b:=B=2,b:=B,b:=2} = M1,
#{c:=C1, c:=_, c:=3, c:=_, c:=C2} = M1,
#{c:=C=_=3=_=C} = M1,
M2 = id(#{"a"=>1,"b"=>2,"c"=>3,"d"=>4}),
#{"a":=A2,"a":=A2,"a":=A2,"b":=B2,"b":=B2,"b":=2} = M2,
#{"a":=_,"a":=_,"a":=_,"b":=_,"b":=_,"b":=2} = M2,
ok.
%% simple build and match variables
t_build_and_match_variables(Config) when is_list(Config) ->
K0 = id(#{}),
K1 = id(1), V1 = id(a),
K2 = id(2), V2 = id(b),
K3 = id(3), V3 = id("c"),
K4 = id("4"), V4 = id("d"),
K5 = id(<<"5">>), V5 = id(<<"e">>),
K6 = id({"6",7}), V6 = id("f"),
K7 = id(#{ "a" => 3 }),
#{K1:=V1} = id(#{K1=>V1}),
#{K1:=V1,K2:=V2} = id(#{K1=>V1,K2=>V2}),
#{K1:=V1,K2:=V2,K3:=V3} = id(#{K1=>V1,K2=>V2,K3=>V3}),
#{K1:=V1,K2:=V2,K3:=V3,K4:=V4} = id(#{K1=>V1,K2=>V2,K3=>V3,K4=>V4}),
#{K1:=V1,K2:=V2,K3:=V3,K4:=V4,K5:=V5} = id(#{K1=>V1,K2=>V2,K3=>V3,K4=>V4,K5=>V5}),
#{K1:=V1,K2:=V2,K3:=V3,K4:=V4,K5:=V5,K6:=V6} = id(#{K1=>V1,K2=>V2,K3=>V3,K4=>V4,K5=>V5,K6=>V6}),
#{K5:=X,K5:=X=3,K4:=4} = id(#{K5=>3,K4=>4}),
#{K5:=X,<<"5">>:=X=3,K4:=4} = id(#{K5=>3,K4=>4}),
#{K5:=X,<<"5">>:=X=3,K4:=4} = id(#{<<"5">>=>3,K4=>4}),
#{ K4:=#{ K3:=#{K1:=V1, K2:=V2}}, K5:=V5} =
id(#{ K5=>V5, K4=>#{ K3=>#{K2 => V2, K1 => V1}}}),
#{ K4 := #{ K5 := Res }, K6 := Res} = id(#{K4=>#{K5 => 99}, K6 => 99}),
%% has keys
#{a :=_,b :=_,K1:=_,K2:=_,K3:=V3,K4:=ResKey,K4:=ResKey,"4":=ResKey,"4":="ok"} =
id(#{ a=>1, b=>1, K1=>V1, K2=>V2, K3=>V3, K4=>"nope", "4"=>"ok" }),
%% function
ok = match_function_map_neg_keys(#{ -1 => a, -2 => b, -3 => c }),
%% map key
#{ K0 := 42 } = id(#{ K0 => 42 }),
#{ K7 := 42 } = id(#{ K7 => 42 }),
%% nil key
KNIL = id([]),
#{KNIL:=ok,1:=2} = id(#{KNIL=>ok,1=>2}),
Bin = <<0:258>>,
#{ Bin := "three" } = id(#{<<0:258>> =>"three"}),
%% error case
{'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3,x:=2} = id(#{K5=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{K5:=2} = id(#{K5=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3} = id({a,b,c}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3} = id(#{K6=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3} = id(K7))),
{'EXIT',{{badmatch,_},_}} = (catch (#{K7:=3} = id(#{K7=>42}))),
ok.
match_function_map_neg_keys(#{ -1 := a, -2 := b, -3 := c }) -> ok.
t_update_assoc_variables(Config) when is_list(Config) ->
K1 = id(1),
K2 = id(2),
K3 = id(3.0),
K4 = id(4),
K5 = id(5),
K6 = id(2.0),
M0 = #{K1=>a,K2=>b,K3=>c,K4=>d,K5=>e},
M1 = M0#{K1=>42,K2=>100,K4=>[a,b,c]},
#{1:=42,2:=100,3.0:=c,4:=[a,b,c],5:=e} = M1,
#{1:=42,2:=b,4:=d,5:=e,2.0:=100,K3:=c,4.0:=[a,b,c]} = M0#{1.0=>float,1:=42,2.0=>wrong,K6=>100,4.0=>[a,b,c]},
M2 = M0#{K3=>new},
#{1:=a,2:=b,K3:=new,4:=d,5:=e} = M2,
M2 = M0#{3.0:=wrong,K3=>new},
#{ <<0:258>> := val } = id(M0#{<<0:258>> => val}), %% binary limitation
%% Errors cases.
BadMap = id(a_bad_map),
{'EXIT',{{badmap,BadMap},_}} = (catch BadMap#{nonexisting=>val}),
{'EXIT',{{badmap,<<>>},_}} = (catch <<>>#{nonexisting=>val}),
ok.
t_update_exact_variables(Config) when is_list(Config) ->
K1 = id(1),
K2 = id(2),
K3 = id(3.0),
K4 = id(4),
M0 = id(#{1=>a,2=>b,3.0=>c,4=>d,5=>e}),
M1 = M0#{K1:=42,K2:=100,K4:=[a,b,c]},
#{1:=42,2:=100,3.0:=c,K4:=[a,b,c],5:=e} = M1,
M1 = M0#{K1:=wrong,1:=also_wrong,K1=>42,2=>wrong,K2:=100,4:=[a,b,c]},
M2 = M0#{K3:=new},
#{1:=a,K2:=b,3.0:=new,K4:=d,5:=e} = M2,
M2 = M0#{3.0=>wrong,K3:=new},
true = M2 =/= M0#{3=>right,3.0:=new},
#{ 3 := right, 3.0 := new } = M0#{3=>right,K3:=new},
M3 = id(#{ 1 => val}),
#{1 := update2,1.0 := new_val4} = M3#{
1.0 => new_val1, K1 := update, K1=> update3,
K1 := update2, 1.0 := new_val2, 1.0 => new_val3,
1.0 => new_val4 },
%% Errors cases.
{'EXIT',{{badmap,_},_}} = (catch ((id(nil))#{ a := b })),
{'EXIT',{{badmap,_},_}} = (catch <<>>#{nonexisting:=val}),
{'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
{'EXIT',{{badkey,1.0},_}} = (catch M0#{1.0:=v,1.0=>v2}),
{'EXIT',{{badkey,_},_}} = (catch M0#{42.0:=v,42:=v2}),
{'EXIT',{{badkey,_},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
{'EXIT',{{badkey,_},_}} = (catch M0#{<<0:257>> := val}), %% limitation
ok.
t_nested_pattern_expressions(Config) when is_list(Config) ->
K1 = id("hello"),
%% K2 = id({ok}),
[_,_,#{ <<"hi">> := wat, K1 := 42 }|_] = id([k,k,#{<<"hi">> => wat, K1 => 42}]),
[_,_,#{ -1 := wat, K1 := 42 }|_] = id([k,k,#{-1 => wat, K1 => 42}]),
[_,_,{#{ -1 := #{ {-3,<<0:300>>} := V1 }, K1 := 42 },3}|_] = id([k,k,{#{-1 => #{{-3,<<0:300>>}=>"hi"}, K1 => 42},3}]),
"hi" = V1,
%%[k,#{ {-1,K1,[]} := {wat,K1}, K2 := 42 }|_] = id([k,#{{-1,K1,[]} => {wat,K1}, K2 => 42}]),
%%[k,#{ [-1,K2,[]] := {wat,K1}, K1 := 42 }|_] = id([k,#{[-1,K2,[]] => {wat,K1}, K1 => 42}]),
ok.
t_guard_update_variables(Config) when is_list(Config) ->
error = map_guard_update_variables(n,#{},#{}),
first = map_guard_update_variables(x,#{}, #{x=>first}),
second = map_guard_update_variables(x,#{y=>old}, #{x=>second,y=>old}),
third = map_guard_update_variables(x,#{x=>old,y=>old}, #{x=>third,y=>old}),
fourth = map_guard_update_variables(x,#{x=>old,y=>old}, #{x=>4,y=>new}),
ok.
map_guard_update_variables(K,M1,M2) when M1#{K=>first} =:= M2 -> first;
map_guard_update_variables(K,M1,M2) when M1#{K=>second} =:= M2 -> second;
map_guard_update_variables(K,M1,M2) when M1#{K:=third} =:= M2 -> third;
map_guard_update_variables(K,M1,M2) when M1#{K:=4,y=>new} =:= M2 -> fourth;
map_guard_update_variables(_,_,_) -> error.
t_guard_sequence_variables(Config) when is_list(Config) ->
{1,"a"} = map_guard_sequence_var_1(a,#{seq=>1,a=>id("a"),b=>no}),
{2,"b"} = map_guard_sequence_var_1(b,#{seq=>2,b=>id("b"),a=>no}),
{3,"c"} = map_guard_sequence_var_1(a,#{seq=>3,a=>id("c"),b=>no}),
{4,"d"} = map_guard_sequence_var_1(b,#{seq=>4,b=>id("d"),a=>no}),
{4,4} = map_guard_sequence_var_1(seq,#{seq=>4}),
{4,4,y} = map_guard_sequence_var_1(seq,#{seq=>4,b=>id("d"),a=>y}),
{5,"d"} = map_guard_sequence_var_1(b,#{seq=>5,b=>id("d"),a=>y}),
%% error case
{'EXIT',{{case_clause,_},_}} = (catch map_guard_sequence_var_1("a",#{seq=>4,val=>id("e")})),
ok.
map_guard_sequence_var_1(K,M) ->
case M of
#{seq:=1=Seq, K:=Val} -> {Seq,Val};
#{seq:=2=Seq, K:=Val} -> {Seq,Val};
#{seq:=3=Seq, K:=Val} -> {Seq,Val};
#{K:=4=Seq, K:=Val1,a:=Val2} -> {Seq,Val1,Val2};
#{seq:=4=Seq, K:=Val} -> {Seq,Val};
#{K:=4=Seq, K:=Val} -> {Seq,Val};
#{seq:=5=Seq, K:=Val} -> {Seq,Val}
end.
t_guard_sequence_mixed(Config) when is_list(Config) ->
M0 = id(#{ a=>1, b=>1, c=>1, d=>1, e=>1, f=>1, g=>1, h=>1 }),
M1 = id(M0#{ d := 3 }),
1 = map_guard_sequence_mixed(a,d,M1),
M2 = id(M1#{ b := 2, d := 4, h := 2 }),
2 = map_guard_sequence_mixed(a,d,M2),
M3 = id(M2#{ b := 3, e := 5, g := 3 }),
3 = map_guard_sequence_mixed(a,e,M3),
M4 = id(M3#{ c := 4, e := 6, h := 1 }),
4 = map_guard_sequence_mixed(a,e,M4),
M5 = id(M4#{ c := 5, f := 7, g := 2 }),
5 = map_guard_sequence_mixed(a,f,M5),
M6 = id(M5#{ c := 6, f := 8, h := 3 }),
6 = map_guard_sequence_mixed(a,f,M6),
%% error case
{'EXIT',{{case_clause,_},_}} = (catch map_guard_sequence_mixed(a,b,M0)),
ok.
map_guard_sequence_mixed(K1,K2,M) ->
case M of
#{ K1 := 1, b := 1, K2 := 3, g := 1} -> 1;
#{ K1 := 1, b := 2, K2 := 4, h := 2} -> 2;
#{ K1 := 1, b := 3, K2 := 5, g := 3} -> 3;
#{ K1 := 1, c := 4, K2 := 6, h := 1} -> 4;
#{ K1 := 1, c := 5, K2 := 7, g := 2} -> 5;
#{ K1 := 1, c := 6, K2 := 8, h := 3} -> 6
end.
t_frequency_table(Config) when is_list(Config) ->
rand:seed(exsplus, {13,1337,54}), % pseudo random
N = 1000,
Ts = rand_terms(N),
#{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}),
ok = check_frequency(Ts,Tf),
ok.
frequency_table([T|Ts], M) ->
case M of
#{ n := N, tf := #{ T := C } = F } ->
frequency_table(Ts,M#{ n := N + 1, tf := F#{ T := C + 1 }});
#{ n := N, tf := F } ->
frequency_table(Ts,M#{ n := N + 1, tf := F#{ T => 1 }})
end;
frequency_table([], M) -> M.
check_frequency(Ts,Tf) ->
check_frequency(Ts,Tf,dict:new()).
check_frequency([T|Ts],Tf,D) ->
case dict:find(T,D) of
error -> check_frequency(Ts,Tf,dict:store(T,1,D));
{ok,C} -> check_frequency(Ts,Tf,dict:store(T,C+1,D))
end;
check_frequency([],Tf,D) ->
validate_frequency(dict:to_list(D),Tf).
validate_frequency([{T,C}|Fs],Tf) ->
case Tf of
#{ T := C } -> validate_frequency(Fs,Tf);
_ -> error
end;
validate_frequency([], _) -> ok.
%% aux
rand_terms(0) -> [];
rand_terms(N) -> [rand_term()|rand_terms(N-1)].
rand_term() ->
case rand:uniform(6) of
1 -> rand_binary();
2 -> rand_number();
3 -> rand_atom();
4 -> rand_tuple();
5 -> rand_list();
6 -> rand_map()
end.
rand_binary() ->
case rand:uniform(3) of
1 -> <<>>;
2 -> <<"hi">>;
3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">>
end.
rand_number() ->
case rand:uniform(3) of
1 -> rand:uniform(5);
2 -> float(rand:uniform(5));
3 -> 1 bsl (63 + rand:uniform(3))
end.
rand_atom() ->
case rand:uniform(3) of
1 -> hi;
2 -> some_atom;
3 -> some_other_atom
end.
rand_tuple() ->
case rand:uniform(3) of
1 -> {ok, rand_term()}; % careful
2 -> {1, 2, 3};
3 -> {<<"yep">>, 1337}
end.
rand_list() ->
case rand:uniform(3) of
1 -> "hi";
2 -> [1,rand_term()]; % careful
3 -> [improper|list]
end.
rand_map() ->
case rand:uniform(3) of
1 -> #{ hi => 3 };
2 -> #{ wat => rand_term(), other => 3 }; % careful
3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
end.
t_build_and_match_over_alloc(Config) when is_list(Config) ->
Ls = id([1,2,3]),
V0 = [a|Ls],
M0 = id(#{ "a" => V0 }),
#{ "a" := V1 } = M0,
V2 = id([c|Ls]),
M2 = id(#{ "a" => V2 }),
#{ "a" := V3 } = M2,
{[a,1,2,3],[c,1,2,3]} = id({V1,V3}),
ok.
t_build_and_match_empty_val(Config) when is_list(Config) ->
F = fun(#{ "hi":=_,{1,2}:=_,1337:=_}) -> ok end,
ok = F(id(#{"hi"=>ok,{1,2}=>ok,1337=>ok})),
%% error case
case (catch (F(id(#{"hi"=>ok})))) of
{'EXIT',{function_clause,_}} -> ok;
{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
Other ->
ct:fail({no_match, Other})
end.
t_build_and_match_val(Config) when is_list(Config) ->
F = fun
(#{ "hi" := first, v := V}) -> {1,V};
(#{ "hi" := second, v := V}) -> {2,V}
end,
{1,"hello"} = F(id(#{"hi"=>first,v=>"hello"})),
{2,"second"} = F(id(#{"hi"=>second,v=>"second"})),
%% error case
case (catch (F(id(#{"hi"=>ok})))) of
{'EXIT',{function_clause,_}} -> ok;
{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
Other ->
ct:fail({no_match, Other})
end.
t_build_and_match_nil(Config) when is_list(Config) ->
%% literals removed the coverage
V1 = id(cookie),
V2 = id(cake),
V3 = id(crisps),
#{ [] := V1, "treat" := V2, {your,treat} := V3 } = id(#{
{your,treat} => V3,
"treat" => V2,
[] => V1 }),
#{ [] := V3, [] := V3 } = id(#{ [] => V1, [] => V3 }),
ok.
t_build_and_match_structure(Config) when is_list(Config) ->
V2 = id("it"),
S = id([42,{"hi", "=)", #{ "a" => 42, any => any, val => "get_" ++ V2}}]),
%% match deep map values
V2 = case S of
[42,{"hi",_, #{ "a" := 42, val := "get_" ++ V1, any := _ }}] -> V1
end,
%% match deep map
ok = case S of
[42,{"hi",_, #{ }}] -> ok
end,
ok.
do_badmap(Test) ->
Terms = [Test,fun erlang:abs/1,make_ref(),self(),0.0/id(-1),
<<1:1>>,<<>>,<<1,2,3>>,
[],{a,b,c},[a,b],atom,10.0,42,(1 bsl 65) + 3],
[Test(T) || T <- Terms].
%% Use this function to avoid compile-time evaluation of an expression.
id(I) -> I.