aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/test/misc_SUITE.erl
blob: e096571d5028a0ab587b1009049d8d74a163c2db (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
%%
%% %CopyrightBegin%
%% 
%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
%% 
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%% 
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%% 
%% %CopyrightEnd%
%%
-module(misc_SUITE).

-export([all/1,init_per_testcase/2,fin_per_testcase/2,
	 tobias/1,empty_string/1,md5/1,silly_coverage/1,
	 confused_literals/1,integer_encoding/1]).
	 
-include("test_server.hrl").

init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
    Dog = test_server:timetrap(?t:minutes(10)),
    [{watchdog,Dog}|Config].

fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
    Dog = ?config(watchdog, Config),
    ?t:timetrap_cancel(Dog),
    ok.

all(suite) ->
    test_lib:recompile(?MODULE),
    [tobias,empty_string,md5,silly_coverage,confused_literals,
     integer_encoding].

%% A bug reported by Tobias Lindahl for a development version of R11B.

tobias(Config) when is_list(Config) ->
    ?line 1 = tobias_1([1,2,3]),
    ok.

tobias_1([H|_T]) ->
    %% In an R11B compiler, the move optimizer in beam_block would
    %% confuse H and _T.
    tobias_2(0, 0),
    H.

tobias_2(_, _) ->
    2.


%% A bug reported by Richard Carlsson. Used to crash beam_asm
%% because of a put_string instruction with an empty string.
%% The real problem was in sys_core_fold (empty strings should
%% be replaced by []).

-record(r, {s = ""}).

empty_string(Config) when is_list(Config) ->
    ?line #r{s="x"} = empty_string_1(#r{}),
    ok.

empty_string_1(T) ->
    case T of
	#r{s = ""} -> T #r{s = "x"}
    end.

md5(Config) when is_list(Config) ->
    case ?MODULE of
	misc_SUITE -> md5();
	_ -> {skip,"Enough to run this case once."}
    end.

md5() ->
    ?line Dir = filename:dirname(code:which(?MODULE)),
    ?line Beams = filelib:wildcard(filename:join(Dir, "*.beam")),
    ?line io:format("Found ~w beam files", [length(Beams)]),
    ?line lists:foreach(fun md5_1/1, Beams).

md5_1(Beam) ->
    ?line {ok,{Mod,[Vsn]}} = beam_lib:version(Beam),
    ?line {ok,Code} = file:read_file(Beam),
    ?line {Mod,<<Vsn:128>>} = {Mod,code:module_md5(Code)}.

%% Cover some code that handles internal errors.

silly_coverage(Config) when is_list(Config) ->
    %% sys_core_fold, sys_core_setel, v3_kernel
    BadCoreErlang = {c_module,[],
		     name,exports,attrs,
		     [{{c_var,[],{foo,2}},seriously_bad_body}]},
    ?line expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end),
    ?line expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end),
    ?line expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end),

    %% v3_codgen
    CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b}]},
    ?line expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),

    %% beam_block
    BlockInput = {?MODULE,[{foo,0}],[],
		  [{function,foo,0,2,
		    [{label,1},
		     {func_info,{atom,?MODULE},{atom,foo},0},
		     {label,2}|non_proper_list],99}]},
    ?line expect_error(fun() -> beam_block:module(BlockInput, []) end),

    %% beam_bool
    BoolInput = {?MODULE,[{foo,0}],[],
		  [{function,foo,0,2,
		    [{label,1},
		     {func_info,{atom,?MODULE},{atom,foo},0},
		     {label,2}|non_proper_list]}],99},
    ?line expect_error(fun() -> beam_bool:module(BoolInput, []) end),

    %% beam_dead
    DeadInput = {?MODULE,[{foo,0}],[],
		  [{function,foo,0,2,
		    [{label,1},
		     {func_info,{atom,?MODULE},{atom,foo},0},
		     {label,2},
		     {jump,bad}]}],99},
    ?line expect_error(fun() -> beam_block:module(DeadInput, []) end),

    %% beam_clean
    CleanInput = {?MODULE,[{foo,0}],[],
		  [{function,foo,0,2,
		    [{label,1},
		     {func_info,{atom,?MODULE},{atom,foo},0},
		     {label,2},
		     {jump,{f,42}}]}],99},
    ?line expect_error(fun() -> beam_clean:module(CleanInput, []) end),

    %% beam_peep
    PeepInput = {?MODULE,[{foo,0}],[],
		 [{function,foo,0,2,
		   [{label,1},
		    {func_info,{atom,?MODULE},{atom,foo},0},
		    {label,2}|non_proper_list]}],99},
    ?line expect_error(fun() -> beam_peep:module(PeepInput, []) end),

    %% beam_bsm. This is tricky. Our function must be sane enough to not crash
    %% btb_index/1, but must crash the main optimization pass.
    BsmInput = {?MODULE,[{foo,0}],[],
		[{function,foo,0,2,
		  [{label,1},
		   {func_info,{atom,?MODULE},{atom,foo},0},
		   {label,2},
		   {test,bs_get_binary2,{f,99},0,[{x,0},{atom,all},1,[]],{x,0}},
		   {block,[a|b]}]}],0},
    ?line expect_error(fun() -> beam_bsm:module(BsmInput, []) end),
    ok.

