1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 1999-2011. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(line_number_SUITE).
   21: 
   22: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
   23: 	 init_per_testcase/2,end_per_testcase/2,
   24: 	 init_per_suite/1,end_per_suite/1,
   25: 	 line_numbers/1]).
   26: -export([crash/1]).
   27: 
   28: -include_lib("test_server/include/test_server.hrl").
   29: 
   30: suite() -> [{ct_hooks,[ts_install_cth]}].
   31: 
   32: all() ->
   33:     cases().
   34: 
   35: groups() ->
   36:     [].
   37: 
   38: init_per_group(_GroupName, Config) ->
   39:     Config.
   40: 
   41: end_per_group(_GroupName, Config) ->
   42:     Config.
   43: 
   44: cases() ->
   45:     [line_numbers].
   46: 
   47: init_per_testcase(_Case, Config) ->
   48:     test_lib:interpret(?MODULE),
   49:     Dog = test_server:timetrap(?t:minutes(1)),
   50:     [{watchdog,Dog}|Config].
   51: 
   52: end_per_testcase(_Case, Config) ->
   53:     Dog = ?config(watchdog, Config),
   54:     ?t:timetrap_cancel(Dog),
   55:     ok.
   56: 
   57: init_per_suite(Config) when is_list(Config) ->
   58:     ?line test_lib:interpret(?MODULE),
   59:     ?line true = lists:member(?MODULE, int:interpreted()),
   60:     Config.
   61: 
   62: end_per_suite(Config) when is_list(Config) ->
   63:     ok.
   64: 
   65: 
   66: 
   67: 
   68: 
   69: %%
   70: %% === Make sure that this is always line 70 ===
   71: %%
   72: line1(Tag, X) ->				%Line 72
   73:     case Tag of					%Line 73
   74: 	a ->
   75: 	    Y = X + 1,				%Line 75
   76: 	    Res = id({ok,Y}),			%Line 76
   77: 	    ?MODULE:crash({ok,42} = Res);	%Line 77
   78: 	b ->
   79: 	    x = id(x),				%Line 79
   80: 	    ok					%Line 80
   81:     end.					%Line 81
   82: 
   83: crash(_) ->					%Line 83
   84:     erlang:error(crash).			%Line 84
   85: 
   86: close_calls(Where) ->				%Line 86
   87:     put(where_to_crash, Where),			%Line 87
   88:     try
   89: 	call1(),				%Line 89
   90: 	call2(),				%Line 90
   91: 	call3(),				%Line 91
   92: 	no_crash				%Line 92
   93:     catch error:crash ->
   94: 	    erlang:get_stacktrace()		%Line 94
   95:     end.					%Line 95
   96: 
   97: call1() ->					%Line 97
   98:     maybe_crash(call1),				%Line 98
   99:     ok.						%Line 99
  100: 
  101: call2() ->					%Line 101
  102:     maybe_crash(call2),				%Line 102
  103:     ok.						%Line 103
  104: 
  105: call3() ->					%Line 105
  106:     maybe_crash(call3),				%Line 106
  107:     ok.						%Line 107
  108: 
  109: maybe_crash(Name) ->				%Line 109
  110:     case get(where_to_crash) of			%Line 110
  111: 	Name ->
  112: 	    erlang:error(crash);		%Line 112
  113: 	_ ->
  114: 	    ok					%Line 114
  115:     end.					%Line 115
  116: 
  117: build_binary1(Size) ->				%Line 117
  118:     id(42),					%Line 118
  119:     <<0:Size>>.					%Line 119
  120: 
  121: build_binary2(Size, Bin) ->			%Line 121
  122:     id(0),					%Line 122
  123:     <<7:Size,Bin/binary>>.			%Line 123
  124: 
  125: do_call_abs(x, Arg) ->				%Line 125
  126:     abs(Arg).					%Line 126
  127: 
  128: do_call_unsafe_bif(x, Arg) ->			%Line 128
  129:     link(Arg).					%Line 129
  130: 
  131: 
  132: line_numbers(Config) when is_list(Config) ->
  133:     File = ?MODULE_STRING ++ ".erl",
  134:     {'EXIT',{{case_clause,bad_tag},
  135: 	     [{?MODULE,line1,2,
  136: 	       [{file,File},{line,73}]},
  137: 	      {?MODULE,line_numbers,1,_}|_]}} =
  138: 	(catch line1(bad_tag, 0)),
  139:     {'EXIT',{badarith,
  140: 	     [{?MODULE,line1,2,
  141: 	       [{file,File},{line,75}]},
  142: 	      {?MODULE,line_numbers,1,_}|_]}} =
  143: 	(catch line1(a, not_an_integer)),
  144:     {'EXIT',{{badmatch,{ok,1}},
  145: 	     [{?MODULE,line1,2,
  146: 	       [{file,File},{line,77}]},
  147: 	      {?MODULE,line_numbers,1,_}|_]}} =
  148: 	(catch line1(a, 0)),
  149:     {'EXIT',{crash,
  150: 	     [{?MODULE,crash,1,
  151: 	       [{file,File},{line,84}]},
  152: 	      {?MODULE,line_numbers,1,_}|_]}} =
  153: 	(catch line1(a, 41)),
  154: 
  155:     [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
  156:      {?MODULE,call1,0,[{file,File},{line,98}]},
  157:      {?MODULE,close_calls,1,[{file,File},{line,89}]},
  158:      {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
  159: 	close_calls(call1),
  160:     [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
  161:      {?MODULE,call2,0,[{file,File},{line,102}]},
  162:      {?MODULE,close_calls,1,[{file,File},{line,90}]},
  163:      {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
  164: 	close_calls(call2),
  165:     [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
  166:      {?MODULE,call3,0,[{file,File},{line,106}]},
  167:      {?MODULE,close_calls,1,[{file,File},{line,91}]},
  168:      {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
  169: 	close_calls(call3),
  170:     no_crash = close_calls(other),
  171: 
  172:     <<0,0>> = build_binary1(16),
  173:     {'EXIT',{badarg,
  174: 	     [{?MODULE,build_binary1,1,
  175: 	       [{file,File},{line,119}]},
  176: 	      {?MODULE,line_numbers,1,
  177: 	       [{file,ModFile},{line,_}]}|_]}} =
  178: 	(catch build_binary1(bad_size)),
  179: 
  180:     <<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
  181:     {'EXIT',{badarg,
  182: 	     [{?MODULE,build_binary2,2,
  183: 	       [{file,File},{line,123}]},
  184: 	      {?MODULE,line_numbers,1,
  185: 	       [{file,ModFile},{line,_}]}|_]}} =
  186: 	(catch build_binary2(bad_size, <<>>)),
  187:     {'EXIT',{badarg,
  188: 	     [%% Beam has an extra here:
  189: 	      %%   {erlang,bit_size,[bad_binary],[]}
  190: 	      %% Since this is an artifact of the implementation,
  191: 	      %% we don't attempt to mimic it in the debugger.
  192: 	      {?MODULE,build_binary2,2,
  193: 	       [{file,File},{line,123}]},
  194: 	      {?MODULE,line_numbers,1,
  195: 	       [{file,ModFile},{line,_}]}|_]}} =
  196: 	(catch build_binary2(8, bad_binary)),
  197: 
  198:     {'EXIT',{function_clause,
  199: 	     [{?MODULE,do_call_abs,[y,y],
  200: 	       [{file,File},{line,125}]},
  201: 	      {?MODULE,line_numbers,1,_}|_]}} =
  202: 	(catch do_call_abs(y, y)),
  203:     {'EXIT',{badarg,
  204: 	     [{erlang,abs,[[]],[]},
  205: 	      {?MODULE,do_call_abs,2,
  206: 	       [{file,File},{line,126}]},
  207: 	      {?MODULE,line_numbers,1,_}|_]}} =
  208: 	(catch do_call_abs(x, [])),
  209: 
  210:     {'EXIT',{badarg,
  211: 	     [{erlang,link,[[]],[]},
  212: 	      {?MODULE,do_call_unsafe_bif,2,
  213: 	       [{file,File},{line,129}]},
  214: 	      {?MODULE,line_numbers,1,_}|_]}} =
  215: 	(catch do_call_unsafe_bif(x, [])),
  216: 
  217:     ok.
  218: 
  219: id(I) ->
  220:     I.