aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/beam_literals_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/beam_literals_SUITE.erl')
-rw-r--r--erts/emulator/test/beam_literals_SUITE.erl433
1 files changed, 433 insertions, 0 deletions
diff --git a/erts/emulator/test/beam_literals_SUITE.erl b/erts/emulator/test/beam_literals_SUITE.erl
new file mode 100644
index 0000000000..75841adbfc
--- /dev/null
+++ b/erts/emulator/test/beam_literals_SUITE.erl
@@ -0,0 +1,433 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-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(beam_literals_SUITE).
+-export([all/1]).
+-export([putting/1, matching_smalls/1, matching_smalls_jt/1,
+ matching_bigs/1, matching_more_bigs/1,
+ matching_bigs_and_smalls/1, badmatch/1, case_clause/1,
+ receiving/1, literal_type_tests/1,
+ put_list/1, fconv/1, literal_case_expression/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [putting, matching_smalls, matching_smalls_jt,
+ matching_bigs, matching_more_bigs,
+ matching_bigs_and_smalls, badmatch, case_clause,
+ receiving, literal_type_tests,
+ put_list, fconv, literal_case_expression].
+
+putting(doc) -> "Test creating lists and tuples containing big number literals.";
+putting(Config) when is_list(Config) ->
+ -773973888575883407313908 = chksum(putting1(8987697898797)).
+
+putting1(X) ->
+ {8797987987987987872256443, [1324483773773], {3.1415, 2.71, [2.5, 35.125|9.31]},
+ [X|349873987387373],
+ [329878349873|-387394729872], -773973937933873929749873}.
+
+matching_bigs(doc) -> "Test matching of a few big number literals (in Beam,"
+ "select_val/3 will NOT be used).";
+matching_bigs(Config) when is_list(Config) ->
+ a = matching1(3972907842873739),
+ b = matching1(-389789298378939783333333333333333333784),
+ other = matching1(42).
+
+matching_smalls(doc) -> "Test matching small numbers (both positive and negative).";
+matching_smalls(Config) when is_list(Config) ->
+ ?line a = m_small(-42),
+ ?line b = m_small(0),
+ ?line c = m_small(105),
+ ?line d = m_small(-13),
+ ?line e = m_small(337848),
+ ?line other = m_small(324),
+ ?line other = m_small(-7),
+ ok.
+
+m_small(-42) -> a;
+m_small(0) -> b;
+m_small(105) -> c;
+m_small(-13) -> d;
+m_small(337848) -> e;
+m_small(_) -> other.
+
+matching_smalls_jt(doc) ->
+ "Test matching small numbers (both positive and negative). "
+ "Make sure that a jump table is used.";
+matching_smalls_jt(Config) when is_list(Config) ->
+ ?line a = m_small_jt(-2),
+ ?line b = m_small_jt(-1),
+ ?line c = m_small_jt(0),
+ ?line d = m_small_jt(2),
+ ?line e = m_small_jt(3),
+ ?line other = m_small(324),
+ ?line other = m_small(-7),
+ ok.
+
+m_small_jt(-2) -> a;
+m_small_jt(-1) -> b;
+m_small_jt(0) -> c;
+m_small_jt(2) -> d;
+m_small_jt(3) -> e;
+m_small_jt(_) -> other.
+
+%% Big numbers, no select_val.
+
+matching1(3972907842873739) -> a;
+matching1(-389789298378939783333333333333333333784) -> b;
+matching1(_) -> other.
+
+
+matching_more_bigs(doc) -> "Test matching of a big number literals (in Beam,"
+ "a select_val/3 instruction will be used).";
+matching_more_bigs(Config) when is_list(Config) ->
+ a = matching2(-999766349740978337),
+ b = matching2(9734097866575478),
+ c = matching2(-966394677364879734),
+ d = matching2(13987294872948990),
+ e = matching2(777723896192459245),
+ other = matching2(7),
+ other = matching2(39789827988888888888888888888347474444444444444444444).
+
+%% Big numbers with select_val.
+
+matching2(-999766349740978337) -> a;
+matching2(9734097866575478) -> b;
+matching2(-966394677364879734) -> c;
+matching2(13987294872948990) -> d;
+matching2(777723896192459245) -> e;
+matching2(_) -> other.
+
+matching_bigs_and_smalls(doc) -> "Test matching of a mix of big numbers and literals.";
+matching_bigs_and_smalls(suite) -> [];
+matching_bigs_and_smalls(Config) when is_list(Config) ->
+ a = matching3(38472928723987239873873),
+ b = matching3(0),
+ c = matching3(-3873973932710954671207461057614287561348756348743634876436784367873),
+ d = matching3(3978429867297393873),
+ e = matching3(42),
+ f = matching3(-4533),
+ other = matching3(77),
+ other = matching3(39274120984379249874219748).
+
+%% Mixed small and big.
+
+matching3(38472928723987239873873) -> a;
+matching3(0) -> b;
+matching3(-3873973932710954671207461057614287561348756348743634876436784367873) -> c;
+matching3(3978429867297393873) -> d;
+matching3(42) -> e;
+matching3(-4533) -> f;
+matching3(_) -> other.
+
+badmatch(doc) -> "Test literal badmatches with big number and floats.";
+badmatch(Config) when is_list(Config) ->
+ %% We are satisfied if we can load this module and run it.
+ Big = id(32984798729847892498297824872982972978239874),
+ Float = id(3.1415927),
+ ?line catch a = Big,
+ ?line catch b = Float,
+ ?line {'EXIT',{{badmatch,3879373498378993387},_}} =
+ (catch c = 3879373498378993387),
+ ?line {'EXIT',{{badmatch,7.0},_}} = (catch d = 7.0),
+ ?line case Big of
+ Big -> ok
+ end,
+ ?line case Float of
+ Float -> ok
+ end,
+ ok.
+
+case_clause(Config) when is_list(Config) ->
+ ?line {'EXIT',{{case_clause,337.0},_}} = (catch case_clause_float()),
+ ?line {'EXIT',{{try_clause,42.0},_}} = (catch try_case_clause_float()),
+ ?line {'EXIT',{{case_clause,37932749837839747383847398743789348734987},_}} =
+ (catch case_clause_big()),
+ ?line {'EXIT',{{try_clause,977387349872349870423364354398566348},_}} =
+ (catch try_case_clause_big()),
+ ok.
+
+case_clause_float() ->
+ case 337.0 of
+ blurf -> ok
+ end.
+
+try_case_clause_float() ->
+ try 42.0 of
+ blurf -> ok
+ catch _:_ ->
+ error
+ end.
+
+case_clause_big() ->
+ case 37932749837839747383847398743789348734987 of
+ blurf -> ok
+ end.
+
+try_case_clause_big() ->
+ try 977387349872349870423364354398566348 of
+ blurf -> ok
+ catch _:_ ->
+ error
+ end.
+
+receiving(doc) -> "Test receive with a big number literal (more than 27 bits, "
+ "less than 32 bits).";
+receiving(Config) when is_list(Config) ->
+ Self = self(),
+ spawn(fun() -> Self ! here_is_a_message end),
+ ok = receive
+ here_is_a_message ->
+ ok
+ after 16#f1234567 ->
+ timeout
+ end.
+
+literal_type_tests(doc) -> "Test type tests on literal values.";
+literal_type_tests(Config) when is_list(Config) ->
+ %% Generate an Erlang module with all different type of type tests.
+ ?line Tests = make_test([{T, L} || T <- type_tests(), L <- literals()]),
+ ?line Mod = literal_test,
+ ?line Func = {function, 0, test, 0, [{clause,0,[],[],Tests}]},
+ ?line Form = [{attribute,0,module,Mod},
+ {attribute,0,compile,export_all},
+ Func, {eof,0}],
+
+ %% Print generated code for inspection.
+ ?line lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
+
+ %% Test compile:form/1. This implies full optimization (default).
+ ?line {ok,Mod,Code1} = compile:forms(Form),
+ ?line {module,Mod} = code:load_binary(Mod, Mod, Code1),
+ ?line Mod:test(),
+ ?line true = code:delete(Mod),
+ ?line code:purge(Mod),
+
+ %% Test compile:form/2. Turn off all optimizations.
+ ?line {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
+ no_copt,no_postopt]),
+ ?line {module,Mod} = code:load_binary(Mod, Mod, Code2),
+ ?line Mod:test(),
+ ?line true = code:delete(Mod),
+ ?line code:purge(Mod),
+ ok.
+
+make_test([{is_function=T,L}|Ts]) ->
+ [test(T, L),test(T, 0, L)|make_test(Ts)];
+make_test([{T,L}|Ts]) ->
+ [test(T, L)|make_test(Ts)];
+make_test([]) -> [].
+
+test(T, L) ->
+ S = lists:flatten(io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T, L, T, L])),
+ {ok,Toks,_Line} = erl_scan:string(S),
+ {ok,E} = erl_parse:parse_exprs(Toks),
+ {value,Val,_Bs} = erl_eval:exprs(E, []),
+ {match,0,{atom,0,Val},hd(E)}.
+
+test(T, A, L) ->
+ S = lists:flatten(io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ",
+ [T,L,A,T,L,A])),
+ {ok,Toks,_Line} = erl_scan:string(S),
+ {ok,E} = erl_parse:parse_exprs(Toks),
+ {value,Val,_Bs} = erl_eval:exprs(E, []),
+ {match,0,{atom,0,Val},hd(E)}.
+
+literals() ->
+ [42,
+ 3.14,
+ -3,
+ 32982724987789283473473838474,
+ [],
+ xxxx].
+
+type_tests() ->
+ [is_boolean,
+ is_integer,
+ is_float,
+ is_number,
+ is_atom,
+ is_list,
+ is_tuple,
+ is_pid,
+ is_reference,
+ is_port,
+ is_binary,
+ is_function].
+
+put_list(Config) when is_list(Config) ->
+ %% put_list x0 Literal Reg
+ ?line [Config|8739757395764] = put_list_rqr(Config),
+ ?line {[Config|7779757395764],Config} = put_list_rqx(Config),
+ ?line [Config|98765432100000] = put_list_rqy(Config),
+
+ %% put_list x Literal Reg
+ ?line [Config|16#FFFFF77777137483769] = put_list_xqr(ignore, Config),
+ ?line {[Config|16#AAAAAFFFFF77777],{a,b},Config} = put_list_xqx({a,b}, Config),
+ ?line [Config|12777765432979879] = put_list_xqy(ignore, Config),
+
+ %% put_list y Literal Reg
+ ?line [Config|17424134793676869867] = put_list_yqr(Config),
+ ?line {[Config|77424134793676869867],Config} = put_list_yqx(Config),
+ ?line {Config,[Config|16#BCDEFF4241676869867]} = put_list_yqy(Config),
+
+ %% put_list Literal x0 Reg
+ ?line [42.0|Config] = put_list_qrr(Config),
+ ?line [Config,42.0|Config] = put_list_qrx(Config),
+ ?line [100.0|Config] = put_list_qry(Config),
+
+ %% put_list Literal x1 Reg
+ ?line [127.0|Config] = put_list_qxr({ignore,me}, Config),
+ ?line [Config,130.0|Config] = put_list_qxx(ignore, Config),
+ ?line [99.0|Config] = put_list_qxy(Config),
+
+ %% put_list Literal y0 Reg
+ ?line [200.0|Config] = put_list_qyr(Config),
+ ?line [Config,210.0|Config] = put_list_qyx(Config),
+ ?line [[300.0|Config]|Config] = put_list_qyy(Config),
+
+ ok.
+
+%% put_list x0 Literal x0
+put_list_rqr(Config) -> [Config|8739757395764].
+
+%% put_list x0 Literal x1
+put_list_rqx(Config) -> {[Config|7779757395764],Config}.
+
+%% put_list x0 Literal y0
+put_list_rqy(Config) ->
+ Res = [Config|98765432100000],
+ id(42),
+ Res.
+
+%% put_list x1 Literal x0
+put_list_xqr(_, Config) -> [Config|16#FFFFF77777137483769].
+
+%% put_list x1 Literal x2
+put_list_xqx(A, Config) -> {[Config|16#AAAAAFFFFF77777],A,Config}.
+
+%% put_list x1 Literal y0
+put_list_xqy(_, Config) ->
+ Res = [Config|12777765432979879],
+ id(42),
+ Res.
+
+%% put_list y0 Literal x0
+put_list_yqr(Config) ->
+ id(Config),
+ [Config|17424134793676869867].
+
+%% put_list y0 Literal x1
+put_list_yqx(Config) ->
+ id(Config),
+ {[Config|77424134793676869867],Config}.
+
+%% put_list y1 Literal y0
+put_list_yqy(Config) ->
+ id(Config),
+ Res = [Config|16#BCDEFF4241676869867],
+ id(Config),
+ {Config,Res}.
+
+%% put_list Literal x0 x0
+put_list_qrr(Config) ->
+ [42.0|Config].
+
+%% put_list Literal x0 x1
+put_list_qrx(Config) ->
+ [Config,42.0|Config].
+
+%% put_list Literal x0 y0
+put_list_qry(Config) ->
+ Res = [100.0|Config],
+ id(0),
+ Res.
+
+%% put_list Literal x1 x0
+put_list_qxr(_, Config) ->
+ [127.0|Config].
+
+%% put_list Literal x1 x2
+put_list_qxx(_, Config) ->
+ [Config,130.0|Config].
+
+%% put_list Literal x1 y0
+put_list_qxy(Config) ->
+ Res = [99.0|Config],
+ id(0),
+ Res.
+
+%% put_list Literal y0 x0
+put_list_qyr(Config) ->
+ id(Config),
+ [200.0|Config].
+
+%% put_list Literal y0 x1
+put_list_qyx(Config) ->
+ id(Config),
+ [Config,210.0|Config].
+
+%% put_list Literal y1 y0
+put_list_qyy(Config) ->
+ id(Config),
+ Res = [300.0|Config],
+ id(Config),
+ [Res|Config].
+
+fconv(Config) when is_list(Config) ->
+ ?line 5.0 = fconv_1(-34444444450.0),
+ ?line 13.0 = fconv_2(7.0),
+ ok.
+
+fconv_1(F) when is_float(F) ->
+ 34444444455 + F.
+
+fconv_2(F) when is_float(F) ->
+ 6.0 + F.
+
+literal_case_expression(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line Src = filename:join(DataDir, "literal_case_expression"),
+ ?line {ok,literal_case_expression=Mod,Code} = compile:file(Src, [from_asm,binary]),
+ ?line {module,Mod} = code:load_binary(Mod, Src, Code),
+ ?line ok = Mod:x(),
+ ?line ok = Mod:y(),
+ ?line true = code:delete(Mod),
+ ?line code:purge(Mod),
+ ok.
+
+%% Help functions.
+
+chksum(Term) ->
+ chksum(Term, 0).
+
+chksum([List|T], Sum) when is_list(List) ->
+ chksum(T, chksum(List, Sum));
+chksum([H|T], Sum) ->
+ chksum(T, chksum(H, Sum));
+chksum([], Sum) -> Sum;
+chksum(Tuple, Sum) when is_tuple(Tuple) ->
+ chksum(tuple_to_list(Tuple), Sum);
+chksum(Int, Sum) when is_integer(Int) ->
+ Sum * 5 + Int;
+chksum(Other, Sum) ->
+ erlang:phash2([Other|Sum], 39729747).
+
+id(I) -> I.