expect_error(Fun) ->
    try	Fun() of
	Any ->
	    io:format("~p", [Any]),
	    ?t:fail(call_was_supposed_to_fail)
    catch
	_:_ ->
	    io:format("~p\n", [erlang:get_stacktrace()])
    end.

confused_literals(Config) when is_list(Config) ->
    ?line {0,infinity} = confused_literals_1(int),
    ?line {0.0,infinity} = confused_literals_1(float),
    ok.

confused_literals_1(int) -> {0,infinity};
confused_literals_1(float) -> {0.0,infinity}.

integer_encoding(Config) when is_list(Config) ->
    case ?MODULE of
	misc_SUITE -> integer_encoding_1(Config);
	_ -> {skip,"Enough to run this case once."}
    end.

integer_encoding_1(Config) ->
    Dog = test_server:timetrap(?t:minutes(4)),
    ?line PrivDir = ?config(priv_dir, Config),
    ?line SrcFile = filename:join(PrivDir, "misc_SUITE_integer_encoding.erl"),
    ?line DataFile = filename:join(PrivDir, "integer_encoding.data"),
    Mod = misc_SUITE_integer_encoding,

    %% Create files.
    ?line {ok,Src} = file:open(SrcFile, [write]),
    ?line {ok,Data} = file:open(DataFile, [write]),
    io:format(Src, "-module(~s).\n", [Mod]),
    io:put_chars(Src, "-export([t/1]).\n"),
    io:put_chars(Src, "t(Last) ->[\n"),
    io:put_chars(Data, "[\n"),

    ?line do_integer_encoding(-(id(1) bsl 10000), Src, Data),
    ?line do_integer_encoding(id(1) bsl 10000, Src, Data),
    ?line do_integer_encoding(2048, 0, Src, Data),

    io:put_chars(Src, "Last].\n\n"),
    ?line ok = file:close(Src),
    io:put_chars(Data, "0].\n\n"),
    ?line ok = file:close(Data),

    %% Compile and load Erlang module.
    ?line SrcRoot = filename:rootname(SrcFile),
    ?line {ok,Mod,Binary} = compile:file(SrcRoot, [binary,report]),
    ?line {module,Mod} = code:load_binary(Mod, SrcRoot, Binary),

    %% Compare lists.
    ?line List = Mod:t(0),
    ?line {ok,[List]} = file:consult(DataFile),
    OneBsl10000 = id(1) bsl 10000,
    ?line [-(1 bsl 10000),OneBsl10000|_] = List,

    %% Cleanup.
    ?line file:delete(SrcFile),
    ?line file:delete(DataFile),
    ?t:timetrap_cancel(Dog),
    ok.

do_integer_encoding(0, _, _, _) -> ok;
do_integer_encoding(N, I0, Src, Data) ->
    I1 = (I0 bsl 5) bor (random:uniform(32) - 1),
    do_integer_encoding(I1, Src, Data),
    I2 = -(I1 bxor (random:uniform(32) - 1)),
    do_integer_encoding(I2, Src, Data),
    do_integer_encoding(N-1, I1, Src, Data).

do_integer_encoding(I, Src, Data) ->
    Str = integer_to_list(I),
    io:put_chars(Src, Str),
    io:put_chars(Src, ", \n"),
    io:put_chars(Data, Str),
    io:put_chars(Data, ", \n").
    
    
id(I) -> I.