%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2007-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% -module(core_alias_SUITE). -export([all/0, suite/0, groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2, tuples/1, cons/1, catastrophic_runtime/1]). -include_lib("common_test/include/ct.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [{group,p}]. groups() -> [{p,[parallel], [tuples, cons, catastrophic_runtime]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), Config. end_per_suite(_Config) -> ok. init_per_group(_GroupName, Config) -> Config. end_per_group(_GroupName, Config) -> Config. id(X) -> X. tuples(Config) when is_list(Config) -> Tuple = id({ok,id(value)}), true = erts_debug:same(Tuple, simple_tuple(Tuple)), true = erts_debug:same(Tuple, simple_tuple_in_map(#{hello => Tuple})), true = erts_debug:same(Tuple, simple_tuple_case_repeated(Tuple, Tuple)), true = erts_debug:same(Tuple, simple_tuple_fun_repeated(Tuple, Tuple)), true = erts_debug:same(Tuple, simple_tuple_twice_head(Tuple, Tuple)), {Tuple1, Tuple2} = id(simple_tuple_twice_body(Tuple)), true = erts_debug:same(Tuple, Tuple1), true = erts_debug:same(Tuple, Tuple2), Nested = id({nested,Tuple}), true = erts_debug:same(Tuple, nested_tuple_part(Nested)), true = erts_debug:same(Nested, nested_tuple_whole(Nested)), true = erts_debug:same(Nested, nested_tuple_with_alias(Nested)), true = erts_debug:same(Tuple, tuple_rebinding_after(Tuple)), Tuple = id(unaliased_tuple_rebinding_before(Tuple)), false = erts_debug:same(Tuple, unaliased_tuple_rebinding_before(Tuple)), Nested = id(unaliased_literal_tuple_head(Nested)), false = erts_debug:same(Nested, unaliased_literal_tuple_head(Nested)), Nested = id(unaliased_literal_tuple_body(Nested)), false = erts_debug:same(Nested, unaliased_literal_tuple_body(Nested)), Nested = id(unaliased_different_var_tuple(Nested, Tuple)), false = erts_debug:same(Nested, unaliased_different_var_tuple(Nested, Tuple)). simple_tuple({ok,X}) -> {ok,X}. simple_tuple_twice_head({ok,X}, {ok,X}) -> {ok,X}. simple_tuple_twice_body({ok,X}) -> {{ok,X},{ok,X}}. simple_tuple_in_map(#{hello := {ok,X}}) -> {ok,X}. simple_tuple_fun_repeated({ok,X}, Y) -> io:format("~p~n", [X]), (fun({ok,X}) -> {ok,X} end)(Y). simple_tuple_case_repeated({ok,X}, Y) -> io:format("~p~n", [X]), case Y of {ok,X} -> {ok,X} end. nested_tuple_part({nested,{ok,X}}) -> {ok,X}. nested_tuple_whole({nested,{ok,X}}) -> {nested,{ok,X}}. nested_tuple_with_alias({nested,{ok,_}=Y}) -> {nested,Y}. tuple_rebinding_after(Y) -> (fun(X) -> {ok,X} end)(Y), case Y of {ok,X} -> {ok,X} end. unaliased_tuple_rebinding_before({ok,X}) -> io:format("~p~n", [X]), (fun(X) -> {ok,X} end)(value). unaliased_literal_tuple_head({nested,{ok,value}=X}) -> io:format("~p~n", [X]), {nested,{ok,value}}. unaliased_literal_tuple_body({nested,{ok,value}=X}) -> Res = {nested,Y={ok,value}}, io:format("~p~n", [[X,Y]]), Res. unaliased_different_var_tuple({nested,{ok,value}=X}, Y) -> io:format("~p~n", [X]), {nested,Y}. cons(Config) when is_list(Config) -> Cons = id([ok|id(value)]), true = erts_debug:same(Cons, simple_cons(Cons)), true = erts_debug:same(Cons, simple_cons_in_map(#{hello => Cons})), true = erts_debug:same(Cons, simple_cons_case_repeated(Cons, Cons)), true = erts_debug:same(Cons, simple_cons_fun_repeated(Cons, Cons)), true = erts_debug:same(Cons, simple_cons_twice_head(Cons, Cons)), {Cons1,Cons2} = id(simple_cons_twice_body(Cons)), true = erts_debug:same(Cons, Cons1), true = erts_debug:same(Cons, Cons2), Nested = id([nested,Cons]), true = erts_debug:same(Cons, nested_cons_part(Nested)), true = erts_debug:same(Nested, nested_cons_whole(Nested)), true = erts_debug:same(Nested, nested_cons_with_alias(Nested)), true = erts_debug:same(Cons, cons_rebinding_after(Cons)), Unstripped = id([a,b]), Stripped = id(cons_with_binary([<<>>|Unstripped])), true = erts_debug:same(Unstripped, Stripped), Cons = id(unaliased_cons_rebinding_before(Cons)), false = erts_debug:same(Cons, unaliased_cons_rebinding_before(Cons)), Nested = id(unaliased_literal_cons_head(Nested)), false = erts_debug:same(Nested, unaliased_literal_cons_head(Nested)), Nested = id(unaliased_literal_cons_body(Nested)), false = erts_debug:same(Nested, unaliased_literal_cons_body(Nested)), Nested = id(unaliased_different_var_cons(Nested, Cons)), false = erts_debug:same(Nested, unaliased_different_var_cons(Nested, Cons)). simple_cons([ok|X]) -> [ok|X]. simple_cons_twice_head([ok|X], [ok|X]) -> [ok|X]. simple_cons_twice_body([ok|X]) -> {[ok|X],[ok|X]}. simple_cons_in_map(#{hello := [ok|X]}) -> [ok|X]. simple_cons_fun_repeated([ok|X], Y) -> io:format("~p~n", [X]), (fun([ok|X]) -> [ok|X] end)(Y). simple_cons_case_repeated([ok|X], Y) -> io:format("~p~n", [X]), case Y of [ok|X] -> [ok|X] end. nested_cons_part([nested,[ok|X]]) -> [ok|X]. nested_cons_whole([nested,[ok|X]]) -> [nested,[ok|X]]. nested_cons_with_alias([nested,[ok|_]=Y]) -> [nested,Y]. cons_with_binary([<<>>,X|Y]) -> cons_with_binary([X|Y]); cons_with_binary(A) -> A. cons_rebinding_after(Y) -> (fun(X) -> [ok|X] end)(Y), case Y of [ok|X] -> [ok|X] end. unaliased_cons_rebinding_before([ok|X]) -> io:format("~p~n", [X]), (fun(X) -> [ok|X] end)(value). unaliased_literal_cons_head([nested,[ok|value]=X]) -> io:format("~p~n", [X]), [nested,[ok|value]]. unaliased_literal_cons_body([nested,[ok|value]=X]) -> Res = [nested,Y=[ok|value]], io:format("~p~n", [[X, Y]]), Res. unaliased_different_var_cons([nested,[ok|value]=X], Y) -> io:format("~p~n", [X]), [nested,Y]. catastrophic_runtime(Config) -> ct:timetrap({minutes, 6}), Depth = 16000, PrivDir = proplists:get_value(priv_dir,Config), Path = filename:join(PrivDir, "catastrophic_runtime.erl"), Term = catastrophic_runtime_1(Depth), Source = ["-module(catastrophic_runtime). t(Value) -> ", Term, "."], ok = file:write_file(Path, Source), {ok, catastrophic_runtime} = compile:file(Path, [return_error]), file:delete(Path), ok. catastrophic_runtime_1(0) -> <<"Value">>; catastrophic_runtime_1(N) -> Nested = catastrophic_runtime_1(N - 1), Integer = integer_to_binary(N), Eq = [<<"{{'.',[],[erlang,'=:=']},[],[Value, \"">>, Integer, <<"\"]}">>], [<<"{{'.',[],[erlang,atom]},[],[">>, Nested, <<",">>, Eq, <<"]}">>].