1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2007-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(core_alias_SUITE). 21 22-export([all/0, suite/0, groups/0,init_per_suite/1, end_per_suite/1, 23 init_per_group/2, end_per_group/2, 24 tuples/1, cons/1, catastrophic_runtime/1]). 25 26-include_lib("common_test/include/ct.hrl"). 27 28suite() -> [{ct_hooks,[ts_install_cth]}]. 29 30all() -> 31 [{group,p}]. 32 33groups() -> 34 [{p,[parallel], 35 [tuples, cons, catastrophic_runtime]}]. 36 37init_per_suite(Config) -> 38 test_lib:recompile(?MODULE), 39 Config. 40 41end_per_suite(_Config) -> 42 ok. 43 44init_per_group(_GroupName, Config) -> 45 Config. 46 47end_per_group(_GroupName, Config) -> 48 Config. 49 50id(X) -> X. 51 52tuples(Config) when is_list(Config) -> 53 Tuple = id({ok,id(value)}), 54 55 true = erts_debug:same(Tuple, simple_tuple(Tuple)), 56 true = erts_debug:same(Tuple, simple_tuple_in_map(#{hello => Tuple})), 57 true = erts_debug:same(Tuple, simple_tuple_case_repeated(Tuple, Tuple)), 58 true = erts_debug:same(Tuple, simple_tuple_fun_repeated(Tuple, Tuple)), 59 true = erts_debug:same(Tuple, simple_tuple_twice_head(Tuple, Tuple)), 60 61 {Tuple1, Tuple2} = id(simple_tuple_twice_body(Tuple)), 62 true = erts_debug:same(Tuple, Tuple1), 63 true = erts_debug:same(Tuple, Tuple2), 64 65 Nested = id({nested,Tuple}), 66 true = erts_debug:same(Tuple, nested_tuple_part(Nested)), 67 true = erts_debug:same(Nested, nested_tuple_whole(Nested)), 68 true = erts_debug:same(Nested, nested_tuple_with_alias(Nested)), 69 70 true = erts_debug:same(Tuple, tuple_rebinding_after(Tuple)), 71 72 Tuple = id(unaliased_tuple_rebinding_before(Tuple)), 73 false = erts_debug:same(Tuple, unaliased_tuple_rebinding_before(Tuple)), 74 Nested = id(unaliased_literal_tuple_head(Nested)), 75 false = erts_debug:same(Nested, unaliased_literal_tuple_head(Nested)), 76 Nested = id(unaliased_literal_tuple_body(Nested)), 77 false = erts_debug:same(Nested, unaliased_literal_tuple_body(Nested)), 78 Nested = id(unaliased_different_var_tuple(Nested, Tuple)), 79 false = erts_debug:same(Nested, unaliased_different_var_tuple(Nested, Tuple)). 80 81simple_tuple({ok,X}) -> 82 {ok,X}. 83simple_tuple_twice_head({ok,X}, {ok,X}) -> 84 {ok,X}. 85simple_tuple_twice_body({ok,X}) -> 86 {{ok,X},{ok,X}}. 87simple_tuple_in_map(#{hello := {ok,X}}) -> 88 {ok,X}. 89simple_tuple_fun_repeated({ok,X}, Y) -> 90 io:format("~p~n", [X]), 91 (fun({ok,X}) -> {ok,X} end)(Y). 92simple_tuple_case_repeated({ok,X}, Y) -> 93 io:format("~p~n", [X]), 94 case Y of {ok,X} -> {ok,X} end. 95 96nested_tuple_part({nested,{ok,X}}) -> 97 {ok,X}. 98nested_tuple_whole({nested,{ok,X}}) -> 99 {nested,{ok,X}}. 100nested_tuple_with_alias({nested,{ok,_}=Y}) -> 101 {nested,Y}. 102 103tuple_rebinding_after(Y) -> 104 (fun(X) -> {ok,X} end)(Y), 105 case Y of {ok,X} -> {ok,X} end. 106unaliased_tuple_rebinding_before({ok,X}) -> 107 io:format("~p~n", [X]), 108 (fun(X) -> {ok,X} end)(value). 109unaliased_literal_tuple_head({nested,{ok,value}=X}) -> 110 io:format("~p~n", [X]), 111 {nested,{ok,value}}. 112unaliased_literal_tuple_body({nested,{ok,value}=X}) -> 113 Res = {nested,Y={ok,value}}, 114 io:format("~p~n", [[X,Y]]), 115 Res. 116unaliased_different_var_tuple({nested,{ok,value}=X}, Y) -> 117 io:format("~p~n", [X]), 118 {nested,Y}. 119 120cons(Config) when is_list(Config) -> 121 Cons = id([ok|id(value)]), 122 123 true = erts_debug:same(Cons, simple_cons(Cons)), 124 true = erts_debug:same(Cons, simple_cons_in_map(#{hello => Cons})), 125 true = erts_debug:same(Cons, simple_cons_case_repeated(Cons, Cons)), 126 true = erts_debug:same(Cons, simple_cons_fun_repeated(Cons, Cons)), 127 true = erts_debug:same(Cons, simple_cons_twice_head(Cons, Cons)), 128 129 {Cons1,Cons2} = id(simple_cons_twice_body(Cons)), 130 true = erts_debug:same(Cons, Cons1), 131 true = erts_debug:same(Cons, Cons2), 132 133 Nested = id([nested,Cons]), 134 true = erts_debug:same(Cons, nested_cons_part(Nested)), 135 true = erts_debug:same(Nested, nested_cons_whole(Nested)), 136 true = erts_debug:same(Nested, nested_cons_with_alias(Nested)), 137 true = erts_debug:same(Cons, cons_rebinding_after(Cons)), 138 139 Unstripped = id([a,b]), 140 Stripped = id(cons_with_binary([<<>>|Unstripped])), 141 true = erts_debug:same(Unstripped, Stripped), 142 143 Cons = id(unaliased_cons_rebinding_before(Cons)), 144 false = erts_debug:same(Cons, unaliased_cons_rebinding_before(Cons)), 145 Nested = id(unaliased_literal_cons_head(Nested)), 146 false = erts_debug:same(Nested, unaliased_literal_cons_head(Nested)), 147 Nested = id(unaliased_literal_cons_body(Nested)), 148 false = erts_debug:same(Nested, unaliased_literal_cons_body(Nested)), 149 Nested = id(unaliased_different_var_cons(Nested, Cons)), 150 false = erts_debug:same(Nested, unaliased_different_var_cons(Nested, Cons)). 151 152simple_cons([ok|X]) -> 153 [ok|X]. 154simple_cons_twice_head([ok|X], [ok|X]) -> 155 [ok|X]. 156simple_cons_twice_body([ok|X]) -> 157 {[ok|X],[ok|X]}. 158simple_cons_in_map(#{hello := [ok|X]}) -> 159 [ok|X]. 160simple_cons_fun_repeated([ok|X], Y) -> 161 io:format("~p~n", [X]), 162 (fun([ok|X]) -> [ok|X] end)(Y). 163simple_cons_case_repeated([ok|X], Y) -> 164 io:format("~p~n", [X]), 165 case Y of [ok|X] -> [ok|X] end. 166 167nested_cons_part([nested,[ok|X]]) -> 168 [ok|X]. 169nested_cons_whole([nested,[ok|X]]) -> 170 [nested,[ok|X]]. 171nested_cons_with_alias([nested,[ok|_]=Y]) -> 172 [nested,Y]. 173 174cons_with_binary([<<>>,X|Y]) -> 175 cons_with_binary([X|Y]); 176cons_with_binary(A) -> 177 A. 178 179cons_rebinding_after(Y) -> 180 (fun(X) -> [ok|X] end)(Y), 181 case Y of [ok|X] -> [ok|X] end. 182unaliased_cons_rebinding_before([ok|X]) -> 183 io:format("~p~n", [X]), 184 (fun(X) -> [ok|X] end)(value). 185unaliased_literal_cons_head([nested,[ok|value]=X]) -> 186 io:format("~p~n", [X]), 187 [nested,[ok|value]]. 188unaliased_literal_cons_body([nested,[ok|value]=X]) -> 189 Res = [nested,Y=[ok|value]], 190 io:format("~p~n", [[X, Y]]), 191 Res. 192unaliased_different_var_cons([nested,[ok|value]=X], Y) -> 193 io:format("~p~n", [X]), 194 [nested,Y]. 195 196catastrophic_runtime(Config) -> 197 ct:timetrap({minutes, 6}), 198 Depth = 16000, 199 200 PrivDir = proplists:get_value(priv_dir,Config), 201 Path = filename:join(PrivDir, "catastrophic_runtime.erl"), 202 203 Term = catastrophic_runtime_1(Depth), 204 Source = ["-module(catastrophic_runtime). t(Value) -> ", Term, "."], 205 ok = file:write_file(Path, Source), 206 207 {ok, catastrophic_runtime} = compile:file(Path, [return_error]), 208 file:delete(Path), 209 210 ok. 211 212catastrophic_runtime_1(0) -> 213 <<"Value">>; 214catastrophic_runtime_1(N) -> 215 Nested = catastrophic_runtime_1(N - 1), 216 Integer = integer_to_binary(N), 217 Eq = [<<"{{'.',[],[erlang,'=:=']},[],[Value, \"">>, Integer, <<"\"]}">>], 218 [<<"{{'.',[],[erlang,atom]},[],[">>, Nested, <<",">>, Eq, <<"]}">>]. 219 220