1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2016. 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%% 21-module(exception_SUITE). 22 23-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 24 init_per_testcase/2,end_per_testcase/2, 25 init_per_suite/1,end_per_suite/1, 26 badmatch/1,pending_errors/1,nil_arith/1, 27 stacktrace/1,nested_stacktrace/1,raise/1,gunilla/1,per/1]). 28 29-export([bad_guy/2]). 30 31-include_lib("common_test/include/ct.hrl"). 32 33suite() -> 34 [{ct_hooks,[ts_install_cth]}, 35 {timetrap,{minutes,1}}]. 36 37%% Filler. 38%% 39%% 40%% This is line 40. 41even(N) when is_integer(N), N > 1, (N rem 2) == 0 -> 42 odd(N-1)++[N]. 43 44odd(N) when is_integer(N), N > 1, (N rem 2) == 1 -> 45 even(N-1)++[N]. 46 47 48all() -> 49 cases(). 50 51groups() -> 52 []. 53 54init_per_group(_GroupName, Config) -> 55 Config. 56 57end_per_group(_GroupName, Config) -> 58 Config. 59 60 61cases() -> 62 [badmatch, pending_errors, nil_arith, stacktrace, 63 nested_stacktrace, raise, gunilla, per]. 64 65-define(try_match(E), 66 catch ?MODULE:bar(), 67 {'EXIT', {{badmatch, nomatch}, _}} = (catch E = nomatch)). 68 69init_per_testcase(_Case, Config) -> 70 test_lib:interpret(?MODULE), 71 Config. 72 73end_per_testcase(_Case, _Config) -> 74 ok. 75 76init_per_suite(Config) when is_list(Config) -> 77 test_lib:interpret(?MODULE), 78 true = lists:member(?MODULE, int:interpreted()), 79 Config. 80 81end_per_suite(Config) when is_list(Config) -> 82 ok. 83 84%% Test that deliberately bad matches are reported correctly. 85 86badmatch(Config) when is_list(Config) -> 87 ?try_match(a), 88 ?try_match(42), 89 ?try_match({a, b, c}), 90 ?try_match([]), 91 ?try_match(1.0), 92 ok. 93 94%% Test various exceptions, in the presence of a previous error suppressed 95%% in a guard. 96pending_errors(Config) when is_list(Config) -> 97 pending(e_badmatch, {badmatch, b}), 98 pending(x, function_clause), 99 pending(e_case, {case_clause, xxx}), 100 pending(e_if, if_clause), 101 pending(e_badarith, badarith), 102 pending(e_undef, undef), 103 pending(e_timeoutval, timeout_value), 104 pending(e_badarg, badarg), 105 pending(e_badarg_spawn, badarg), 106 ok. 107 108bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed) 109 ok; 110bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed) 111 ok; 112bad_guy(_, e_case) -> 113 case id(xxx) of 114 ok -> ok 115 end; % case_clause 116bad_guy(_, e_if) -> 117 if 118 a == b -> ok 119 end; % if_clause 120bad_guy(_, e_badarith) -> 121 1+b; % badarith 122bad_guy(_, e_undef) -> 123 non_existing_module:foo(); % undef 124bad_guy(_, e_timeoutval) -> 125 receive 126 after arne -> % timeout_value 127 ok 128 end; 129bad_guy(_, e_badarg) -> 130 node(xxx); % badarg 131bad_guy(_, e_badarg_spawn) -> 132 spawn({}, {}, {}); % badarg 133bad_guy(_, e_badmatch) -> 134 a = id(b). % badmatch 135 136pending(Arg, Expected) -> 137 pending(pe_badarith, Arg, Expected), 138 pending(pe_badarg, Arg, Expected). 139 140pending(First, Second, Expected) -> 141 pending_catched(First, Second, Expected), 142 pending_exit_message([First, Second], Expected). 143 144pending_catched(First, Second, Expected) -> 145 ok = io:format("Catching bad_guy(~p, ~p)", [First, Second]), 146 case catch bad_guy(First, Second) of 147 {'EXIT', Reason} -> 148 pending(Reason, bad_guy, [First, Second], Expected); 149 Other -> 150 ct:fail({not_exit, Other}) 151 end. 152 153pending_exit_message(Args, Expected) -> 154 ok = io:format("Trapping EXITs from spawn_link(~p, ~p, ~p)", 155 [?MODULE, bad_guy, Args]), 156 process_flag(trap_exit, true), 157 Pid = spawn_link(?MODULE, bad_guy, Args), 158 receive 159 {'EXIT', Pid, Reason} -> 160 pending(Reason, bad_guy, Args, Expected); 161 Other -> 162 ct:fail({unexpected_message, Other}) 163 after 10000 -> 164 ct:fail(timeout) 165 end, 166 process_flag(trap_exit, false). 167 168pending({badarg, [{erlang,Bif,BifArgs,_},{?MODULE,Func,Arity,_}|_]}, 169 Func, Args, _Code) 170 when is_atom(Bif), is_list(BifArgs), length(Args) == Arity -> 171 ok; 172pending({undef,[{non_existing_module,foo,[],_}|_]}, _, _, _) -> 173 ok; 174pending({function_clause,[{?MODULE,Func,Args,_}|_]}, Func, Args, _Code) -> 175 ok; 176pending({Code,[{?MODULE,Func,Arity,_}|_]}, Func, Args, Code) 177 when length(Args) == Arity -> 178 ok; 179pending(Reason, _Function, _Args, _Code) -> 180 ct:fail({bad_exit_reason,Reason}). 181 182%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash. 183 184nil_arith(Config) when is_list(Config) -> 185 ba_plus_minus_times([], []), 186 187 ba_plus_minus_times([], 0), 188 ba_plus_minus_times([], 42), 189 ba_plus_minus_times([], 38724978123478923784), 190 ba_plus_minus_times([], 38.72), 191 192 ba_plus_minus_times(0, []), 193 ba_plus_minus_times(334, []), 194 ba_plus_minus_times(387249797813478923784, []), 195 ba_plus_minus_times(344.22, []), 196 197 ba_div_rem([], []), 198 199 ba_div_rem([], 0), 200 ba_div_rem([], 1), 201 ba_div_rem([], 42), 202 ba_div_rem([], 38724978123478923784), 203 ba_div_rem(344.22, []), 204 205 ba_div_rem(0, []), 206 ba_div_rem(1, []), 207 ba_div_rem(334, []), 208 ba_div_rem(387249797813478923784, []), 209 ba_div_rem(344.22, []), 210 211 ba_div_rem(344.22, 0.0), 212 ba_div_rem(1, 0.0), 213 ba_div_rem(392873498733971, 0.0), 214 215 ba_bop([], []), 216 ba_bop(0, []), 217 ba_bop(42, []), 218 ba_bop(-42342742987343, []), 219 ba_bop(238.342, []), 220 ba_bop([], 0), 221 ba_bop([], -243), 222 ba_bop([], 243), 223 ba_bop([], 2438724982478933), 224 ba_bop([], 3987.37), 225 226 ba_bnot([]), 227 ba_bnot(23.33), 228 229 ba_shift([], []), 230 ba_shift([], 0), 231 ba_shift([], 4), 232 ba_shift([], -4), 233 ba_shift([], 2343333333333), 234 ba_shift([], -333333333), 235 ba_shift([], 234.00), 236 ba_shift(23, []), 237 ba_shift(0, []), 238 ba_shift(-3433443433433323, []), 239 ba_shift(433443433433323, []), 240 ba_shift(343.93, []), 241 ok. 242 243ba_plus_minus_times(A, B) -> 244 io:format("~p + ~p", [A, B]), 245 {'EXIT', {badarith, _}} = (catch A + B), 246 io:format("~p - ~p", [A, B]), 247 {'EXIT', {badarith, _}} = (catch A - B), 248 io:format("~p * ~p", [A, B]), 249 {'EXIT', {badarith, _}} = (catch A * B). 250 251ba_div_rem(A, B) -> 252 io:format("~p / ~p", [A, B]), 253 {'EXIT', {badarith, _}} = (catch A / B), 254 io:format("~p div ~p", [A, B]), 255 {'EXIT', {badarith, _}} = (catch A div B), 256 io:format("~p rem ~p", [A, B]), 257 {'EXIT', {badarith, _}} = (catch A rem B). 258 259ba_bop(A, B) -> 260 io:format("~p band ~p", [A, B]), 261 {'EXIT', {badarith, _}} = (catch A band B), 262 io:format("~p bor ~p", [A, B]), 263 {'EXIT', {badarith, _}} = (catch A bor B), 264 io:format("~p bxor ~p", [A, B]), 265 {'EXIT', {badarith, _}} = (catch A bxor B). 266 267ba_shift(A, B) -> 268 io:format("~p bsl ~p", [A, B]), 269 {'EXIT', {badarith, _}} = (catch A bsl B), 270 io:format("~p bsr ~p", [A, B]), 271 {'EXIT', {badarith, _}} = (catch A bsr B). 272 273ba_bnot(A) -> 274 io:format("bnot ~p", [A]), 275 {'EXIT', {badarith, _}} = (catch bnot A). 276 277stacktrace(Conf) when is_list(Conf) -> 278 V = [make_ref()|self()], 279 {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} = 280 stacktrace_1({'abs',V}, error, {value,V}), 281 {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} = 282 stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}), 283 {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} = 284 stacktrace_1({value,V}, error, {value,V}), 285 {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} = 286 stacktrace_1({value,V}, error, {throw,V}), 287 ok. 288 289stacktrace_1(X, C1, Y) -> 290 try try foo(X) of 291 C1 -> value1 292 catch 293 C1:D1:S1 -> {caught1,D1,S1} 294 after 295 foo(Y) 296 end of 297 V2 -> {value2,V2} 298 catch 299 C2:D2:S2 -> {caught2,{C2,D2},S2} 300 end. 301 302 303 304nested_stacktrace(Conf) when is_list(Conf) -> 305 V = [{make_ref()}|[self()]], 306 value1 = nested_stacktrace_1({{value,{V,x1}},void,{V,x1}}, 307 {void,void,void}), 308 {caught1, 309 [{?MODULE,my_add,2,_}|_], 310 value2} = nested_stacktrace_1({{'add',{V,x1}},error,badarith}, 311 {{value,{V,x2}},void,{V,x2}}), 312 {caught1, 313 [{?MODULE,my_add,2,_}|_], 314 {caught2,[{erlang,abs,[V],_}|_]}} = 315 nested_stacktrace_1({{'add',{V,x1}},error,badarith}, 316 {{'abs',V},error,badarg}), 317 ok. 318 319nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) -> 320 try foo(X1) of 321 V1 -> value1 322 catch 323 C1:V1:S1 -> 324 T2 = try foo(X2) of 325 V2 -> value2 326 catch 327 C2:V2:S2 -> {caught2,S2} 328 end, 329 {caught1,S1,T2} 330 end. 331 332 333 334raise(Conf) when is_list(Conf) -> 335 erase(raise), 336 A = 337 try 338 try foo({'div',{1,0}}) 339 catch 340 error:badarith:A0 -> 341 put(raise, A0), 342 erlang:raise(error, badarith, A0) 343 end 344 catch 345 error:badarith:A1 -> 346 A1 = get(raise) 347 end, 348 [{?MODULE,my_div,2,_}|_] = A, 349 %% 350 N = 8, % Must be even 351 N = erlang:system_flag(backtrace_depth, N), 352 try even(N) 353 catch error:function_clause -> ok 354 end, 355 %% 356 C = odd_even(N+1, []), 357 try 358 odd(N+1) 359 catch 360 error:function_clause -> ok 361 end, 362 try 363 erlang:raise(error, function_clause, C) 364 catch 365 error:function_clause -> ok 366 end, 367 ok. 368 369odd_even(N, R) when is_integer(N), N > 1 -> 370 odd_even(N-1, 371 [if (N rem 2) == 0 -> 372 {?MODULE,even,1,[{file,?MODULE_STRING++".erl"}, 373 {line,42}]}; 374 true -> 375 {?MODULE,odd,1,[{file,?MODULE_STRING++".erl"}, 376 {line,45}]} 377 end|R]); 378odd_even(1, R) -> 379 [{?MODULE,odd,[1],[{file,?MODULE_STRING++".erl"}, 380 {line,44}]}|R]. 381 382foo({value,Value}) -> Value; 383foo({'div',{A,B}}) -> 384 my_div(A, B); 385foo({'add',{A,B}}) -> 386 my_add(A, B); 387foo({'abs',X}) -> 388 my_abs(X); 389foo({error,Error}) -> 390 erlang:error(Error); 391foo({throw,Throw}) -> 392 erlang:throw(Throw); 393foo({exit,Exit}) -> 394 erlang:exit(Exit); 395foo({raise,{Class,Reason,Stacktrace}}) -> 396 erlang:raise(Class, Reason, Stacktrace). 397%%foo(function_clause) -> % must not be defined! 398 399my_div(A, B) -> 400 A div B. 401 402my_add(A, B) -> 403 A + B. 404 405my_abs(X) -> abs(X). 406 407gunilla(Config) when is_list(Config) -> 408 {throw,kalle} = gunilla_1(), 409 ok. 410 411gunilla_1() -> 412 try try arne() 413 after 414 pelle 415 end 416 catch 417 C:R -> 418 {C,R} 419 end. 420 421arne() -> 422 %% Empty stack trace used to cause change the error class to 'error'. 423 erlang:raise(throw, kalle, []). 424 425per(Config) when is_list(Config) -> 426 try 427 t1(0,pad,0), 428 t2(0,pad,0) 429 catch 430 error:badarith -> 431 ok 432 end. 433 434t1(_,X,_) -> 435 (1 bsl X) + 1. 436 437t2(_,X,_) -> 438 (X bsl 1) + 1. 439 440id(I) -> I. 441