diff options
Diffstat (limited to 'lib/compiler/test')
139 files changed, 24161 insertions, 0 deletions
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile new file mode 100644 index 0000000000..ad2f63e9e5 --- /dev/null +++ b/lib/compiler/test/Makefile @@ -0,0 +1,155 @@ +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + andor_SUITE \ + apply_SUITE \ + beam_validator_SUITE \ + bs_bincomp_SUITE \ + bs_bit_binaries_SUITE \ + bs_construct_SUITE \ + bs_match_SUITE \ + bs_utf_SUITE \ + core_fold_SUITE \ + compile_SUITE \ + compilation_SUITE \ + core_SUITE \ + error_SUITE \ + float_SUITE \ + fun_SUITE \ + guard_SUITE \ + inline_SUITE \ + lc_SUITE \ + match_SUITE \ + misc_SUITE \ + num_bif_SUITE \ + pmod_SUITE \ + parteval_SUITE \ + receive_SUITE \ + record_SUITE \ + trycatch_SUITE \ + warnings_SUITE \ + test_lib + +NO_OPT= \ + andor \ + apply \ + bs_construct \ + bs_match \ + bs_utf \ + core_fold \ + float \ + fun \ + guard \ + lc \ + match \ + misc \ + num_bif \ + receive \ + record \ + trycatch + +R11= \ + andor \ + apply \ + float \ + fun \ + match \ + num_bif \ + receive \ + record \ + trycatch + +CORE_MODULES = \ + bs_shadowed_size_var \ + nested_call_in_case + + +NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE) +NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl) +POST_OPT_MODULES= $(NO_OPT:%=%_post_opt_SUITE) +POST_OPT_ERL_FILES= $(POST_OPT_MODULES:%=%.erl) +R11_MODULES= $(R11:%=%_r11_SUITE) +R11_ERL_FILES= $(R11_MODULES:%=%.erl) + +ERL_FILES= $(MODULES:%=%.erl) + +CORE_FILES= $(CORE_MODULES:%=%.core) + +##TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +##INSTALL_PROGS= $(TARGET_FILES) + +EMAKEFILE=Emakefile + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/compiler_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include +clint + +EBIN = . + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(R11_ERL_FILES) + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ + > $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(NO_OPT_MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +no_copt $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(POST_OPT_MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +r11 $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(R11_MODULES) >> $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core + +docs: + +# ---------------------------------------------------- +# Special targets +# ---------------------------------------------------- + +%_no_opt_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + +%_post_opt_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + +%_r11_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + +release_tests_spec: make_emakefile + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) compiler.dynspec compiler.cover \ + $(EMAKEFILE) $(ERL_FILES) $(CORE_FILES) $(RELSYSDIR) + $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \ + $(R11_ERL_FILES) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl new file mode 100644 index 0000000000..34609a49f2 --- /dev/null +++ b/lib/compiler/test/andor_SUITE.erl @@ -0,0 +1,397 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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(andor_SUITE). + +-export([all/1, + t_case/1,t_and_or/1,t_andalso/1,t_orelse/1,inside/1,overlap/1, + combined/1,in_case/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [t_case,t_and_or,t_andalso,t_orelse,inside,overlap,combined,in_case]. + +t_case(Config) when is_list(Config) -> + %% We test boolean cases almost but not quite like cases + %% generated by andalso/orelse. + ?line less = t_case_a(1, 2), + ?line not_less = t_case_a(2, 2), + ?line {'EXIT',{{case_clause,false},_}} = (catch t_case_b({x,y,z}, 2)), + ?line {'EXIT',{{case_clause,true},_}} = (catch t_case_b(a, a)), + ?line eq = t_case_c(a, a), + ?line ne = t_case_c(42, []), + ?line t = t_case_d(x, x, true), + ?line f = t_case_d(x, x, false), + ?line f = t_case_d(x, y, true), + ?line {'EXIT',{badarg,_}} = (catch t_case_d(x, y, blurf)), + ?line true = (catch t_case_e({a,b}, {a,b})), + ?line false = (catch t_case_e({a,b}, 42)), + + ?line true = t_case_xy(42, 100, 700), + ?line true = t_case_xy(42, 100, whatever), + ?line false = t_case_xy(42, wrong, 700), + ?line false = t_case_xy(42, wrong, whatever), + + ?line true = t_case_xy(0, whatever, 700), + ?line true = t_case_xy(0, 100, 700), + ?line false = t_case_xy(0, whatever, wrong), + ?line false = t_case_xy(0, 100, wrong), + + ok. + +t_case_a(A, B) -> + case A < B of + [_|_] -> ok; + true -> less; + false -> not_less; + {a,b,c} -> ok; + _Var -> ok + end. + +t_case_b(A, B) -> + case A =:= B of + blurf -> ok + end. + +t_case_c(A, B) -> + case not(A =:= B) of + true -> ne; + false -> eq + end. + +t_case_d(A, B, X) -> + case (A =:= B) and X of + true -> t; + false -> f + end. + +t_case_e(A, B) -> + case A =:= B of + Bool when is_tuple(A) -> id(Bool) + end. + +t_case_xy(X, Y, Z) -> + Res = t_case_x(X, Y, Z), + Res = t_case_y(X, Y, Z). + +t_case_x(X, Y, Z) -> + case abs(X) =:= 42 of + true -> + Y =:= 100; + false -> + Z =:= 700 + end. + +t_case_y(X, Y, Z) -> + case abs(X) =:= 42 of + false -> + Z =:= 700; + true -> + Y =:= 100 + end. + +t_and_or(Config) when is_list(Config) -> + ?line true = true and true, + ?line false = true and false, + ?line false = false and true, + ?line false = false and false, + + ?line true = id(true) and true, + ?line false = id(true) and false, + ?line false = id(false) and true, + ?line false = id(false) and false, + + ?line true = true and id(true), + ?line false = true and id(false), + ?line false = false and id(true), + ?line false = false and id(false), + + ?line true = true or true, + ?line true = true or false, + ?line true = false or true, + ?line false = false or false, + + ?line true = id(true) or true, + ?line true = id(true) or false, + ?line true = id(false) or true, + ?line false = id(false) or false, + + ?line true = true or id(true), + ?line true = true or id(false), + ?line true = false or id(true), + ?line false = false or id(false), + + ok. + +t_andalso(Config) when is_list(Config) -> + Bs = [true,false], + Ps = [{X,Y} || X <- Bs, Y <- Bs], + lists:foreach(fun (P) -> t_andalso_1(P) end, Ps), + + ?line true = true andalso true, + ?line false = true andalso false, + ?line false = false andalso true, + ?line false = false andalso false, + + ?line false = false andalso glurf, + ?line false = false andalso exit(exit_now), + + ?line true = not id(false) andalso not id(false), + ?line false = not id(false) andalso not id(true), + ?line false = not id(true) andalso not id(false), + ?line false = not id(true) andalso not id(true), + + ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)), + ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)), + ?line false = id(false) andalso not id(glurf), + ?line false = false andalso not id(glurf), + + ok. + +t_orelse(Config) when is_list(Config) -> + Bs = [true,false], + Ps = [{X,Y} || X <- Bs, Y <- Bs], + lists:foreach(fun (P) -> t_orelse_1(P) end, Ps), + + ?line true = true orelse true, + ?line true = true orelse false, + ?line true = false orelse true, + ?line false = false orelse false, + + ?line true = true orelse glurf, + ?line true = true orelse exit(exit_now), + + ?line true = not id(false) orelse not id(false), + ?line true = not id(false) orelse not id(true), + ?line true = not id(true) orelse not id(false), + ?line false = not id(true) orelse not id(true), + + ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)), + ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)), + ?line true = id(true) orelse not id(glurf), + ?line true = true orelse not id(glurf), + + ok. + +t_andalso_1({X,Y}) -> + io:fwrite("~w andalso ~w: ",[X,Y]), + V1 = echo(X) andalso echo(Y), + V1 = if + X andalso Y -> true; + true -> false + end, + check(V1, X and Y). + +t_orelse_1({X,Y}) -> + io:fwrite("~w orelse ~w: ",[X,Y]), + V1 = echo(X) orelse echo(Y), + V1 = if + X orelse Y -> true; + true -> false + end, + check(V1, X or Y). + +inside(Config) when is_list(Config) -> + ?line true = inside(-8, 1), + ?line false = inside(-53.5, -879798), + ?line false = inside(1.0, -879), + ?line false = inside(59, -879), + ?line false = inside(-11, 1.0), + ?line false = inside(100, 0.2), + ?line false = inside(100, 1.2), + ?line false = inside(-53.5, 4), + ?line false = inside(1.0, 5.3), + ?line false = inside(59, 879), + ok. + +inside(Xm, Ym) -> + X = -10.0, + Y = -2.0, + W = 20.0, + H = 4.0, + Res = inside(Xm, Ym, X, Y, W, H), + Res = if + X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H -> true; + true -> false + end, + case not id(Res) of + Outside -> + Outside = if + not(X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H) -> true; + true -> false + end + end, + {Res,Xm,Ym,X,Y,W,H} = inside_guard(Xm, Ym, X, Y, W, H), + io:format("~p =< ~p andalso ~p < ~p andalso ~p =< ~p andalso ~p < ~p ==> ~p", + [X,Xm,Xm,X+W,Y,Ym,Ym,Y+H,Res]), + Res. + +inside(Xm, Ym, X, Y, W, H) -> + X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H. + +inside_guard(Xm, Ym, X, Y, W, H) when X =< Xm andalso Xm < X+W + andalso Y =< Ym andalso Ym < Y+H -> + {true,Xm,Ym,X,Y,W,H}; +inside_guard(Xm, Ym, X, Y, W, H) -> + {false,Xm,Ym,X,Y,W,H}. + +overlap(Config) when is_list(Config) -> + ?line true = overlap(7.0, 2.0, 8.0, 0.5), + ?line true = overlap(7.0, 2.0, 8.0, 2.5), + ?line true = overlap(7.0, 2.0, 5.3, 2), + ?line true = overlap(7.0, 2.0, 0.0, 100.0), + + ?line false = overlap(-1, 2, -35, 0.5), + ?line false = overlap(-1, 2, 777, 0.5), + ?line false = overlap(-1, 2, 2, 10), + ?line false = overlap(2, 10, 12, 55.3), + ok. + +overlap(Pos1, Len1, Pos2, Len2) -> + Res = case Pos1 of + Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2) + orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) -> + true; + Pos1 -> false + end, + Res = (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2) + orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1), + Res = case Pos1 of + Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2) + orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) -> + true; + Pos1 -> false + end, + id(Res). + + +-define(COMB(A,B,C), (A andalso B orelse C)). + +combined(Config) when is_list(Config) -> + ?line false = comb(false, false, false), + ?line true = comb(false, false, true), + ?line false = comb(false, true, false), + ?line true = comb(false, true, true), + + ?line false = comb(true, false, false), + ?line true = comb(true, true, false), + ?line true = comb(true, false, true), + ?line true = comb(true, true, true), + + ?line false = comb(false, blurf, false), + ?line true = comb(false, blurf, true), + ?line true = comb(true, true, blurf), + + ?line false = ?COMB(false, false, false), + ?line true = ?COMB(false, false, true), + ?line false = ?COMB(false, true, false), + ?line true = ?COMB(false, true, true), + + ?line false = ?COMB(true, false, false), + ?line true = ?COMB(true, true, false), + ?line true = ?COMB(true, false, true), + ?line true = ?COMB(true, true, true), + + ?line false = ?COMB(false, blurf, false), + ?line true = ?COMB(false, blurf, true), + ?line true = ?COMB(true, true, blurf), + + ok. +-undef(COMB). + +comb(A, B, C) -> + Res = A andalso B orelse C, + Res = if + A andalso B orelse C -> true; + true -> false + end, + NotRes = if + not(A andalso B orelse C) -> true; + true -> false + end, + NotRes = id(not Res), + Res = A andalso B orelse C, + Res = if + A andalso B orelse C -> true; + true -> false + end, + NotRes = id(not Res), + Res = if + A andalso B orelse C -> true; + true -> false + end, + id(Res). + +%% Test that a boolean expression in a case expression is properly +%% optimized (in particular, that the error behaviour is correct). +in_case(Config) when is_list(Config) -> + ?line edge_rings = in_case_1(1, 1, 1, 1, 1), + ?line not_loop = in_case_1(0.5, 1, 1, 1, 1), + ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4), + ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)), + ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)), + ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)), + ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)), + ok. + +in_case_1(LenUp, LenDw, LenN, Rotation, Count) -> + Res = in_case_1_body(LenUp, LenDw, LenN, Rotation, Count), + Res = in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count), + Res. + +in_case_1_body(LenUp, LenDw, LenN, Rotation, Count) -> + case (LenUp/Count > 0.707) and (LenN/Count > 0.707) and + (abs(Rotation) > 0.707) of + true -> + edge_rings; + false -> + case (LenUp >= 1) or (LenDw >= 1) or + (LenN =< 1) or (Count < 4) of + true -> + not_loop; + false -> + loop + end + end. + +in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) -> + case (LenUp/Count > 0.707) andalso (LenN/Count > 0.707) andalso + (abs(Rotation) > 0.707) of + true -> edge_rings; + false when LenUp >= 1 orelse LenDw >= 1 orelse + LenN =< 1 orelse Count < 4 -> not_loop; + false -> loop + end. + +check(V1, V0) -> + if V1 /= V0 -> + io:fwrite("error: ~w.\n", [V1]), + ?t:fail(); + true -> + io:fwrite("ok: ~w.\n", [V1]) + end. + +echo(X) -> + io:fwrite("eval(~w); ",[X]), + X. + +id(I) -> I. + + diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl new file mode 100644 index 0000000000..f23dd6c2db --- /dev/null +++ b/lib/compiler/test/apply_SUITE.erl @@ -0,0 +1,107 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(apply_SUITE). + +-export([all/1,mfa/1,fun_apply/1]). + +-export([foo/0,bar/1,baz/2]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [mfa,fun_apply]. + +-define(APPLY0(M, F), (fun(Res) -> Res = M:F() end)(apply(M, F, []))). +-define(APPLY1(M, F, A1), (fun(Res) -> Res = M:F(A1) end)(apply(M, F, [A1]))). +-define(APPLY2(M, F, A1, A2), (fun(Res) -> Res = M:F(A1, A2) end)(apply(M, F, [A1,A2]))). + +mfa(Config) when is_list(Config) -> + ?line ok = ?APPLY0(?MODULE, foo), + ?line {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]), + ?line {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}), + + ?line Mod = id(?MODULE), + ?line ok = ?APPLY0(Mod, foo), + ?line {[a,b]} = ?APPLY1(Mod, bar, [a,b]), + ?line {39,{a}} = ?APPLY2(Mod, baz, 39, {a}), + + ?line ok = ?APPLY0(?MODULE, (id(foo))), + ?line {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]), + ?line {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}), + + ?line ok = ?APPLY0(Mod, (id(foo))), + ?line {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]), + ?line {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}), + + ?line {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)), + ?line {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)), + ?line {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)), + + ?line ok = apply(Mod, foo, id([])), + ?line {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])), + ?line {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])), + + ?line Erlang = id(erlang), + ?line Self = self(), + ?line Self = ?APPLY0(Erlang, self), + ?line 42.0 = ?APPLY1(Erlang, abs, -42.0), + ?line b = ?APPLY2(Erlang, element, 2, {a,b,c}), + ?line true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1), + ?line true = ?APPLY1(Erlang, is_function, fun() -> ok end), + ?line false = ?APPLY1(Erlang, is_function, blurf), + ?line true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1), + ?line true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0), + ?line false = ?APPLY2(Erlang, is_function, blurf, 0), + + ?line apply(Mod, foo, []). + +foo() -> + ok. + +bar(A) -> + {A}. + +baz(A, B) -> + {A,B}. + +-define(FUNAPPLY0(F), (fun(Res) -> Res = F() end)(apply(F, []))). +-define(FUNAPPLY1(F, A1), (fun(Res) -> Res = F(A1) end)(apply(F, [A1]))). +-define(FUNAPPLY2(F, A1, A2), (fun(Res) -> Res = F(A1, A2) end)(apply(F, [A1,A2]))). + +fun_apply(Config) when is_list(Config) -> + ?line Self = self(), + + ?line Self = ?FUNAPPLY0(fun() -> self() end), + ?line Self = ?FUNAPPLY0((id(fun() -> self() end))), + ?line ok = ?FUNAPPLY0(fun ?MODULE:foo/0), + ?line ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))), + + ?line -42 = ?FUNAPPLY1(fun(A) -> -A end, 42), + ?line [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]), + ?line {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]), + ?line {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]), + + ?line {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b), + ?line {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]), + ?line {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}), + + ok. + +id(I) -> I. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl new file mode 100644 index 0000000000..ef8feb8a27 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -0,0 +1,375 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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_validator_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + beam_files/1,compiler_bug/1,stupid_but_valid/1, + xrange/1,yrange/1,stack/1,call_last/1,merge_undefined/1, + uninit/1,unsafe_catch/1, + dead_code/1,mult_labels/1, + overwrite_catchtag/1,overwrite_trytag/1,accessing_tags/1,bad_catch_try/1, + cons_guard/1, + freg_range/1,freg_uninit/1,freg_state/1, + bin_match/1,bin_aligned/1,bad_dsetel/1, + state_after_fault_in_catch/1,no_exception_in_catch/1, + undef_label/1,illegal_instruction/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), + [beam_files,compiler_bug,stupid_but_valid, + xrange,yrange,stack,call_last,merge_undefined, + uninit,unsafe_catch, + dead_code,mult_labels, + overwrite_catchtag,overwrite_trytag,accessing_tags,bad_catch_try, + cons_guard, + freg_range,freg_uninit,freg_state, + bin_match,bin_aligned, + bad_dsetel,state_after_fault_in_catch,no_exception_in_catch, + undef_label,illegal_instruction]. + +beam_files(Config) when is_list(Config) -> + ?line {ok,Cwd} = file:get_cwd(), + ?line Parent = filename:dirname(Cwd), + ?line Wc = filename:join([Parent,"*","*.beam"]), + %% Must have at least two files here, or there will could be + %% a grammatical error in the output of the io:format/2 call below. ;-) + ?line [_,_|_] = Fs = filelib:wildcard(Wc), + ?line io:format("~p files\n", [length(Fs)]), + beam_files_1(Fs, 0). + +beam_files_1([F|Fs], Errors) -> + ?line case beam_validator:file(F) of + ok -> + beam_files_1(Fs, Errors); + {error,Es} -> + io:format("File: ~s", [F]), + io:format("Error: ~p\n", [Es]), + beam_files_1(Fs, Errors+1) + end; +beam_files_1([], 0) -> ok; +beam_files_1([], Errors) -> + ?line io:format("~p error(s)", [Errors]), + ?line ?t:fail(). + +compiler_bug(Config) when is_list(Config) -> + %% Check that the compiler returns an error if we try to + %% assemble one of the bad '.S' files. + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "stack"), + ?line error = compile:file(File, [asm,report_errors,binary,time]), + ok. + +%% The following code is stupid but it should compile. +stupid_but_valid(Config) when is_list(Config) -> + AnAtom = nisse, + ?line try setelement(5, setelement(6, AnAtom, value), another_value) of + Term -> ?line ?t:fail({what_happened,Term}) + catch + error:badarg -> ok + end, + ok. + +xrange(Config) when is_list(Config) -> + Errors = do_val(xrange, Config), + ?line + [{{t,sum_1,2}, + {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, + {uninitialized_reg,{x,-1}}}}, + {{t,sum_2,2}, + {{bif,'+',{f,0},[{x,0},{x,1024}],{x,0}},4, + {uninitialized_reg,{x,1024}}}}, + {{t,sum_3,2}, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, + {invalid_store,{x,-1},number}}}, + {{t,sum_4,2}, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,1024}},4,limit}}] = Errors, + ok. + +yrange(Config) when is_list(Config) -> + Errors = do_val(yrange, Config), + ?line + [{{t,sum_1,2}, + {{move,{x,1},{y,-1}},5, + {invalid_store,{y,-1},term}}}, + {{t,sum_2,2}, + {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},8, + {uninitialized_reg,{y,1024}}}}, + {{t,sum_3,2}, + {{move,{x,1},{y,1024}},5,limit}}, + {{t,sum_4,2}, + {{move,{x,1},{y,-1}},5, + {invalid_store,{y,-1},term}}}] = Errors, + ok. + +stack(Config) when is_list(Config) -> + Errors = do_val(stack, Config), + ?line [{{t,a,2},{return,11,{stack_frame,2}}}, + {{t,b,2},{{deallocate,2},4,{allocated,none}}}, + {{t,c,2},{{deallocate,2},12,{allocated,none}}}, + {{t,d,2}, + {{allocate,2,2},5,{existing_stack_frame,{size,2}}}}, + {{t,e,2},{{deallocate,5},6,{allocated,2}}}, + {{t,bad_1,0},{{allocate_zero,2,10},4,{{x,9},not_live}}}, + {{t,bad_2,0},{{move,{y,0},{x,0}},5,{unassigned,{y,0}}}}] = Errors, + ok. + +call_last(Config) when is_list(Config) -> + Errors = do_val(call_last, Config), + ?line [{{t,a,1},{{call_last,1,{f,8},2},11,{allocated,1}}}, + {{t,b,1}, + {{call_ext_last,2,{extfunc,lists,seq,2},2}, + 11, + {allocated,1}}}] = Errors, + ok. + +merge_undefined(Config) when is_list(Config) -> + Errors = do_val(merge_undefined, Config), + ?line [{{t,handle_call,2}, + {{call_ext,2,{extfunc,debug,filter,2}}, + 22, + {uninitialized_reg,{y,0}}}}] = Errors, + ok. + +uninit(Config) when is_list(Config) -> + Errors = do_val(uninit, Config), + ?line + [{{t,sum_1,2}, + {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}}, + {{t,sum_2,2}, + {{call,1,{f,10}},6,{uninitialized_reg,{y,0}}}}, + {{t,sum_3,2}, + {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}}, + 7, + {unassigned,{y,0}}}}] = Errors, + ok. + +unsafe_catch(Config) when is_list(Config) -> + Errors = do_val(unsafe_catch, Config), + ?line + [{{t,small,2}, + {{bs_put_integer,{f,0},{integer,16},1, + {field_flags,[aligned,unsigned,big]},{y,0}}, + 20, + {unassigned,{y,0}}}}] = Errors, + ok. + +dead_code(Config) when is_list(Config) -> + [] = do_val(dead_code, Config), + ok. + +mult_labels(Config) when is_list(Config) -> + [] = do_val(erl_prim_loader, Config, ".beam"), + ok. + +overwrite_catchtag(Config) when is_list(Config) -> + Errors = do_val(overwrite_catchtag, Config), + ?line + [{{overwrite_catchtag,foo,1}, + {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors, + ok. + +overwrite_trytag(Config) when is_list(Config) -> + Errors = do_val(overwrite_trytag, Config), + ?line + [{{overwrite_trytag,foo,1}, + {{kill,{y,2}},9,{trytag,_}}}] = Errors, + ok. + +accessing_tags(Config) when is_list(Config) -> + Errors = do_val(accessing_tags, Config), + ?line + [{{accessing_tags,foo,1}, + {{move,{y,0},{x,0}},6,{catchtag,_}}}, + {{accessing_tags,bar,1}, + {{move,{y,0},{x,0}},6,{trytag,_}}}] = Errors, + ok. + +bad_catch_try(Config) when is_list(Config) -> + Errors = do_val(bad_catch_try, Config), + ?line [{{bad_catch_try,bad_1,1}, + {{'catch',{x,0},{f,3}}, + 5,{invalid_store,{x,0},{catchtag,[3]}}}}, + {{bad_catch_try,bad_2,1}, + {{catch_end,{x,9}}, + 8,{source_not_y_reg,{x,9}}}}, + {{bad_catch_try,bad_3,1}, + {{catch_end,{y,1}},9,{bad_type,{atom,kalle}}}}, + {{bad_catch_try,bad_4,1}, + {{'try',{x,0},{f,15}},5,{invalid_store,{x,0},{trytag,[15]}}}}, + {{bad_catch_try,bad_5,1}, + {{try_case,{y,1}},12,{bad_type,term}}}, + {{bad_catch_try,bad_6,1}, + {{try_end,{y,1}},8,{bad_type,{integer,1}}}}] = Errors, + ok. + +cons_guard(Config) when is_list(Config) -> + Errors = do_val(cons, Config), + ?line + [{{cons,foo,1}, + {{get_list,{x,0},{x,1},{x,2}}, + 5, + {bad_type,{needed,cons},{actual,term}}}}] = Errors, + ok. + +freg_range(Config) when is_list(Config) -> + Errors = do_val(freg_range, Config), + ?line + [{{t,sum_1,2}, + {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}}, + 5, + {bad_source,{fr,-1}}}}, + {{t,sum_2,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}}, + 6, + {uninitialized_reg,{fr,1024}}}}, + {{t,sum_3,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}, + 7, + {bad_target,{fr,-1}}}}, + {{t,sum_4,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}, + 7, + limit}}] = Errors, + ok. + +freg_uninit(Config) when is_list(Config) -> + Errors = do_val(freg_uninit, Config), + ?line + [{{t,sum_1,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 6, + {uninitialized_reg,{fr,1}}}}, + {{t,sum_2,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 9, + {uninitialized_reg,{fr,0}}}}] = Errors, + ok. + +freg_state(Config) when is_list(Config) -> + Errors = do_val(freg_state, Config), + ?line + [{{t,sum_1,2}, + {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 6, + {bad_floating_point_state,undefined}}}, + {{t,sum_2,2}, + {{fmove,{fr,0},{x,0}}, + 8, + {bad_floating_point_state,cleared}}}, + {{t,sum_3,2}, + {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}}, + 8, + {unsafe_instruction,{float_error_state,cleared}}}}, + {{t,sum_4,2}, + {{fcheckerror,{f,0}}, + 4, + {bad_floating_point_state,undefined}}}, + {{t,sum_5,2}, + {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors, + ok. + +bin_match(Config) when is_list(Config) -> + Errors = do_val(bin_match, Config), + ?line + [{{t,t,1},{{bs_save,0},4,no_bs_match_state}}, + {{t,x,1},{{bs_restore,1},16,{no_save_point,1}}}] = Errors, + ok. + +bin_aligned(Config) when is_list(Config) -> + Errors = do_val(bin_aligned, Config), + ?line + [{{t,decode,1}, + {{bs_put_integer,{f,0}, + {integer,5}, + 1, + {field_flags,[unsigned,big,aligned]}, + {integer,0}}, + 10, + {aligned_flag_set,{bits,3}}}}] = Errors, + ok. + +bad_dsetel(Config) when is_list(Config) -> + Errors = do_val(bad_dsetel, Config), + ?line + [{{t,t,1}, + {{set_tuple_element,{x,1},{x,0},1}, + 15, + illegal_context_for_set_tuple_element}}] = Errors, + ok. + +state_after_fault_in_catch(Config) when is_list(Config) -> + Errors = do_val(state_after_fault_in_catch, Config), + [{{t,foo,1}, + {{move,{x,1},{x,0}},10,{uninitialized_reg,{x,1}}}}, + {{state_after_fault_in_catch,if_end,1}, + {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}, + {{state_after_fault_in_catch,case_end,1}, + {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}, + {{state_after_fault_in_catch,badmatch,1}, + {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}] = Errors, + ok. + +no_exception_in_catch(Config) when is_list(Config) -> + Errors = do_val(no_exception_in_catch, Config), + [{{no_exception_in_catch,nested_of_1,4}, + {{move,{x,3},{x,0}},91,{uninitialized_reg,{x,3}}}}] = Errors, + ok. + +undef_label(Config) when is_list(Config) -> + Errors = do_val(undef_label, Config), + [{{undef_label,t,1},{undef_labels,[42]}}, + {{undef_label,x,1},{return,4,no_entry_label}}] = Errors, + ok. + +illegal_instruction(Config) when is_list(Config) -> + Errors = do_val(illegal_instruction, Config), + [{{illegal_instruction,t,1}, + {{my_illegal_instruction,{x,0}},4,unknown_instruction}}, + {{'_',x,1},{bad_func_info,1,illegal_instruction}}, + {{'_',y,0},{[],0,illegal_instruction}}] = Errors, + ok. + + + +%%%------------------------------------------------------------------------- + +do_val(Name, Config) -> + do_val(Name, Config, ".S"). + +do_val(Name, Config, Type) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, atom_to_list(Name)++Type), + ?line case beam_validator:file(File) of + {error,Errors} -> + ?line io:format("~p:~n~s", + [File,beam_validator:format_error(Errors)]), + Errors; + ok -> [] + end. diff --git a/lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S b/lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S new file mode 100644 index 0000000000..2728a2fa32 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S @@ -0,0 +1,31 @@ +{module, accessing_tags}. %% version = 0 + +{exports, [{foo,1},{bar,1}]}. + +{attributes, []}. + +{function, foo, 1, 2}. + {label,1}. + {func_info,{atom,accessing_tags},{atom,foo},1}. + {label,2}. + {allocate,1,1}. + {'catch',{y,0},{f,3}}. + {move,{y,0},{x,0}}. %Retrieve the catch tag. + {call,1,{f,2}}. + {label,3}. + {catch_end,{y,0}}. + {deallocate,1}. + return. + +{function, bar, 1, 5}. + {label,4}. + {func_info,{atom,accessing_tags},{atom,bar},1}. + {label,5}. + {allocate,1,1}. + {'try',{y,0},{f,6}}. + {move,{y,0},{x,0}}. %Retrieve the try tag. + {call,5,{f,2}}. + {label,6}. + {catch_end,{y,0}}. + {deallocate,1}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S b/lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S new file mode 100644 index 0000000000..2a53f0dd93 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S @@ -0,0 +1,168 @@ +{module, bad_catch_try}. %% version = 0 + +{exports, [{bad_1,1}, + {bad_2,1}, + {bad_3,1}, + {bad_4,1}, + {bad_5,1}, + {bad_6,1}, + {foo,1}, + {module_info,0}, + {module_info,1}]}. + +{attributes, []}. + +{labels, 31}. + + +{function, bad_1, 1, 2}. + {label,1}. + {func_info,{atom,bad_catch_try},{atom,bad_1},1}. + {label,2}. + {allocate,1,1}. + {'catch',{x,0},{f,3}}. + {call,1,{f,26}}. + {label,3}. + {catch_end,{x,0}}. + {test,is_tuple,{f,4},[{x,0}]}. + {test,test_arity,{f,4},[{x,0},2]}. + {get_tuple_element,{x,0},0,{x,1}}. + {test,is_eq_exact,{f,4},[{x,1},{atom,'EXIT'}]}. + {move,{atom,error},{x,0}}. + {deallocate,1}. + return. + {label,4}. + {move,{atom,ok},{x,0}}. + {deallocate,1}. + return. + + +{function, bad_2, 1, 6}. + {label,5}. + {func_info,{atom,bad_catch_try},{atom,bad_2},1}. + {label,6}. + {allocate,1,1}. + {'catch',{y,0},{f,7}}. + {call,1,{f,26}}. + {label,7}. + {catch_end,{x,9}}. + {test,is_tuple,{f,8},[{x,0}]}. + {test,test_arity,{f,8},[{x,0},2]}. + {get_tuple_element,{x,0},0,{x,1}}. + {test,is_eq_exact,{f,8},[{x,1},{atom,'EXIT'}]}. + {move,{atom,error},{x,0}}. + {deallocate,1}. + return. + {label,8}. + {move,{atom,ok},{x,0}}. + {deallocate,1}. + return. + + +{function, bad_3, 1, 10}. + {label,9}. + {func_info,{atom,bad_catch_try},{atom,bad_3},1}. + {label,10}. + {allocate,1,1}. + {'catch',{y,0},{f,11}}. + {call,1,{f,26}}. + {label,11}. + {move,{atom,kalle},{y,1}}. + {catch_end,{y,1}}. + {test,is_tuple,{f,12},[{x,0}]}. + {test,test_arity,{f,12},[{x,0},2]}. + {get_tuple_element,{x,0},0,{x,1}}. + {test,is_eq_exact,{f,12},[{x,1},{atom,'EXIT'}]}. + {move,{atom,error},{x,0}}. + {deallocate,1}. + return. + {label,12}. + {move,{atom,ok},{x,0}}. + {deallocate,1}. + return. + + +{function, bad_4, 1, 14}. + {label,13}. + {func_info,{atom,bad_catch_try},{atom,bad_4},1}. + {label,14}. + {allocate_zero,1,1}. + {'try',{x,0},{f,15}}. + {call,1,{f,26}}. + {try_end,{y,0}}. + {move,{atom,ok},{x,0}}. + {jump,{f,16}}. + {label,15}. + {try_case,{y,0}}. + {test,is_ne_exact,{f,16},[{x,0},{atom,error}]}. + {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}. + {'%live',1}. + {label,16}. + {deallocate,1}. + return. + + +{function, bad_5, 1, 18}. + {label,17}. + {func_info,{atom,bad_catch_try},{atom,bad_5},1}. + {label,18}. + {allocate_zero,1,1}. + {'try',{y,0},{f,19}}. + {call,1,{f,26}}. + {try_end,{y,0}}. + {move,{atom,ok},{x,0}}. + {jump,{f,20}}. + {label,19}. + {move,{x,0},{y,1}}. + {try_case,{y,1}}. + {test,is_ne_exact,{f,20},[{x,0},{atom,error}]}. + {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}. + {'%live',1}. + {label,20}. + {deallocate,1}. + return. + + +{function, bad_6, 1, 22}. + {label,21}. + {func_info,{atom,bad_catch_try},{atom,bad_6},1}. + {label,22}. + {allocate_zero,1,1}. + {'try',{y,0},{f,23}}. + {call,1,{f,26}}. + {move,{integer,1},{y,1}}. + {try_end,{y,1}}. + {move,{atom,ok},{x,0}}. + {jump,{f,24}}. + {label,23}. + {try_case,{y,0}}. + {test,is_ne_exact,{f,24},[{x,0},{atom,error}]}. + {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}. + {'%live',1}. + {label,24}. + {deallocate,1}. + return. + + +{function, foo, 1, 26}. + {label,25}. + {func_info,{atom,bad_catch_try},{atom,foo},1}. + {label,26}. + return. + + +{function, module_info, 0, 28}. + {label,27}. + {func_info,{atom,bad_catch_try},{atom,module_info},0}. + {label,28}. + {move,{atom,bad_catch_try},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 30}. + {label,29}. + {func_info,{atom,bad_catch_try},{atom,module_info},1}. + {label,30}. + {move,{x,0},{x,1}}. + {move,{atom,bad_catch_try},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S b/lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S new file mode 100644 index 0000000000..279b2fa97f --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S @@ -0,0 +1,52 @@ +{module, t}. %% version = 0 + +{exports, [{module_info,0},{module_info,1},{t,1}]}. + +{attributes, []}. + +{labels, 8}. + + +{function, t, 1, 2}. + {label,1}. + {func_info,{atom,t},{atom,t},1}. + {label,2}. + {test,is_tuple,{f,3},[{x,0}]}. + {test,test_arity,{f,3},[{x,0},7]}. + {get_tuple_element,{x,0},0,{x,1}}. + {test,is_eq_exact,{f,3},[{x,1},{atom,r}]}. + {allocate,0,1}. + {move,{x,0},{x,1}}. + {move,{integer,1},{x,2}}. + {move,{integer,3},{x,0}}. + {call_ext,3,{extfunc,erlang,setelement,3}}. + {test_heap,6,1}. + {put_string,3,{string,"abc"},{x,1}}. + {set_tuple_element,{x,1},{x,0},1}. + {'%live',1}. + {deallocate,0}. + return. + {label,3}. + {test_heap,3,0}. + {put_tuple,2,{x,0}}. + {put,{atom,badrecord}}. + {put,{atom,r}}. + {'%live',1}. + {call_ext_only,1,{extfunc,erlang,error,1}}. + + +{function, module_info, 0, 5}. + {label,4}. + {func_info,{atom,t},{atom,module_info},0}. + {label,5}. + {move,{atom,t},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 7}. + {label,6}. + {func_info,{atom,t},{atom,module_info},1}. + {label,7}. + {move,{x,0},{x,1}}. + {move,{atom,t},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S b/lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S new file mode 100644 index 0000000000..2f353fbd25 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S @@ -0,0 +1,47 @@ +{module, t}. %% version = 0 + +{exports, [{decode,1},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 7}. + + +{function, decode, 1, 2}. + {label,1}. + {func_info,{atom,t},{atom,decode},1}. + {label,2}. + {move,{integer,1},{x,1}}. + {bif,size,{f,0},[{x,0}],{x,2}}. + {bs_add,{f,0},[{x,1},{x,2},1],{x,1}}. + {bs_init2,{f,0},{x,1},0,1,{field_flags,[]},{x,1}}. + {bs_put_integer,{f,0}, + {integer,3}, + 1, + {field_flags,[aligned,unsigned,big]}, + {integer,0}}. + {bs_put_binary,{f,0},{atom,all},8,{field_flags,[unsigned,big]},{x,0}}. + {bs_put_integer,{f,0}, + {integer,5}, + 1, + {field_flags,[unsigned,big,aligned]}, + {integer,0}}. + {move,{x,1},{x,0}}. + return. + + +{function, module_info, 0, 4}. + {label,3}. + {func_info,{atom,t},{atom,module_info},0}. + {label,4}. + {move,{atom,t},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 6}. + {label,5}. + {func_info,{atom,t},{atom,module_info},1}. + {label,6}. + {move,{x,0},{x,1}}. + {move,{atom,t},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/bin_match.S b/lib/compiler/test/beam_validator_SUITE_data/bin_match.S new file mode 100644 index 0000000000..96df0f7933 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/bin_match.S @@ -0,0 +1,64 @@ +{module, bin_match}. %% version = 0 + +{exports, [{t,1}]}. + +{attributes, []}. + +{labels, 8}. + + +{function, t, 1, 2}. + {label,1}. + {func_info,{atom,t},{atom,t},1}. + {label,2}. +%% {test,bs_start_match,{f,1},[{x,0}]}. + {bs_save,0}. + {test,bs_get_integer, + {f,3}, + [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,1}]}. + {test,bs_get_integer, + {f,3}, + [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,2}]}. + {test,bs_test_tail,{f,3},[0]}. + {test_heap,3,3}. + {put_tuple,2,{x,0}}. + {put,{x,1}}. + {put,{x,2}}. + {'%live',1}. + return. + {label,3}. + {bs_restore,0}. + {test,bs_get_integer, + {f,1}, + [{integer,32},1,{field_flags,[aligned,unsigned,big]},{x,1}]}. + {test,bs_test_tail,{f,1},[0]}. + {move,{x,1},{x,0}}. + return. + +{function, x, 1, 5}. + {label,4}. + {func_info,{atom,t},{atom,x},1}. + {label,5}. + {test,bs_start_match,{f,4},[{x,0}]}. + {bs_save,0}. + {test,bs_get_integer, + {f,6}, + [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,1}]}. + {test,bs_get_integer, + {f,6}, + [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,2}]}. + {test,bs_test_tail,{f,6},[0]}. + {test_heap,3,3}. + {put_tuple,2,{x,0}}. + {put,{x,1}}. + {put,{x,2}}. + {'%live',1}. + return. + {label,6}. + {bs_restore,1}. + {test,bs_get_integer, + {f,4}, + [{integer,32},1,{field_flags,[aligned,unsigned,big]},{x,1}]}. + {test,bs_test_tail,{f,4},[0]}. + {move,{x,1},{x,0}}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/call_last.S b/lib/compiler/test/beam_validator_SUITE_data/call_last.S new file mode 100644 index 0000000000..827b6c0ae6 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/call_last.S @@ -0,0 +1,71 @@ +{module, call_last}. %% version = 0 + +{exports, [{a,1},{b,1},{bar,1},{foo,1},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 13}. + + +{function, a, 1, 2}. + {label,1}. + {func_info,{atom,t},{atom,a},1}. + {label,2}. + {allocate,1,1}. + {move,{x,0},{y,0}}. + {bif,'+',{f,0},[{y,0},{integer,1}],{x,0}}. + {'%live',1}. + {call,1,{f,6}}. + {bif,'+',{f,0},[{y,0},{integer,2}],{x,0}}. + {'%live',1}. + {call_last,1,{f,8},2}. + + +{function, b, 1, 4}. + {label,3}. + {func_info,{atom,t},{atom,b},1}. + {label,4}. + {allocate,1,1}. + {move,{x,0},{y,0}}. + {bif,'+',{f,0},[{y,0},{integer,1}],{x,0}}. + {'%live',1}. + {call,1,{f,6}}. + {move,{y,0},{x,1}}. + {move,{integer,0},{x,0}}. + {call_ext_last,2,{extfunc,lists,seq,2},2}. + + +{function, foo, 1, 6}. + {label,5}. + {func_info,{atom,t},{atom,foo},1}. + {label,6}. + {move,{x,0},{x,1}}. + {move,{atom,glurf},{x,0}}. + {call_ext_only,2,{extfunc,erlang,put,2}}. + + +{function, bar, 1, 8}. + {label,7}. + {func_info,{atom,t},{atom,bar},1}. + {label,8}. + {bif,get,{f,0},[{atom,glurf}],{x,1}}. + {bif,'+',{f,0},[{x,0},{x,1}],{x,0}}. + {'%live',1}. + return. + + +{function, module_info, 0, 10}. + {label,9}. + {func_info,{atom,t},{atom,module_info},0}. + {label,10}. + {move,{atom,t},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 12}. + {label,11}. + {func_info,{atom,t},{atom,module_info},1}. + {label,12}. + {move,{x,0},{x,1}}. + {move,{atom,t},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/cons.S b/lib/compiler/test/beam_validator_SUITE_data/cons.S new file mode 100644 index 0000000000..83b9daa6f5 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/cons.S @@ -0,0 +1,38 @@ +{module, cons}. %% version = 0 + +{exports, [{foo,1},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 7}. + + +{function, foo, 1, 2}. + {label,1}. + {func_info,{atom,cons},{atom,foo},1}. + {label,2}. +% {test,is_nonempty_list,{f,1},[{x,0}]}. + {test_heap,3,1}. + {get_list,{x,0},{x,1},{x,2}}. % <= {bad_type,{needed,cons},{actual,term}} + {put_tuple,2,{x,0}}. + {put,{x,1}}. + {put,{x,2}}. + {'%live',1}. + return. + + +{function, module_info, 0, 4}. + {label,3}. + {func_info,{atom,cons},{atom,module_info},0}. + {label,4}. + {move,{atom,cons},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 6}. + {label,5}. + {func_info,{atom,cons},{atom,module_info},1}. + {label,6}. + {move,{x,0},{x,1}}. + {move,{atom,cons},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/dead_code.S b/lib/compiler/test/beam_validator_SUITE_data/dead_code.S new file mode 100644 index 0000000000..f964f98fba --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/dead_code.S @@ -0,0 +1,48 @@ +{module, dead_code}. %% version = 0 + +{exports, [{execute,0},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 10}. + + +{function, execute, 0, 2}. + {label,1}. + {func_info,{atom,dead_code},{atom,execute},0}. + {label,2}. + {allocate,0,0}. + {'%live',0}. + {call_ext,0,{extfunc,foo,fie,0}}. + {test,is_ne,{f,4},[{x,0},{integer,0}]}. + {test,is_ne,{f,4},[{x,0},{integer,1}]}. + {label,3}. + {test,is_ne,{f,4},[{x,0},{integer,2}]}. + {test,is_ne,{f,4},[{x,0},{integer,3}]}. + {case_end,{x,0}}. + {label,4}. + {move,{atom,ok},{x,0}}. + {'%live',1}. + {deallocate,0}. + return. + {'%','Moved code'}. + {label,5}. + {case_end,{x,0}}. + + +{function, module_info, 0, 7}. + {label,6}. + {func_info,{atom,dead_code},{atom,module_info},0}. + {label,7}. + {move,nil,{x,0}}. + {'%live',1}. + return. + + +{function, module_info, 1, 9}. + {label,8}. + {func_info,{atom,dead_code},{atom,module_info},1}. + {label,9}. + {move,nil,{x,0}}. + {'%live',1}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beam b/lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beam Binary files differnew file mode 100644 index 0000000000..dd58a88e42 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beam diff --git a/lib/compiler/test/beam_validator_SUITE_data/freg_range.S b/lib/compiler/test/beam_validator_SUITE_data/freg_range.S new file mode 100644 index 0000000000..ee583a923e --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/freg_range.S @@ -0,0 +1,53 @@ +{module, freg_range}. %% version = 0 + +{exports, [{module_info,0},{module_info,1},{prod,2},{sum,2},{sum_prod,3}]}. + +{attributes, []}. + +{labels, 8}. + + +{function, sum_1, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,sum_1},2}. + {label,2}. + fclearerror. + {bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}}. + {'%live',1}. + return. + + +{function, sum_2, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,sum_2},2}. + {label,4}. + {fconv,{x,0},{fr,0}}. + fclearerror. + {bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}}. + {'%live',1}. + return. + + +{function, sum_3, 2, 6}. + {label,5}. + {func_info,{atom,t},{atom,sum_3},2}. + {label,6}. + {fconv,{x,0},{fr,0}}. + {fconv,{x,1},{fr,1}}. + fclearerror. + {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}. + {'%live',1}. + return. + + +{function, sum_4, 2, 8}. + {label,7}. + {func_info,{atom,t},{atom,sum_4},2}. + {label,8}. + {fconv,{x,0},{fr,0}}. + {fconv,{x,1},{fr,1}}. + fclearerror. + {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}. + {'%live',1}. + return. + diff --git a/lib/compiler/test/beam_validator_SUITE_data/freg_state.S b/lib/compiler/test/beam_validator_SUITE_data/freg_state.S new file mode 100644 index 0000000000..ff4d7548ae --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/freg_state.S @@ -0,0 +1,59 @@ +{module, freg_state}. %% version = 0 + +{exports, []}. + +{attributes, []}. + + +{function, sum_1, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,sum_1},2}. + {label,2}. + {fconv,{x,0},{fr,0}}. + {fconv,{x,1},{fr,1}}. + {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}. + {'%live',1}. + return. + +{function, sum_2, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,sum_2},2}. + {label,4}. + {fconv,{x,0},{fr,0}}. + {fconv,{x,1},{fr,1}}. + fclearerror. + {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}. + {fmove,{fr,0},{x,0}}. + {'%live',1}. + return. + +{function, sum_3, 2, 6}. + {label,5}. + {func_info,{atom,t},{atom,sum_3},2}. + {label,6}. + {fconv,{x,0},{fr,0}}. + {fconv,{x,1},{fr,1}}. + fclearerror. + {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}. + {bif,'-',{f,0},[{x,1},{x,0}],{x,1}}. + {fcheckerror,{f,0}}. + {fmove,{fr,0},{x,0}}. + {'%live',1}. + return. + +{function, sum_4, 2, 8}. + {label,6}. + {func_info,{atom,t},{atom,sum_4},2}. + {label,8}. + {fcheckerror,{f,0}}. + {fmove,{fr,0},{x,0}}. + {'%live',1}. + return. + +{function, sum_5, 2, 10}. + {label,9}. + {func_info,{atom,t},{atom,sum_5},2}. + {label,10}. + fclearerror. + fclearerror. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S b/lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S new file mode 100644 index 0000000000..f8d805d9ec --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S @@ -0,0 +1,32 @@ +{module, freg_uninit}. %% version = 0 + +{exports, []}. + +{attributes, []}. + +{labels, 8}. + + +{function, sum_1, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,sum_1},2}. + {label,2}. + {fconv,{x,0},{fr,0}}. + fclearerror. + {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}. + {'%live',1}. + return. + + +{function, sum_2, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,sum_2},2}. + {label,4}. + {fconv,{x,0},{fr,0}}. + {fconv,{x,1},{fr,1}}. + fclearerror. + {fcheckerror,{f,0}}. + {call,2,{f,8}}. + {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}. + {'%live',1}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S b/lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S new file mode 100644 index 0000000000..d6e92abc71 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S @@ -0,0 +1,26 @@ +{module, illegal_instruction}. %% version = 0 + +{exports, []}. + +{attributes, []}. + +{labels, 7}. + + +{function, t, 1, 2}. + {label,1}. + {func_info,{atom,illegal_instruction},{atom,t},1}. + {label,2}. + {my_illegal_instruction,{x,0}}. + return. + + +{function, x, 1, 4}. + {label,3}. + bad_func_info. + {label,4}. + {my_illegal_instruction,{x,0}}. + return. + +{function, y, 0, 17}. +
\ No newline at end of file diff --git a/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S b/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S new file mode 100644 index 0000000000..3d76127824 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S @@ -0,0 +1,84 @@ +{module, merge_undefined}. %% version = 0 + +{exports, [{bar,2},{foo,1},{handle_call,2},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 15}. + + +{function, handle_call, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,handle_call},2}. + {label,2}. + {test,is_atom,{f,1},[{x,0}]}. + {select_val,{x,0},{f,1},{list,[{atom,gurka},{f,3},{atom,delete},{f,4}]}}. + {label,3}. + {allocate_heap,2,6,2}. + %% The Y registers are not initialized here. + {test,is_eq_exact,{f,5},[{x,0},{atom,ok}]}. + {move,{atom,nisse},{x,0}}. + {call_ext,1,{extfunc,erlang,exit,1}}. + {label,4}. + {allocate_heap,1,6,2}. + {move,{x,1},{y,0}}. + {put_string,2,{string,"~p"},{x,0}}. + {put_list,{y,0},nil,{x,1}}. + {'%live',2}. + {call_ext,2,{extfunc,io,format,2}}. + {test,is_ne_exact,{f,6},[{x,0},{atom,ok}]}. + {label,5}. + {move,{atom,logReader},{x,1}}. + {move,{atom,console},{x,0}}. + {call_ext,2,{extfunc,debug,filter,2}}. + {test_heap,14,1}. + {put_list,{atom,logReader},nil,{x,1}}. + {put_list,{atom,console},{x,1},{x,1}}. + {put_tuple,3,{x,2}}. + {put,{atom,debug}}. + {put,{atom,filter}}. + {put,{x,1}}. + {put_tuple,2,{x,1}}. + {put,{x,2}}. + {put,{x,0}}. + {put_tuple,2,{x,0}}. + {put,{atom,badmatch}}. + {put,{x,1}}. + {'%live',1}. + {call_ext,1,{extfunc,erlang,exit,1}}. + {label,6}. + {move,{y,0},{x,0}}. + {call_last,1,{f,8},1}. + + +{function, foo, 1, 8}. + {label,7}. + {func_info,{atom,t},{atom,foo},1}. + {label,8}. + {move,{atom,ok},{x,0}}. + return. + + +{function, bar, 2, 10}. + {label,9}. + {func_info,{atom,t},{atom,bar},2}. + {label,10}. + {move,{atom,ok},{x,0}}. + return. + + +{function, module_info, 0, 12}. + {label,11}. + {func_info,{atom,t},{atom,module_info},0}. + {label,12}. + {move,{atom,t},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 14}. + {label,13}. + {func_info,{atom,t},{atom,module_info},1}. + {label,14}. + {move,{x,0},{x,1}}. + {move,{atom,t},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S b/lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S new file mode 100644 index 0000000000..e08a718a39 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S @@ -0,0 +1,209 @@ +{module, no_exception_in_catch}. %% version = 0 + +{exports, [{foo,1},{module_info,0},{module_info,1},{nested_of_1,4}]}. + +{attributes, []}. + +{labels, 22}. + + +{function, nested_of_1, 4, 2}. + {label,1}. + {func_info,{atom,no_exception_in_catch},{atom,nested_of_1},4}. + {label,2}. + {test,is_tuple,{f,1},[{x,0}]}. + {test,test_arity,{f,1},[{x,0},3]}. + {allocate_zero,15,4}. + {get_tuple_element,{x,0},0,{y,9}}. + {get_tuple_element,{x,0},1,{y,10}}. + {get_tuple_element,{x,0},2,{y,11}}. + {move,{x,3},{y,14}}. + {move,{x,2},{y,13}}. + {move,{x,1},{y,12}}. + {move,{atom,nested3},{x,0}}. + {call_ext,1,{extfunc,erlang,erase,1}}. + {move,{atom,nested4},{x,0}}. + {call_ext,1,{extfunc,erlang,erase,1}}. + {move,{atom,nested},{x,0}}. + {call_ext,1,{extfunc,erlang,erase,1}}. + {bif,self,nofail,[],{x,0}}. + {'try',{y,8},{f,13}}. + {'try',{y,7},{f,11}}. + {'try',{y,6},{f,9}}. + {'try',{y,5},{f,7}}. +%% Because the following instructions can't possible throw an exception, +%% label 7 used to get no state. Now the try_end itself will save the state. + {move,{x,0},{y,4}}. + {bif,self,nofail,[],{x,0}}. + {'%live',1}. + {try_end,{y,5}}. + {test,is_eq_exact,{f,15},[{x,0},{y,4}]}. + {'try',{y,5},{f,6}}. + {'try',{y,3},{f,3}}. + {move,{y,9},{x,0}}. + {call,1,{f,17}}. + {try_end,{y,3}}. + {test,is_eq_exact,{f,15},[{x,0},{y,11}]}. + {move,{y,12},{x,0}}. + {call,1,{f,17}}. + {test_heap,3,1}. + {put_tuple,2,{x,1}}. + {put,{atom,value1}}. + {put,{x,0}}. + {move,{x,1},{x,0}}. + {jump,{f,5}}. + {label,3}. + {try_case,{y,3}}. + {move,{x,1},{y,1}}. + {move,{x,0},{y,2}}. + {move,{x,2},{y,3}}. + {bif,'=:=',{f,4},[{x,0},{y,10}],{x,3}}. + {move,{x,3},{y,0}}. + {bif,'=:=',{f,4},[{x,1},{y,11}],{x,4}}. + {bif,'and',{f,4},[{x,3},{x,4}],{x,3}}. + {test,is_eq_exact,{f,4},[{x,3},{atom,true}]}. + {kill,{y,0}}. + {kill,{y,1}}. + {kill,{y,2}}. + {kill,{y,3}}. + {move,{y,12},{x,0}}. + {call,1,{f,17}}. + {test_heap,3,1}. + {put_tuple,2,{x,1}}. + {put,{atom,caught1}}. + {put,{x,0}}. + {move,{x,1},{x,0}}. + {jump,{f,5}}. + {label,4}. + {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}. + {'%live',1}. + {label,5}. + {try_end,{y,5}}. + {move,{x,0},{y,5}}. + {move,{y,13},{x,0}}. + {call,1,{f,17}}. + {move,{x,0},{x,1}}. + {move,{atom,nested3},{x,0}}. + {call_ext,2,{extfunc,erlang,put,2}}. + {move,{y,5},{x,0}}. + {jump,{f,8}}. + {label,6}. + {try_case,{y,5}}. + {move,{x,2},{y,5}}. + {move,{x,1},{y,3}}. + {move,{y,13},{x,0}}. + {call,1,{f,17}}. + {move,{x,0},{x,1}}. + {move,{atom,nested3},{x,0}}. + {call_ext,2,{extfunc,erlang,put,2}}. + {bif,raise,{f,0},[{y,5},{y,3}],{x,0}}. + {'%live',1}. + {jump,{f,8}}. + {label,7}. +%% The instructions here used to be not checked. + {move,{x,3},{x,0}}. + {try_case,{y,5}}. + {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}. + {'%live',1}. + {label,8}. + {try_end,{y,6}}. + {move,{x,0},{y,13}}. + {kill,{y,3}}. + {kill,{y,4}}. + {kill,{y,5}}. + {kill,{y,9}}. + {kill,{y,10}}. + {kill,{y,11}}. + {kill,{y,12}}. + {move,{y,14},{x,0}}. + {call,1,{f,17}}. + {move,{x,0},{x,1}}. + {move,{atom,nested4},{x,0}}. + {call_ext,2,{extfunc,erlang,put,2}}. + {move,{y,13},{x,0}}. + {jump,{f,10}}. + {label,9}. + {try_case,{y,6}}. + {move,{x,2},{y,13}}. + {move,{x,1},{y,12}}. + {kill,{y,3}}. + {kill,{y,4}}. + {kill,{y,5}}. + {kill,{y,9}}. + {kill,{y,10}}. + {kill,{y,11}}. + {move,{y,14},{x,0}}. + {call,1,{f,17}}. + {move,{x,0},{x,1}}. + {move,{atom,nested4},{x,0}}. + {call_ext,2,{extfunc,erlang,put,2}}. + {bif,raise,{f,0},[{y,13},{y,12}],{x,0}}. + {'%live',1}. + {label,10}. + {try_end,{y,7}}. + {test_heap,3,1}. + {put_tuple,2,{x,1}}. + {put,{atom,value}}. + {put,{x,0}}. + {move,{x,1},{x,0}}. + {jump,{f,12}}. + {label,11}. + {try_case,{y,7}}. + {test_heap,6,3}. + {put_tuple,2,{x,3}}. + {put,{x,0}}. + {put,{x,1}}. + {put_tuple,2,{x,0}}. + {put,{atom,caught}}. + {put,{x,3}}. + {'%live',1}. + {label,12}. + {try_end,{y,8}}. + {move,{x,0},{y,14}}. + {move,{atom,finalized},{x,1}}. + {kill,{y,12}}. + {kill,{y,13}}. + {move,{atom,nested},{x,0}}. + {call_ext,2,{extfunc,erlang,put,2}}. + {move,{y,14},{x,0}}. + {jump,{f,14}}. + {label,13}. + {try_case,{y,8}}. + {move,{x,2},{y,14}}. + {move,{x,1},{y,13}}. + {move,{atom,finalized},{x,1}}. + {kill,{y,12}}. + {move,{atom,nested},{x,0}}. + {call_ext,2,{extfunc,erlang,put,2}}. + {bif,raise,{f,0},[{y,14},{y,13}],{x,0}}. + {'%live',1}. + {label,14}. + {move,{x,0},{y,14}}. + {kill,{y,13}}. + {move,{atom,nested3},{x,0}}. + {call_ext,1,{extfunc,erlang,erase,1}}. + {move,{x,0},{y,13}}. + {move,{atom,nested4},{x,0}}. + {call_ext,1,{extfunc,erlang,erase,1}}. + {move,{x,0},{y,12}}. + {move,{atom,nested},{x,0}}. + {call_ext,1,{extfunc,erlang,erase,1}}. + {test_heap,5,1}. + {put_tuple,4,{x,1}}. + {put,{y,14}}. + {put,{y,13}}. + {put,{y,12}}. + {put,{x,0}}. + {move,{x,1},{x,0}}. + {deallocate,15}. + return. + {label,15}. + {try_case_end,{x,0}}. + + +{function, foo, 1, 17}. + {label,16}. + {func_info,{atom,no_exception_in_catch},{atom,foo},1}. + {label,17}. + {move,{atom,ok},{x,0}}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S b/lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S new file mode 100644 index 0000000000..f6ad0ac50a --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S @@ -0,0 +1,38 @@ +{module, overwrite_catchtag}. %% version = 0 + +{exports, [{foo,1},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 8}. + + +{function, foo, 1, 2}. + {label,1}. + {func_info,{atom,overwrite_catchtag},{atom,foo},1}. + {label,2}. + {allocate,1,1}. + {'catch',{y,0},{f,3}}. + {move,{x,0},{y,0}}. % <= {catchtag,3} + {call,1,{f,2}}. + {label,3}. + {catch_end,{y,0}}. + {deallocate,1}. + return. + + +{function, module_info, 0, 5}. + {label,4}. + {func_info,{atom,overwrite_catchtag},{atom,module_info},0}. + {label,5}. + {move,{atom,overwrite_catchtag},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 7}. + {label,6}. + {func_info,{atom,overwrite_catchtag},{atom,module_info},1}. + {label,7}. + {move,{x,0},{x,1}}. + {move,{atom,overwrite_catchtag},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S b/lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S new file mode 100644 index 0000000000..db552d5418 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S @@ -0,0 +1,53 @@ +{module, overwrite_trytag}. %% version = 0 + +{exports, [{foo,1},{module_info,0},{module_info,1}]}. + +{attributes, []}. + +{labels, 9}. + + +{function, foo, 1, 2}. + {label,1}. + {func_info,{atom,overwrite_trytag},{atom,foo},1}. + {label,2}. + {allocate_zero,3,1}. + {'try',{y,2},{f,3}}. + {move,{x,0},{y,1}}. + {'%live',1}. + {call,1,{f,2}}. + {kill,{y,2}}. + {try_end,{y,2}}. + {move,{x,0},{y,2}}. + {move,{y,1},{x,0}}. + {call,1,{f,2}}. + {move,{y,2},{x,0}}. + {jump,{f,4}}. + {label,3}. + {try_case,{y,2}}. + {move,{x,2},{y,2}}. + {move,{x,1},{y,0}}. + {move,{y,1},{x,0}}. + {call,1,{f,2}}. + {bif,raise,{f,0},[{y,2},{y,0}],{x,0}}. + {'%live',1}. + {label,4}. + {deallocate,3}. + return. + + +{function, module_info, 0, 6}. + {label,5}. + {func_info,{atom,overwrite_trytag},{atom,module_info},0}. + {label,6}. + {move,{atom,overwrite_trytag},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 8}. + {label,7}. + {func_info,{atom,overwrite_trytag},{atom,module_info},1}. + {label,8}. + {move,{x,0},{x,1}}. + {move,{atom,overwrite_trytag},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/lib/compiler/test/beam_validator_SUITE_data/stack.S b/lib/compiler/test/beam_validator_SUITE_data/stack.S new file mode 100644 index 0000000000..244c22a2f9 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/stack.S @@ -0,0 +1,89 @@ +{module, stack}. %% version = 0 + +{exports, [{a,2},{b,2},{c,2},{d,2},{e,2}]}. + +{attributes, []}. + +{labels, 21}. + + +{function, a, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,a},2}. + {label,2}. + {allocate,2,2}. + {move,{x,1},{y,1}}. + {move,{x,0},{y,0}}. + {'%live',0}. + {call,0,{f,16}}. + {bif,'+',{f,0},[{y,0},{y,1}],{x,0}}. + {'%live',1}. + return. + + +{function, b, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,b},2}. + {label,4}. + {deallocate,2}. + return. + + +{function, c, 2, 6}. + {label,5}. + {func_info,{atom,t},{atom,c},2}. + {label,6}. + {allocate,2,2}. + {move,{x,1},{y,1}}. + {move,{x,0},{y,0}}. + {'%live',0}. + {call,0,{f,16}}. + {bif,'+',{f,0},[{y,0},{y,1}],{x,0}}. + {'%live',1}. + {deallocate,2}. + {deallocate,2}. + return. + + +{function, d, 2, 8}. + {label,7}. + {func_info,{atom,t},{atom,d},2}. + {label,8}. + {allocate,2,2}. + {allocate,2,2}. + {deallocate,2}. + return. + +{function, e, 2, 14}. + {label,13}. + {func_info,{atom,t},{atom,e},2}. + {label,14}. + {allocate,2,2}. + {move,{atom,ok},{x,0}}. + {deallocate,5}. + return. + + +{function, bad_1, 0, 10}. + {label,9}. + {func_info,{atom,t},{atom,bad_1},0}. + {label,10}. + {allocate_zero,2,10}. + {move,{y,0},{x,0}}. + return. + + +{function, bad_2, 0, 12}. + {label,11}. + {func_info,{atom,t},{atom,bad_2},0}. + {label,12}. + {allocate_zero,2,0}. + {move,{y,0},{x,0}}. + return. + +{function, foo, 0, 16}. + {label,15}. + {func_info,{atom,t},{atom,foo},0}. + {label,16}. + {move,{atom,ok},{x,0}}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S b/lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S new file mode 100644 index 0000000000..8e27347ed5 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S @@ -0,0 +1,58 @@ +{module, state_after_fault_in_catch}. %% version = 0 + +{exports, [{foo,1},{if_end,1},{case_end,1},{badmatch,1}]}. + +{attributes, []}. + +{labels, 12}. + + +{function, foo, 1, 2}. + {label,1}. + {func_info,{atom,t},{atom,foo},1}. + {label,2}. + {allocate,1,0}. + {'catch',{y,0},{f,3}}. + {move,{atom,apa},{x,0}}. + {call_ext,1,{extfunc,erlang,fault,1}}. + {label,3}. + {catch_end,{y,0}}. + {move,{x,1},{x,0}}. + return. + +{function, if_end, 1, 5}. + {label,4}. + {func_info,{atom,state_after_fault_in_catch},{atom,if_end},1}. + {label,5}. + {allocate,1,0}. + {'catch',{y,0},{f,6}}. + if_end. + {label,6}. + {catch_end,{y,0}}. + {move,{x,1},{x,0}}. + return. + +{function, case_end, 1, 8}. + {label,7}. + {func_info,{atom,state_after_fault_in_catch},{atom,case_end},1}. + {label,8}. + {allocate,1,1}. + {'catch',{y,0},{f,9}}. + {case_end,{x,0}}. + {label,9}. + {catch_end,{y,0}}. + {move,{x,1},{x,0}}. + return. + +{function, badmatch, 1, 11}. + {label,10}. + {func_info,{atom,state_after_fault_in_catch},{atom,badmatch},1}. + {label,11}. + {allocate,1,1}. + {'catch',{y,0},{f,12}}. + {badmatch,{x,0}}. + {label,12}. + {catch_end,{y,0}}. + {move,{x,1},{x,0}}. + return. + diff --git a/lib/compiler/test/beam_validator_SUITE_data/undef_label.S b/lib/compiler/test/beam_validator_SUITE_data/undef_label.S new file mode 100644 index 0000000000..dd29066bf4 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/undef_label.S @@ -0,0 +1,22 @@ +{module, undef_label}. %% version = 0 + +{exports, []}. + +{attributes, []}. + +{labels, 7}. + + +{function, t, 1, 2}. + {label,1}. + {func_info,{atom,undef_label},{atom,t},1}. + {label,2}. + {test,is_eq_exact,{f,42},[{x,0},{atom,x}]}. + {move,{atom,ok},{x,0}}. + return. + +{function, x, 1, 17}. + {label,3}. + {func_info,{atom,undef_label},{atom,x},1}. + {label,4}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/uninit.S b/lib/compiler/test/beam_validator_SUITE_data/uninit.S new file mode 100644 index 0000000000..1a45c31411 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/uninit.S @@ -0,0 +1,48 @@ +{module, uninit}. %% version = 0 + +{exports, []}. + +{attributes, []}. + +{function, sum_1, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,sum_1},2}. + {label,2}. + {allocate,1,2}. + {move,{y,0},{x,0}}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + +{function, sum_2, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,sum_2},2}. + {label,4}. + {allocate,1,2}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + +{function, sum_3, 2, 6}. + {label,5}. + {func_info,{atom,t},{atom,sum_3},2}. + {label,6}. + {allocate_zero,1,2}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + +{function, id, 1, 10}. + {label,9}. + {func_info,{atom,t},{atom,id},1}. + {label,10}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S b/lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S new file mode 100644 index 0000000000..500ac11377 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S @@ -0,0 +1,67 @@ +{module, unsafe_catch}. %% version = 0 + +{exports, [{small,2}]}. + +{attributes, []}. + +{labels, 14}. + + +{function, small, 2, 5}. + {label,4}. + {func_info,{atom,t},{atom,small},2}. + {label,5}. + {allocate_zero,2,2}. + {'catch',{y,1},{f,6}}. + {bs_init2,{f,0},1,0,2,{field_flags,[]},{x,2}}. + {bs_put_integer,{f,0}, + {integer,8}, + 1, + {field_flags,[aligned,unsigned,big]}, + {x,0}}. + {move,{x,1},{y,0}}. + {move,{x,2},{x,0}}. + {label,6}. + {catch_end,{y,1}}. + {test,is_tuple,{f,7},[{x,0}]}. + {test,test_arity,{f,7},[{x,0},2]}. + {get_tuple_element,{x,0},0,{x,1}}. + {test,is_eq_exact,{f,7},[{x,1},{atom,'EXIT'}]}. + {bs_init2,{f,0},0,0,0,{field_flags,[]},{x,0}}. + {label,7}. + {'catch',{y,1},{f,8}}. + {bs_init2,{f,0},2,0,1,{field_flags,[]},{x,1}}. + {bs_put_integer,{f,0}, + {integer,16}, + 1, + {field_flags,[aligned,unsigned,big]}, + {y,0}}. + {move,{x,0},{y,0}}. + {move,{x,1},{x,0}}. + {label,8}. + {catch_end,{y,1}}. + {test,is_tuple,{f,9},[{x,0}]}. + {test,test_arity,{f,9},[{x,0},2]}. + {get_tuple_element,{x,0},0,{x,1}}. + {test,is_eq_exact,{f,9},[{x,1},{atom,'EXIT'}]}. + {bs_init2,{f,0},0,0,0,{field_flags,[]},{x,0}}. + {label,9}. + {move,{integer,0},{x,1}}. + {bif,size,{f,0},[{x,0}],{x,2}}. + {bs_add,{f,0},[{x,1},{x,2},1],{x,1}}. + {bif,size,{f,0},[{y,0}],{x,2}}. + {bs_add,{f,0},[{x,1},{x,2},1],{x,1}}. + {bs_init2,{f,0},{x,1},0,2,{field_flags,[]},{x,1}}. + {bs_put_binary,{f,0}, + {atom,all}, + 8, + {field_flags,[aligned,unsigned,big]}, + {y,0}}. + {bs_put_binary,{f,0}, + {atom,all}, + 8, + {field_flags,[aligned,unsigned,big]}, + {x,0}}. + {move,{x,1},{x,0}}. + {deallocate,2}. + return. diff --git a/lib/compiler/test/beam_validator_SUITE_data/xrange.S b/lib/compiler/test/beam_validator_SUITE_data/xrange.S new file mode 100644 index 0000000000..3abbdffbc2 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/xrange.S @@ -0,0 +1,44 @@ +{module, xrange}. %% version = 0 + +{exports, [{module_info,0},{module_info,1},{prod,2},{sum,2},{sum_prod,3}]}. + +{attributes, []}. + +{labels, 8}. + + +{function, sum_1, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,sum_1},2}. + {label,2}. + {bif,'+',{f,0},[{x,-1},{x,1}],{x,0}}. + {'%live',1}. + return. + + +{function, sum_2, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,sum_2},2}. + {label,4}. + {bif,'+',{f,0},[{x,0},{x,1024}],{x,0}}. + {'%live',1}. + return. + + +{function, sum_3, 2, 6}. + {label,5}. + {func_info,{atom,t},{atom,sum_3},2}. + {label,6}. + {bif,'+',{f,0},[{x,0},{x,1}],{x,-1}}. + {'%live',1}. + return. + + +{function, sum_4, 2, 8}. + {label,7}. + {func_info,{atom,t},{atom,sum_4},2}. + {label,8}. + {bif,'+',{f,0},[{x,0},{x,1}],{x,1024}}. + {'%live',1}. + return. + diff --git a/lib/compiler/test/beam_validator_SUITE_data/yrange.S b/lib/compiler/test/beam_validator_SUITE_data/yrange.S new file mode 100644 index 0000000000..483b14ebd3 --- /dev/null +++ b/lib/compiler/test/beam_validator_SUITE_data/yrange.S @@ -0,0 +1,76 @@ +{module, yrange}. %% version = 0 + +{exports, [{id,1}, + {module_info,0}, + {module_info,1}, + {sum_1,2}, + {sum_2,2}, + {sum_3,2}, + {sum_4,2}]}. + +{attributes, []}. + +{labels, 15}. + + +{function, sum_1, 2, 2}. + {label,1}. + {func_info,{atom,t},{atom,sum_1},2}. + {label,2}. + {allocate,1,2}. + {move,{x,1},{y,-1}}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + + +{function, sum_2, 2, 4}. + {label,3}. + {func_info,{atom,t},{atom,sum_2},2}. + {label,4}. + {allocate,1,2}. + {move,{x,1},{y,0}}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,1024}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + + +{function, sum_3, 2, 6}. + {label,5}. + {func_info,{atom,t},{atom,sum_3},2}. + {label,6}. + {allocate,1,2}. + {move,{x,1},{y,1024}}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + + +{function, sum_4, 2, 8}. + {label,7}. + {func_info,{atom,t},{atom,sum_4},2}. + {label,8}. + {allocate,1,2}. + {move,{x,1},{y,-1}}. + {'%live',1}. + {call,1,{f,10}}. + {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}. + {'%live',1}. + {deallocate,1}. + return. + + +{function, id, 1, 10}. + {label,9}. + {func_info,{atom,t},{atom,id},1}. + {label,10}. + return. diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl new file mode 100644 index 0000000000..a64a5d590b --- /dev/null +++ b/lib/compiler/test/bs_bincomp_SUITE.erl @@ -0,0 +1,297 @@ +%% +%% %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% +%% +%% Originally based on Per Gustafsson's test suite. +%% + +-module(bs_bincomp_SUITE). + +-export([all/1, + byte_aligned/1,bit_aligned/1,extended_byte_aligned/1, + extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1, + nomatch/1,sizes/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [byte_aligned,bit_aligned,extended_byte_aligned, + extended_bit_aligned,mixed,filters,trim_coverage, + nomatch,sizes]. + + +byte_aligned(Config) when is_list(Config) -> + cs_init(), + ?line <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>), + <<1:32/little,2:32/little,3:32/little,4:32/little>> = + cs(<< <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>), + ?line cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>), + cs_end(). + +bit_aligned(Config) when is_list(Config) -> + cs_init(), + ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + cs(<< <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>), + ?line <<"ABCDEFG">> = + cs(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>), + ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + cs(<< <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>), + ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + cs(<< <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>), + cs_end(). + +extended_byte_aligned(Config) when is_list(Config) -> + cs_init(), + ?line <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>), + ?line "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>], + ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> = + cs(<< <<X:32/little>> || X <- [1,2,3,4] >>), + ?line [256,512,768,1024] = + [X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>], + cs_end(). + +extended_bit_aligned(Config) when is_list(Config) -> + cs_init(), + ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + cs(<< <<(X+32):7>> || X <- "ABCDEFG" >>), + ?line "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>], + ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + cs(<< <<X:31/little>> || X <- [1,2,3,4] >>), + ?line [256,512,768,1024] = + [X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>], + cs_end(). + +mixed(Config) when is_list(Config) -> + cs_init(), + ?line <<2,3,3,4,4,5,5,6>> = + cs(<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>), + ?line <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>, + ?line <<2,3,3,4,4,5,5,6>> = + cs(<< <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>), + One = id([1,2,3,4]), + Two = id([1,2]), + ?line <<2,3,3,4,4,5,5,6>> = + cs(<< <<(X+Y)>> || X <- One, Y <- Two >>), + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>], + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]], + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, + <<Y:3>> <= <<1:3,2:3>> >>), + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>), + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + cs(<< <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>), + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + cs_default(<< <<(X+Y):3>> || {X,Y} <- [{1,1},{1,2},{2,1},{2,2}, + {3,1},{3,2},{4,1},{4,2}] >>), + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>], + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, {_,Y} <- [{a,1},{b,2}]], + cs_end(). + +filters(Config) when is_list(Config) -> + cs_init(), + ?line <<"BDF">> = + cs_default(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>, + X rem 2 == 0>>), + ?line <<"abc">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", + is_less_than(X, $D)>>), + ?line <<"efg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", + not is_less_than(X, $E)>>), + ?line <<"b">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", + is_less_than(X, $D), + X rem 2 == 0>>), + ?line <<"eg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", + not is_less_than(X, $E), + X rem 2 == 1>>), + + %% Filtering by a non-matching pattern. + ?line <<"abd">> = cs_default(<< <<X:8>> || + <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8, + 1:1,$e:7,0:4>> >>), + + ?line <<42,42>> = cs_default(<< <<42:8>> || + 42 <- [1,2,3,42,43,42] >>), + cs_end(). + +is_less_than(X, C) when X < C -> true; +is_less_than(_, _) -> false. + +trim_coverage(Config) when is_list(Config) -> + ?line <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}), + ?line <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]), + ?line <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0, + 64,68,0,0,0,0,0,0,192,171,198,0,0,0,0,0>> = + coverage_lightfv(555, 777, {3.0,40.0,-3555.0}), + ok. + +coverage_materialiv(A, B, Params) -> + A = id(A), + B = id(B), + <<(tuple_size(Params)):32, + (<< <<C:32>> || C <- tuple_to_list(Params)>>)/binary, + 0:(((1+tuple_size(Params)) rem 2)*32)>>. + +coverage_lightfv(Light, Pname, Params) -> + id(<<Light:32,Pname:32,(size(Params)):32, + (<< <<C:64/float>> || C <- tuple_to_list(Params)>>)/binary, + 0:(((1+size(Params)) rem 2)*32)>>). + +coverage_trimmer(Params) -> + X = id(0), + Y = id(1), + id({X,Y}), + << <<(begin {A,B,D} = id({C,C,C}), id(0), + coverage_summer(A, B, C, D) end):32/float>> || + C <- Params >>. + +coverage_summer(A, B, C, D) -> A+B+C+D. + +nomatch(Config) when is_list(Config) -> + ?line <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>, + ok. + +sizes(Config) when is_list(Config) -> + ?line cs_init(), + Fun0 = fun(List) -> + cs(<< <<E:8>> || E <- List >>) + end, + ?line <<>> = Fun0([]), + ?line <<1>> = Fun0([1]), + ?line <<1,2>> = Fun0([1,2]), + ?line <<1,2,3>> = Fun0([1,2,3]), + + Fun1 = fun(List) -> + cs(<< <<E:16>> || E <- List >>) + end, + ?line <<>> = Fun1([]), + ?line <<1:16>> = Fun1([1]), + ?line <<1:16,2:16>> = Fun1([1,2]), + ?line <<1:16,2:16,3:16>> = Fun1([1,2,3]), + + Fun2 = fun(List) -> + cs(<< <<E:4>> || E <- List >>) + end, + ?line <<>> = Fun2([]), + ?line <<1:4>> = Fun2([1]), + ?line <<1:4,13:4>> = Fun2([1,13]), + ?line <<1:4,13:4,7:4>> = Fun2([1,13,7]), + ?line <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)), + + Fun3 = fun(List) -> + cs(<< <<E:3>> || E <- List >>) + end, + ?line <<>> = Fun3([]), + ?line <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]), + ?line <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)), + + Fun4 = fun(List, Size) -> + cs(<< <<E:Size>> || E <- List >>) + end, + ?line <<>> = Fun4([], 8), + ?line <<42:6>> = Fun4([42], 6), + ?line <<42:16>> = Fun4([42], 16), + + Fun5 = fun(List, Sz1, Sz2, Sz3) -> + cs(<< <<E:Sz1,(E+1):Sz2/unit:8,(E+2):Sz3/unit:8>> || E <- List >>) + end, + ?line <<>> = Fun5([], 1, 1, 1), + ?line <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7), + + Fun6 = fun(List, Size) -> + cs(<< <<E:8,(E+1):Size>> || E <- List >>) + end, + ?line <<>> = Fun6([], 42), + ?line <<42,43:20>> = Fun6([42], 20), + + %% Binary generators. + + Fun10 = fun(Bin) -> + cs(<< <<E:16>> || <<E:8>> <= Bin >>) + end, + ?line <<>> = Fun10(<<>>), + ?line <<1:16>> = Fun10(<<1>>), + ?line <<1:16,2:16>> = Fun10(<<1,2>>), + + Fun11 = fun(Bin) -> + cs(<< <<E:8>> || <<E:16>> <= Bin >>) + end, + ?line <<>> = Fun11(<<>>), + ?line <<1>> = Fun11(<<1:16>>), + ?line <<1,2>> = Fun11(<<1:16,2:16>>), + ?line <<1,2>> = Fun11(<<1:16,2:16,0:1>>), + ?line <<1,2>> = Fun11(<<1:16,2:16,0:7>>), + ?line <<1,2>> = Fun11(<<1:16,2:16,42:8>>), + ?line <<1,2>> = Fun11(<<1:16,2:16,42:9>>), + ?line <<1,2>> = Fun11(<<1:16,2:16,255:15>>), + + Fun12 = fun(Bin, Sz1, Sz2) -> + cs(<< <<E:Sz1>> || <<E:Sz2>> <= Bin >>) + end, + ?line <<>> = Fun12(<<>>, 1, 1), + ?line Binary = list_to_binary(lists:seq(0, 255)), + ?line Binary = Fun12(Binary, 1, 1), + ?line Binary = Fun12(Binary, 4, 4), + ?line Binary = Fun12(Binary, 8, 8), + ?line <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6), + + Fun13 = fun(Sz) -> + cs_default(<< <<C:8>> || <<C:4>> <= <<1:4,2:4,3:4,0:Sz>> >>) + end, + ?line <<1,2,3>> = Fun13(0), + ?line <<1,2,3,0>> = Fun13(4), + ?line <<1,2,3,0>> = Fun13(5), + ?line <<1,2,3,0>> = Fun13(6), + ?line <<1,2,3,0>> = Fun13(7), + ?line <<1,2,3,0,0>> = Fun13(8), + + ?line {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>), + + ?line cs_end(), + ok. + + + +cs_init() -> + erts_debug:set_internal_state(available_internal_state, true), + ok. + +cs_end() -> + erts_debug:set_internal_state(available_internal_state, false), + ok. + +%% Verify that the allocated size is exact (rounded up to the nearest byte). +cs(Bin) -> + ByteSize = byte_size(Bin), + {refc_binary,ByteSize,{binary,ByteSize},_} = + erts_debug:get_internal_state({binary_info,Bin}), + Bin. + +%% Verify that the allocated size of the binary is the default size. +cs_default(Bin) -> + ByteSize = byte_size(Bin), + {refc_binary,ByteSize,{binary,256},_} = + erts_debug:get_internal_state({binary_info,Bin}), + Bin. + +id(I) -> I. diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl new file mode 100644 index 0000000000..6337460b13 --- /dev/null +++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl @@ -0,0 +1,155 @@ +%% +%% %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% +%% +%% Originally based on Per Gustafsson's test suite. +%% + +-module(bs_bit_binaries_SUITE). + +-export([all/1, + misc/1,horrid_match/1,test_bitstr/1,test_bit_size/1,asymmetric_tests/1, + big_asymmetric_tests/1,binary_to_and_from_list/1, + big_binary_to_and_from_list/1,send_and_receive/1, + send_and_receive_alot/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [misc,horrid_match,test_bitstr,test_bit_size,asymmetric_tests, + big_asymmetric_tests,binary_to_and_from_list,big_binary_to_and_from_list, + send_and_receive,send_and_receive_alot]. + +misc(Config) when is_list(Config) -> + ?line <<1:100>> = <<1:100>>, + ?line {ok,ok} = {match(7),match(9)}, + ?line {ok,ok} = {match1(15),match1(31)}, + ok. + + +match(N) -> + <<0:N>> = <<0:N>>, + ok. + +match1(N) -> + <<42:N/little>> = <<42:N/little>>, + ok. + +test_bit_size(Config) when is_list(Config) -> + ?line 101 = erlang:bit_size(<<1:101>>), + ?line 1001 = erlang:bit_size(<<1:1001>>), + ?line 1001 = erlang:bit_size(<<-10:1001>>), + ?line 80 = erlang:bit_size(<<1:80>>), + ?line 800 = erlang:bit_size(<<1:800>>), + ?line Bin = <<0:16#1000000>>, + ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), + ?line 16#10000001 = erlang:bit_size(BigBin), + %% Only run these on computers with lots of memory + %% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), + %% 16#100000011 = erlang:bit_size(HugeBin), + ?line 0 = erlang:bit_size(<<>>), + ok. + +horrid_match(Config) when is_list(Config) -> + ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>, + ?line <<42:24/little>> = B, + ok. + +test_bitstr(Config) when is_list(Config) -> + ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>, + ?line <<1:1,6>> = B, + ?line B = <<1:1,6>>, + ok. + +asymmetric_tests(Config) when is_list(Config) -> + ?line <<1:12>> = <<0,1:4>>, + ?line <<0,1:4>> = <<1:12>>, + ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>, + ?line <<1,254,0,0:1>> = X, + ?line X = <<1,254,0,0:1>>, + ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>, + ?line <<1,254,0,0:1>> = X1, + ?line X1 = <<1,254,0,0:1>>, + ok. + +big_asymmetric_tests(Config) when is_list(Config) -> + ?line <<1:875,1:12>> = <<1:875,0,1:4>>, + ?line <<1:875,0,1:4>> = <<1:875,1:12>>, + ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>, + ?line <<1,254,0,0:1,1:875>> = X, + ?line X = <<1,254,0,0:1,1:875>>, + ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>, + ?line <<1,254,0,0:1,1:875>> = X1, + ?line X1 = <<1,254,0,0:1,1:875>>, + ok. + +binary_to_and_from_list(Config) when is_list(Config) -> + ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)), + ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>), + ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]), + ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>), + ok. + +big_binary_to_and_from_list(Config) when is_list(Config) -> + ?line <<1:800,2,3,4,1:1>> = + list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)), + ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>), + ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]), + ok. + +send_and_receive(Config) when is_list(Config) -> + ?line Bin = <<1,2:7>>, + Pid = spawn_link(fun() -> receiver(Bin) end), + ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>}, + ?line receive + ok -> + ok + end. + +receiver(Bin) -> + receive + {Pid,<<1:7,8:5,Bin/bitstring>>} -> + Pid ! ok + end. + +send_and_receive_alot(Config) when is_list(Config) -> + Bin = <<1:1000001>>, + Pid = spawn_link(fun() -> receiver_alot(Bin) end), + spamalot(100,Bin,Pid). + +spamalot(N,Bin,Pid) when N > 0 -> + Pid ! {self(),<<1:7,8:5,Bin/bitstring>>}, + receive + ok -> + ok + end, + spamalot(N-1,Bin,Pid); +spamalot(0,_Bin,Pid) -> + Pid ! no_more, + ok. + +receiver_alot(Bin) -> + receive + {Pid,<<1:7,8:5,Bin/bitstring>>} -> + Pid ! ok; + no_more -> ok + end, + receiver_alot(Bin). + + + diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl new file mode 100644 index 0000000000..1862a28bbe --- /dev/null +++ b/lib/compiler/test/bs_construct_SUITE.erl @@ -0,0 +1,499 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% + +%%% While similar to bs_construct_SUITE in the emulator test suite, +%%% this module is more corncerned with testing sizes than the contents +%%% of binaries. + +-module(bs_construct_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + two/1,test1/1,fail/1,float_bin/1,in_guard/1,in_catch/1, + nasty_literals/1,coerce_to_float/1,side_effect/1, + opt/1,otp_7556/1,float_arith/1,otp_8054/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [two,test1,fail,float_bin,in_guard,in_catch,nasty_literals, + side_effect,opt,otp_7556,float_arith,otp_8054]. + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +two(Config) when is_list(Config) -> + <<0,1,2,3,4,6,7,8,9>> = two_1([0], [<<1,2,3,4>>,<<6,7,8,9>>]), + ok. + +two_1(P, L) -> + list_to_binary([P|L]). + + +big(1) -> + 57285702734876389752897683. + +i(X) -> X. + +id(I) -> I. + +-define(T(B, L), {B, ??B, L}). +-define(N(B), {B, ??B, unknown}). + +-define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)). + +l(I_13, I_big1, I_16, Bin) -> + [ + ?T(<<-43>>, + [256-43]), + ?T(<<4:4,7:4>>, + [4*16+7]), + ?T(<<45:I_16/little>>, + [45,0]), + ?T(<<777:16/little>>, + [9,3]), + ?T(<<777:I_13,13:3>>, + [24,77]), + ?T(<<5:4,987:I_13,537:7>>, + [81,237,153]), + ?T(<<0.0:32/float>>, + [0,0,0,0]), + ?T(<<0.125:32/float>>, + [62,0,0,0]), + ?T(<<1.0:32/little-float>>, + [0,0,128,63]), + ?T(<<I_big1:32>>, + [138,99,0,147]), + ?T(<<57285702734876389752897684:(I_16+16)>>, + [138,99,0,148]), + ?T(<<-1:17/unit:8>>, + lists:duplicate(17, 255)), + ?T(<<-1:8/unit:17>>, + lists:duplicate(17, 255)), + ?T(<<4:(I_16-8)/unit:2,5:2/unit:8>>, + [0,4,0,5]), + ?T(<<1:1, 0:(I_13-7), 1:1>>, + [129]), + ?T(<<1:3,"string",9:5>>, + [46,110,142,77,45,204,233]), + ?T(<<37.98:64/native-float>>, + native_3798()), + ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>, + native_bignum()), + + ?T(<<Bin/binary>>, + [165,90,195]), + ?T(<<79,Bin/binary>>, + [79,165,90,195]), + ?T(<<3479:I_13,Bin/binary,7:3>>, + [108,189,42,214,31]), + ?T(<<3479:I_13,Bin/binary,7:1/unit:3>>, + [108,189,42,214,31]), + ?T(<<869:16/little,3479:I_13,Bin/binary,7:1/unit:3>>, + [101,3,108,189,42,214,31]), + ?T(<<869:16/little,3479:I_13,Bin/binary,7:1/unit:3,Bin/binary>>, + [101,3,108,189,42,214,31,165,90,195]), + + %% Test of aligment flag. + ?T(<<0:I_13/unit:8,1:6,0:2>>, + [0,0,0,0,0,0,0,0,0,0,0,0,0,4]), + + %% Test of literals (coverage). + ?T(<<0:128>>,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + ?T(<<0:13/little,7:3>>,[0,7]), + ?T(<<16#77FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:264>>, + [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + 16#77,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF, + 16#FF,16#FF,16#FF,16#FF,16#FF,16#FF]), + + %% Mix different units. + ?T(<<37558955:(I_16-12)/unit:8,1:1>>, + [2,61,26,171,<<1:1>>]) + ]. + +native_3798() -> + case <<1:16/native>> of + <<0,1>> -> [64,66,253,112,163,215,10,61]; + <<1,0>> -> [61,10,215,163,112,253,66,64] + end. + +native_bignum() -> + case <<1:16/native>> of + <<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217]; + <<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129] + end. + +evaluate(Str, Vars) -> + {ok,Tokens,_} = + erl_scan:string(Str ++ " . "), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + case erl_eval:expr(Expr, Vars) of + {value, Result, _} -> + Result + end. + +eval_list([], _Vars) -> + []; +eval_list([{C_bin, Str, Bytes} | Rest], Vars) -> + case catch evaluate(Str, Vars) of + {'EXIT', Error} -> + io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]), + exit(Error); + E_bin -> + [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)] + end. + +one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) -> + io:format(" ~s, ~p~n", [Str, Bytes]), + Bin = list_to_bitstring(Bytes), + if + C_bin == Bin -> + ok; + true -> + io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", + [Str, Bytes, bitstring_to_list(C_bin)]), + test_server:fail(comp) + end, + if + E_bin == Bin -> + ok; + true -> + io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", + [Str, Bytes, bitstring_to_list(E_bin)]), + test_server:fail(comp) + end; +one_test({C_bin, E_bin, Str, Result}) -> + io:format(" ~s ~p~n", [Str, C_bin]), + if + C_bin == E_bin -> + ok; + true -> + Arbitrary = case Result of + unknown -> + size(C_bin); + _ -> + Result + end, + case equal_lists(bitstring_to_list(C_bin), + bitstring_to_list(E_bin), + Arbitrary) of + false -> + io:format("ERROR: Compiled not equal to interpreted:" + "~n ~p, ~p.~n", + [bitstring_to_list(C_bin), bitstring_to_list(E_bin)]), + test_server:fail(comp); + 0 -> + ok; + %% For situations where the final bits may not matter, like + %% for floats: + N when integer(N) -> + io:format("Info: compiled and interpreted differ in the" + " last bytes:~n ~p, ~p.~n", + [bitstring_to_list(C_bin), bitstring_to_list(E_bin)]), + ok + end + end. + +equal_lists([], [], _) -> + 0; +equal_lists([], _, _) -> + false; +equal_lists(_, [], _) -> + false; +equal_lists([A|AR], [A|BR], R) -> + equal_lists(AR, BR, R); +equal_lists(A, B, R) -> + if + length(A) /= length(B) -> + false; + length(A) =< R -> + R; + true -> + false + end. + +test1(Config) when is_list(Config) -> + ?line I_13 = i(13), + ?line I_big1 = big(1), + ?line I_16 = i(16), + ?line Bin = i(<<16#A5,16#5A,16#C3>>), + ?line Vars = lists:sort([{'I_13',I_13}, + {'I_big1',I_big1}, + {'I_16',I_16}, + {'Bin',Bin}]), + ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1, I_16, Bin), Vars)). + +fail(Config) when is_list(Config) -> + I_minus_777 = i(-777), + I_minus_2047 = i(-2047), + + %% One negative field size, but the sum of field sizes will be 1 byte. + %% Make sure that we reject that properly. + + ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8, + 57:I_minus_2047/unit:8>>), + + %% Same thing, but use literals. + ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8, + 57:(-2047)/unit:8>>), + + %% Not numbers. + ?line {'EXIT',{badarg,_}} = (catch <<45:(i(not_a_number))>>), + ?line {'EXIT',{badarg,_}} = (catch <<13:8,45:(i(not_a_number))>>), + + %% Unaligned sizes. + BadSz = i(7), + Bitstr = i(<<42:17>>), + + ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:4/binary>>), + ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:BadSz/binary>>), + + ?line [] = [X || {X} <- [], X == <<Bitstr:BadSz/binary>>], + ?line [] = [X || {X} <- [], X == <<Bitstr:4/binary>>], + + %% Literals with incorrect type. + ?line {'EXIT',{badarg,_}} = (catch <<42.0/integer>>), + ?line {'EXIT',{badarg,_}} = (catch <<42/binary>>), + ?line {'EXIT',{badarg,_}} = (catch <<an_atom/integer>>), + + ok. + +float_bin(Config) when is_list(Config) -> + %% Some more coverage. + ?line {<<1,2,3>>,7.0} = float_bin_1(4), + F = 42.0, + ?line <<42,0,0,0,0,0,0,69,64>> = <<(id(42)),F/little-float>>, + ok. + +float_bin_1(F) -> + {<<1,2,3>>,F+3.0}. + +in_guard(Config) when is_list(Config) -> + ?line 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5), + ?line 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), + ?line 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), + ?line nope = in_guard_1(<<1>>, 42, b), + ?line nope = in_guard_1(<<1>>, a, b), + ?line nope = in_guard_1(<<1,2>>, 1, 1), + ?line nope = in_guard_1(<<4,5>>, 1, 2.71), + ?line nope = in_guard_1(<<4,5>>, 1, <<12,13>>), + + ?line 1 = in_guard_2(<<0,56>>, 7, blurf), + ?line 2 = in_guard_2(<<1,255>>, 511, blurf), + ?line 3 = in_guard_2(<<0,3>>, 0, blurf), + ?line 4 = in_guard_2(<<>>, 1, {<<7:16>>}), + ?line nope = in_guard_2(<<4,5>>, 1, blurf), + + ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>), + ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>), + ?line nope = in_guard_3(<<>>, <<>>), + + ?line ok = in_guard_4(<<15:4>>, 255), + ?line nope = in_guard_4(<<15:8>>, 255), + ok. + +in_guard_1(Bin, A, B) when <<A:13,B:3>> == Bin -> 1; +in_guard_1(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2; +in_guard_1(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3; +in_guard_1(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen; +in_guard_1(_, _, _) -> nope. + +in_guard_2(Bin, A, _T) when <<A:13,0:3>> == Bin -> 1; +in_guard_2(Bin, A, _T) when <<A:16>> == Bin -> 2; +in_guard_2(Bin, A, _T) when <<A:14,3:2>> == Bin -> 3; +in_guard_2(_Bin, A, T) when {A,b} > {0,1}, {<<A:14,3:2>>} == T -> 4; +in_guard_2(_, _, _) -> nope. + +in_guard_3(Bin, A) when <<A/binary,42>> =:= Bin -> 42; +in_guard_3(_, _) -> nope. + +in_guard_4(Bin, A) when <<A:4>> =:= Bin -> ok; +in_guard_4(_, _) -> nope. + +in_catch(Config) when is_list(Config) -> + ?line <<42,0,5>> = small(42, 5), + ?line <<255>> = small(255, <<1,2,3,4,5,6,7,8,9>>), + ?line <<1,2>> = small(<<7,8,9,10>>, 258), + ?line <<>> = small(<<1,2,3,4,5>>, <<7,8,9,10>>), + ok. + +small(A, B) -> + case begin + case catch <<A:8>> of + {'EXIT',_} -> <<>>; + ResA0 -> ResA0 + end + end of + ResA -> ok + end, + case begin + case catch <<B:16>> of + {'EXIT',_} -> <<>>; + ResB0 -> ResB0 + end + end of + ResB -> ok + end, + <<ResA/binary,ResB/binary>>. + +nasty_literals(Config) when is_list(Config) -> + case erlang:system_info(endian) of + big -> + ?line [0,42] = binary_to_list(id(<<42:16/native>>)); + little -> + ?line [42,0] = binary_to_list(id(<<42:16/native>>)) + end, + + ?line Bin0 = id(<<1,2,3,0:10000000,4,5,6>>), + ?line 1250006 = size(Bin0), + ?line <<1,2,3,0:10000000,4,5,6>> = Bin0, + + ?line Bin1 = id(<<0:10000000,7,8,-1:10000000,9,10,0:10000000>>), + ?line 3750004 = size(Bin1), + ?line <<0:10000000,7,8,-1:10000000/signed,9,10,0:10000000>> = Bin1, + + ?line <<255,255,0,0,0>> = id(<<255,255,0,0,0>>), + + %% Coverage. + I = 16#7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF, + id(<<I:260>>), + + ok. + +-define(COF(Int0), + ?line (fun(Int) -> + true = <<Int:32/float>> =:= <<(float(Int)):32/float>>, + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>, + ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + +-define(COF64(Int0), + ?line (fun(Int) -> + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + +nonliteral(X) -> X. + +coerce_to_float(Config) when is_list(Config) -> + ?COF(0), + ?COF(-1), + ?COF(1), + ?COF(42), + ?COF(255), + ?COF(-255), + ?COF(38474), + ?COF(387498738948729893849444444443), + ?COF(-37489378937773899999999999999993), + ?COF64(298748888888888888888888888883478264866528467367364766666666666666663), + ?COF64(-367546729879999999999947826486652846736736476555566666663), + ok. + +side_effect(Config) when is_list(Config) -> + {'EXIT',{badarg,_}} = (catch side_effect_1(a)), + {'EXIT',{badarg,_}} = (catch side_effect_1(<<>>)), + ?line ok = side_effect_1(42), + ok. + +side_effect_1(A) -> + <<A:17>>, %Warning intentional. + ok. + +-record(otp_7029, {a,b}). + +opt(Config) when is_list(Config) -> + ?line 42 = otp_7029(#otp_7029{a = <<>>,b = 42}), + N = 16, + ?line <<1,3,65>> = id(<<1,833:N>>), + ?line <<1,66,3>> = id(<<1,834:N/little>>), + ?line <<1,65,136,0,0>> = id(<<1,17.0:32/float>>), + ?line <<1,64,8,0,0,0,0,0,0>> = id(<<1,3.0:N/float-unit:4>>), + ?line <<1,0,0,0,0,0,0,8,64>> = id(<<1,3.0:N/little-float-unit:4>>), + ?line {'EXIT',{badarg,_}} = (catch id(<<3.1416:N/float>>)), + + B = <<1,2,3,4,5>>, + ?line <<0,1,2,3,4,5>> = id(<<0,B/binary>>), + ?line <<1,2,3,4,5,19>> = id(<<B:5/binary,19>>), + ?line <<1,2,3,42>> = id(<<B:3/binary,42>>), + + ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(2.5)/binary>>), + ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(-16)/binary>>), + ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(anka)>>), + ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>), + ?line {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>), + + case id(false) of + true -> ?line opt_dont_call_me(); + false -> ok + end, + + ok. + +opt_dont_call_me() -> + N = 16#12345678, + <<0:N>>. + +otp_7029(R) -> + #otp_7029{a = <<>>} = R, + R#otp_7029.b. + +otp_7556(Config) when is_list(Config) -> + [otp_7556(<<>>, 1024, 1024, 1024) || _ <- lists:seq(0, 1023)], + ok. + +otp_7556(Bin, A, B, C) -> + %% When allocating the binary, the sizes 16*A and 16*A would + %% be forgotten. + <<Bin/binary,(-1):A/unit:16,0:B/unit:16,(-1):C/unit:16>>. + +%% Test binary construction combined with floating point operations +%% (mostly to cover code in beam_flatten that combines the allocation +%% for a binary construction with a later allocation). + +float_arith(Config) when is_list(Config) -> + ?line {<<1,2,3,64,69,0,0,0,0,0,0>>,21.0} = do_float_arith(<<1,2,3>>, 42, 2), + ok. + +do_float_arith(Bin0, X, Y) -> + Bin = <<Bin0/binary,X/float>>, + {Bin,X / Y}. + +otp_8054(Config) when is_list(Config) -> + ?line <<"abc">> = otp_8054_1([null,1,2,3], <<"abc">>), + ok. + +otp_8054_1([H|T], Bin) -> + _ = case H of + null -> + %% The beam_validator would complain about {x,3} + %% not being live in bs_append/8 because of a live + %% optimization bug. + <<Bin/binary>>; + _ -> + ok + end, + otp_8054_1(T, Bin); +otp_8054_1([], Bin) -> Bin. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl new file mode 100644 index 0000000000..5c2797170b --- /dev/null +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -0,0 +1,991 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(bs_match_SUITE). +-compile(nowarn_shadow_vars). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + fun_shadow/1,int_float/1,otp_5269/1,null_fields/1,wiger/1, + bin_tail/1,save_restore/1,shadowed_size_var/1, + partitioned_bs_match/1,function_clause/1, + unit/1,shared_sub_bins/1,bin_and_float/1, + dec_subidentifiers/1,skip_optional_tag/1, + wfbm/1,degenerated_match/1,bs_sum/1,coverage/1, + multiple_uses/1,zero_label/1,followed_by_catch/1, + matching_meets_construction/1,simon/1,matching_and_andalso/1, + otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1, + match_string/1,zero_width/1,bad_size/1,haystack/1]). + +-export([coverage_id/1]). + +-include("test_server.hrl"). + + +all(suite) -> + test_lib:recompile(?MODULE), + [fun_shadow,int_float,otp_5269,null_fields,wiger,bin_tail,save_restore, + shadowed_size_var,partitioned_bs_match,function_clause,unit, + shared_sub_bins,bin_and_float,dec_subidentifiers,skip_optional_tag, + wfbm,degenerated_match,bs_sum,coverage,multiple_uses,zero_label, + followed_by_catch,matching_meets_construction,simon,matching_and_andalso, + otp_7188,otp_7233,otp_7240,otp_7498,match_string,zero_width,bad_size, + haystack]. + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +fun_shadow(Config) when is_list(Config) -> + %% OTP-5270 + ?line 7 = fun_shadow_1(), + ?line 7 = fun_shadow_2(8), + ?line 7 = fun_shadow_3(), + ?line no = fun_shadow_4(8), + ok. + +fun_shadow_1() -> + L = 8, + F = fun(<<L:L,B:L>>) -> B end, + F(<<16:8, 7:16>>). + +fun_shadow_2(L) -> + F = fun(<<L:L,B:L>>) -> B end, + F(<<16:8, 7:16>>). + +fun_shadow_3() -> + L = 8, + F = fun(<<L:L,B:L,L:L>>) -> B end, + F(<<16:8, 7:16,16:16>>). + +fun_shadow_4(L) -> + F = fun(<<L:L,B:L,L:L>>) -> B; + (_) -> no end, + F(<<16:8, 7:16,15:16>>). + +int_float(Config) when is_list(Config) -> + %% OTP-5323 + ?line <<103133.0:64/float>> = <<103133:64/float>>, + ?line <<103133:64/float>> = <<103133:64/float>>, + ok. + +%% Stolen from erl_eval_SUITE and modified. +%% OTP-5269. Bugs in the bit syntax. +otp_5269(Config) when is_list(Config) -> + ?line check(fun() -> L = 8, + F = fun(<<A:L,B:A>>) -> B end, + F(<<16:8, 7:16>>) + end, + 7), + ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, + 7), + ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, + 32), + ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, + [32]), + ?line check(fun() -> [X || <<A:8, + B:A>> <- [<<16:8,19:16>>], + <<X:8>> <- [<<B:8>>]] end, + [19]), + ?line check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end, + 28), + ?line check(fun() -> + <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, + {Size,B,Rest} + end, + {2,<<"AB">>,<<"CD">>}), + ?line check(fun() -> X = 32, + [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, + %% "binsize variable" ^ + [1,2]), + + ok. + +null_fields(Config) when is_list(Config) -> + ?line check(fun() -> + W = id(0), + F = fun(<<_:W>>) -> tail; + (<<>>) -> empty + end, + F(<<>>) + end, tail), + ?line check(fun() -> + F = fun(<<_/binary>>) -> tail; + (<<>>) -> empty + end, + F(<<>>) + end, tail), + ok. + +wiger(Config) when is_list(Config) -> + ?line ok1 = wcheck(<<3>>), + ?line ok2 = wcheck(<<1,2,3>>), + ?line ok3 = wcheck(<<4>>), + ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), + ?line {error,<<>>} = wcheck(<<>>), + ok. + +wcheck(<<A>>) when A==3-> + ok1; +wcheck(<<_,_:2/binary>>) -> + ok2; +wcheck(<<_>>) -> + ok3; +wcheck(Other) -> + {error,Other}. + +bin_tail(Config) when is_list(Config) -> + S = <<"abcde">>, + ?line $a = bin_tail_c(S, 0), + ?line $c = bin_tail_c(S, 2), + ?line $e = bin_tail_c(S, 4), + ?line {'EXIT',_} = (catch bin_tail_c(S, 5)), + ?line {'EXIT',_} = (catch bin_tail_c_var(S, 5)), + + ?line $a = bin_tail_d(S, 0), + ?line $b = bin_tail_d(S, 8), + ?line $d = bin_tail_d(S, 3*8), + ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 1)), + ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 9)), + ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)), + ?line {'EXIT',_} = (catch bin_tail_d_var(S, 1)), + + ?line ok = bin_tail_e(<<2:2,0:1,1:5>>), + ?line ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>), + ?line error = bin_tail_e(<<3:2,1:1,1:5,42:64>>), + ?line error = bin_tail_e(<<>>), + ok. + +bin_tail_c(Bin, Offset) -> + Res = bin_tail_c_dead(Bin, Offset), + <<_:Offset/binary,_,Tail/binary>> = Bin, + {Res,Tail} = bin_tail_c_var(Bin, Offset), + Res. + +bin_tail_c_dead(Bin, Offset) -> + <<_:Offset/binary,C,_/binary>> = Bin, + C. + +bin_tail_c_var(Bin, Offset) -> + <<_:Offset/binary,C,Tail/binary>> = Bin, + {C,Tail}. + + +bin_tail_d(Bin, BitOffset) -> + Res = bin_tail_d_dead(Bin, BitOffset), + <<_:BitOffset,_:8,Tail/binary>> = Bin, + {Res,Tail} = bin_tail_d_var(Bin, BitOffset), + Res. + +bin_tail_d_dead(Bin, BitOffset) -> + <<_:BitOffset,C,_/binary>> = Bin, + C. + +bin_tail_d_var(Bin, BitOffset) -> + <<_:BitOffset,C,Tail/binary>> = Bin, + {C,Tail}. + +bin_tail_e(Bin) -> + case bin_tail_e_dead(Bin) of + ok -> + <<_,Tail/binary>> = Bin, + Tail = bin_tail_e_var(Bin), + ok; + error -> + bin_tail_e_var(Bin) + end. + +bin_tail_e_dead(Bin) -> + case Bin of + %% The binary is aligned at the end; neither the bs_skip_bits2 nor + %% bs_test_tail2 instructions are needed. + <<2:2,_:1,1:5,_/binary>> -> ok; + _ -> error + end. + +bin_tail_e_var(Bin) -> + case Bin of + %% The binary is aligned at the end; neither the bs_skip_bits2 nor + %% bs_test_tail2 instructions are needed. + <<2:2,_:1,1:5,Tail/binary>> -> Tail; + _ -> error + end. + +save_restore(Config) when is_list(Config) -> + ?line 0 = save_restore_1(<<0:2,42:6>>), + ?line {1,3456} = save_restore_1(<<1:2,3456:14>>), + ?line {2,7981234} = save_restore_1(<<2:2,7981234:30>>), + ?line {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>), + + A = <<" x">>, + B = <<".x">>, + C = <<"-x">>, + + ?line {" ",<<"x">>} = lll(A), + ?line {" ",<<"x">>} = mmm(A), + ?line {" ",<<"x">>} = nnn(A), + ?line {" ",<<"x">>} = ooo(A), + + ?line {".",<<"x">>} = lll(B), + ?line {".",<<"x">>} = mmm(B), + ?line {".",<<"x">>} = nnn(B), + ?line {".",<<"x">>} = ooo(B), + + ?line {"-",<<"x">>} = lll(C), + ?line {"-",<<"x">>} = mmm(C), + ?line {"-",<<"x">>} = nnn(C), + ?line {"-",<<"x">>} = ooo(C), + + Bin = <<-1:64>>, + case bad_float_unpack_match(Bin) of + -1 -> ok; + _Other -> ?line ?t:fail(bad_return_value_probably_NaN) + end. + +save_restore_1(Bin) -> + case Bin of + <<0:2,_:6>> -> 0; + <<1:2,A:14>> -> {1,A}; + <<2:2,A:30>> -> {2,A}; + <<A:64>> -> {3,A} + end. + +lll(<<Char, Tail/binary>>) -> {[Char],Tail}. + +mmm(<<$.,$.,$., Tail/binary>>) -> Tail; +mmm(<<$\s,$-,$\s, Tail/binary>>) -> Tail; +mmm(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail! + +nnn(<<"...", Tail/binary>>) -> Tail; +nnn(<<" - ", Tail/binary>>) -> Tail; +nnn(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail! + +ooo(<<" - ", Tail/binary>>) -> Tail; +ooo(<<Char, Tail/binary>>) -> {[Char],Tail}. + +bad_float_unpack_match(<<F:64/float>>) -> F; +bad_float_unpack_match(<<I:64/integer-signed>>) -> I. + + +shadowed_size_var(Config) when is_list(Config) -> + ?line PrivDir = ?config(priv_dir, Config), + ?line Dir = filename:dirname(code:which(?MODULE)), + ?line Core = filename:join(Dir, "bs_shadowed_size_var"), + ?line Opts = [from_core,{outdir,PrivDir}|test_lib:opt_opts(?MODULE)], + ?line io:format("~p", [Opts]), + ?line {ok,Mod} = c:c(Core, Opts), + ?line [42|<<"abcde">>] = Mod:filter_essentials([<<42:32>>|<<5:32,"abcde">>]), + ok. + +partitioned_bs_match(Config) when is_list(Config) -> + ?line <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>), + ?line error = partitioned_bs_match(10, <<7,8,15,13>>), + ?line error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}), + ?line ok = partitioned_bs_match(0, <<>>), + ?line {'EXIT',{function_clause,[{?MODULE,partitioned_bs_match,[-1,blurf]}|_]}} = + (catch partitioned_bs_match(-1, blurf)), + ?line {'EXIT',{function_clause,[{?MODULE,partitioned_bs_match,[-1,<<1,2,3>>]}|_]}} = + (catch partitioned_bs_match(-1, <<1,2,3>>)), + + ?line {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>), + ?line {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>), + ?line {'EXIT',{function_clause,[{?MODULE,partitioned_bs_match_2,[4,<<0:17>>]}|_]}} = + (catch partitioned_bs_match_2(4, <<0:17>>)), + ok. + +partitioned_bs_match(_, <<42:8,T/binary>>) -> + T; +partitioned_bs_match(N, _) when N > 0 -> + error; +partitioned_bs_match(_, <<>>) -> + ok. + +partitioned_bs_match_2(1, <<B:8,T/binary>>) -> + {B,T}; +partitioned_bs_match_2(Len, <<_:8,T/binary>>) -> + {Len,T}. + +function_clause(Config) when is_list(Config) -> + ?line ok = function_clause_1(<<0,7,0,7,42>>), + ?line {'EXIT',{function_clause, + [{?MODULE,function_clause_1,[<<0,1,2,3>>]}|_]}} = + (catch function_clause_1(<<0,1,2,3>>)), + ?line {'EXIT',{function_clause, + [{?MODULE,function_clause_1,[<<0,1,2,3>>]}|_]}} = + (catch function_clause_1(<<0,7,0,1,2,3>>)), + ok. + +function_clause_1(<<0:8,7:8,T/binary>>) -> + function_clause_1(T); +function_clause_1(<<_:8>>) -> + ok. + +unit(Config) when is_list(Config) -> + ?line 42 = peek1(<<42>>), + ?line 43 = peek1(<<43,1,2>>), + ?line 43 = peek1(<<43,1,2,(-1):1>>), + ?line 43 = peek1(<<43,1,2,(-1):2>>), + ?line 43 = peek1(<<43,1,2,(-1):7>>), + + ?line 99 = peek8(<<99>>), + ?line 100 = peek8(<<100,101>>), + ?line {'EXIT',{function_clause,[{?MODULE,peek8,[<<100,101,0:1>>]}|_]}} = + (catch peek8(<<100,101,0:1>>)), + + ?line 37484 = peek16(<<37484:16>>), + ?line 37489 = peek16(<<37489:16,5566:16>>), + ?line {'EXIT',{function_clause,[{?MODULE,peek16,[<<8>>]}|_]}} = + (catch peek16(<<8>>)), + ?line {'EXIT',{function_clause,[{?MODULE,peek16,[<<42:15>>]}|_]}} = + (catch peek16(<<42:15>>)), + ?line {'EXIT',{function_clause,[{?MODULE,peek16,[<<1,2,3,4,5>>]}|_]}} = + (catch peek16(<<1,2,3,4,5>>)), + + ?line 127 = peek7(<<127:7>>), + ?line 100 = peek7(<<100:7,19:7>>), + ?line {'EXIT',{function_clause,[{?MODULE,peek7,[<<1,2>>]}|_]}} = + (catch peek7(<<1,2>>)), + ok. + +peek1(<<B:8,_/bitstring>>) -> B. + +peek7(<<B:7,_/binary-unit:7>>) -> B. + +peek8(<<B:8,_/binary>>) -> B. + +peek16(<<B:16,_/binary-unit:16>>) -> B. + +shared_sub_bins(Config) when is_list(Config) -> + ?line {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0), + ok. + +sum(<<B,T/binary>>, Acc, Sum) -> + sum(T, [T|Acc], Sum+B); +sum(<<>>, Last, Sum) -> {Sum,Last}. + + +bin_and_float(Config) when is_list(Config) -> + ?line 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0), + ok. + +bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X), + is_float(Y), + is_float(Z) -> + bin_and_float(T, Sum+X*X+Y*Y+Z*Z); +bin_and_float(<<>>, Sum) -> Sum. + +dec_subidentifiers(Config) when is_list(Config) -> + ?line {[],<<1,2,3>>} = + do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2), + ?line {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2), + ?line {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0), + ok. + +do_dec_subidentifiers(Buffer, Av, Al, Len) -> + Res = dec_subidentifiers(Buffer, Av, Al, Len), + Res = dec_subidentifiers2(Buffer, Av, Al, Len), + Res = dec_subidentifiers4(Buffer, Av, Al, Len), + Res = dec_subidentifiers3(Buffer, Av, Al, Len). + +dec_subidentifiers(Buffer, _Av, Al, 0) -> + {lists:reverse(Al),Buffer}; +dec_subidentifiers(<<1:1,H:7,T/binary>>, Av, Al, Len) -> + dec_subidentifiers(T, (Av bsl 7) bor H, Al, Len-1); +dec_subidentifiers(<<H,T/binary>>, Av, Al, Len) -> + dec_subidentifiers(T, 0, [((Av bsl 7) bor H)|Al], Len-1). + +dec_subidentifiers2(<<Buffer/binary>>, _Av, Al, 0) -> + {lists:reverse(Al),Buffer}; +dec_subidentifiers2(<<1:1,H:7,T/binary>>, Av, Al, Len) -> + dec_subidentifiers2(T, (Av bsl 7) bor H, Al, Len-1); +dec_subidentifiers2(<<H,T/binary>>, Av, Al, Len) -> + dec_subidentifiers2(T, 0, [((Av bsl 7) bor H)|Al], Len-1). + +dec_subidentifiers3(Buffer, _Av, Al, 0) when is_binary(Buffer) -> + {lists:reverse(Al),Buffer}; +dec_subidentifiers3(<<1:1,H:7,T/binary>>, Av, Al, Len) -> + dec_subidentifiers3(T, (Av bsl 7) bor H, Al, Len-1); +dec_subidentifiers3(<<H,T/binary>>, Av, Al, Len) -> + dec_subidentifiers3(T, 0, [((Av bsl 7) bor H)|Al], Len-1). + +dec_subidentifiers4(<<1:1,H:7,T/binary>>, Av, Al, Len) when Len =/= 0 -> + dec_subidentifiers4(T, (Av bsl 7) bor H, Al, Len-1); +dec_subidentifiers4(<<H,T/binary>>, Av, Al, Len) when Len =/= 0 -> + dec_subidentifiers4(T, 0, [((Av bsl 7) bor H)|Al], Len-1); +dec_subidentifiers4(Buffer, _Av, Al, 0) -> + {lists:reverse(Al),Buffer}. + + +skip_optional_tag(Config) when is_list(Config) -> + {ok,<<>>} = skip_optional_tag(<<42>>, <<42>>), + {ok,<<>>} = skip_optional_tag(<<42,1>>, <<42,1>>), + {ok,<<1,2,3>>} = skip_optional_tag(<<42>>, <<42,1,2,3>>), + missing = skip_optional_tag(<<2:3>>, blurf), + ok. + +skip_optional_tag(<<>>, Binary) -> + {ok,Binary}; +skip_optional_tag(<<Tag,RestTag/binary>>, <<Tag,Rest/binary>>) -> + skip_optional_tag(RestTag, Rest); +skip_optional_tag(_, _) -> missing. + +-define(DATELEN, 16). + +wfbm(Config) when is_list(Config) -> + %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski, + %% with modifications. + ?line {nomatch,0} = check_for_dot_or_space(<<" ">>), + ?line {nomatch,0} = check_for_dot_or_space(<<" abc">>), + ?line {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>), + ?line {nomatch,0} = check_for_dot_or_space(<<".gurka">>), + ?line {nomatch,1} = check_for_dot_or_space(<<"g.urka">>), + + ?line nomatch = get_tail(<<>>), + ?line {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>), + ?line {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>), + ?line nomatch = get_tail(<<"200y.2007.10.23.blurf ">>), + ?line {'EXIT',_} = (catch get_tail({no,binary,at,all})), + ?line {'EXIT',_} = (catch get_tail(no_binary)), + ok. + +check_for_dot_or_space(Bin) -> + check_for_dot_or_space(Bin, 0). + +check_for_dot_or_space(<<$\s, _/binary>>, 0) -> + {nomatch,0}; +check_for_dot_or_space(Bin, Len) -> + case Bin of + <<Front:Len/binary, $\s, _/binary>> -> + {ok,Front}; + <<_:Len/binary, $., _/binary>> -> + {nomatch,Len}; + _ -> + check_for_dot_or_space(Bin, Len+1) + end. + +get_tail(<<>>) -> + nomatch; +get_tail(Bin) -> + <<Front:?DATELEN/binary, Tail/binary>> = Bin, + case Front of + <<_:3/binary,"x/",Y:4/binary,$/,M:2/binary,$/,D:2/binary,$/>> -> + case check_for_dot_or_space(Tail) of + {ok,Match} -> + {ok,<<Y/binary,$/,M/binary,$/,D/binary,$/, Match/binary>>}; + {nomatch,Skip} -> {skip,?DATELEN + Skip} + end; + _ -> nomatch + end. + +degenerated_match(Config) when is_list(Config) -> + ?line error = degenerated_match_1(<<>>), + ?line 1 = degenerated_match_1(<<1:1>>), + ?line 2 = degenerated_match_1(<<42,43>>), + + ?line error = degenerated_match_2(<<>>), + ?line no_split = degenerated_match_2(<<1,2>>), + ?line {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>), + + ok. + +degenerated_match_1(<<>>) -> error; +degenerated_match_1(Bin) -> byte_size(Bin). + +degenerated_match_2(<<>>) -> error; +degenerated_match_2(Bin) -> + case byte_size(Bin) > 4 of + true -> + split_binary(Bin, 4); + false -> + no_split + end. + +bs_sum(Config) when is_list(Config) -> + ?line 0 = bs_sum_1([]), + ?line 0 = bs_sum_1(<<>>), + ?line 42 = bs_sum_1([42]), + ?line 1 = bs_sum_1(<<1>>), + ?line 10 = bs_sum_1([1,2,3,4]), + ?line 15 = bs_sum_1(<<1,2,3,4,5>>), + ?line 21 = bs_sum_1([1,2,3|<<4,5,6>>]), + ?line 15 = bs_sum_1([1,2,3|{4,5}]), + ?line 6 = bs_sum_1([1,2,3|zero]), + ?line 6 = bs_sum_1([1,2,3|0]), + ?line 7 = bs_sum_1([1,2,3|one]), + + ?line {'EXIT',{function_clause,_}} = (catch bs_sum_1({too,big,tuple})), + ?line {'EXIT',{function_clause,_}} = (catch bs_sum_1([1,2,3|{too,big,tuple}])), + + ?line [] = sneaky_alias(<<>>), + ?line [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)), + ?line {'EXIT',{function_clause,[{?MODULE,sneaky_alias,[<<1>>]}|_]}} = + (catch sneaky_alias(id(<<1>>))), + ?line {'EXIT',{function_clause,[{?MODULE,sneaky_alias,[[1,2,3,4]]}|_]}} = + (catch sneaky_alias(lists:seq(1, 4))), + ok. + +bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T); +bs_sum_1([H|T]) -> H+bs_sum_1(T); +bs_sum_1({A,B}=_Tuple=_AliasForNoGoodReason) -> A+B; +bs_sum_1(0) -> 0; +bs_sum_1(zero=_Zero) -> 0; +bs_sum_1(one) -> 1; +bs_sum_1([]) -> 0; +bs_sum_1(<<>>) -> 0. + +sneaky_alias(<<>>=L) -> binary_to_list(L); +sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)]. + +coverage(Config) when is_list(Config) -> + ?line 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>), + ?line 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>), + ?line {'EXIT',{function_clause,_}} = (catch coverage_fold(fun(B, A) -> + A+B + end, 0, [a,b,c])), + + ?line {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple), + ?line {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} = + coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}), + + ?line {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}), + + ?line [42] = coverage_apply(<<42>>, [coverage_id]), + + ?line do_coverage_bin_to_term_list([]), + ?line do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]), + ?line {'EXIT',{function_clause, + [{?MODULE,coverage_bin_to_term_list,[<<0,0,0,7>>]}|_]}} = + (catch do_coverage_bin_to_term_list_1(<<7:32>>)), + + ?line <<>> = coverage_per_key(<<4:32>>), + ?line <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>), + + ok. + +coverage_fold(Fun, Acc, <<H,T/binary>>) -> + IdFun = fun id/1, + coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T); +coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc. + +coverage_build(Acc0, <<H,T/binary>>, Tuple0) -> + Str = id(<<H:(id(4)),(H-1):4,"abc">>), + Acc = id(<<Acc0/bitstring,Str/bitstring>>), + Tuple = setelement(2, setelement(3, Tuple0, 43), 42), + if + byte_size(Acc) > 0 -> + coverage_build(Acc, T, Tuple) + end; +coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}. + +coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x -> + setelement(H, Tuple, T1). + +coverage_apply(<<H,T/binary>>, [F|Fs]) -> + [?MODULE:F(H)|coverage_apply(T, Fs)]; +coverage_apply(<<>>, []) -> []. + +coverage_id(I) -> id(I). + +do_coverage_bin_to_term_list(L) -> + Bin = << <<(begin BinTerm = term_to_binary(Term), + <<(byte_size(BinTerm)):32,BinTerm/binary>> end)/binary>> || + Term <- L >>, + L = do_coverage_bin_to_term_list_1(Bin), + L = do_coverage_bin_to_term_list_1(<<Bin/binary,7:32,"garbage">>), + L = do_coverage_bin_to_term_list_1(<<7:32,"garbage",Bin/binary>>). + +do_coverage_bin_to_term_list_1(Bin) -> + Res = coverage_bin_to_term_list(Bin), + Res = coverage_bin_to_term_list(Bin, []), + Res = coverage_bin_to_term_list_catch(Bin), + Res = coverage_bin_to_term_list_catch(Bin, []). + +coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>) -> + try binary_to_term(BinTerm) of + Term -> [Term|coverage_bin_to_term_list(T)] + catch + error:badarg -> coverage_bin_to_term_list(T) + end; +coverage_bin_to_term_list(<<>>) -> []. + +coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) -> + try binary_to_term(BinTerm) of + Term -> coverage_bin_to_term_list(T, [Term|Acc]) + catch + error:badarg -> coverage_bin_to_term_list(T, Acc) + end; +coverage_bin_to_term_list(<<>>, Acc) -> lists:reverse(Acc). + +coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>) -> + case catch binary_to_term(BinTerm) of + {'EXIT',_} -> coverage_bin_to_term_list_catch(T); + Term -> [Term|coverage_bin_to_term_list_catch(T)] + end; +coverage_bin_to_term_list_catch(<<>>) -> []. + +coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) -> + case catch binary_to_term(BinTerm) of + {'EXIT',_} -> coverage_bin_to_term_list_catch(T, Acc); + Term -> coverage_bin_to_term_list_catch(T, [Term|Acc]) + end; +coverage_bin_to_term_list_catch(<<>>, Acc) -> lists:reverse(Acc). + +coverage_per_key(<<BinSize:32,Bin/binary>> = B) -> + true = (byte_size(B) =:= BinSize), + Bin. + +multiple_uses(Config) when is_list(Config) -> + ?line {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>), + ?line true = multiple_uses_2(<<0,0,197,18>>), + ?line <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1), + ok. + +multiple_uses_1(<<X:16,Tail/binary>>) -> + %% NOT OPTIMIZED: sub binary is matched or used in more than one place + {Y,Z} = multiple_uses_match(Tail), + {X,Y,Z,Tail}. + +multiple_uses_2(<<_:16,Tail/binary>>) -> + %% NOT OPTIMIZED: sub binary is matched or used in more than one place + multiple_uses_cmp(Tail, Tail). + +multiple_uses_3(<<_:16,Tail/binary>>, Fun) -> + %% NOT OPTIMIZED: sub binary is used or returned + Fun(Tail). + +multiple_uses_match(<<Y:16,Z:16>>) -> + {Y,Z}. + +multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true; +multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false. + +zero_label(Config) when is_list(Config) -> + ?line <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>), + ?line <<"CE">> = read_pols(<<"noFACE">>), + ok. + +read_pols(Data) -> + <<PolygonType:4/binary,Rest/binary>> = Data, + %% Intentional warning. + (PolygonType == <<"FACE">>) or (PolygonType == <<"PTCH">>), + Rest. + +followed_by_catch(Config) when is_list(Config) -> + ok = handle(<<0,1,2,3,4,5>>). + +-record(rec,{field}). +handle(<<>>) -> ok; +handle(Msg) -> + <<_DataLen:16, Rest/binary>> = Msg, + case catch fooX:func() of + [X] -> + X#rec.field; + _ -> + ok + end, + handle(Rest). + +matching_meets_construction(Config) when is_list(Config) -> + Bin = id(<<"abc">>), + Len = id(2), + Tail0 = id(<<1,2,3,4,5>>), + ?line <<_:Len/binary,Tail/binary>> = Tail0, + ?line Res = <<Tail/binary,Bin/binary>>, + ?line <<3,4,5,"abc">> = Res, + ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)), + ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)), + ?line <<"Bbc">> = matching_meets_construction_3(<<"Abc">>), + + ?line <<1,2>> = encode_octet_string(<<1,2,3>>, 2), + ok. + +matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>. + +matching_meets_construction_2(<<"A",H/binary>>) -> <<"B",H/float>>. + +matching_meets_construction_3(<<"A",H/binary>>) -> <<"B",H/binary>>. + +encode_octet_string(<<OctetString/binary>>, Len) -> + <<OctetString:Len/binary-unit:8>>. + +simon(Config) when is_list(Config) -> + ?line one = simon(blurf, <<>>), + ?line two = simon(0, <<42>>), + ?line {'EXIT',{function_clause,[{?MODULE,simon,[17,<<1>>]}|_]}} = (catch simon(17, <<1>>)), + ?line {'EXIT',{function_clause,[{?MODULE,simon,[0,<<1,2,3>>]}|_]}} = (catch simon(0, <<1,2,3>>)), + + ?line one = simon2(blurf, <<9>>), + ?line two = simon2(0, <<9,1>>), + ?line {'EXIT',{function_clause,[{?MODULE,simon2,[0,<<9,10,11>>]}|_]}} = + (catch simon2(0, <<9,10,11>>)), + ok. + +simon(_, <<>>) -> one; +simon(0, <<_>>) -> two. + +simon2(_, <<9>>) -> one; +simon2(0, <<_:16>>) -> two. + + +%% OTP-7113: Crash in v3_codegen. +matching_and_andalso(Config) when is_list(Config) -> + ?line ok = matching_and_andalso_1(<<1,2,3>>, 3), + ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)), + ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)), + ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)), + ok. + +matching_and_andalso_1(<<Bitmap/binary>>, K) + when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K -> + ok. + +%% Thanks to Tomas Stejskal. +otp_7188(Config) when is_list(Config) -> + MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,68,97,110,105,101,108,32,76, + 97,110,100,97,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66, + 101,115,116,32,79,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115, + 116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,12>>, + ?line {ok,{"ID3v1", + [{title,<<68,117,154,105,232,107,121>>}, + {artist,<<"Daniel Landa">>}, + {album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3). + +parse_v1_or_v11_tag(<<"TAG", Title:30/binary, + Artist:30/binary, Album:30/binary, + _Year:4/binary, _Comment:28/binary, + 0:8, Track:8, _Genre:8>>) -> + {ok, + {"ID3v1.1", + [{track, Track}, {title, trim(Title)}, + {artist, trim(Artist)}, {album, trim(Album)}]}}; +parse_v1_or_v11_tag(<<"TAG", Title:30/binary, + Artist:30/binary, Album:30/binary, + _Year:4/binary, _Comment:30/binary, + _Genre:8>>) -> + {ok, + {"ID3v1", + [{title, trim(Title)}, + {artist, trim(Artist)}, + {album, trim(Album)}]}}; +parse_v1_or_v11_tag(_) -> + error. + +trim(Bin) -> + list_to_binary(trim_blanks(binary_to_list(Bin))). + +trim_blanks(L) -> + lists:reverse(skip_blanks_and_zero(lists:reverse(L))). + +skip_blanks_and_zero([$\s|T]) -> + skip_blanks_and_zero(T); +skip_blanks_and_zero([0|T]) -> + skip_blanks_and_zero(T); +skip_blanks_and_zero(L) -> + L. + +%% OTP-7233. Record and binary matching optimizations clashed. +%% Thanks to Vladimir Klebansky. + +-record(rec_otp_7233, {key, val}). + +otp_7233(Config) when is_list(Config) -> + ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}), + ?line [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format), + erase(io_format), + ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}), + ?line undefined = get(io_format), + ok. + +otp_7233_1(Rec) -> + <<K:2/binary,_Rest:5/binary>> = Rec#rec_otp_7233.key, + case K of + <<"XX">> -> + Value = Rec#rec_otp_7233.val, + case lists:keysearch("xxxxxxxx", 1, Value) of + {value,T} -> put(io_format, [Rec#rec_otp_7233.key,T]); + false -> ok + end; + _ -> ok + end. + + +otp_7240(Config) when is_list(Config) -> + ?line a = otp_7240_a(0, <<>>), + ?line b = otp_7240_a(1, 2), + + ?line a = otp_7240_b(anything, <<>>), + ?line b = otp_7240_b(1, {x,y}), + + ?line a = otp_7240_c(anything, <<>>), + ?line b = otp_7240_c(1, <<2>>), + + ?line a = otp_7240_d(anything, <<>>), + ?line b = otp_7240_d(again, <<2>>), + + ?line a = otp_7240_e(anything, <<>>), + ?line b = otp_7240_e(1, 41), + + ?line a = otp_7240_f(anything, <<>>), + ?line b = otp_7240_f(1, {}), + + ok. + +otp_7240_a(_, <<>>) -> a; +otp_7240_a(1, 2) -> b. + +otp_7240_b(_, <<>>) -> a; +otp_7240_b(1, {_,_}) -> b. + +otp_7240_c(_, <<>>) -> a; +otp_7240_c(1, <<2>>) -> b. + +otp_7240_d(_, <<>>) -> a; +otp_7240_d(_, <<2>>) -> b. + +otp_7240_e(_, <<>>) -> a; +otp_7240_e(1, B) when B < 42 -> b. + +otp_7240_f(_, <<>>) -> a; +otp_7240_f(1, B) when is_tuple(B) -> b. + +otp_7498(Config) when is_list(Config) -> + ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0), + ?line <<2,3>> = otp_7498_foo(<<1,2,3>>, 1), + ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2), + + ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0), + ?line <<2,3>> = otp_7498_bar(<<1,2,3>>, 1), + ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2), + ?line <<>> = otp_7498_bar(<<>>, 2), + ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3), + + ok. + +otp_7498_foo(Bin, 0) -> + otp_7498_foo(Bin, 42); +otp_7498_foo(<<_A, Rest/bitstring>>, 1) -> + otp_7498_foo(Rest, 43); +otp_7498_foo(Bin, _I) -> + Bin. + +otp_7498_bar(Bin, 0) -> + otp_7498_bar(Bin, 42); +otp_7498_bar(<<_A, Rest/bitstring>>, 1) -> + otp_7498_bar(Rest, 43); +otp_7498_bar(<<>>, 2) -> + otp_7498_bar(<<>>, 44); +otp_7498_bar(Bin, _I) -> + Bin. + + +match_string(Config) when is_list(Config) -> + %% To make sure that native endian really is handled correctly + %% (i.e. that the compiler does not attempt to use bs_match_string/4 + %% instructions for native segments), running this test is not enough. + %% Either examine the generated for do_match_string_native/1 or + %% check the coverage for the v3_kernel module. + case erlang:system_info(endian) of + little -> + ?line do_match_string_native(<<$a,0,$b,0>>); + big -> + ?line do_match_string_native(<<0,$a,0,$b>>) + end, + + ?line do_match_string_big(<<0,$a,0,$b>>), + ?line do_match_string_little(<<$a,0,$b,0>>), + + ?line do_match_string_big_signed(<<255,255>>), + ?line do_match_string_little_signed(<<255,255>>), + + ?line plain = no_match_string_opt(<<"abc">>), + ?line strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>), + + ok. + +do_match_string_native(<<$a:16/native,$b:16/native>>) -> ok. + +do_match_string_big(<<$a:16/big,$b:16/big>>) -> ok. + +do_match_string_little(<<$a:16/little,$b:16/little>>) -> ok. + +do_match_string_big_signed(<<(-1):16/signed>>) -> ok. + +do_match_string_little_signed(<<(-1):16/little-signed>>) -> ok. + +no_match_string_opt(<<"abc">>) -> plain; +no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange. + + +%% OTP-7591: A zero-width segment in matching would crash the compiler. + +zero_width(Config) when is_list(Config) -> + ?line <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>, + ?line 2 = Len, + ?line Str = <<"hi">>, + + %% Match sure that values that cannot fit in a segment will not match. + case id(<<0:8>>) of + <<256:8>> -> ?line ?t:fail(); + _ -> ok + end, + ok. + + +%% OTP_7650: A invalid size for binary segments could crash the compiler. +bad_size(Config) when is_list(Config) -> + Tuple = {a,b,c}, + ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)), + Binary = <<1,2,3>>, + ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)), + ok. + +haystack(Config) when is_list(Config) -> + ?line <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>), + ?line [<<0:10/unit:8>>, + <<0:20/unit:8>>] = haystack_2(<<1:8192>>), + ok. + +%% Used to crash the compiler. +haystack_1(Haystack) -> + Subs = [10], + [begin + <<B:Y/binary>> = Haystack, + B + end || Y <- Subs], + Haystack. + +%% There would be an incorrect badmatch exception. +haystack_2(Haystack) -> + Subs = [{687,10},{369,20}], + [begin + <<_:X/binary,B:Y/binary,_/binary>> = Haystack, + B + end || {X,Y} <- Subs ]. + +check(F, R) -> + R = F(). + +id(I) -> I. diff --git a/lib/compiler/test/bs_shadowed_size_var.core b/lib/compiler/test/bs_shadowed_size_var.core new file mode 100644 index 0000000000..d1d5ebba6d --- /dev/null +++ b/lib/compiler/test/bs_shadowed_size_var.core @@ -0,0 +1,25 @@ +module 'bs_shadowed_size_var' ['filter_essentials'/1] + attributes [] + +%% Reduced code from beam_asm inlined using the old inliner. + +'filter_essentials'/1 = + fun (_cor0) -> + case _cor0 of + <[#{#<Sz>(32,1,'integer',['unsigned','big']) }#|T]> when 'true' -> + let <_cor4> = + case T of + %% Variable 'Sz' repeated here. Should work. + <#{#<Sz>(32,1,'integer',['unsigned','big']), + #<Data>(Sz,8,'binary',['unsigned','big'])}#> when 'true' -> + Data + <_cor5> when 'true' -> + primop 'match_fail' + ({'case_clause',{_cor5}}) + end + in [Sz|_cor4] + <_cor5> when 'true' -> + primop 'match_fail' + ({'function_clause',_cor5}) + end +end diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl new file mode 100644 index 0000000000..d93bdef73d --- /dev/null +++ b/lib/compiler/test/bs_utf_SUITE.erl @@ -0,0 +1,396 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-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(bs_utf_SUITE). + +-export([all/1, + utf8_roundtrip/1,unused_utf_char/1,utf16_roundtrip/1, + utf32_roundtrip/1,guard/1,extreme_tripping/1, + literals/1,coverage/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [utf8_roundtrip,unused_utf_char,utf16_roundtrip, + utf32_roundtrip,guard,extreme_tripping, + literals,coverage]. + +utf8_roundtrip(Config) when is_list(Config) -> + ?line [utf8_roundtrip_1(P) || P <- utf_data()], + ok. + +utf8_roundtrip_1({Str,Bin,Bin}) -> + ?line Str = utf8_to_list(Bin), + ?line Bin = list_to_utf8(Str), + ?line [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str], + ?line [error = utf8_guard(C, <<C/utf8>>) || C <- Str], + ok. + +utf8_guard(C, Bin) when <<42,C/utf8>> =:= Bin -> ok; +utf8_guard(_, _) -> error. + +utf8_to_list(<<C/utf8,T/binary>>) -> + [C|utf8_to_list(T)]; +utf8_to_list(<<>>) -> []. + +list_to_utf8(L) -> + list_to_utf8(L, <<>>). + +list_to_utf8([H|T], Bin) -> + list_to_utf8(T, <<Bin/binary,H/utf8>>); +list_to_utf8([], Bin) -> Bin. + +unused_utf_char(Config) when is_list(Config) -> + [true = utf8_len(Utf8) =:= length(Str) || + {Str,Utf8} <- utf_data()], + ok. + +utf8_len(B) -> + utf8_len(B, 0). + +utf8_len(<<_/utf8,T/binary>>, N) -> + utf8_len(T, N+1); +utf8_len(<<>>, N) -> N. + +utf16_roundtrip(Config) when is_list(Config) -> + ?line {Str,Big,Big,Little,Little} = utf16_data(), + ?line 4 = utf16_big_len(Big), + ?line 4 = utf16_little_len(Little), + ?line Str = big_utf16_to_list(Big), + ?line Str = little_utf16_to_list(Little), + + ?line Big = list_to_big_utf16(Str), + ?line Little = list_to_little_utf16(Str), + + ok. + +utf16_big_len(B) -> + utf16_big_len(B, 0). + +utf16_big_len(<<_/utf16,T/binary>>, N) -> + utf16_big_len(T, N+1); +utf16_big_len(<<>>, N) -> N. + +utf16_little_len(B) -> + utf16_little_len(B, 0). + +utf16_little_len(<<_/little-utf16,T/binary>>, N) -> + utf16_little_len(T, N+1); +utf16_little_len(<<>>, N) -> N. + +list_to_big_utf16(List) -> + list_to_big_utf16(List, <<>>). + +list_to_big_utf16([H|T], Bin) -> + list_to_big_utf16(T, <<Bin/binary,H/utf16>>); +list_to_big_utf16([], Bin) -> Bin. + +list_to_little_utf16(List) -> + list_to_little_utf16(List, <<>>). + +list_to_little_utf16([H|T], Bin) -> + list_to_little_utf16(T, <<Bin/binary,H/little-utf16>>); +list_to_little_utf16([], Bin) -> Bin. + +big_utf16_to_list(<<H/utf16,T/binary>>) -> + [H|big_utf16_to_list(T)]; +big_utf16_to_list(<<>>) -> []. + +little_utf16_to_list(<<H/little-utf16,T/binary>>) -> + [H|little_utf16_to_list(T)]; +little_utf16_to_list(<<>>) -> []. + +utf32_roundtrip(Config) when is_list(Config) -> + ?line {Str,Big,Big,Little,Little} = utf32_data(), + ?line 4 = utf32_big_len(Big), + ?line 4 = utf32_little_len(Little), + ?line Str = big_utf32_to_list(Big), + ?line Str = little_utf32_to_list(Little), + + ?line Big = list_to_big_utf32(Str), + ?line Little = list_to_little_utf32(Str), + + ok. + +utf32_big_len(B) -> + utf32_big_len(B, 0). + +utf32_big_len(<<_/utf32,T/binary>>, N) -> + utf32_big_len(T, N+1); +utf32_big_len(<<>>, N) -> N. + +utf32_little_len(B) -> + utf32_little_len(B, 0). + +utf32_little_len(<<_/little-utf32,T/binary>>, N) -> + utf32_little_len(T, N+1); +utf32_little_len(<<>>, N) -> N. + +list_to_big_utf32(List) -> + list_to_big_utf32(List, <<>>). + +list_to_big_utf32([H|T], Bin) -> + list_to_big_utf32(T, <<Bin/binary,H/utf32>>); +list_to_big_utf32([], Bin) -> Bin. + +list_to_little_utf32(List) -> + list_to_little_utf32(List, <<>>). + +list_to_little_utf32([H|T], Bin) -> + list_to_little_utf32(T, <<Bin/binary,H/little-utf32>>); +list_to_little_utf32([], Bin) -> Bin. + +big_utf32_to_list(<<H/utf32,T/binary>>) -> + [H|big_utf32_to_list(T)]; +big_utf32_to_list(<<>>) -> []. + +little_utf32_to_list(<<H/little-utf32,T/binary>>) -> + [H|little_utf32_to_list(T)]; +little_utf32_to_list(<<>>) -> []. + + +guard(Config) when is_list(Config) -> + ?line error = do_guard(16#D800), + ok. + +do_guard(C) when byte_size(<<C/utf8>>) =/= 42 -> ok; +do_guard(C) when byte_size(<<C/utf16>>) =/= 42 -> ok; +do_guard(C) when byte_size(<<C/utf32>>) =/= 42 -> ok; +do_guard(_) -> error. + +%% The purpose of this test is to make sure that +%% the delayed creation of sub-binaries works. + +extreme_tripping(Config) when is_list(Config) -> + ?line Unicode = lists:seq(0, 1024), + ?line Utf8 = unicode_to_utf8(Unicode, <<>>), + ?line Utf16 = utf8_to_utf16(Utf8, <<>>), + ?line Utf32 = utf8_to_utf32(Utf8, <<>>), + ?line Utf32 = utf16_to_utf32(Utf16, <<>>), + ?line Utf8 = utf32_to_utf8(Utf32, <<>>), + ?line Unicode = utf32_to_unicode(Utf32), + ok. + +unicode_to_utf8([C|T], Bin) -> + unicode_to_utf8(T, <<Bin/bytes,C/utf8>>); +unicode_to_utf8([], Bin) -> Bin. + +utf8_to_utf16(<<C/utf8,T/binary>>, Bin) -> + utf8_to_utf16(T, <<Bin/bytes,C/utf16>>); +utf8_to_utf16(<<>>, Bin) -> Bin. + +utf16_to_utf32(<<C/utf16,T/binary>>, Bin) -> + utf16_to_utf32(T, <<Bin/bytes,C/utf32>>); +utf16_to_utf32(<<>>, Bin) -> Bin. + +utf8_to_utf32(<<C/utf8,T/binary>>, Bin) -> + utf8_to_utf32(T, <<Bin/bytes,C/utf32>>); +utf8_to_utf32(<<>>, Bin) -> Bin. + +utf32_to_utf8(<<C/utf32,T/binary>>, Bin) -> + utf32_to_utf8(T, <<Bin/bytes,C/utf8>>); +utf32_to_utf8(<<>>, Bin) -> Bin. + +utf32_to_unicode(<<C/utf32,T/binary>>) -> + [C|utf32_to_unicode(T)]; +utf32_to_unicode(<<>>) -> []. + +literals(Config) when is_list(Config) -> + ?line abc_utf8 = match_literal(<<"abc"/utf8>>), + ?line abc_utf8 = match_literal(<<$a,$b,$c>>), + + ?line abc_utf16be = match_literal(<<"abc"/utf16>>), + ?line abc_utf16be = match_literal(<<$a:16,$b:16,$c:16>>), + ?line abc_utf16le = match_literal(<<"abc"/little-utf16>>), + ?line abc_utf16le = match_literal(<<$a:16/little,$b:16/little,$c:16/little>>), + + ?line abc_utf32be = match_literal(<<"abc"/utf32>>), + ?line abc_utf32be = match_literal(<<$a:32,$b:32,$c:32>>), + ?line abc_utf32le = match_literal(<<"abc"/little-utf32>>), + ?line abc_utf32le = match_literal(<<$a:32/little,$b:32/little,$c:32/little>>), + + ?line bjorn_utf8 = match_literal(<<"bj\366rn"/utf8>>), + ?line bjorn_utf8 = match_literal(<<$b,$j,195,182,$r,$n>>), + + ?line bjorn_utf16be = match_literal(<<"bj\366rn"/utf16>>), + ?line bjorn_utf16be = match_literal(<<$b:16,$j:16,246:16,$r:16,$n:16>>), + ?line bjorn_utf16le = match_literal(<<"bj\366rn"/little-utf16>>), + ?line bjorn_utf16le = match_literal(<<$b:16/little,$j:16/little, + 246:16/little,$r:16/little, + $n:16/little>>), + ?line <<244,143,191,191>> = <<16#10ffff/utf8>>, + + %% Invalid literals. + I = 0, + ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf8,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf8,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf8,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/little-utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf16,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf32,I/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf32,I/utf8>>), + + B = 16#10FFFF+1, + ?line {'EXIT',{badarg,_}} = (catch <<B/utf8>>), + ?line {'EXIT',{badarg,_}} = (catch <<B/utf16>>), + ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf16>>), + ?line {'EXIT',{badarg,_}} = (catch <<B/utf32>>), + ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf32>>), + + %% Matching of bad literals. + ?line error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8 + ?line error = bad_literal_match(<<239,191,190>>), %16#FFFE in UTF-8 + ?line error = bad_literal_match(<<239,191,191>>), %16#FFFF in UTF-8 + ?line error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8 + + ?line error = bad_literal_match(<<255,254>>), %16#FFFE in UTF-16 + ?line error = bad_literal_match(<<255,255>>), %16#FFFF in UTF-16 + + ?line error = bad_literal_match(<<16#D800:32>>), + ?line error = bad_literal_match(<<16#FFFE:32>>), + ?line error = bad_literal_match(<<16#FFFF:32>>), + ?line error = bad_literal_match(<<16#110000:32>>), + ?line error = bad_literal_match(<<16#D800:32/little>>), + ?line error = bad_literal_match(<<16#FFFE:32/little>>), + ?line error = bad_literal_match(<<16#FFFF:32/little>>), + ?line error = bad_literal_match(<<16#110000:32/little>>), + + ok. + +match_literal(<<"abc"/utf8>>) -> abc_utf8; +match_literal(<<"abc"/big-utf16>>) -> abc_utf16be; +match_literal(<<"abc"/little-utf16>>) -> abc_utf16le; +match_literal(<<"abc"/big-utf32>>) -> abc_utf32be; +match_literal(<<"abc"/little-utf32>>) -> abc_utf32le; +match_literal(<<"bj\366rn"/utf8>>) -> bjorn_utf8; +match_literal(<<"bj\366rn"/big-utf16>>) -> bjorn_utf16be; +match_literal(<<"bj\366rn"/little-utf16>>) -> bjorn_utf16le. + +bad_literal_match(<<16#D800/utf8>>) -> ok; +bad_literal_match(<<16#FFFE/utf8>>) -> ok; +bad_literal_match(<<16#FFFF/utf8>>) -> ok; +bad_literal_match(<<16#110000/utf8>>) -> ok; +bad_literal_match(<<16#FFFE/utf16>>) -> ok; +bad_literal_match(<<16#FFFF/utf16>>) -> ok; +bad_literal_match(<<16#D800/utf32>>) -> ok; +bad_literal_match(<<16#110000/utf32>>) -> ok; +bad_literal_match(<<16#D800/little-utf32>>) -> ok; +bad_literal_match(<<16#110000/little-utf32>>) -> ok; +bad_literal_match(_) -> error. + +coverage(Config) when is_list(Config) -> + %% Cover bit syntax matching optimizations in v3_kernel. + ?line 0 = coverage_1(<<4096/utf8,65536/utf8,0>>), + ?line 1 = coverage_1(<<4096/utf8,65536/utf8,1>>), + + ?line 0 = coverage_2(<<4096/utf8,65536/utf8,0>>), + ?line 1 = coverage_2(<<1024/utf8,1025/utf8,1>>), + + ?line {'EXIT',{function_clause,_}} = (catch coverage_3(1)), + + %% Cover beam_flatten (combining the heap allocation in + %% a subsequent test_heap instruction into the bs_init2 + %% instruction). + {ok,<<533/utf8>>} = cover_test_heap_utf8(533), + {ok,<<1024/utf16>>} = cover_test_heap_utf16(1024), + {ok,<<7966/utf32>>} = cover_test_heap_utf32(7966), + + ok. + +coverage_1(<<4096/utf8,65536/utf8,0>>) -> 0; +coverage_1(<<4096/utf8,65536/utf8,1>>) -> 1. + +coverage_2(<<4096/utf8,65536/utf8,0>>) -> 0; +coverage_2(<<1024/utf8,1025/utf8,1>>) -> 1. + +coverage_3(<<16#7fffffff/utf8,65536/utf8,0>>) -> 0. + +cover_test_heap_utf8(C) -> {ok,<<C/utf8>>}. +cover_test_heap_utf16(C) -> {ok,<<C/utf16>>}. +cover_test_heap_utf32(C) -> {ok,<<C/utf32>>}. + +utf_data() -> +%% From RFC-3629. + + %% Give the compiler a chance to do some constant propagation. + NotIdentical = 16#2262, + + [ + %% "A<NOT IDENTICAL TO><ALPHA>." + {[16#0041,NotIdentical,16#0391,16#002E], + <<16#0041/utf8,NotIdentical/utf8,16#0391/utf8,16#002E/utf8>>, + <<16#41,16#E2,16#89,16#A2,16#CE,16#91,16#2E>>}, + + %% Korean "hangugeo" (meaning "the Korean language") + {[16#D55C,16#AD6D,16#C5B4], + <<16#D55C/utf8,16#AD6D/utf8,16#C5B4/utf8>>, + <<16#ED,16#95,16#9C,16#EA,16#B5,16#AD,16#EC,16#96,16#B4>>}, + + %% Japanese "nihongo" (meaning "the Japanese language"). + {[16#65E5,16#672C,16#8A9E], + <<16#65E5/utf8,16#672C/utf8,16#8A9E/utf8>>, + <<16#E6,16#97,16#A5,16#E6,16#9C,16#AC,16#E8,16#AA,16#9E>>} + ]. + +utf16_data() -> + %% Example from RFC-2781. "*=Ra", where "*" represents a + %% hypothetical Ra hieroglyph (code point 16#12345). + + %% Give the compiler a chance to do some constant propagation. + RaHieroglyph = 16#12345, + + %% First as a list of Unicode characters. + {[RaHieroglyph,16#3D,16#52,16#61], + + %% Big endian (the two binaries should be equal). + <<RaHieroglyph/big-utf16,16#3D/big-utf16,16#52/big-utf16,16#61/big-utf16>>, + <<16#D8,16#08,16#DF,16#45,16#00,16#3D,16#00,16#52,16#00,16#61>>, + + %% Little endian (the two binaries should be equal). + <<RaHieroglyph/little-utf16,16#3D/little-utf16, + 16#52/little-utf16,16#61/little-utf16>>, + <<16#08,16#D8,16#45,16#DF,16#3D,16#00,16#52,16#00,16#61,16#00>>}. + +utf32_data() -> + %% "A<NOT IDENTICAL TO><ALPHA>." + NotIdentical = 16#2262, + {[16#0041,NotIdentical,16#0391,16#002E], + + %% Big endian. + <<16#0041/utf32,NotIdentical/utf32,16#0391/utf32,16#002E/utf32>>, + <<16#41:32,NotIdentical:32,16#0391:32,16#2E:32>>, + + %% Little endian. + <<16#0041/little-utf32,NotIdentical/little-utf32, + 16#0391/little-utf32,16#002E/little-utf32>>, + <<16#41:32/little,NotIdentical:32/little, + 16#0391:32/little,16#2E:32/little>>}. + diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl new file mode 100644 index 0000000000..d4843c9eba --- /dev/null +++ b/lib/compiler/test/compilation_SUITE.erl @@ -0,0 +1,599 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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% +%% +%%% Purpose : Compiles various modules with tough code + +-module(compilation_SUITE). + +-include("test_server.hrl"). + +-compile(export_all). + +all(suite) -> + test_lib:recompile(?MODULE), + [self_compile_old_inliner,self_compile, + compiler_1,compiler_3,compiler_5, + beam_compiler_1, beam_compiler_2, beam_compiler_3, + beam_compiler_4, beam_compiler_5, beam_compiler_6, + beam_compiler_7, beam_compiler_8, beam_compiler_9, + beam_compiler_10, beam_compiler_11, beam_compiler_12, + nested_tuples_in_case_expr, + otp_2330, guards, vsn, + otp_2380, otp_2141, otp_2173, otp_4790, + const_list_256, + bin_syntax_1, bin_syntax_2, bin_syntax_3, + bin_syntax_4, bin_syntax_5, bin_syntax_6, + live_var, convopts, + bad_functional_value, + catch_in_catch, redundant_case, long_string, + otp_5076, complex_guard, otp_5092, otp_5151, + otp_5235,otp_5244, + trycatch_4, opt_crash, + otp_5404,otp_5436,otp_5481,otp_5553,otp_5632, + otp_5714,otp_5872,otp_6121,otp_6121a,otp_6121b, + otp_7202,otp_7345,on_load + ]. + +-define(comp(N), + N(Config) when is_list(Config) -> try_it(N, Config)). + +-define(comp_fail(N), + N(Config) when is_list(Config) -> failure(N, Config)). + +?comp(compiler_1). +?comp(compiler_3). +?comp(compiler_4). +?comp(compiler_5). + +?comp(beam_compiler_1). +?comp(beam_compiler_2). +?comp(beam_compiler_3). +?comp(beam_compiler_4). +?comp(beam_compiler_5). +?comp(beam_compiler_6). +?comp(beam_compiler_8). +?comp(beam_compiler_9). +?comp(beam_compiler_10). +?comp(beam_compiler_11). +?comp(beam_compiler_12). +?comp(beam_compiler_13). + +?comp(nested_tuples_in_case_expr). + +?comp(otp_2330). +?comp(otp_2380). +?comp(otp_2141). +?comp(otp_2173). +?comp(otp_4790). +?comp(otp_5235). + +?comp(otp_5244). + +?comp(guards). + +?comp(pattern_expr). + +?comp(const_list_256). + +?comp(bin_syntax_1). +?comp(bin_syntax_2). +?comp(bin_syntax_3). +?comp(bin_syntax_4). + +?comp(bin_syntax_6). + +?comp(otp_5076). + +?comp(complex_guard). + +?comp(otp_5092). +?comp(otp_5151). + +%%% By Per Gustafsson <[email protected]> + +bin_syntax_5(Config) when is_list(Config) -> + {<<45>>,<<>>} = split({int, 1}, <<1:16,45>>). + +split({int, N}, <<N:16,B:N/binary,T/binary>>) -> + {B,T}. + +%% This program works with the old version of the compiler +%% but, the core erlang that it produces have the same variable appearing +%% looks like this: +%% +%% split({int, N}, <<_core1:16, B:N/binary, T/binary>>) when _core1==N +%% +%% with my change it will look like this: +%% +%% split({int, N}, <<_core1:16, B:_core1/binary, T/binary>>) when _core1==N +%% +%% This means that everything worked fine as long as the pattern +%% matching order was left-to-right but on core erlang any order should be possible + +?comp(live_var). + +?comp(trycatch_4). +?comp(bad_functional_value). + +?comp(catch_in_catch). + +?comp(opt_crash). + +?comp(otp_5404). +?comp(otp_5436). +?comp(otp_5481). +?comp(otp_5553). +?comp(otp_5632). +?comp(otp_5714). +?comp(otp_5872). +?comp(otp_6121). +?comp(otp_6121a). +?comp(otp_6121b). +?comp(convopts). +?comp(otp_7202). +?comp(on_load). + +beam_compiler_7(doc) -> + "Code snippet submitted from Ulf Wiger which fails in R3 Beam."; +beam_compiler_7(suite) -> []; +beam_compiler_7(Config) when list(Config) -> + ?line done = empty(2, false). + +empty(N, Toggle) when N > 0 -> + %% R3 Beam copies the second argument to the first before call. + empty(N-1, not(Toggle)); +empty(_, _) -> + done. + +redundant_case(Config) when is_list(Config) -> + d = redundant_case_1(1), + d = redundant_case_1(2), + d = redundant_case_1(3), + d = redundant_case_1(4), + d = redundant_case_1(5), + d = redundant_case_1({glurf,glarf}), + ok. + +%% This function always returns 'd'. Check that the compiler otptimizes +%% it properly. +redundant_case_1(1) -> d; +redundant_case_1(2) -> d; +redundant_case_1(3) -> d; +redundant_case_1(4) -> d; +redundant_case_1(_) -> d. + +failure(Module, Conf) -> + ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)), + ?line Out = ?config(priv_dir,Conf), + ?line io:format("Compiling: ~s\n", [Src]), + ?line CompRc = compile:file(Src, [{outdir,Out},return,time]), + ?line io:format("Result: ~p\n",[CompRc]), + ?line case CompRc of + error -> ok; + {error,Errors,_} -> check_errors(Errors); + _ -> test_server:fail({no_error, CompRc}) + end, + ok. + +check_errors([{_,Eds}|T]) -> + check_error(Eds), + check_errors(T); +check_errors([]) -> ok. + +check_error([{_,Mod,Error}|T]) -> + check_error_1(Mod:format_error(Error)), + check_error(T); +check_error([{Mod,Error}|T]) -> + check_error_1(Mod:format_error(Error)), + check_error(T); +check_error([]) -> ok. + +check_error_1(Str0) -> + Str = lists:flatten(Str0), + io:format("~s\n", [Str]), + case Str of + "internal"++_=Str -> + ?t:fail(internal_compiler_error); + _ -> + ok + end. + +-define(TC(Body), tc(fun() -> Body end, ?LINE)). + +try_it(Module, Conf) -> + %% Change 'false' to 'true' to start a new node for every module. + try_it(false, Module, Conf). + +try_it(StartNode, Module, Conf) -> + ?line OtherOpts = [], %Can be changed to [time] if needed + ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)), + ?line Out = ?config(priv_dir,Conf), + ?line io:format("Compiling: ~s\n", [Src]), + ?line CompRc0 = compile:file(Src, [clint,{outdir,Out},report, + bin_opt_info|OtherOpts]), + ?line io:format("Result: ~p\n",[CompRc0]), + ?line {ok,_Mod} = CompRc0, + + ?line Dog = test_server:timetrap(test_server:minutes(10)), + Node = case StartNode of + false -> + node(); + true -> + ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)), + ?line {ok,Node0} = start_node(compiler, Pa), + Node0 + end, + + ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), + ?line load_and_call(Out, Module), + ?line test_server:timetrap_cancel(Dog), + + ?line NewDog = test_server:timetrap(test_server:minutes(10)), + ?line io:format("Compiling (without optimization): ~s\n", [Src]), + ?line CompRc1 = compile:file(Src, + [no_copt,no_postopt,{outdir,Out},report|OtherOpts]), + + ?line io:format("Result: ~p\n",[CompRc1]), + ?line {ok,_Mod} = CompRc1, + ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), + ?line test_server:timetrap_cancel(NewDog), + + ?line LastDog = test_server:timetrap(test_server:minutes(10)), + ?line io:format("Compiling (with old inliner): ~s\n", [Src]), + ?line CompRc2 = compile:file(Src, [{outdir,Out},report,bin_opt_info, + {inline,1000}|OtherOpts]), + ?line io:format("Result: ~p\n",[CompRc2]), + ?line {ok,_Mod} = CompRc2, + ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), + ?line test_server:timetrap_cancel(LastDog), + + case StartNode of + false -> ok; + true -> ?line test_server:stop_node(Node) + end, + ?line test_server:timetrap_cancel(LastDog), + ok. + +load_and_call(Out, Module) -> + ?line io:format("Loading...\n",[]), + ?line {module,Module} = code:load_abs(filename:join(Out, Module)), + + ?line io:format("Calling...\n",[]), + %% Call M:M, and expect ok back, that's our interface + ?line CallRc = Module:Module(), + ?line io:format("Got value: ~p\n",[CallRc]), + + ?line ok = CallRc, + + %% Smoke-test of beam disassembler. + ?line test_lib:smoke_disasm(Module), + + ?line true = erlang:delete_module(Module), + ?line true = erlang:purge_module(Module), + + %% Restore state of trap_exit just in case. (Since the compiler + %% uses a temporary process, we will get {'EXIT',Pid,normal} messages + %% if trap_exit is true.) + + process_flag(trap_exit, false), + ok. + + +tc(F, Line) -> + {Diff,Value} = timer:tc(erlang, apply, [F,[]]), + io:format("~p: ~p\n", [Line,Diff]), + Value. + +start_node(Name, Args) -> + case test_server:start_node(Name, slave, [{args, Args}]) of + {ok, Node} -> + {ok, Node}; + Error -> + ?line test_server:fail(Error) + end. + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_, []) -> []. + +vsn(suite) -> [vsn_1, vsn_2, vsn_3]. + +vsn_1(doc) -> + "Test generation of 'vsn' attribute"; +vsn_1(suite) -> []; +vsn_1(Conf) when list(Conf) -> + ?line M = vsn_1, + + ?line compile_load(M, ?config(data_dir, Conf), Conf), + ?line Vsn1 = get_vsn(M), + ?line timer:sleep(1000), + + ?line compile_load(M, ?config(data_dir, Conf), Conf), + ?line Vsn2 = get_vsn(M), + + ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"), + Conf), + ?line Vsn3 = get_vsn(M), + ?line if + Vsn1 == Vsn2, Vsn2 == Vsn3 -> + ok; + true -> + test_server:fail({vsn, Vsn1, Vsn2, Vsn3}) + end, + ok. + +vsn_2(doc) -> + "Test overriding of generation of 'vsn' attribute"; +vsn_2(suite) -> []; +vsn_2(Conf) when list(Conf) -> + ?line M = vsn_2, + + ?line compile_load(M, ?config(data_dir, Conf), Conf), + ?line Vsn = get_vsn(M), + ?line case Vsn of + [34] -> + ok; + _ -> + test_server:fail({vsn, Vsn}) + end, + ok. + +vsn_3(doc) -> + "Test that different code yields different generated 'vsn'"; +vsn_3(suite) -> []; +vsn_3(Conf) when list(Conf) -> + ?line M = vsn_3, + + ?line compile_load(M, ?config(data_dir, Conf), Conf), + ?line Vsn1 = get_vsn(M), + + ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"), + Conf), + ?line Vsn2 = get_vsn(M), + ?line if + Vsn1 /= Vsn2 -> + ok; + true -> + test_server:fail({vsn, Vsn1, Vsn2}) + end, + ok. + +get_vsn(M) -> + {value, {vsn, V}} = lists:keysearch(vsn, 1, M:module_info(attributes)), + V. + +long_string(Config) when is_list(Config) -> + %% The test must complete in one minute - it should be plenty of time. + ?line Dog = test_server:timetrap(test_server:minutes(1)), + ?line try_it(long_string, Config), + ?line test_server:timetrap_cancel(Dog), + ok. + +compile_load(Module, Dir, Conf) -> + ?line Src = filename:join(Dir, atom_to_list(Module)), + ?line Out = ?config(priv_dir,Conf), + ?line CompRc = compile:file(Src, [{outdir,Out}]), + ?line {ok, Module} = CompRc, + ?line code:purge(Module), + ?line {module, Module} = + code:load_abs(filename:join(Out, atom_to_list(Module))), + ok. + +self_compile(Config) when is_list(Config) -> + self_compile_1(Config, "new", [inline]). + +self_compile_old_inliner(Config) when is_list(Config) -> + %% The old inliner is useful for testing that sys_core_fold does not + %% introduce name capture problems. + self_compile_1(Config, "old", [verbose,{inline,500}]). + +self_compile_1(Config, Prefix, Opts) -> + ?line Dog = test_server:timetrap(test_server:minutes(40)), + + ?line Priv = ?config(priv_dir,Config), + ?line Version = compiler_version(), + + %% Compile the compiler. (In this node to get better coverage.) + ?line CompA = make_compiler_dir(Priv, Prefix++"compiler_a"), + ?line VsnA = Version ++ ".0", + ?line compile_compiler(compiler_src(), CompA, VsnA, [clint|Opts]), + + %% Compile the compiler again using the newly compiled compiler. + %% (In another node because reloading the compiler would disturb cover.) + CompilerB = Prefix++"compiler_b", + ?line CompB = make_compiler_dir(Priv, Prefix++"compiler_b"), + ?line VsnB = VsnA ++ ".0", + ?line self_compile_node(CompilerB, CompA, CompB, VsnB, Opts), + + %% Compare compiler directories. + ?line compare_compilers(CompA, CompB), + + %% Compile and compare compiler C. + ?line CompilerC = Prefix++"compiler_c", + ?line CompC = make_compiler_dir(Priv, CompilerC), + ?line VsnC = VsnB ++ ".0", + ?line self_compile_node(CompilerC, CompB, CompC, VsnC, Opts), + ?line compare_compilers(CompB, CompC), + + ?line test_server:timetrap_cancel(Dog), + ok. + +self_compile_node(NodeName0, CompilerDir, OutDir, Version, Opts) -> + ?line NodeName = list_to_atom(NodeName0), + ?line Dog = test_server:timetrap(test_server:minutes(10)), + ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++ + " -pa " ++ CompilerDir, + ?line {ok,Node} = start_node(NodeName, Pa), + ?line Files = compiler_src(), + ?line ok = rpc:call(Node, ?MODULE, compile_compiler, [Files,OutDir,Version,Opts]), + ?line test_server:stop_node(Node), + ?line test_server:timetrap_cancel(Dog), + ok. + +compile_compiler(Files, OutDir, Version, InlineOpts) -> + io:format("~s", [code:which(compile)]), + io:format("Compiling ~s into ~s", [Version,OutDir]), + Opts = [report, + bin_opt_info, + {outdir,OutDir}, + {d,'COMPILER_VSN',"\""++Version++"\""}, + nowarn_shadow_vars, + {i,filename:join(code:lib_dir(stdlib), "include")}|InlineOpts], + lists:foreach(fun(File) -> + {ok,_} = compile:file(File, Opts) + end, Files). + +compiler_src() -> + filelib:wildcard(filename:join([code:lib_dir(compiler), "src", "*.erl"])). + +compiler_modules(Dir) -> + Files = filelib:wildcard(filename:join(Dir, "*.beam")), + [list_to_atom(filename:rootname(filename:basename(F))) || F <- Files]. + +make_compiler_dir(Priv, Dir0) -> + ?line Dir = filename:join(Priv, Dir0), + ?line ok = file:make_dir(Dir), + Dir. + +make_current(Dir) -> + true = code:add_patha(Dir), + lists:foreach(fun(File) -> + c:l(File) + end, compiler_modules(Dir)), + io:format("~p\n", [code:which(compile)]). + +compiler_version() -> + {value,{version,Version}} = lists:keysearch(version, 1, + compile:module_info(compile)), + Version. + +compare_compilers(ADir, BDir) -> + {[],[],D} = beam_lib:cmp_dirs(ADir, BDir), + [] = [T || {A,_}=T <- D, + filename:basename(A) =/= "beam_asm.beam"]. %Contains compiler version. + + +%%% +%%% The only test of the following code is that it compiles. +%%% + +%% Slightly simplifed from megaco_binary_term_id_gen. +%% beam_block failed to note that the {gc_bif,'-'...} instruction could +%% fail, and that therefore {y,0} need to be initialized. +%% {allocate,8,6}. +%% %% {init,{y,0}} needed here. +%% {get_list,{x,1},{x,6},{x,7}}. +%% {'catch',{y,7},{f,3}}. +%% {move,{x,4},{y,1}}. +%% {move,{x,3},{y,2}}. +%% {move,{x,2},{y,3}}. +%% {move,{x,5},{y,4}}. +%% {move,{x,7},{y,5}}. +%% {move,{x,6},{y,6}}. +%% {gc_bif,'-',{f,0},8,[{x,3},{x,6}],{x,0}}. +%% {move,{x,0},{y,0}}. + +encode_wildcards3([],[],_,_) -> []; +encode_wildcards3([Level|Levels],[BitsInLevel|BitsRest],LevelNo,TotSize) -> + case (catch ?MODULE:encode_wildcard(Level,BitsInLevel,TotSize-BitsInLevel, + length(Levels))) of + {'EXIT',{Reason,Info}} -> + exit({Reason,{LevelNo,Info}}); + + no_wildcard -> + encode_wildcards3(Levels,BitsRest,LevelNo+1,TotSize-BitsInLevel); + + {level,Wl} -> + [Wl| + encode_wildcards3(Levels,BitsRest,LevelNo+1,TotSize-BitsInLevel)]; + + {recursive,Wr} -> + [Wr] + end. + +%% Slightly simplified code from hipe_rtl_ssapre. +%% beam_block used to do the following incorrect optimization: +%% +%% {gc_bif,length,{f,0},1,[{x,0}],{x,3}}. +%% ^^^^^ Was {x,0} - changing to {x,3} is not safe. +%% {gc_bif,'+',{f,0},0,[{y,2},{integer,1}],{x,0}}. +%% ^^^ Only one register live +%% . . . +%% {call_last,4,{f,2},4}. %% beam_validator noted that {x,3} wasn't live. + +find_operands(Cfg,XsiGraph,[],_Count) -> + {Cfg,XsiGraph}; +find_operands(Cfg,XsiGraph,ActiveList,Count) -> + {NewCfg,TempActiveList}=?MODULE:find_operands_for_active_list(Cfg,XsiGraph, + ActiveList,[]), + NewActiveList=lists:reverse(TempActiveList), + [Count+1, length(NewActiveList), length(digraph:vertices(XsiGraph))], + find_operands(NewCfg,XsiGraph,NewActiveList,Count+1). + + +%% The following code +%% +%% {get_list,{x,2},{x,0},{x,1}}. +%% {gc_bif,length,{f,0},1,[{x,0}],{x,0}}. +%% {move,{x,0},{x,1}}. +%% +%% was incorrectly optimized to +%% +%% {get_list,{x,2},{x,0},{y,0}}. +%% {gc_bif,length,{f,0},3,[{x,0}],{x,1}}. +%% +%% because beam_block:is_transparent({x,1}, +%% {gc_bif,length,{f,0},3,[{x,0}],{x,1}} +%% incorrectly returned true. + +-record(contextId,{cid,device_type,contextRef}). +-record(dpRef,{cid,tlli,ms_device_context_id}). +-record(qosProfileBssgp,{peak_bit_rate_msb, + peak_bit_rate_lsb, + t_a_precedence}). +-record(llUnitdataReq,{sapi, + l3_pdu_length, + pdu_life}). +-record(ptmsi,{value}). + +otp_7345(Config) when is_list(Config) -> + #llUnitdataReq{l3_pdu_length=3,pdu_life=4} = + otp_7345(#contextId{}, 0, [[1,2,3],4,5]). + + +otp_7345(ObjRef, _RdEnv, Args) -> + Cid = ObjRef#contextId.cid, + _DpRef = + #dpRef{cid = Cid, + ms_device_context_id = cid_id, + tlli = #ptmsi{value = 0}}, + _QosProfile = + #qosProfileBssgp{peak_bit_rate_msb = 0, + peak_bit_rate_lsb = 80, + t_a_precedence = 49}, + [Cpdu|_] = Args, + LlUnitdataReq = + #llUnitdataReq{sapi = 7, + l3_pdu_length = length(Cpdu), + pdu_life = + id(42) + div + 10}, + id(LlUnitdataReq). + +id(I) -> I. diff --git a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl new file mode 100644 index 0000000000..126a573e83 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(bad_functional_value). + +-export([?MODULE/0,a/0]). + +?MODULE() -> + ok. + +a() -> + .list_to_atom("ok"). + diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl new file mode 100644 index 0000000000..d6c9c869c8 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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_compiler_1). +-export([beam_compiler_1/0]). + +beam_compiler_1() -> + ok. + +-record(foo,{a,b}). + +try_me() -> + X = #foo{}, + Y = #foo{}, + {X#foo.a == Y#foo.a,X#foo.b}. + diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl new file mode 100644 index 0000000000..a1264055bd --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl @@ -0,0 +1,27 @@ +%% +%% %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_compiler_10). +-export([?MODULE/0,start_timer/0]). + +?MODULE() -> + ok. + +start_timer() -> + Self = self(), + spawn(fun() -> receive after 1000 -> Self ! show end end). diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl new file mode 100644 index 0000000000..4be32ab505 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl @@ -0,0 +1,31 @@ +%% +%% %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_compiler_11). + +-export([?MODULE/0,a/0]). + +?MODULE() -> + ok. + +a() -> + case foo:bar() of + A -> ok + end, + A = 3. + diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl new file mode 100644 index 0000000000..baee6b9bce --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl @@ -0,0 +1,29 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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_compiler_12). + +-export([?MODULE/0,t/1]). + +?MODULE() -> + ok. + +t(Name) -> + {ok = {file_info,_,regular,_,AccTime1,ModTime1,_,_,_,_,_,_,_,_}} = + prim_file:read_file_info(Name). + diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl new file mode 100644 index 0000000000..0c094d584a --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl @@ -0,0 +1,35 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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_compiler_2). +-export([beam_compiler_2/0]). + +beam_compiler_2() -> + ok. + +-record(foo,{a,b}). + +try_me() -> + try_me({foo,x,z},{foo,y,z}). + +try_me(X,Y) -> + f(X#foo.a =/= Y#foo.a,X#foo.b =/= X#foo.b). + +f(A,B) -> + A. + diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl new file mode 100644 index 0000000000..aced49b69c --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl @@ -0,0 +1,29 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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_compiler_3). +-export([beam_compiler_3/0, f/0]). + +%% From Ulf Wiger. + +beam_compiler_3() -> + ok. + +f() -> + [_|T] = lists:reverse("xxx"), + T. diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl new file mode 100644 index 0000000000..5e74d3cd3c --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl @@ -0,0 +1,150 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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_compiler_4). +-export([beam_compiler_4/0]). + +%% From Ulf Wiger. + +beam_compiler_4() -> + ok. + +selected_alarm(_Env, Parameters) -> + UnWebParam = x, + [Time, Severity, Info, Cause, + Type, Sender, Name, FaultId] = bar:foo(), + + %% The following case generates no test heap instructions, + %% but the test heap generated before the call to bar:foo(), + %% will be moved to here. And the number of words to allocate + %% will be ridicously big (> 65535) and will not fit in a 16 big + %% word. + + SenderLink = case Name of + "pchScheduledConnectionAlarm" -> + Sender; + "pchVpVcAlarm" -> + Sender; + "pchSystemMemoryAlarm" -> + Sender; + "uniProtocolRestartFailureAlarm" -> + Sender; + "spvcScheduledConnectionAlarm" -> + Sender; + "eqmSwitchCoreInterfaceAlarm" -> + Sender; + "atmPhysicalLayerAlarm" -> + Sender; + "atmBufferCongestionAlarm" -> + Sender; + "sdhLinkAlarm" -> + Sender; + "sdhFarEndAlarm" -> + Sender; + "sdhUpperQosAlarm" -> + Sender; + "sdhLowerQosAlarm" -> + Sender; + "eqmSwitchCoreAlarm" -> + Sender; + "eqmEtAlarm" -> + Sender; + "eqmHwIdentityFaultAlarm" -> + Sender; + "eqmOperatorBlockedEquipmentAlarm" -> + Sender; + "pdh34PathAlarm" -> + Sender; + "pdh34ObservationAlarm" -> + Sender; + "pdh34UpperQosAlarm" -> + Sender; + "pdh34LowerQosAlarm" -> + Sender; + "nsySynchRefAlarm" -> + Sender; + "nsySynchRefBlockedAlarm" -> + Sender; + "nsySynchNodeHoldoverAlarm" -> + Sender; + "nsySynchNodeNotWorkingAlarm" -> + Sender; + "eqmAtbAlarm" -> + Sender; + "eqmCbEtAlarm" -> + Sender; + "eqmCpAlarm" -> + Sender; + "eqmCpInterfaceAlarm" -> + Sender; + "eqmCbClkAlarm" -> + Sender; + "eqmCbClkInterfaceAlarm" -> + Sender; + "eqmCbClkVelocityAlarm" -> + Sender; + "eqmCbClkPhaseDiffAlarm" -> + Sender; + "eqmHwNotFoundAlarm" -> + Sender; + "eqmPduAlarm" -> + Sender; + "eqmFanAlarm" -> + Sender; + "eqmLocAlarm" -> + Sender; + "eqmCustomerDefined1Alarm" -> + Sender; + "eqmCustomerDefined2Alarm" -> + Sender; + "eqmCustomerDefined3Alarm" -> + Sender; + "eqmCustomerDefined4Alarm" -> + Sender; + "eqmOperatorBlockedLinkAlarm" -> + Sender; + "eqmPowerFilterAlarm" -> + Sender; + "eqmCbAbrAlarm" -> + Sender; + "eqmAlarmCutOffAlarm" -> + Sender; + OtherAlarm -> + Sender + end, + + %% The testHeap instruction generated here will move up to before + %% the case. + + bar:foo("<TABLE> + <TR><TD ALIGN=LEFT>Fault id: + <TD>" ++ FaultId ++ " + <TR><TD ALIGN=LEFT>Name: + <TD>" ++ Name ++ " + <TR><TD ALIGN=LEFT>Sender: + <TD>" ++ SenderLink ++ " + <TR><TD ALIGN=LEFT>Class: + <TD>" ++ Type ++ " + <TR><TD ALIGN=LEFT>Cause: + <TD>" ++ Cause ++ " + <TR><TD ALIGN=LEFT>Severity: + <TD>" ++ Severity ++ " + <TR><TD ALIGN=LEFT>Information: + <TD>" ++ Info ++ " + <TR><TD ALIGN=LEFT>Time: + <TD>" ++ Time). diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl new file mode 100644 index 0000000000..a23a0d518c --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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_compiler_5). +-export([beam_compiler_5/0]). + +-compile(export_all). + +beam_compiler_5() -> + ok. + +t() -> + [_|_] = x. diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl new file mode 100644 index 0000000000..f263fd75b2 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl @@ -0,0 +1,153 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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_compiler_6). +-export([beam_compiler_6/0]). + +%% From Ulf Wiger, modified by Bjorn Gustavsson to provoke the +%% same error with partly corrected compiler in P3A. + +beam_compiler_6() -> + ok. + +selected_alarm(_Env, Parameters) -> + UnWebParam = x, + [Time, Severity, Info, Cause, + Type, Sender, Name, FaultId] = bar:foo(), + + %% Each branch of the case needs two words of heap, + %% but the test heap generated before the call to bar:foo(), + %% will be merged to the testHeap of each branch, summed and + %% moved before the branch. And the number of words to allocate + %% will be ridiculously big (> 65535) and will not fit in a + %% 16 bit word. + + SenderLink = + case Name of + "pchScheduledConnectionAlarm" -> + [Sender]; + "pchVpVcAlarm" -> + [Sender]; + "pchSystemMemoryAlarm" -> + [Sender]; + "uniProtocolRestartFailureAlarm" -> + [Sender]; + "spvcScheduledConnectionAlarm" -> + [Sender]; + "eqmSwitchCoreInterfaceAlarm" -> + [Sender]; + "atmPhysicalLayerAlarm" -> + [Sender]; + "atmBufferCongestionAlarm" -> + [Sender]; + "sdhLinkAlarm" -> + [Sender]; + "sdhFarEndAlarm" -> + [Sender]; + "sdhUpperQosAlarm" -> + [Sender]; + "sdhLowerQosAlarm" -> + [Sender]; + "eqmSwitchCoreAlarm" -> + [Sender]; + "eqmEtAlarm" -> + [Sender]; + "eqmHwIdentityFaultAlarm" -> + [Sender]; + "eqmOperatorBlockedEquipmentAlarm" -> + [Sender]; + "pdh34PathAlarm" -> + [Sender]; + "pdh34ObservationAlarm" -> + [Sender]; + "pdh34UpperQosAlarm" -> + [Sender]; + "pdh34LowerQosAlarm" -> + [Sender]; + "nsySynchRefAlarm" -> + [Sender]; + "nsySynchRefBlockedAlarm" -> + [Sender]; + "nsySynchNodeHoldoverAlarm" -> + [Sender]; + "nsySynchNodeNotWorkingAlarm" -> + [Sender]; + "eqmAtbAlarm" -> + [Sender]; + "eqmCbEtAlarm" -> + [Sender]; + "eqmCpAlarm" -> + [Sender]; + "eqmCpInterfaceAlarm" -> + [Sender]; + "eqmCbClkAlarm" -> + [Sender]; + "eqmCbClkInterfaceAlarm" -> + [Sender]; + "eqmCbClkVelocityAlarm" -> + [Sender]; + "eqmCbClkPhaseDiffAlarm" -> + [Sender]; + "eqmHwNotFoundAlarm" -> + [Sender]; + "eqmPduAlarm" -> + [Sender]; + "eqmFanAlarm" -> + [Sender]; + "eqmLocAlarm" -> + [Sender]; + "eqmCustomerDefined1Alarm" -> + [Sender]; + "eqmCustomerDefined2Alarm" -> + [Sender]; + "eqmCustomerDefined3Alarm" -> + [Sender]; + "eqmCustomerDefined4Alarm" -> + [Sender]; + "eqmOperatorBlockedLinkAlarm" -> + [Sender]; + "eqmPowerFilterAlarm" -> + [Sender]; + "eqmCbAbrAlarm" -> + [Sender]; + "eqmAlarmCutOffAlarm" -> + [Sender]; + OtherAlarm -> + [Sender] + end, + + %% The testHeap instruction generated here will move up to before + %% the case. + + bar:foo("<TABLE> + <TR><TD ALIGN=LEFT>Fault id: + <TD>" ++ FaultId ++ " + <TR><TD ALIGN=LEFT>Name: + <TD>" ++ Name ++ " + <TR><TD ALIGN=LEFT>Sender: + <TD>" ++ SenderLink ++ " + <TR><TD ALIGN=LEFT>Class: + <TD>" ++ Type ++ " + <TR><TD ALIGN=LEFT>Cause: + <TD>" ++ Cause ++ " + <TR><TD ALIGN=LEFT>Severity: + <TD>" ++ Severity ++ " + <TR><TD ALIGN=LEFT>Information: + <TD>" ++ Info ++ " + <TR><TD ALIGN=LEFT>Time: + <TD>" ++ Time). diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl new file mode 100644 index 0000000000..f1f4839798 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl @@ -0,0 +1,31 @@ +%% +%% %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_compiler_8). + +-compile(export_all). + +beam_compiler_8() -> + ok. + +t(Key, Me) -> + Fun = fun(X) -> + me_rec:key_values(X, Key) < me_rec:key_values(Me, Key) + end. + + diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl new file mode 100644 index 0000000000..581b908753 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl @@ -0,0 +1,67 @@ +%% +%% %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_compiler_9). + +-export([compile/2, test/0, ?MODULE/0]). + +?MODULE() -> + ok. + +test() -> + Failures = failures(), + compile_files([hd(Failures)]). + +compile_files([File | Files]) -> + Pid = spawn(?MODULE, compile, [File, self()]), + Time = infinity, + receive + done -> + compile_files(Files) + after + Time -> + io:fwrite("Compilation not completed within ~w ms~n", [Time]), + exit(Pid, die), + compile_files(Files) + end; + +compile_files([]) -> + done. + + + +compile(File, Parent) -> + io:fwrite("Compiling: ~s~n", [File]), + statistics(runtime), + statistics(wall_clock), + statistics(reductions), + Result = c:c(File), + {_, Rslc} = statistics(runtime), + {_, Tslc} = statistics(wall_clock), + {_, Reds} = statistics(reductions), + io:fwrite("Result: ~w~n", [Result]), + io:fwrite("Reductions: ~w~n", [Reds]), + io:fwrite("Time: ~w~n", [Tslc]), + io:fwrite("Cpu time: ~w~n", [Rslc]), + io:nl(), + Parent ! done. + + + +failures() -> + [test]. diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl new file mode 100644 index 0000000000..7df1543d83 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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(bin_syntax_1). + +-export([f/2,?MODULE/0]). + +?MODULE() -> + ok. + +f(X, Y) -> + case X of + a -> + Y2 = 8 + end, + <<5:Y2>> = Y. diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl new file mode 100644 index 0000000000..dcf7b0f8bd --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl @@ -0,0 +1,41 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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(bin_syntax_2). + +-export([?MODULE/0]). + +%% This module tests that constant propagation is done properly. + +?MODULE() -> + 258 = b(<<1,2>>), + F = c(), + 259 = F(<<1,3>>), + ok. + +b(B) -> + Sz = 16, + <<X:Sz/integer>> = B, + X. + +c() -> + Size = 16, + fun(Bin) -> + <<X:Size/integer>> = Bin, + X + end. diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl new file mode 100644 index 0000000000..93d35d5628 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl @@ -0,0 +1,35 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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(bin_syntax_3). +-export([?MODULE/0,decode_integer/3]). + +?MODULE() -> + ok. + +decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) when B1 == 0 -> + Bin = <<Skip:Len/unit:8, Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>, + Size = size(Bin), + <<Int:Size/unit:8>> = Bin, + {Int,Buffer2,RemovedBytes}; +decode_integer(Len,<<B1:1,B2:7,Bs/binary>>,RemovedBytes) -> + Bin = <<Skip:Len/unit:8,Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>, + Size = size(Bin), + <<N:Size/unit:8>> = <<B2,Bs/binary>>, + Int = N - (1 bsl (8 * size(Bin) -1)), + {Int,Buffer2,RemovedBytes}. diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl new file mode 100644 index 0000000000..fe0ce80270 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl @@ -0,0 +1,32 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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(bin_syntax_4). +-export([?MODULE/0,f4b/2,f4c/2]). + +?MODULE() -> + ok. + +f4b(X, Y) -> + fun (<< A:Y >>, Y, B) -> fum(A, X, Y, B) end. + +f4c(X, Y) -> + fun (Y, << A:Y >>, B) -> fum(A, X, Y, B) end. + +fum(A, B, C, D) -> + {A,B,C,D}. diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl new file mode 100644 index 0000000000..8de3a9094f --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl @@ -0,0 +1,39 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(bin_syntax_6). +-export([?MODULE/0,x/1,y/1]). + +?MODULE() -> + ok. + +x(X) -> + blurf(), + B = {X,"OK",<<>>}, + catch b({a,B}). + +y(X) -> + blurf(), + B = {X,"OK",<<42>>}, + catch b({a,B}). + +blurf() -> + ok. + +b(_) -> + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl b/lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl new file mode 100644 index 0000000000..c732a912f0 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl @@ -0,0 +1,51 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(catch_in_catch). + +-export([?MODULE/0,do_start/1]). + +?MODULE() -> + process_flag(trap_exit, true), + Pid = spawn_link(?MODULE, do_start, [x]), + receive + {'EXIT',Pid,good_exit} -> ok; + Other -> + io:format("Unexpected: ~p\n", [Other]), + error + after 32000 -> + io:format("No message received\n"), + error + end. + +do_start(Param) -> + init(Param), + exit(good_exit). + +init(Param) -> + process_flag(trap_exit, true), + %% The catches were improperly nested, causing a "No catch found" crash. + (catch begin + foo(Param), + (catch exit(bar)) + end + ), + ignore. + +foo(_) -> + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_1.erl b/lib/compiler/test/compilation_SUITE_data/compiler_1.erl new file mode 100644 index 0000000000..6dbd80d962 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/compiler_1.erl @@ -0,0 +1,742 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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(compiler_1). +-compile([export_all]). + +compiler_1() -> ok. + +-define(log(Format,Args),mnesia_test_lib:log(Format,Args,?FILE,?LINE)). +-define(warning(Format,Args),?log("<WARNING> " ++ Format,Args)). +-define(error(Format,Args), + mnesia_test_lib:note_error(Format,Args,?FILE,?LINE), + ?log("<ERROR> " ++ Format,Args)). + +-define(match(ExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + ExpectedRes -> + ?log("ok, result as expected: ~p~n",[AcTuAlReS]), + {success,AcTuAlReS}; + _ -> + ?error("actual result was: ~p~n",[AcTuAlReS]), + {fail,AcTuAlReS} + end + end()). + +-define(match_inverse(NotExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + NotExpectedRes -> + ?error("actual result was: ~p~n",[AcTuAlReS]), + {fail,AcTuAlReS}; + _ -> + ?log("ok, result as expected: ~p~n",[AcTuAlReS]), + {success,AcTuAlReS} + end + end()). + +-define(match_receive(ExpectedMsg), + ?match(ExpectedMsg,mnesia_test_lib:pick_msg())). + +%% ExpectedMsgs must be completely bound +-define(match_multi_receive(ExpectedMsgs), + fun() -> + TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs), + ?match(TmPeXpCtEdMsGs, + lists:sort(lists:map(fun(_) -> + mnesia_test_lib:pick_msg() + end, + TmPeXpCtEdMsGs))) + end()). + +-define(setup(), mnesia_test_lib:setup(?FILE,?LINE)). + +-define(start_activities(Nodes), + fun() -> + AcTiViTyPiDs = + lists:map(fun(Node) -> + spawn_link(Node, + mnesia_test_lib, + activity_evaluator, + [self()]) + end, + Nodes), + ?match_multi_receive(AcTiViTyPiDs) + end()). + +-define(start_transactions(Pids), + ?match_multi_receive(lists:map(fun(Pid) -> + Pid ! begin_trans, + {Pid,begin_trans} + end, + Pids))). + +-define(acquire_nodes(N,Nodes), + mnesia_test_lib:acquire_nodes(N,Nodes,?FILE,?LINE)). + + + +%%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories +%%% Author: Hakan Mattsson [email protected] +%%% Purpose: Evil usage of the API +%%% +%%% Invoke all functions in the API and try to cover all legal uses +%%% cases as well the illegal dito. This is a complement to the +%%% other more explicit test cases. +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% show/0 +%%% +%%% Prints out the complete test case structure +%%% +%%% show/1 +%%% +%%% Prints out parts of the test case structure +%%% +%%% test/0 +%%% +%%% Run the complete test suite. +%%% Reads Nodes from nodes.profile and starts them if neccessary. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/1 +%%% +%%% Run parts of the test suite. +%%% Reads Nodes from nodes.profile and starts them if neccessary. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/2 +%%% +%%% Run parts of the test suite on the given Nodes, +%%% assuming that the nodes are up and running. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/3 +%%% +%%% Run parts of the test suite on permutations of the given Nodes, +%%% assuming that the nodes are up and running. Uses test/2. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% See the module mnesia_test_lib for further information. +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +show() -> mnesia_test_lib:show([{?MODULE,all}]). +show(TestCases) -> mnesia_test_lib:show([{?MODULE,TestCases}]). +test() -> mnesia_test_lib:test([{?MODULE,all}]). +test(TestCases) -> mnesia_test_lib:test([{?MODULE,TestCases}]). +test(TestCases,Nodes) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes). +test(TestCases,Nodes,Config) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes,Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +old_all(suite) -> + [ + system_info, table_info, error_description, + db_node_lifecycle, start_and_stop, transaction, checkpoint, backup, + table_lifecycle, replica_management, replica_location, index_lifecycle, + trans_access, dirty_access, table_sync, snmp_access, debug_support + ]. + +trans_access(suite) -> + [ {mnesia_dirty_access_test,all} ]. + +dirty_access(suite) -> + [ {mnesia_trans_access_test,all} ]. + +%% Get meta info about Mnesia +system_info(suite) -> []; +system_info(Nodes) -> + ?match(yes,mnesia:system_info(is_running)), + ?match(Nodes,mnesia:system_info(db_nodes)), + ?match(Nodes,mnesia:system_info(running_db_nodes)), + ?match(true,mnesia:system_info(have_disc)), + ?match(A when atom(A),mnesia:system_info(debug)), + ?match(L when list(L),mnesia:system_info(directory)), + ?match(L when list(L),mnesia:system_info(log_version)), + ?match({_,_},mnesia:system_info(schema_version)), + ?match(L when list(L),mnesia:system_info(tables)), + ?match(L when list(L),mnesia:system_info(local_tables)), + ?match(L when list(L),mnesia:system_info(held_locks)), + ?match(L when list(L),mnesia:system_info(lock_queue)), + ?match(L when list(L),mnesia:system_info(transactions)), + ?match(I when integer(I),mnesia:system_info(transaction_failures)), + ?match(I when integer(I),mnesia:system_info(transaction_commits)), + ?match(I when integer(I),mnesia:system_info(transaction_restarts)), + ?match(L when list(L),mnesia:system_info(checkpoints)), + ?match(A when atom(A),mnesia:system_info(backup_module)), + ?match(true,mnesia:system_info(auto_repair)), + ?match({_,_},mnesia:system_info(dump_log_interval)), + ?match(A when atom(A),mnesia:system_info(dump_log_update_in_place)), + ?match(I when integer(I),mnesia:system_info(transaction_log_writes)), + ?match({'EXIT',{aborted,badarg}},mnesia:system_info(ali_baba)), + done. + +%% Get meta info about table +table_info(suite) -> []; +table_info(Nodes) -> + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + + Tab = table_info, + Type = bag, + ValPos = 3, + Attrs = [k,v], + Arity = length(Attrs) +1, + Schema = [{name,Tab},{type,Type},{attributes,Attrs},{index,[ValPos]}, + {disc_only_copies,[Node1]},{ram_copies,[Node2]},{disc_copies,[Node3]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + + Size = 10, + Keys = lists:seq(1,Size), + Records = [{Tab,A,7} || A <- Keys], + lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), + ?match(Mem when integer(Mem),mnesia:table_info(Tab,memory)), + ?match(Size,mnesia:table_info(Tab,size)), + ?match(Type,mnesia:table_info(Tab,type)), + ?match([Node3],mnesia:table_info(Tab,disc_copies)), + ?match([Node2],mnesia:table_info(Tab,ram_copies)), + ?match([Node1],mnesia:table_info(Tab,disc_only_copies)), + Read = [Node1,Node2,Node3], + ?match(true,lists:member(mnesia:table_info(Tab,where_to_read),Read)), + Write = lists:sort([Node1,Node2,Node3]), + ?match(Write,lists:sort(mnesia:table_info(Tab,where_to_write))), + WriteLock = lists:sort([Node2,Node3]), + ?match([ValPos],mnesia:table_info(Tab,index)), + ?match(Arity,mnesia:table_info(Tab,arity)), + ?match(Attrs,mnesia:table_info(Tab,attributes)), + ?match({Tab,'_','_'},mnesia:table_info(Tab,wild_pattern)), + ?match({atomic,Attrs}, mnesia:transaction(fun() -> + mnesia:table_info(Tab,attributes) end)), + + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add and drop db nodes + +db_node_lifecycle(suite) -> []; +db_node_lifecycle(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + Tab = db_node_lifecycle, + + Schema = [{name,Tab},{ram_copies,[Node1,Node2]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ?match({aborted,active}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + + ?match([], mnesia_test_lib:stop_mnesia(Nodes)), + ?match(ok, mnesia:delete_schema(Nodes)), + ?match({error,_}, mnesia:create_schema(foo)), + ?match({error,_}, mnesia:create_schema([foo])), + ?match({error,_}, mnesia:create_schema([foo@bar])), + ?match({error,_}, mnesia:start()), + + ?match(ok, mnesia:create_schema(Nodes)), + ?match([],mnesia_test_lib:start_mnesia(Nodes)), + ?match({atomic,ok}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo@bar])), + + ?match([], mnesia_test_lib:stop_mnesia([Node2])), + ?match(ok,mnesia:delete_schema([Node2])), + AddFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:add_db_node(Node2)), ok end, + ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[AddFun])), + DelFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:del_db_node(Node2)), ok end, + ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[DelFun])), + + ?match({atomic,ok}, rpc:call(Node1,mnesia,add_db_node,[Node2])), + ?match({aborted,already_exists}, rpc:call(Node1,mnesia,add_db_node,[Node2])), + ?match([],mnesia_test_lib:start_mnesia([Node2])), + ?match({atomic,ok}, mnesia:create_table(Schema)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Start and stop the system + +start_and_stop(suite) -> []; +start_and_stop(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match({started,_}, rpc:call(Node1,mnesia,start,[])), + ?match({started,_}, rpc:call(Node1,mnesia,start,[])), + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match([],mnesia_test_lib:start_mnesia(Nodes)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Checkpoints and backup management + +checkpoint(suite) -> []; +checkpoint(Nodes) -> + OneNode = ?acquire_nodes(1,Nodes), + checkpoint(OneNode,Nodes), + TwoNodes = ?acquire_nodes(2,Nodes), + checkpoint(TwoNodes,Nodes). + +checkpoint(TabNodes,Nodes) -> + [Node1] = ?acquire_nodes(1,TabNodes), + CreateTab = fun(Type,N,Ns) -> + Tab0 = lists:concat(["local_checkpoint_",Type,N]), + Tab = list_to_atom(Tab0), + Schema = [{name,Tab},{Type,Ns}], + ?match({atomic,ok},mnesia:delete_table(Tab)), + ?match({atomic,ok},mnesia:create_table(Schema)), + Tab + end, + CreateTabs = fun(Type) -> + CreateTab(Type,1,hd(TabNodes)), + CreateTab(Type,2,TabNodes), + CreateTab(Type,3,lists:last(TabNodes)) + end, + Types = [ram_copies,disc_copies,disc_only_copies], + Tabs = lists:append(lists:map(CreateTabs,Types)), + Recs = lists:sort([{T,N,N} || T <- Tabs,N <- lists:seq(1,10)]), + lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs), + + CpName = a_checkpoint_name, + MinArgs = [{name,CpName},{min,Tabs},{allow_remote,false}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[MinArgs])), + ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + MaxArgs = [{name,CpName},{max,Tabs},{allow_remote,true}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[MaxArgs])), + ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + Args = [{name,CpName},{min,Tabs},{allow_remote,false}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[Args])), + Recs2 = lists:sort([{T,K,0} || {T,K,_} <- Recs]), + lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs2), + ?match({atomic,ok},rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + ?match({error,no_exists},mnesia:deactivate_checkpoint(CpName)), + ?match({error,badarg},mnesia:activate_checkpoint(foo)), + ?match({error,badarg},mnesia:activate_checkpoint([{foo,foo}])), + ?match({error,badarg},mnesia:activate_checkpoint([{max,foo}])), + ?match({error,badarg},mnesia:activate_checkpoint([{min,foo}])), + ?match({error,no_exists},mnesia:activate_checkpoint([{min,[foo@bar]}])), + ?match({error,badarg},mnesia:activate_checkpoint([{allow_remote,foo}])), + + Fun = fun(Tab) -> ?match({atomic,ok},mnesia:delete_table(Tab)) end, + lists:foreach(Fun,Tabs), + done. + +backup(suite) -> + [ + backup_schema, restore_schema, backup_checkpoint, restore_tables + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Use and misuse transactions + +transaction(suite) -> []; +transaction(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + ?match({atomic,ali_baba}, mnesia:transaction(fun() -> ali_baba end)), + ?match({aborted,_}, mnesia:transaction(no_fun)), + ?match({aborted,_}, mnesia:transaction(?MODULE,no_fun,[foo])), + + {success,[A,B,C,D,E,F,G,H]} = ?start_activities(lists:duplicate(8,Node1)), + ?start_transactions([A,B,C,D,E,F,G,H]), + + A ! fun() -> mnesia:abort(abort_bad_trans) end, + ?match_receive({A,{aborted,abort_bad_trans}}), + + B ! fun() -> 1 = 2 end, + ?match_receive({B,{aborted,_}}), + + C ! fun() -> throw(throw_bad_trans) end, + ?match_receive({C,{aborted,{throw,throw_bad_trans}}}), + + D ! fun() -> exit(exit_bad_trans) end, + ?match_receive({D,{aborted,exit_bad_trans}}), + + E ! fun() -> exit(normal) end, + ?match_receive({E,{aborted,normal}}), + + F ! fun() -> exit(abnormal) end, + ?match_receive({F,{aborted,abnormal}}), + + G ! fun() -> exit(G,abnormal) end, + ?match_receive({'EXIT',G,abnormal}), + + H ! fun() -> exit(H,kill) end, + ?match_receive({'EXIT',H,killed}), + + ?match({atomic,ali_baba}, + mnesia:transaction(fun() -> ali_baba end,infinity)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,1)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,0)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,-1)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,foo)), + Fun = fun() -> ?match({aborted,nested_transaction}, + mnesia:transaction(fun() -> ok end)), ok end, + ?match({atomic,ok},mnesia:transaction(Fun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create and delete tables + +%% Get meta info about table + +replica_location(suite) -> []; +replica_location(Nodes) -> + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + Tab = replica_location, + + %% Create three replicas + Schema = [{name,Tab},{disc_only_copies,[Node1]}, + {ram_copies,[Node2]},{disc_copies,[Node3]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[Node2],[Node3],Nodes), + + %% Delete one replica + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node3],Nodes), + + %% Move one replica + ?match({atomic,ok}, mnesia:move_table_copy(Tab, Node1, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node3],Nodes), + + %% Change replica type + ?match({atomic,ok}, mnesia:change_table_copy_type(Tab, Node2,ram_copies)), + mnesia_test_lib:verify_replica_location(Tab,[],[Node2],[Node3],Nodes), + + done. + +table_lifecycle(suite) -> []; +table_lifecycle(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + + ?match({atomic,ok}, mnesia:create_table([{type,bag}, + {ram_copies,[Node1]}, + {attributes,[rajtan,tajtan]}, + {name,order_of_args}])), + ?match([],mnesia:dirty_read({order_of_args,4711})), + ?match({atomic,ok}, mnesia:create_table([{name,already_exists}, + {ram_copies,[Node1]}])), + ?match({aborted,already_exists}, + mnesia:create_table([{name,already_exists},{ram_copies,[Node1]}])), + ?match({aborted,not_a_db_node}, + mnesia:create_table([{name,no_node},{ram_copies,[foo]}])), + ?match({aborted,not_a_db_node}, + mnesia:create_table([{name,no_host},{ram_copies,[foo@bar]}])), + ?match({aborted,badarg}, + mnesia:create_table([{name,zero_arity},{attributes,[]}])), + ?match({aborted,badarg}, mnesia:create_table([])), + ?match({aborted,badarg}, mnesia:create_table(atom)), + ?match({aborted,badarg}, + mnesia:create_table({cstruct,table_name_as_atom})), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{ram_copies,foo}])), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{disc_only_copies,foo}])), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{disc_copies,foo}])), + + CreateFun = + fun() -> ?match({aborted,nested_transaction}, + mnesia:create_table([{name,nested_trans}])), ok + end, + ?match({atomic,ok},mnesia:transaction(CreateFun)), + ?match({atomic,ok},mnesia:create_table([{name,remote_tab}, + {ram_copies,[Node2]}])), + + ?match({atomic,ok}, mnesia:create_table([{name,a_brand_new_tab}, + {ram_copies,[Node1]}])), + ?match([],mnesia:dirty_read({a_brand_new_tab,4711})), + ?match({atomic,ok}, mnesia:delete_table(a_brand_new_tab)), + ?match({'EXIT',{aborted,no_exists}}, + mnesia:dirty_read({a_brand_new_tab,4711})), + ?match({aborted,no_exists}, mnesia:delete_table(a_brand_new_tab)), + ?match({aborted,badarg}, mnesia:create_table([])), + + ?match({atomic,ok}, mnesia:create_table([{name,nested_del_trans}, + {ram_copies,[Node1]}])), + DeleteFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:delete_table(nested_del_trans)), ok end, + ?match({atomic,ok}, mnesia:transaction(DeleteFun)), + + ?match({aborted,bad_type}, + mnesia:create_table([{name,create_with_index},{index,2}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[-1]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[0]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[1]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[2]}])), + ?match({atomic,ok}, + mnesia:create_table([{name,create_with_index},{index,[3]}, + {ram_copies,[Node1]}])), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add, drop and move replicas, change storage types +%% Change table layout (only arity change supported) + +replica_management(suite) -> []; +replica_management(Nodes) -> + %% add_table_copy/3, del_table_copy/2, move_table_copy/3, + %% change_table_copy_type/3, transform_table/3 + + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + + Tab = replica_management, + Attrs = [k,v], + + %% + %% Add, delete and change replicas + %% + ?match({atomic,ok}, + mnesia:create_table([{name,Tab},{attributes,Attrs}, + {ram_copies,[Node1]}])), + mnesia_test_lib:verify_replica_location(Tab,[],[Node1],[],Nodes), + %% R - - + ?match({aborted,combine_error}, + mnesia:add_table_copy(Tab, Node2, disc_copies)), + ?match({aborted,combine_error}, + mnesia:change_table_copy_type(Tab, Node1, disc_copies)), + ?match({atomic,ok}, mnesia:del_table_copy(Tab,Node1)), + mnesia_test_lib:verify_replica_location(Tab,[],[],[],Nodes), + %% - - - + ?match({aborted,no_exists}, + mnesia:add_table_copy(Tab, Node3, ram_copies)), + + ?match({atomic,ok}, mnesia:create_table([{name,Tab}, + {attributes,Attrs}, + {disc_copies,[Node1]}])), + mnesia_test_lib:verify_replica_location(Tab,[],[],[Node1],Nodes), + %% D - - + ?match({aborted,badarg}, + mnesia:add_table_copy(Tab, Node2, bad_storage_type)), + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node1],Nodes), + %% D DO - + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), + %% D DO R + ?match({atomic,ok}, + mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node1,Node2],[Node3],[],Nodes), + %% DO DO R + ?match({aborted,already_exists}, + mnesia:add_table_copy(Tab, Node3, ram_copies)), + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node1)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[],Nodes), + %% - DO R + ?match({aborted,_}, mnesia:del_table_copy(Tab, Node1)), + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), + %% D DO R + ?match({atomic,ok}, + mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2,Node3],[],[Node1],Nodes), + %% D DO DO + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node1],Nodes), + %% D - DO + ?match({aborted,already_exists}, + mnesia:change_table_copy_type(Tab, Node1, disc_copies)), + + %% + %% Move replica + %% + ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node1,Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],Nodes), + %% - D DO + ?match({aborted,_}, mnesia:move_table_copy(Tab,Node1,Node2)), + ?match([], mnesia_test_lib:stop_mnesia([Node3])), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2], + Nodes -- [Node3]), + %% - D DO + ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node3,Node1)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2], + Nodes -- [Node3]), + %% DO D - + ?match([],mnesia_test_lib:start_mnesia([Node3])), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],Nodes), + %% DO D - + + %% + %% Transformer + %% + + NewAttrs = Attrs ++ [extra], + Transformer = + fun(Rec) -> list_to_tuple(tuple_to_list(Rec) ++ [initial_value]) end, + ?match({atomic,ok}, mnesia:transform_table(Tab, Transformer,NewAttrs)), + ?match({atomic,ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, 0)), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, -1)), + ?match({aborted,badarg}, mnesia:transform_table(Tab, Transformer, [])), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, no_fun, NewAttrs)), + + NestedFun = + fun() -> + ?match({aborted,_}, + mnesia:move_table_copy(Tab,Node1,Node2)), + ?match({aborted,_}, + mnesia:add_table_copy(Tab,Node1,ram_copies)), + ?match({aborted,_}, + mnesia:del_table_copy(Tab,Node1)), + T = fun(_) -> 4711 end, + ?match({aborted,_}, + mnesia:transform_table(Tab,Transformer, T)), + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add and drop indecies + +index_lifecycle(suite) -> + [ add_table_index, create_live_table_index, del_table_index ]. + +%% Add table index + +add_table_index(suite) -> []; +add_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = add_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,BadValPos)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,2)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,1)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,0)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,-1)), + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + ?match({aborted,already_exists}, mnesia:add_table_index(Tab,ValPos)), + + NestedFun = fun() -> + ?match({aborted,nested_transaction}, + mnesia:add_table_index(Tab,ValPos)), + + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +create_live_table_index(suite) -> []; +create_live_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = create_live_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + mnesia:dirty_write({Tab,1,2}), + + Fun = fun() -> + ?match(ok, mnesia:write({Tab,2,2})), + ok + end, + ?match({atomic,ok},mnesia:transaction(Fun)), + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + done. + +%% Drop table index + +del_table_index(suite) ->[]; +del_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = del_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + ?match({aborted,no_exists}, + mnesia:del_table_index(Tab,BadValPos)), + ?match({atomic,ok}, mnesia:del_table_index(Tab,ValPos)), + + NestedFun = + fun() -> + ?match({aborted,nested_transaction}, + mnesia:del_table_index(Tab,ValPos)), + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Syncronize table with log or disc +%% +table_sync(suite) -> + [ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ]. + +%% Dump ram tables on disc +dump_tables(suite) -> []; +dump_tables(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + Tab = dump_tables, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node2]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + + %% Dump 10 records + Size = 10, + Keys = lists:seq(1,Size), + Records = [{Tab,A,7} || A <- Keys], + lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), + AllKeys = fun() -> lists:sort(mnesia:all_keys(Tab)) end, + + ?match({atomic,Keys}, mnesia:transaction(AllKeys)), + ?match(ok, mnesia:dump_tables(Tab)), + + %% Delete one record + ?match(ok,mnesia:dirty_delete({Tab,5})), + Keys2 = lists:delete(5,Keys), + ?match({atomic,Keys2}, mnesia:transaction(AllKeys)), + + %% Check that all 10 is restored after a stop + ?match([], mnesia_test_lib:stop_mnesia([Node1,Node2])), + ?match([],mnesia_test_lib:start_mnesia([Node1,Node2])), + ?match(ok,mnesia:wait_for_tables([Tab],infinity)), + ?match({atomic,Keys}, mnesia:transaction(AllKeys)), + + ?match(ok, mnesia:dump_tables([foo])), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make Mnesia table accessible via SNMP + +snmp_access(suite) -> + [ + snmp_open_table, snmp_close_table, + snmp_get_row, snmp_get_next_index, snmp_get_mnesia_key + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Check that the debug support has not decayed + +debug_support(suite) -> + [ info, schema, schema, kill, lkill ]. + diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_3.erl b/lib/compiler/test/compilation_SUITE_data/compiler_3.erl new file mode 100644 index 0000000000..47891a22b5 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/compiler_3.erl @@ -0,0 +1,33 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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(compiler_3). +-export([compiler_3/0]). +-record(rec,{a}). + +compiler_3() -> + guard_record(). + +guard_record() -> + 1=func(#rec{}), + {'EXIT',_} = (catch func({rec})), + ok. + +func(X) when record(X, +rec) -> + 1. diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_5.erl b/lib/compiler/test/compilation_SUITE_data/compiler_5.erl new file mode 100644 index 0000000000..c2a0c2064f --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/compiler_5.erl @@ -0,0 +1,49 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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(compiler_5). +-export([compiler_5/0]). + +compiler_5() -> + f0(), + f1(), + f2(), + ok. + +%% compiler treats records with 1 and 2 fields differently... +-record(nil, {}). +-record(foo, {hello=1}). +-record(bar, {hello=2,there=3}). + +f0() -> + R1 = #nil{}, + R2 = R1#nil{}, %% stupid code, but compiler shouldn't crash + R1 = R2, + ok. + +f1() -> + R1 = #foo{}, + R2 = R1#foo{}, %% stupid code, but compiler shouldn't crash + R1 = R2, + ok. + +f2() -> + R1 = #bar{}, + R2 = R1#bar{}, %% stupid code, but compiler shouldn't crash + R1 = R2, + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/complex_guard.erl b/lib/compiler/test/compilation_SUITE_data/complex_guard.erl new file mode 100644 index 0000000000..961aa6a460 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/complex_guard.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(complex_guard). + +-compile(export_all). + +?MODULE() -> + ok. + +f(X1,Y1,Z1) -> + if + ((X1 =:= 4) or (X1 =:= 5)) and ((Y1 =:= 4) or (Y1 =:= 5)) and ((Z1 =:= 4) or (Z1 =:= 5)) or ((X1 =:= 1) or (X1 =:= 2) or (X1 =:= 3)) and ((Y1 =:= 1) or (Y1 =:= 2) or (Y1 =:= 3)) and ((Z1 =:= 1) or (Z1 =:= 2) or (Z1 =:= 3)) -> + true + end. + diff --git a/lib/compiler/test/compilation_SUITE_data/const_list_256.erl b/lib/compiler/test/compilation_SUITE_data/const_list_256.erl new file mode 100644 index 0000000000..0baf427911 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/const_list_256.erl @@ -0,0 +1,282 @@ +%% +%% %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(const_list_256). +-export([?MODULE/0]). + +?MODULE() -> + put_list(x), + ok. + +put_list(A) -> + [{A, 255}, + {A, 254}, + {A, 253}, + {A, 252}, + {A, 251}, + {A, 250}, + {A, 249}, + {A, 248}, + {A, 247}, + {A, 246}, + {A, 245}, + {A, 244}, + {A, 243}, + {A, 242}, + {A, 241}, + {A, 240}, + {A, 239}, + {A, 238}, + {A, 237}, + {A, 236}, + {A, 235}, + {A, 234}, + {A, 233}, + {A, 232}, + {A, 231}, + {A, 230}, + {A, 229}, + {A, 228}, + {A, 227}, + {A, 226}, + {A, 225}, + {A, 224}, + {A, 223}, + {A, 222}, + {A, 221}, + {A, 220}, + {A, 219}, + {A, 218}, + {A, 217}, + {A, 216}, + {A, 215}, + {A, 214}, + {A, 213}, + {A, 212}, + {A, 211}, + {A, 210}, + {A, 209}, + {A, 208}, + {A, 207}, + {A, 206}, + {A, 205}, + {A, 204}, + {A, 203}, + {A, 202}, + {A, 201}, + {A, 200}, + {A, 199}, + {A, 198}, + {A, 197}, + {A, 196}, + {A, 195}, + {A, 194}, + {A, 193}, + {A, 192}, + {A, 191}, + {A, 190}, + {A, 189}, + {A, 188}, + {A, 187}, + {A, 186}, + {A, 185}, + {A, 184}, + {A, 183}, + {A, 182}, + {A, 181}, + {A, 180}, + {A, 179}, + {A, 178}, + {A, 177}, + {A, 176}, + {A, 175}, + {A, 174}, + {A, 173}, + {A, 172}, + {A, 171}, + {A, 170}, + {A, 169}, + {A, 168}, + {A, 167}, + {A, 166}, + {A, 165}, + {A, 164}, + {A, 163}, + {A, 162}, + {A, 161}, + {A, 160}, + {A, 159}, + {A, 158}, + {A, 157}, + {A, 156}, + {A, 155}, + {A, 154}, + {A, 153}, + {A, 152}, + {A, 151}, + {A, 150}, + {A, 149}, + {A, 148}, + {A, 147}, + {A, 146}, + {A, 145}, + {A, 144}, + {A, 143}, + {A, 142}, + {A, 141}, + {A, 140}, + {A, 139}, + {A, 138}, + {A, 137}, + {A, 136}, + {A, 135}, + {A, 134}, + {A, 133}, + {A, 132}, + {A, 131}, + {A, 130}, + {A, 129}, + {A, 128}, + {A, 127}, + {A, 126}, + {A, 125}, + {A, 124}, + {A, 123}, + {A, 122}, + {A, 121}, + {A, 120}, + {A, 119}, + {A, 118}, + {A, 117}, + {A, 116}, + {A, 115}, + {A, 114}, + {A, 113}, + {A, 112}, + {A, 111}, + {A, 110}, + {A, 109}, + {A, 108}, + {A, 107}, + {A, 106}, + {A, 105}, + {A, 104}, + {A, 103}, + {A, 102}, + {A, 101}, + {A, 100}, + {A, 99}, + {A, 98}, + {A, 97}, + {A, 96}, + {A, 95}, + {A, 94}, + {A, 93}, + {A, 92}, + {A, 91}, + {A, 90}, + {A, 89}, + {A, 88}, + {A, 87}, + {A, 86}, + {A, 85}, + {A, 84}, + {A, 83}, + {A, 82}, + {A, 81}, + {A, 80}, + {A, 79}, + {A, 78}, + {A, 77}, + {A, 76}, + {A, 75}, + {A, 74}, + {A, 73}, + {A, 72}, + {A, 71}, + {A, 70}, + {A, 69}, + {A, 68}, + {A, 67}, + {A, 66}, + {A, 65}, + {A, 64}, + {A, 63}, + {A, 62}, + {A, 61}, + {A, 60}, + {A, 59}, + {A, 58}, + {A, 57}, + {A, 56}, + {A, 55}, + {A, 54}, + {A, 53}, + {A, 52}, + {A, 51}, + {A, 50}, + {A, 49}, + {A, 48}, + {A, 47}, + {A, 46}, + {A, 45}, + {A, 44}, + {A, 43}, + {A, 42}, + {A, 41}, + {A, 40}, + {A, 39}, + {A, 38}, + {A, 37}, + {A, 36}, + {A, 35}, + {A, 34}, + {A, 33}, + {A, 32}, + {A, 31}, + {A, 30}, + {A, 29}, + {A, 28}, + {A, 27}, + {A, 26}, + {A, 25}, + {A, 24}, + {A, 23}, + {A, 22}, + {A, 21}, + {A, 20}, + {A, 19}, + {A, 18}, + {A, 17}, + {A, 16}, + {A, 15}, + {A, 14}, + {A, 13}, + {A, 12}, + {A, 11}, + {A, 10}, + {A, 9}, + {A, 8}, + {A, 7}, + {A, 6}, + {A, 5}, + {A, 4}, + {A, 3}, + {A, 2}, + {A, 1}, + {A, 0}]. diff --git a/lib/compiler/test/compilation_SUITE_data/convopts.erl b/lib/compiler/test/compilation_SUITE_data/convopts.erl new file mode 100644 index 0000000000..429c683ca9 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/convopts.erl @@ -0,0 +1,159 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-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(convopts). + +-export([?MODULE/0]). + +-define(UINT32_MAX, ((1 bsl 32) - 1)). + +?MODULE() -> + Type = 12345, + Inst = 1, + Zone = 0, + case convopts([{dest, {tipc_name, Type, Inst, Zone}}]) of + {ok, [{$B, <<Type:32, Inst:32, Zone:32>>}]} -> + ok; + Other -> + {error, Other} + end. + + + +convopts(Opts) -> + catch + case getopts(Opts, [active, recvfrom, importance, distribution, + dest]) of + {[Active, Recvfrom, Importance, Distribution, + Dest], []} -> + {R, RR} = + case {Active, Recvfrom} of + {[], [recvfrom]} -> + throw({error, einval}); + {_, [recvfrom]} -> + {$r, $R}; + {_, _} -> + {$e, $E} + end, + {ok, + lists:flatten( + [case Active of + [{active, true}] -> + [{R, <<?UINT32_MAX:32>>}]; + [{active, N}] when integer(N), + 0 =< N, N < ?UINT32_MAX -> + [{R, <<N:32>>}]; + [{active, N}] when integer(N), + -?UINT32_MAX < N, N < 0 -> + [{RR, <<-N:32>>}]; + [{active, once}] -> + [{R, <<1:32>>}]; + [{active, false}] -> + [{R, <<0:32>>}]; + [] -> + []; + _ -> + throw({error, einval}) + end, + case Importance of + [{importance, normal}] -> + [{$i, []}]; + [{importance, high}] -> + [{$I, []}]; + [] -> + []; + _ -> + throw({error, einval}) + end, + case Distribution of + [distribution] -> + [{$d, []}]; + [] -> + []; + _ -> + throw({error, einval}) + end, + case Dest of + %% Port addressed message + [{dest, {tipc_port_id, Port, Proc}}] + when binary(Port), + integer(Proc), 0 =< Proc, Proc =< ?UINT32_MAX + ; + list(Port), + integer(Proc), 0 =< Proc, Proc =< ?UINT32_MAX -> + [{$p, [Port | <<Proc:32>>]}]; + %% Name addressed message + [{dest, {tipc_name, Type, Inst, Zone}}] + when integer(Type), 0 =< Type, Type =< ?UINT32_MAX, + integer(Inst), 0 =< Inst, Inst =< ?UINT32_MAX, + integer(Zone), 0 =< Zone, Zone =< ?UINT32_MAX -> + [{$B, <<Type:32, Inst:32, Zone:32>>}]; + %% + %% This undocumented clause uses an undocumented + %% feature of the TIPC socket interface that takes + %% advantage of some gory internals of the protocol. + %% It is protocol implementation dependant and + %% breaks the whole idea of location transparency + %% for name addressed messages. Therefore it should + %% only be used when all other possibilities are + %% exhausted. + %% + [{dest, {tipc_name, Type, Inst, + {tipc_processor_id, + Zone, Subnetwork, Processor}}}] + when integer(Type), 0 =< Type, Type =< ?UINT32_MAX, + integer(Inst), 0 =< Inst, Inst =< ?UINT32_MAX, + integer(Zone), + 0 =< Zone, Zone < 16#FF, + integer(Subnetwork), + 0 =< Subnetwork, Subnetwork < 16#FFF, + integer(Processor), + 0 =< Processor, Processor < 16#FFF -> + [{$B, <<Type:32, + Inst:32, + Zone:8, Subnetwork:12, Processor:12>>}]; + [] -> + []; + _ -> + throw({error, einval}) + end + ])}; + _ -> + throw({error, einval}) + end. + + + +getopts(List, Options) when list(List), list(Options) -> + getopts_1(Options, List, []). + +getopts_1([], List, Result) -> + {lists:reverse(Result), List}; +getopts_1([Option | Options], List, Result) -> + {Optvals, Remaining} = getopts_2(List, Option, [], []), + getopts_1(Options, Remaining, [Optvals | Result]). + +getopts_2([], _Option, Result, Remaining) -> + {lists:reverse(Result), lists:reverse(Remaining)}; +getopts_2([Option | Tail], Option, Result, Remaining) -> + getopts_2(Tail, Option, [Option | Result], Remaining); +getopts_2([Optval | Tail], Option, Result, Remaining) + when element(1, Optval) == Option -> + getopts_2(Tail, Option, [Optval | Result], Remaining); +getopts_2([Other | Tail], Option, Result, Remaining) -> + getopts_2(Tail, Option, Result, [Other | Remaining]). diff --git a/lib/compiler/test/compilation_SUITE_data/guards.erl b/lib/compiler/test/compilation_SUITE_data/guards.erl new file mode 100644 index 0000000000..84e41b8ede --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/guards.erl @@ -0,0 +1,106 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(guards). + +-export([guards/0]). + +guards() -> + ok = t(), + ok = f(), + ok = ct(1), + ok = multi(1), + ok = multi(2), + ok = multi(3). + +%% The following tests are always true. +t() when integer(42) -> + ok; +t() when float(2.0) -> + ok; +t() when number(7) -> + ok; +t() when number(3.14) -> + ok; +t() when atom(error) -> + ok; +t() when list([a]) -> + ok; +t() when tuple({}) -> + ok; +t() when tuple({1, 2}) -> + ok. + +%% The following tests are always false. +f() when integer(a) -> + ok; +f() when float(b) -> + ok; +f() when number(c) -> + ok; +f() when atom(42) -> + ok; +f() when list(33) -> + ok; +f() when list({}) -> + ok; +f() when list({1, 2}) -> + ok; +f() when tuple(33) -> + ok; +f() when tuple([a]) -> + ok; +f() when tuple([]) -> + ok; +f() when tuple(35) -> + ok; +f() -> + ok. + +%% The following tests are always true. +ct(X) -> + case X of + Y when integer(42) -> + ok; + Y when float(2.0) -> + ok; + Y when number(7) -> + ok; + Y when number(3.14) -> + ok; + Y when atom(error) -> + ok; + Y when list([a]) -> + ok; + Y when tuple({}) -> + ok; + Y when tuple({1, 2}) -> + ok + end. + +multi(X) -> + case X of + Y when float(Y) ; integer(Y) -> + ok; + Y when Y > 1, Y < 10 ; atom(Y) -> + ok; + Y when Y == 4, number(Y) ; list(Y) -> + pannkaka; + Y when Y==3 ; Y==5 ; Y==6 -> + ok + end. diff --git a/lib/compiler/test/compilation_SUITE_data/live_var.erl b/lib/compiler/test/compilation_SUITE_data/live_var.erl new file mode 100644 index 0000000000..483eec0630 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/live_var.erl @@ -0,0 +1,30 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-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(live_var). +-export([?MODULE/0,start/0]). + +?MODULE() -> + ok. + +start() -> + receive + after 3000 -> + A = 5 + end, + A. diff --git a/lib/compiler/test/compilation_SUITE_data/long_string.erl b/lib/compiler/test/compilation_SUITE_data/long_string.erl new file mode 100644 index 0000000000..b3cf77b13f --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/long_string.erl @@ -0,0 +1,670 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(long_string). + +-export([?MODULE/0]). + +?MODULE() -> + Options = "some stupid long string", + 49252 = length(generate(Options, "348927432097sfkjfkljf329")), + ok. + +generate(Options, Glurf) -> + "asdhfaslfdjhhwleirsk e4kjhr430usduy fdk;///s llsjkf;laskjfsdfkjasdfkj +sdkljflasdfkjasldkfjasd" ++ Options ++ +"CSAgICAgICBWZXJzaW9uIDIsIEp1bmUgMTk5MQoKIENvcHlyaWdodCAoQykgMTk4OSwgMTk5MSBG +cmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIEluYy4KICAgICAgICAgICAgICAgICAgICAgICA1OSBU +ZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiBFdmVy +eW9uZSBpcyBwZXJtaXR0ZWQgdG8gY29weSBhbmQgZGlzdHJpYnV0ZSB2ZXJiYXRpbSBjb3BpZXMK +IG9mIHRoaXMgbGljZW5zZSBkb2N1bWVudCwgYnV0IGNoYW5naW5nIGl0IGlzIG5vdCBhbGxvd2Vk +LgoKCQkJICAgIFByZWFtYmxlCgogIFRoZSBsaWNlbnNlcyBmb3IgbW9zdCBzb2Z0d2FyZSBhcmUg +ZGVzaWduZWQgdG8gdGFrZSBhd2F5IHlvdXIKZnJlZWRvbSB0byBzaGFyZSBhbmQgY2hhbmdlIGl0 +LiAgQnkgY29udHJhc3QsIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMKTGljZW5zZSBpcyBpbnRlbmRl +ZCB0byBndWFyYW50ZWUgeW91ciBmcmVlZG9tIHRvIHNoYXJlIGFuZCBjaGFuZ2UgZnJlZQpzb2Z0 +d2FyZS0tdG8gbWFrZSBzdXJlIHRoZSBzb2Z0d2FyZSBpcyBmcmVlIGZvciBhbGwgaXRzIHVzZXJz +LiAgVGhpcwpHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFwcGxpZXMgdG8gbW9zdCBvZiB0aGUgRnJl +ZSBTb2Z0d2FyZQpGb3VuZGF0aW9uJ3Mgc29mdHdhcmUgYW5kIHRvIGFueSBvdGhlciBwcm9ncmFt +IHdob3NlIGF1dGhvcnMgY29tbWl0IHRvCnVzaW5nIGl0LiAgKFNvbWUgb3RoZXIgRnJlZSBTb2Z0 +d2FyZSBGb3VuZGF0aW9uIHNvZnR3YXJlIGlzIGNvdmVyZWQgYnkKdGhlIEdOVSBMaWJyYXJ5IEdl +bmVyYWwgUHVibGljIExpY2Vuc2UgaW5zdGVhZC4pICBZb3UgY2FuIGFwcGx5IGl0IHRvCnlvdXIg +cHJvZ3JhbXMsIHRvby4KCiAgV2hlbiB3ZSBzcGVhayBvZiBmcmVlIHNvZnR3YXJlLCB3ZSBhcmUg +cmVmZXJyaW5nIHRvIGZyZWVkb20sIG5vdApwcmljZS4gIE91ciBHZW5lcmFsIFB1YmxpYyBMaWNl +bnNlcyBhcmUgZGVzaWduZWQgdG8gbWFrZSBzdXJlIHRoYXQgeW91CmhhdmUgdGhlIGZyZWVkb20g +dG8gZGlzdHJpYnV0ZSBjb3BpZXMgb2YgZnJlZSBzb2Z0d2FyZSAoYW5kIGNoYXJnZSBmb3IKdGhp +cyBzZXJ2aWNlIGlmIHlvdSB3aXNoKSwgdGhhdCB5b3UgcmVjZWl2ZSBzb3VyY2UgY29kZSBvciBj +YW4gZ2V0IGl0CmlmIHlvdSB3YW50IGl0LCB0aGF0IHlvdSBjYW4gY2hhbmdlIHRoZSBzb2Z0d2Fy +ZSBvciB1c2UgcGllY2VzIG9mIGl0CmluIG5ldyBmcmVlIHByb2dyYW1zOyBhbmQgdGhhdCB5b3Ug +a25vdyB5b3UgY2FuIGRvIHRoZXNlIHRoaW5ncy4KCiAgVG8gcHJvdGVjdCB5b3VyIHJpZ2h0cywg +d2UgbmVlZCB0byBtYWtlIHJlc3RyaWN0aW9ucyB0aGF0IGZvcmJpZAphbnlvbmUgdG8gZGVueSB5 +b3UgdGhlc2UgcmlnaHRzIG9yIHRvIGFzayB5b3UgdG8gc3VycmVuZGVyIHRoZSByaWdodHMuClRo +ZXNlIHJlc3RyaWN0aW9ucyB0cmFuc2xhdGUgdG8gY2VydGFpbiByZXNwb25zaWJpbGl0aWVzIGZv +ciB5b3UgaWYgeW91CmRpc3RyaWJ1dGUgY29waWVzIG9mIHRoZSBzb2Z0d2FyZSwgb3IgaWYgeW91 +IG1vZGlmeSBpdC4KCiAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkaXN0cmlidXRlIGNvcGllcyBvZiBz +dWNoIGEgcHJvZ3JhbSwgd2hldGhlcgpncmF0aXMgb3IgZm9yIGEgZmVlLCB5b3UgbXVzdCBnaXZl +IHRoZSByZWNpcGllbnRzIGFsbCB0aGUgcmlnaHRzIHRoYXQKeW91IGhhdmUuICBZb3UgbXVzdCBt +YWtlIHN1cmUgdGhhdCB0aGV5LCB0b28sIHJlY2VpdmUgb3IgY2FuIGdldCB0aGUKc291cmNlIGNv +ZGUuICBBbmQgeW91IG11c3Qgc2hvdyB0aGVtIHRoZXNlIHRlcm1zIHNvIHRoZXkga25vdyB0aGVp +cgpyaWdodHMuCgogIFdlIHByb3RlY3QgeW91ciByaWdodHMgd2l0aCB0d28gc3RlcHM6ICgxKSBj +b3B5cmlnaHQgdGhlIHNvZnR3YXJlLCBhbmQKKDIpIG9mZmVyIHlvdSB0aGlzIGxpY2Vuc2Ugd2hp +Y2ggZ2l2ZXMgeW91IGxlZ2FsIHBlcm1pc3Npb24gdG8gY29weSwKZGlzdHJpYnV0ZSBhbmQvb3Ig +bW9kaWZ5IHRoZSBzb2Z0d2FyZS4KCiAgQWxzbywgZm9yIGVhY2ggYXV0aG9yJ3MgcHJvdGVjdGlv +biBhbmQgb3Vycywgd2Ugd2FudCB0byBtYWtlIGNlcnRhaW4KdGhhdCBldmVyeW9uZSB1bmRlcnN0 +YW5kcyB0aGF0IHRoZXJlIGlzIG5vIHdhcnJhbnR5IGZvciB0aGlzIGZyZWUKc29mdHdhcmUuICBJ +ZiB0aGUgc29mdHdhcmUgaXMgbW9kaWZpZWQgYnkgc29tZW9uZSBlbHNlIGFuZCBwYXNzZWQgb24s +IHdlCndhbnQgaXRzIHJlY2lwaWVudHMgdG8ga25vdyB0aGF0IHdoYXQgdGhleSBoYXZlIGlzIG5v +dCB0aGUgb3JpZ2luYWwsIHNvCnRoYXQgYW55IHByb2JsZW1zIGludHJvZHVjZWQgYnkgb3RoZXJz +IHdpbGwgbm90IHJlZmxlY3Qgb24gdGhlIG9yaWdpbmFsCmF1dGhvcnMnIHJlcHV0YXRpb25zLgoK +ICBGaW5hbGx5LCBhbnkgZnJlZSBwcm9ncmFtIGlzIHRocmVhdGVuZWQgY29uc3RhbnRseSBieSBz +b2Z0d2FyZQpwYXRlbnRzLiAgV2Ugd2lzaCB0byBhdm9pZCB0aGUgZGFuZ2VyIHRoYXQgcmVkaXN0 +cmlidXRvcnMgb2YgYSBmcmVlCnByb2dyYW0gd2lsbCBpbmRpdmlkdWFsbHkgb2J0YWluIHBhdGVu +dCBsaWNlbnNlcywgaW4gZWZmZWN0IG1ha2luZyB0aGUKcHJvZ3JhbSBwcm9wcmlldGFyeS4gIFRv +IHByZXZlbnQgdGhpcywgd2UgaGF2ZSBtYWRlIGl0IGNsZWFyIHRoYXQgYW55CnBhdGVudCBtdXN0 +IGJlIGxpY2Vuc2VkIGZvciBldmVyeW9uZSdzIGZyZWUgdXNlIG9yIG5vdCBsaWNlbnNlZCBhdCBh +bGwuCgogIFRoZSBwcmVjaXNlIHRlcm1zIGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0 +cmlidXRpb24gYW5kCm1vZGlmaWNhdGlvbiBmb2xsb3cuCgwKCQkgICAgR05VIEdFTkVSQUwgUFVC +TElDIExJQ0VOU0UKICAgVEVSTVMgQU5EIENPTkRJVElPTlMgRk9SIENPUFlJTkcsIERJU1RSSUJV +VElPTiBBTkQgTU9ESUZJQ0FUSU9OCgogIDAuIFRoaXMgTGljZW5zZSBhcHBsaWVzIHRvIGFueSBw +cm9ncmFtIG9yIG90aGVyIHdvcmsgd2hpY2ggY29udGFpbnMKYSBub3RpY2UgcGxhY2VkIGJ5IHRo +ZSBjb3B5cmlnaHQgaG9sZGVyIHNheWluZyBpdCBtYXkgYmUgZGlzdHJpYnV0ZWQKdW5kZXIgdGhl +IHRlcm1zIG9mIHRoaXMgR2VuZXJhbCBQdWJsaWMgTGljZW5zZS4gIFRoZSAiUHJvZ3JhbSIsIGJl +bG93LApyZWZlcnMgdG8gYW55IHN1Y2ggcHJvZ3JhbSBvciB3b3JrLCBhbmQgYSAid29yayBiYXNl +ZCBvbiB0aGUgUHJvZ3JhbSIKbWVhbnMgZWl0aGVyIHRoZSBQcm9ncmFtIG9yIGFueSBkZXJpdmF0 +aXZlIHdvcmsgdW5kZXIgY29weXJpZ2h0IGxhdzoKdGhhdCBpcyB0byBzYXksIGEgd29yayBjb250 +YWluaW5nIHRoZSBQcm9ncmFtIG9yIGEgcG9ydGlvbiBvZiBpdCwKZWl0aGVyIHZlcmJhdGltIG9y +IHdpdGggbW9kaWZpY2F0aW9ucyBhbmQvb3IgdHJhbnNsYXRlZCBpbnRvIGFub3RoZXIKbGFuZ3Vh +Z2UuICAoSGVyZWluYWZ0ZXIsIHRyYW5zbGF0aW9uIGlzIGluY2x1ZGVkIHdpdGhvdXQgbGltaXRh +dGlvbiBpbgp0aGUgdGVybSAibW9kaWZpY2F0aW9uIi4pICBFYWNoIGxpY2Vuc2VlIGlzIGFkZHJl +c3NlZCBhcyAieW91Ii4KCkFjdGl2aXRpZXMgb3RoZXIgdGhhbiBjb3B5aW5nLCBkaXN0cmlidXRp +b24gYW5kIG1vZGlmaWNhdGlvbiBhcmUgbm90CmNvdmVyZWQgYnkgdGhpcyBMaWNlbnNlOyB0aGV5 +IGFyZSBvdXRzaWRlIGl0cyBzY29wZS4gIFRoZSBhY3Qgb2YKcnVubmluZyB0aGUgUHJvZ3JhbSBp +cyBub3QgcmVzdHJpY3RlZCwgYW5kIHRoZSBvdXRwdXQgZnJvbSB0aGUgUHJvZ3JhbQppcyBjb3Zl +cmVkIG9ubHkgaWYgaXRzIGNvbnRlbnRzIGNvbnN0aXR1dGUgYSB3b3JrIGJhc2VkIG9uIHRoZQpQ +cm9ncmFtIChpbmRlcGVuZGVudCBvZiBoYXZpbmcgYmVlbiBtYWRlIGJ5IHJ1bm5pbmcgdGhlIFBy +b2dyYW0pLgpXaGV0aGVyIHRoYXQgaXMgdHJ1ZSBkZXBlbmRzIG9uIHdoYXQgdGhlIFByb2dyYW0g +ZG9lcy4KCiAgMS4gWW91IG1heSBjb3B5IGFuZCBkaXN0cmlidXRlIHZlcmJhdGltIGNvcGllcyBv +ZiB0aGUgUHJvZ3JhbSdzCnNvdXJjZSBjb2RlIGFzIHlvdSByZWNlaXZlIGl0LCBpbiBhbnkgbWVk +aXVtLCBwcm92aWRlZCB0aGF0IHlvdQpjb25zcGljdW91c2x5IGFuZCBhcHByb3ByaWF0ZWx5IHB1 +Ymxpc2ggb24gZWFjaCBjb3B5IGFuIGFwcHJvcHJpYXRlCmNvcHlyaWdodCBub3RpY2UgYW5kIGRp +c2NsYWltZXIgb2Ygd2FycmFudHk7IGtlZXAgaW50YWN0IGFsbCB0aGUKbm90aWNlcyB0aGF0IHJl +ZmVyIHRvIHRoaXMgTGljZW5zZSBhbmQgdG8gdGhlIGFic2VuY2Ugb2YgYW55IHdhcnJhbnR5Owph +bmQgZ2l2ZSBhbnkgb3RoZXIgcmVjaXBpZW50cyBvZiB0aGUgUHJvZ3JhbSBhIGNvcHkgb2YgdGhp +cyBMaWNlbnNlCmFsb25nIHdpdGggdGhlIFByb2dyYW0uCgpZb3UgbWF5IGNoYXJnZSBhIGZlZSBm +b3IgdGhlIHBoeXNpY2FsIGFjdCBvZiB0cmFuc2ZlcnJpbmcgYSBjb3B5LCBhbmQKeW91IG1heSBh +dCB5b3VyIG9wdGlvbiBvZmZlciB3YXJyYW50eSBwcm90ZWN0aW9uIGluIGV4Y2hhbmdlIGZvciBh +IGZlZS4KCiAgMi4gWW91IG1heSBtb2RpZnkgeW91ciBjb3B5IG9yIGNvcGllcyBvZiB0aGUgUHJv +Z3JhbSBvciBhbnkgcG9ydGlvbgpvZiBpdCwgdGh1cyBmb3JtaW5nIGEgd29yayBiYXNlZCBvbiB0 +aGUgUHJvZ3JhbSwgYW5kIGNvcHkgYW5kCmRpc3RyaWJ1dGUgc3VjaCBtb2RpZmljYXRpb25zIG9y +IHdvcmsgdW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb24gMQphYm92ZSwgcHJvdmlkZWQgdGhhdCB5 +b3UgYWxzbyBtZWV0IGFsbCBvZiB0aGVzZSBjb25kaXRpb25zOgoKICAgIGEpIFlvdSBtdXN0IGNh +dXNlIHRoZSBtb2RpZmllZCBmaWxlcyB0byBjYXJyeSBwcm9taW5lbnQgbm90aWNlcwogICAgc3Rh +dGluZyB0aGF0IHlvdSBjaGFuZ2VkIHRoZSBmaWxlcyBhbmQgdGhlIGRhdGUgb2YgYW55IGNoYW5n +ZS4KCiAgICBiKSBZb3UgbXVzdCBjYXVzZSBhbnkgd29yayB0aGF0IHlvdSBkaXN0cmlidXRlIG9y +IHB1Ymxpc2gsIHRoYXQgaW4KICAgIHdob2xlIG9yIGluIHBhcnQgY29udGFpbnMgb3IgaXMgZGVy +aXZlZCBmcm9tIHRoZSBQcm9ncmFtIG9yIGFueQogICAgcGFydCB0aGVyZW9mLCB0byBiZSBsaWNl +bnNlZCBhcyBhIHdob2xlIGF0IG5vIGNoYXJnZSB0byBhbGwgdGhpcmQKICAgIHBhcnRpZXMgdW5k +ZXIgdGhlIHRlcm1zIG9mIHRoaXMgTGljZW5zZS4KCiAgICBjKSBJZiB0aGUgbW9kaWZpZWQgcHJv +Z3JhbSBub3JtYWxseSByZWFkcyBjb21tYW5kcyBpbnRlcmFjdGl2ZWx5CiAgICB3aGVuIHJ1biwg +eW91IG11c3QgY2F1c2UgaXQsIHdoZW4gc3RhcnRlZCBydW5uaW5nIGZvciBzdWNoCiAgICBpbnRl +cmFjdGl2ZSB1c2UgaW4gdGhlIG1vc3Qgb3JkaW5hcnkgd2F5LCB0byBwcmludCBvciBkaXNwbGF5 +IGFuCiAgICBhbm5vdW5jZW1lbnQgaW5jbHVkaW5nIGFuIGFwcHJvcHJpYXRlIGNvcHlyaWdodCBu +b3RpY2UgYW5kIGEKICAgIG5vdGljZSB0aGF0IHRoZXJlIGlzIG5vIHdhcnJhbnR5IChvciBlbHNl +LCBzYXlpbmcgdGhhdCB5b3UgcHJvdmlkZQogICAgYSB3YXJyYW50eSkgYW5kIHRoYXQgdXNlcnMg +bWF5IHJlZGlzdHJpYnV0ZSB0aGUgcHJvZ3JhbSB1bmRlcgogICAgdGhlc2UgY29uZGl0aW9ucywg +YW5kIHRlbGxpbmcgdGhlIHVzZXIgaG93IHRvIHZpZXcgYSBjb3B5IG9mIHRoaXMKICAgIExpY2Vu +c2UuICAoRXhjZXB0aW9uOiBpZiB0aGUgUHJvZ3JhbSBpdHNlbGYgaXMgaW50ZXJhY3RpdmUgYnV0 +CiAgICBkb2VzIG5vdCBub3JtYWxseSBwcmludCBzdWNoIGFuIGFubm91bmNlbWVudCwgeW91ciB3 +b3JrIGJhc2VkIG9uCiAgICB0aGUgUHJvZ3JhbSBpcyBub3QgcmVxdWlyZWQgdG8gcHJpbnQgYW4g +YW5ub3VuY2VtZW50LikKDApUaGVzZSByZXF1aXJlbWVudHMgYXBwbHkgdG8gdGhlIG1vZGlmaWVk +IHdvcmsgYXMgYSB3aG9sZS4gIElmCmlkZW50aWZpYWJsZSBzZWN0aW9ucyBvZiB0aGF0IHdvcmsg +YXJlIG5vdCBkZXJpdmVkIGZyb20gdGhlIFByb2dyYW0sCmFuZCBjYW4gYmUgcmVhc29uYWJseSBj +b25zaWRlcmVkIGluZGVwZW5kZW50IGFuZCBzZXBhcmF0ZSB3b3JrcyBpbgp0aGVtc2VsdmVzLCB0 +aGVuIHRoaXMgTGljZW5zZSwgYW5kIGl0cyB0ZXJtcywgZG8gbm90IGFwcGx5IHRvIHRob3NlCnNl +Y3Rpb25zIHdoZW4geW91IGRpc3RyaWJ1dGUgdGhlbSBhcyBzZXBhcmF0ZSB3b3Jrcy4gIEJ1dCB3 +aGVuIHlvdQpkaXN0cmlidXRlIHRoZSBzYW1lIHNlY3Rpb25zIGFzIHBhcnQgb2YgYSB3aG9sZSB3 +aGljaCBpcyBhIHdvcmsgYmFzZWQKb24gdGhlIFByb2dyYW0sIHRoZSBkaXN0cmlidXRpb24gb2Yg +dGhlIHdob2xlIG11c3QgYmUgb24gdGhlIHRlcm1zIG9mCnRoaXMgTGljZW5zZSwgd2hvc2UgcGVy +bWlzc2lvbnMgZm9yIG90aGVyIGxpY2Vuc2VlcyBleHRlbmQgdG8gdGhlCmVudGlyZSB3aG9sZSwg +YW5kIHRodXMgdG8gZWFjaCBhbmQgZXZlcnkgcGFydCByZWdhcmRsZXNzIG9mIHdobyB3cm90ZSBp +dC4KClRodXMsIGl0IGlzIG5vdCB0aGUgaW50ZW50IG9mIHRoaXMgc2VjdGlvbiB0byBjbGFpbSBy +aWdodHMgb3IgY29udGVzdAp5b3VyIHJpZ2h0cyB0byB3b3JrIHdyaXR0ZW4gZW50aXJlbHkgYnkg +eW91OyByYXRoZXIsIHRoZSBpbnRlbnQgaXMgdG8KZXhlcmNpc2UgdGhlIHJpZ2h0IHRvIGNvbnRy +b2wgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkZXJpdmF0aXZlIG9yCmNvbGxlY3RpdmUgd29ya3MgYmFz +ZWQgb24gdGhlIFByb2dyYW0uCgpJbiBhZGRpdGlvbiwgbWVyZSBhZ2dyZWdhdGlvbiBvZiBhbm90 +aGVyIHdvcmsgbm90IGJhc2VkIG9uIHRoZSBQcm9ncmFtCndpdGggdGhlIFByb2dyYW0gKG9yIHdp +dGggYSB3b3JrIGJhc2VkIG9uIHRoZSBQcm9ncmFtKSBvbiBhIHZvbHVtZSBvZgphIHN0b3JhZ2Ug +b3IgZGlzdHJpYnV0aW9uIG1lZGl1bSBkb2VzIG5vdCBicmluZyB0aGUgb3RoZXIgd29yayB1bmRl +cgp0aGUgc2NvcGUgb2YgdGhpcyBMaWNlbnNlLgoKICAzLiBZb3UgbWF5IGNvcHkgYW5kIGRpc3Ry +aWJ1dGUgdGhlIFByb2dyYW0gKG9yIGEgd29yayBiYXNlZCBvbiBpdCwKdW5kZXIgU2VjdGlvbiAy +KSBpbiBvYmplY3QgY29kZSBvciBleGVjdXRhYmxlIGZvcm0gdW5kZXIgdGhlIHRlcm1zIG9mClNl +Y3Rpb25zIDEgYW5kIDIgYWJvdmUgcHJvdmlkZWQgdGhhdCB5b3UgYWxzbyBkbyBvbmUgb2YgdGhl +IGZvbGxvd2luZzoKCiAgICBhKSBBY2NvbXBhbnkgaXQgd2l0aCB0aGUgY29tcGxldGUgY29ycmVz +cG9uZGluZyBtYWNoaW5lLXJlYWRhYmxlCiAgICBzb3VyY2UgY29kZSwgd2hpY2ggbXVzdCBiZSBk +aXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgU2VjdGlvbnMKICAgIDEgYW5kIDIgYWJvdmUg +b24gYSBtZWRpdW0gY3VzdG9tYXJpbHkgdXNlZCBmb3Igc29mdHdhcmUgaW50ZXJjaGFuZ2U7IG9y +LAoKICAgIGIpIEFjY29tcGFueSBpdCB3aXRoIGEgd3JpdHRlbiBvZmZlciwgdmFsaWQgZm9yIGF0 +IGxlYXN0IHRocmVlCiAgICB5ZWFycywgdG8gZ2l2ZSBhbnkgdGhpcmQgcGFydHksIGZvciBhIGNo +YXJnZSBubyBtb3JlIHRoYW4geW91cgogICAgY29zdCBvZiBwaHlzaWNhbGx5IHBlcmZvcm1pbmcg +c291cmNlIGRpc3RyaWJ1dGlvbiwgYSBjb21wbGV0ZQogICAgbWFjaGluZS1yZWFkYWJsZSBjb3B5 +IG9mIHRoZSBjb3JyZXNwb25kaW5nIHNvdXJjZSBjb2RlLCB0byBiZQogICAgZGlzdHJpYnV0ZWQg +dW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb25zIDEgYW5kIDIgYWJvdmUgb24gYSBtZWRpdW0KICAg +IGN1c3RvbWFyaWx5IHVzZWQgZm9yIHNvZnR3YXJlIGludGVyY2hhbmdlOyBvciwKCiAgICBjKSBB +Y2NvbXBhbnkgaXQgd2l0aCB0aGUgaW5mb3JtYXRpb24geW91IHJlY2VpdmVkIGFzIHRvIHRoZSBv +ZmZlcgogICAgdG8gZGlzdHJpYnV0ZSBjb3JyZXNwb25kaW5nIHNvdXJjZSBjb2RlLiAgKFRoaXMg +YWx0ZXJuYXRpdmUgaXMKICAgIGFsbG93ZWQgb25seSBmb3Igbm9uY29tbWVyY2lhbCBkaXN0cmli +dXRpb24gYW5kIG9ubHkgaWYgeW91CiAgICByZWNlaXZlZCB0aGUgcHJvZ3JhbSBpbiBvYmplY3Qg +Y29kZSBvciBleGVjdXRhYmxlIGZvcm0gd2l0aCBzdWNoCiAgICBhbiBvZmZlciwgaW4gYWNjb3Jk +IHdpdGggU3Vic2VjdGlvbiBiIGFib3ZlLikKClRoZSBzb3VyY2UgY29kZSBmb3IgYSB3b3JrIG1l +YW5zIHRoZSBwcmVmZXJyZWQgZm9ybSBvZiB0aGUgd29yayBmb3IKbWFraW5nIG1vZGlmaWNhdGlv +bnMgdG8gaXQuICBGb3IgYW4gZXhlY3V0YWJsZSB3b3JrLCBjb21wbGV0ZSBzb3VyY2UKY29kZSBt +ZWFucyBhbGwgdGhlIHNvdXJjZSBjb2RlIGZvciBhbGwgbW9kdWxlcyBpdCBjb250YWlucywgcGx1 +cyBhbnkKYXNzb2NpYXRlZCBpbnRlcmZhY2UgZGVmaW5pdGlvbiBmaWxlcywgcGx1cyB0aGUgc2Ny +aXB0cyB1c2VkIHRvCmNvbnRyb2wgY29tcGlsYXRpb24gYW5kIGluc3RhbGxhdGlvbiBvZiB0aGUg +ZXhlY3V0YWJsZS4gIEhvd2V2ZXIsIGFzIGEKc3BlY2lhbCBleGNlcHRpb24sIHRoZSBzb3VyY2Ug +Y29kZSBkaXN0cmlidXRlZCBuZWVkIG5vdCBpbmNsdWRlCmFueXRoaW5nIHRoYXQgaXMgbm9ybWFs +bHkgZGlzdHJpYnV0ZWQgKGluIGVpdGhlciBzb3VyY2Ugb3IgYmluYXJ5CmZvcm0pIHdpdGggdGhl +IG1ham9yIGNvbXBvbmVudHMgKGNvbXBpbGVyLCBrZXJuZWwsIGFuZCBzbyBvbikgb2YgdGhlCm9w +ZXJhdGluZyBzeXN0ZW0gb24gd2hpY2ggdGhlIGV4ZWN1dGFibGUgcnVucywgdW5sZXNzIHRoYXQg +Y29tcG9uZW50Cml0c2VsZiBhY2NvbXBhbmllcyB0aGUgZXhlY3V0YWJsZS4KCklmIGRpc3RyaWJ1 +dGlvbiBvZiBleGVjdXRhYmxlIG9yIG9iamVjdCBjb2RlIGlzIG1hZGUgYnkgb2ZmZXJpbmcKYWNj +ZXNzIHRvIGNvcHkgZnJvbSBhIGRlc2lnbmF0ZWQgcGxhY2UsIHRoZW4gb2ZmZXJpbmcgZXF1aXZh +bGVudAphY2Nlc3MgdG8gY29weSB0aGUgc291cmNlIGNvZGUgZnJvbSB0aGUgc2FtZSBwbGFjZSBj +b3VudHMgYXMKZGlzdHJpYnV0aW9uIG9mIHRoZSBzb3VyY2UgY29kZSwgZXZlbiB0aG91Z2ggdGhp +cmQgcGFydGllcyBhcmUgbm90CmNvbXBlbGxlZCB0byBjb3B5IHRoZSBzb3VyY2UgYWxvbmcgd2l0 +aCB0aGUgb2JqZWN0IGNvZGUuCgwKICA0LiBZb3UgbWF5IG5vdCBjb3B5LCBtb2RpZnksIHN1Ymxp +Y2Vuc2UsIG9yIGRpc3RyaWJ1dGUgdGhlIFByb2dyYW0KZXhjZXB0IGFzIGV4cHJlc3NseSBwcm92 +aWRlZCB1bmRlciB0aGlzIExpY2Vuc2UuICBBbnkgYXR0ZW1wdApvdGhlcndpc2UgdG8gY29weSwg +bW9kaWZ5LCBzdWJsaWNlbnNlIG9yIGRpc3RyaWJ1dGUgdGhlIFByb2dyYW0gaXMKdm9pZCwgYW5k +IHdpbGwgYXV0b21hdGljYWxseSB0ZXJtaW5hdGUgeW91ciByaWdodHMgdW5kZXIgdGhpcyBMaWNl +bnNlLgpIb3dldmVyLCBwYXJ0aWVzIHdobyBoYXZlIHJlY2VpdmVkIGNvcGllcywgb3IgcmlnaHRz +LCBmcm9tIHlvdSB1bmRlcgp0aGlzIExpY2Vuc2Ugd2lsbCBub3QgaGF2ZSB0aGVpciBsaWNlbnNl +cyB0ZXJtaW5hdGVkIHNvIGxvbmcgYXMgc3VjaApwYXJ0aWVzIHJlbWFpbiBpbiBmdWxsIGNvbXBs +aWFuY2UuCgogIDUuIFlvdSBhcmUgbm90IHJlcXVpcmVkIHRvIGFjY2VwdCB0aGlzIExpY2Vuc2Us +IHNpbmNlIHlvdSBoYXZlIG5vdApzaWduZWQgaXQuICBIb3dldmVyLCBub3RoaW5nIGVsc2UgZ3Jh +bnRzIHlvdSBwZXJtaXNzaW9uIHRvIG1vZGlmeSBvcgpkaXN0cmlidXRlIHRoZSBQcm9ncmFtIG9y +IGl0cyBkZXJpdmF0aXZlIHdvcmtzLiAgVGhlc2UgYWN0aW9ucyBhcmUKcHJvaGliaXRlZCBieSBs +YXcgaWYgeW91IGRvIG5vdCBhY2NlcHQgdGhpcyBMaWNlbnNlLiAgVGhlcmVmb3JlLCBieQptb2Rp +Znlpbmcgb3IgZGlzdHJpYnV0aW5nIHRoZSBQcm9ncmFtIChvciBhbnkgd29yayBiYXNlZCBvbiB0 +aGUKUHJvZ3JhbSksIHlvdSBpbmRpY2F0ZSB5b3VyIGFjY2VwdGFuY2Ugb2YgdGhpcyBMaWNlbnNl +IHRvIGRvIHNvLCBhbmQKYWxsIGl0cyB0ZXJtcyBhbmQgY29uZGl0aW9ucyBmb3IgY29weWluZywg +ZGlzdHJpYnV0aW5nIG9yIG1vZGlmeWluZwp0aGUgUHJvZ3JhbSBvciB3b3JrcyBiYXNlZCBvbiBp +dC4KCiAgNi4gRWFjaCB0aW1lIHlvdSByZWRpc3RyaWJ1dGUgdGhlIFByb2dyYW0gKG9yIGFueSB3 +b3JrIGJhc2VkIG9uIHRoZQpQcm9ncmFtKSwgdGhlIHJlY2lwaWVudCBhdXRvbWF0aWNhbGx5IHJl +Y2VpdmVzIGEgbGljZW5zZSBmcm9tIHRoZQpvcmlnaW5hbCBsaWNlbnNvciB0byBjb3B5LCBkaXN0 +cmlidXRlIG9yIG1vZGlmeSB0aGUgUHJvZ3JhbSBzdWJqZWN0IHRvCnRoZXNlIHRlcm1zIGFuZCBj +b25kaXRpb25zLiAgWW91IG1heSBub3QgaW1wb3NlIGFueSBmdXJ0aGVyCnJlc3RyaWN0aW9ucyBv +biB0aGUgcmVjaXBpZW50cycgZXhlcmNpc2Ugb2YgdGhlIHJpZ2h0cyBncmFudGVkIGhlcmVpbi4K +WW91IGFyZSBub3QgcmVzcG9uc2libGUgZm9yIGVuZm9yY2luZyBjb21wbGlhbmNlIGJ5IHRoaXJk +IHBhcnRpZXMgdG8KdGhpcyBMaWNlbnNlLgoKICA3LiBJZiwgYXMgYSBjb25zZXF1ZW5jZSBvZiBh +IGNvdXJ0IGp1ZGdtZW50IG9yIGFsbGVnYXRpb24gb2YgcGF0ZW50CmluZnJpbmdlbWVudCBvciBm +b3IgYW55IG90aGVyIHJlYXNvbiAobm90IGxpbWl0ZWQgdG8gcGF0ZW50IGlzc3VlcyksCmNvbmRp +dGlvbnMgYXJlIGltcG9zZWQgb24geW91ICh3aGV0aGVyIGJ5IGNvdXJ0IG9yZGVyLCBhZ3JlZW1l +bnQgb3IKb3RoZXJ3aXNlKSB0aGF0IGNvbnRyYWRpY3QgdGhlIGNvbmRpdGlvbnMgb2YgdGhpcyBM +aWNlbnNlLCB0aGV5IGRvIG5vdApleGN1c2UgeW91IGZyb20gdGhlIGNvbmRpdGlvbnMgb2YgdGhp +cyBMaWNlbnNlLiAgSWYgeW91IGNhbm5vdApkaXN0cmlidXRlIHNvIGFzIHRvIHNhdGlzZnkgc2lt +dWx0YW5lb3VzbHkgeW91ciBvYmxpZ2F0aW9ucyB1bmRlciB0aGlzCkxpY2Vuc2UgYW5kIGFueSBv +dGhlciBwZXJ0aW5lbnQgb2JsaWdhdGlvbnMsIHRoZW4gYXMgYSBjb25zZXF1ZW5jZSB5b3UKbWF5 +IG5vdCBkaXN0cmlidXRlIHRoZSBQcm9ncmFtIGF0IGFsbC4gIEZvciBleGFtcGxlLCBpZiBhIHBh +dGVudApsaWNlbnNlIHdvdWxkIG5vdCBwZXJtaXQgcm95YWx0eS1mcmVlIHJlZGlzdHJpYnV0aW9u +IG9mIHRoZSBQcm9ncmFtIGJ5CmFsbCB0aG9zZSB3aG8gcmVjZWl2ZSBjb3BpZXMgZGlyZWN0bHkg +b3IgaW5kaXJlY3RseSB0aHJvdWdoIHlvdSwgdGhlbgp0aGUgb25seSB3YXkgeW91IGNvdWxkIHNh +dGlzZnkgYm90aCBpdCBhbmQgdGhpcyBMaWNlbnNlIHdvdWxkIGJlIHRvCnJlZnJhaW4gZW50aXJl +bHkgZnJvbSBkaXN0cmlidXRpb24gb2YgdGhlIFByb2dyYW0uCgpJZiBhbnkgcG9ydGlvbiBvZiB0 +aGlzIHNlY3Rpb24gaXMgaGVsZCBpbnZhbGlkIG9yIHVuZW5mb3JjZWFibGUgdW5kZXIKYW55IHBh +cnRpY3VsYXIgY2lyY3Vtc3RhbmNlLCB0aGUgYmFsYW5jZSBvZiB0aGUgc2VjdGlvbiBpcyBpbnRl +bmRlZCB0bwphcHBseSBhbmQgdGhlIHNlY3Rpb24gYXMgYSB3aG9sZSBpcyBpbnRlbmRlZCB0byBh +cHBseSBpbiBvdGhlcgpjaXJjdW1zdGFuY2VzLgoKSXQgaXMgbm90IHRoZSBwdXJwb3NlIG9mIHRo +aXMgc2VjdGlvbiB0byBpbmR1Y2UgeW91IHRvIGluZnJpbmdlIGFueQpwYXRlbnRzIG9yIG90aGVy +IHByb3BlcnR5IHJpZ2h0IGNsYWltcyBvciB0byBjb250ZXN0IHZhbGlkaXR5IG9mIGFueQpzdWNo +IGNsYWltczsgdGhpcyBzZWN0aW9uIGhhcyB0aGUgc29sZSBwdXJwb3NlIG9mIHByb3RlY3Rpbmcg +dGhlCmludGVncml0eSBvZiB0aGUgZnJlZSBzb2Z0d2FyZSBkaXN0cmlidXRpb24gc3lzdGVtLCB3 +aGljaCBpcwppbXBsZW1lbnRlZCBieSBwdWJsaWMgbGljZW5zZSBwcmFjdGljZXMuICBNYW55IHBl +b3BsZSBoYXZlIG1hZGUKZ2VuZXJvdXMgY29udHJpYnV0aW9ucyB0byB0aGUgd2lkZSByYW5nZSBv +ZiBzb2Z0d2FyZSBkaXN0cmlidXRlZAp0aHJvdWdoIHRoYXQgc3lzdGVtIGluIHJlbGlhbmNlIG9u +IGNvbnNpc3RlbnQgYXBwbGljYXRpb24gb2YgdGhhdApzeXN0ZW07IGl0IGlzIHVwIHRvIHRoZSBh +dXRob3IvZG9ub3IgdG8gZGVjaWRlIGlmIGhlIG9yIHNoZSBpcyB3aWxsaW5nCnRvIGRpc3RyaWJ1 +dGUgc29mdHdhcmUgdGhyb3VnaCBhbnkgb3RoZXIgc3lzdGVtIGFuZCBhIGxpY2Vuc2VlIGNhbm5v +dAppbXBvc2UgdGhhdCBjaG9pY2UuCgpUaGlzIHNlY3Rpb24gaXMgaW50ZW5kZWQgdG8gbWFrZSB0 +aG9yb3VnaGx5IGNsZWFyIHdoYXQgaXMgYmVsaWV2ZWQgdG8KYmUgYSBjb25zZXF1ZW5jZSBvZiB0 +aGUgcmVzdCBvZiB0aGlzIExpY2Vuc2UuCgwKICA4LiBJZiB0aGUgZGlzdHJpYnV0aW9uIGFuZC9v +ciB1c2Ugb2YgdGhlIFByb2dyYW0gaXMgcmVzdHJpY3RlZCBpbgpjZXJ0YWluIGNvdW50cmllcyBl +aXRoZXIgYnkgcGF0ZW50cyBvciBieSBjb3B5cmlnaHRlZCBpbnRlcmZhY2VzLCB0aGUKb3JpZ2lu +YWwgY29weXJpZ2h0IGhvbGRlciB3aG8gcGxhY2VzIHRoZSBQcm9ncmFtIHVuZGVyIHRoaXMgTGlj +ZW5zZQptYXkgYWRkIGFuIGV4cGxpY2l0IGdlb2dyYXBoaWNhbCBkaXN0cmlidXRpb24gbGltaXRh +dGlvbiBleGNsdWRpbmcKdGhvc2UgY291bnRyaWVzLCBzbyB0aGF0IGRpc3RyaWJ1dGlvbiBpcyBw +ZXJtaXR0ZWQgb25seSBpbiBvciBhbW9uZwpjb3VudHJpZXMgbm90IHRodXMgZXhjbHVkZWQuICBJ +biBzdWNoIGNhc2UsIHRoaXMgTGljZW5zZSBpbmNvcnBvcmF0ZXMKdGhlIGxpbWl0YXRpb24gYXMg +aWYgd3JpdHRlbiBpbiB0aGUgYm9keSBvZiB0aGlzIExpY2Vuc2UuCgogIDkuIFRoZSBGcmVlIFNv +ZnR3YXJlIEZvdW5kYXRpb24gbWF5IHB1Ymxpc2ggcmV2aXNlZCBhbmQvb3IgbmV3IHZlcnNpb25z +Cm9mIHRoZSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZyb20gdGltZSB0byB0aW1lLiAgU3VjaCBu +ZXcgdmVyc2lvbnMgd2lsbApiZSBzaW1pbGFyIGluIHNwaXJpdCB0byB0aGUgcHJlc2VudCB2ZXJz +aW9uLCBidXQgbWF5IGRpZmZlciBpbiBkZXRhaWwgdG8KYWRkcmVzcyBuZXcgcHJvYmxlbXMgb3Ig +Y29uY2VybnMuCgpFYWNoIHZlcnNpb24gaXMgZ2l2ZW4gYSBkaXN0aW5ndWlzaGluZyB2ZXJzaW9u +IG51bWJlci4gIElmIHRoZSBQcm9ncmFtCnNwZWNpZmllcyBhIHZlcnNpb24gbnVtYmVyIG9mIHRo +aXMgTGljZW5zZSB3aGljaCBhcHBsaWVzIHRvIGl0IGFuZCAiYW55CmxhdGVyIHZlcnNpb24iLCB5 +b3UgaGF2ZSB0aGUgb3B0aW9uIG9mIGZvbGxvd2luZyB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMK +ZWl0aGVyIG9mIHRoYXQgdmVyc2lvbiBvciBvZiBhbnkgbGF0ZXIgdmVyc2lvbiBwdWJsaXNoZWQg +YnkgdGhlIEZyZWUKU29mdHdhcmUgRm91bmRhdGlvbi4gIElmIHRoZSBQcm9ncmFtIGRvZXMgbm90 +IHNwZWNpZnkgYSB2ZXJzaW9uIG51bWJlciBvZgp0aGlzIExpY2Vuc2UsIHlvdSBtYXkgY2hvb3Nl +IGFueSB2ZXJzaW9uIGV2ZXIgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlCkZvdW5kYXRp +b24uCgogIDEwLiBJZiB5b3Ugd2lzaCB0byBpbmNvcnBvcmF0ZSBwYXJ0cyBvZiB0aGUgUHJvZ3Jh +bSBpbnRvIG90aGVyIGZyZWUKcHJvZ3JhbXMgd2hvc2UgZGlzdHJpYnV0aW9uIGNvbmRpdGlvbnMg +YXJlIGRpZmZlcmVudCwgd3JpdGUgdG8gdGhlIGF1dGhvcgp0byBhc2sgZm9yIHBlcm1pc3Npb24u +ICBGb3Igc29mdHdhcmUgd2hpY2ggaXMgY29weXJpZ2h0ZWQgYnkgdGhlIEZyZWUKU29mdHdhcmUg +Rm91bmRhdGlvbiwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgd2Ugc29t +ZXRpbWVzCm1ha2UgZXhjZXB0aW9ucyBmb3IgdGhpcy4gIE91ciBkZWNpc2lvbiB3aWxsIGJlIGd1 +aWRlZCBieSB0aGUgdHdvIGdvYWxzCm9mIHByZXNlcnZpbmcgdGhlIGZyZWUgc3RhdHVzIG9mIGFs +bCBkZXJpdmF0aXZlcyBvZiBvdXIgZnJlZSBzb2Z0d2FyZSBhbmQKb2YgcHJvbW90aW5nIHRoZSBz +aGFyaW5nIGFuZCByZXVzZSBvZiBzb2Z0d2FyZSBnZW5lcmFsbHkuCgoJCQkgICAgTk8gV0FSUkFO +VFkKCiAgMTEuIEJFQ0FVU0UgVEhFIFBST0dSQU0gSVMgTElDRU5TRUQgRlJFRSBPRiBDSEFSR0Us +IFRIRVJFIElTIE5PIFdBUlJBTlRZCkZPUiBUSEUgUFJPR1JBTSwgVE8gVEhFIEVYVEVOVCBQRVJN +SVRURUQgQlkgQVBQTElDQUJMRSBMQVcuICBFWENFUFQgV0hFTgpPVEhFUldJU0UgU1RBVEVEIElO +IFdSSVRJTkcgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORC9PUiBPVEhFUiBQQVJUSUVTClBST1ZJ +REUgVEhFIFBST0dSQU0gIkFTIElTIiBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFSVRI +RVIgRVhQUkVTU0VECk9SIElNUExJRUQsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBU +SEUgSU1QTElFRCBXQVJSQU5USUVTIE9GCk1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1Ig +QSBQQVJUSUNVTEFSIFBVUlBPU0UuICBUSEUgRU5USVJFIFJJU0sgQVMKVE8gVEhFIFFVQUxJVFkg +QU5EIFBFUkZPUk1BTkNFIE9GIFRIRSBQUk9HUkFNIElTIFdJVEggWU9VLiAgU0hPVUxEIFRIRQpQ +Uk9HUkFNIFBST1ZFIERFRkVDVElWRSwgWU9VIEFTU1VNRSBUSEUgQ09TVCBPRiBBTEwgTkVDRVNT +QVJZIFNFUlZJQ0lORywKUkVQQUlSIE9SIENPUlJFQ1RJT04uCgogIDEyLiBJTiBOTyBFVkVOVCBV +TkxFU1MgUkVRVUlSRUQgQlkgQVBQTElDQUJMRSBMQVcgT1IgQUdSRUVEIFRPIElOIFdSSVRJTkcK +V0lMTCBBTlkgQ09QWVJJR0hUIEhPTERFUiwgT1IgQU5ZIE9USEVSIFBBUlRZIFdITyBNQVkgTU9E +SUZZIEFORC9PUgpSRURJU1RSSUJVVEUgVEhFIFBST0dSQU0gQVMgUEVSTUlUVEVEIEFCT1ZFLCBC +RSBMSUFCTEUgVE8gWU9VIEZPUiBEQU1BR0VTLApJTkNMVURJTkcgQU5ZIEdFTkVSQUwsIFNQRUNJ +QUwsIElOQ0lERU5UQUwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIEFSSVNJTkcKT1VUIE9GIFRI +RSBVU0UgT1IgSU5BQklMSVRZIFRPIFVTRSBUSEUgUFJPR1JBTSAoSU5DTFVESU5HIEJVVCBOT1Qg +TElNSVRFRApUTyBMT1NTIE9GIERBVEEgT1IgREFUQSBCRUlORyBSRU5ERVJFRCBJTkFDQ1VSQVRF +IE9SIExPU1NFUyBTVVNUQUlORUQgQlkKWU9VIE9SIFRISVJEIFBBUlRJRVMgT1IgQSBGQUlMVVJF +IE9GIFRIRSBQUk9HUkFNIFRPIE9QRVJBVEUgV0lUSCBBTlkgT1RIRVIKUFJPR1JBTVMpLCBFVkVO +IElGIFNVQ0ggSE9MREVSIE9SIE9USEVSIFBBUlRZIEhBUyBCRUVOIEFEVklTRUQgT0YgVEhFClBP +U1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFUy4KCgkJICAgICBFTkQgT0YgVEVSTVMgQU5EIENPTkRJ +VElPTlMKDAoJICAgIEhvdyB0byBBcHBseSBUaGVzZSBUZXJtcyB0byBZb3VyIE5ldyBQcm9ncmFt +cwoKICBJZiB5b3UgZGV2ZWxvcCBhIG5ldyBwcm9ncmFtLCBhbmQgeW91IHdhbnQgaXQgdG8gYmUg +b2YgdGhlIGdyZWF0ZXN0CnBvc3NpYmxlIHVzZSB0byB0aGUgcHVibGljLCB0aGUgYmVzdCB3YXkg +dG8gYWNoaWV2ZSB0aGlzIGlzIHRvIG1ha2UgaXQKZnJlZSBzb2Z0d2FyZSB3aGljaCBldmVyeW9u +ZSBjYW4gcmVkaXN0cmlidXRlIGFuZCBjaGFuZ2UgdW5kZXIgdGhlc2UgdGVybXMuCgogIFRvIGRv +IHNvLCBhdHRhY2ggdGhlIGZvbGxvd2luZyBub3RpY2VzIHRvIHRoZSBwcm9ncmFtLiAgSXQgaXMg +c2FmZXN0CnRvIGF0dGFjaCB0aGVtIHRvIHRoZSBzdGFydCBvZiBlYWNoIHNvdXJjZSBmaWxlIHRv +IG1vc3QgZWZmZWN0aXZlbHkKY29udmV5IHRoZSBleGNsdXNpb24gb2Ygd2FycmFudHk7IGFuZCBl +YWNoIGZpbGUgc2hvdWxkIGhhdmUgYXQgbGVhc3QKdGhlICJjb3B5cmlnaHQiIGxpbmUgYW5kIGEg +cG9pbnRlciB0byB3aGVyZSB0aGUgZnVsbCBub3RpY2UgaXMgZm91bmQuCgogICAgPG9uZSBsaW5l +IHRvIGdpdmUgdGhlIHByb2dyYW0ncyBuYW1lIGFuZCBhIGJyaWVmIGlkZWEgb2Ygd2hhdCBpdCBk +b2VzLj4KICAgIENvcHlyaWdodCAoQykgPHllYXI+ICA8bmFtZSBvZiBhdXRob3I+CgogICAgVGhp +cyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9v +ciBtb2RpZnkKICAgIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGlj +IExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5CiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9u +OyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgogICAgKGF0IHlvdXIgb3B0aW9u +KSBhbnkgbGF0ZXIgdmVyc2lvbi4KCiAgICBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g +dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJS +QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAgICBNRVJDSEFOVEFC +SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiAgICBH +TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgoKICAgIFlvdSBzaG91 +bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNl +CiAgICBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBT +b2Z0d2FyZQogICAgRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAs +IEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQoKCkFsc28gYWRkIGluZm9ybWF0aW9uIG9uIGhv +dyB0byBjb250YWN0IHlvdSBieSBlbGVjdHJvbmljIGFuZCBwYXBlciBtYWlsLgoKSWYgdGhlIHBy +b2dyYW0gaXMgaW50ZXJhY3RpdmUsIG1ha2UgaXQgb3V0cHV0IGEgc2hvcnQgbm90aWNlIGxpa2Ug +dGhpcwp3aGVuIGl0IHN0YXJ0cyBpbiBhbiBpbnRlcmFjdGl2ZSBtb2RlOgoKICAgIEdub21vdmlz +aW9uIHZlcnNpb24gNjksIENvcHlyaWdodCAoQykgeWVhciBuYW1lIG9mIGF1dGhvcgogICAgR25v +bW92aXNpb24gY29tZXMgd2l0aCBBQlNPTFVURUxZIE5PIFdBUlJBTlRZOyBmb3IgZGV0YWlscyB0 +eXBlIGBzaG93IHcnLgogICAgVGhpcyBpcyBmcmVlIHNvZnR3YXJlLCBhbmQgeW91IGFyZSB3ZWxj +b21lIHRvIHJlZGlzdHJpYnV0ZSBpdAogICAgdW5kZXIgY2VydGFpbiBjb25kaXRpb25zOyB0eXBl +IGBzaG93IGMnIGZvciBkZXRhaWxzLgoKVGhlIGh5cG90aGV0aWNhbCBjb21tYW5kcyBgc2hvdyB3 +JyBhbmQgYHNob3cgYycgc2hvdWxkIHNob3cgdGhlIGFwcHJvcHJpYXRlCnBhcnRzIG9mIHRoZSBH +ZW5lcmFsIFB1YmxpYyBMaWNlbnNlLiAgT2YgY291cnNlLCB0aGUgY29tbWFuZHMgeW91IHVzZSBt +YXkKYmUgY2FsbGVkIHNvbWV0aGluZyBvdGhlciB0aGFuIGBzaG93IHcnIGFuZCBgc2hvdyBjJzsg +dGhleSBjb3VsZCBldmVuIGJlCm1vdXNlLWNsaWNrcyBvciBtZW51IGl0ZW1zLS13aGF0ZXZlciBz +dWl0cyB5b3VyIHByb2dyYW0uCgpZb3Ugc2hvdWxkIGFsc28gZ2V0IHlvdXIgZW1wbG95ZXIgKGlm +IHlvdSB3b3JrIGFzIGEgcHJvZ3JhbW1lcikgb3IgeW91cgpzY2hvb2wsIGlmIGFueSwgdG8gc2ln +biBhICJjb3B5cmlnaHQgZGlzY2xhaW1lciIgZm9yIHRoZSBwcm9ncmFtLCBpZgpuZWNlc3Nhcnku +ICBIZXJlIGlzIGEgc2FtcGxlOyBhbHRlciB0aGUgbmFtZXM6CgogIFlveW9keW5lLCBJbmMuLCBo +ZXJlYnkgZGlzY2xhaW1zIGFsbCBjb3B5cmlnaHQgaW50ZXJlc3QgaW4gdGhlIHByb2dyYW0KICBg +R25vbW92aXNpb24nICh3aGljaCBtYWtlcyBwYXNzZXMgYXQgY29tcGlsZXJzKSB3cml0dGVuIGJ5 +IEphbWVzIEhhY2tlci4KCiAgPHNpZ25hdHVyZSBvZiBUeSBDb29uPiwgMSBBcHJpbCAxOTg5CiAg +VHkgQ29vbiwgUHJlc2lkZW50IG9mIFZpY2UKClRoaXMgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBk +b2VzIG5vdCBwZXJtaXQgaW5jb3Jwb3JhdGluZyB5b3VyIHByb2dyYW0gaW50bwpwcm9wcmlldGFy +eSBwcm9ncmFtcy4gIElmIHlvdXIgcHJvZ3JhbSBpcyBhIHN1YnJvdXRpbmUgbGlicmFyeSwgeW91 +IG1heQpjb25zaWRlciBpdCBtb3JlIHVzZWZ1bCB0byBwZXJtaXQgbGlua2luZyBwcm9wcmlldGFy +eSBhcHBsaWNhdGlvbnMgd2l0aCB0aGUKbGlicmFyeS4gIElmIHRoaXMgaXMgd2hhdCB5b3Ugd2Fu +dCB0byBkbywgdXNlIHRoZSBHTlUgTGlicmFyeSBHZW5lcmFsClB1YmxpYyBMaWNlbnNlIGluc3Rl +YWQgb2YgdGhpcyBMaWNlbnNlLgo= +ClxjaGFwdGVye1RoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZX0KClxiZWdpbntjZW50ZXJ9 +CntccGFyaW5kZW50IDBpbgoKVmVyc2lvbiAyLCBKdW5lIDE5OTEKCkNvcHlyaWdodCBcY29weXJp +Z2h0XCAxOTg5LCAxOTkxIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLgoKXGJpZ3NraXAK +CjU5IFRlbXBsZSBQbGFjZSAtIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNywgVVNB +CgpcYmlnc2tpcAoKRXZlcnlvbmUgaXMgcGVybWl0dGVkIHRvIGNvcHkgYW5kIGRpc3RyaWJ1dGUg +dmVyYmF0aW0gY29waWVzCm9mIHRoaXMgbGljZW5zZSBkb2N1bWVudCwgYnV0IGNoYW5naW5nIGl0 +IGlzIG5vdCBhbGxvd2VkLgp9ClxlbmR7Y2VudGVyfQoKXGJlZ2lue2NlbnRlcn0Ke1xiZlxsYXJn +ZSBQcmVhbWJsZX0KXGVuZHtjZW50ZXJ9CgoKVGhlIGxpY2Vuc2VzIGZvciBtb3N0IHNvZnR3YXJl +IGFyZSBkZXNpZ25lZCB0byB0YWtlIGF3YXkgeW91ciBmcmVlZG9tIHRvCnNoYXJlIGFuZCBjaGFu +Z2UgaXQuICBCeSBjb250cmFzdCwgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGlzCmlu +dGVuZGVkIHRvIGd1YXJhbnRlZSB5b3VyIGZyZWVkb20gdG8gc2hhcmUgYW5kIGNoYW5nZSBmcmVl +IHNvZnR3YXJlLS0tdG8KbWFrZSBzdXJlIHRoZSBzb2Z0d2FyZSBpcyBmcmVlIGZvciBhbGwgaXRz +IHVzZXJzLiAgVGhpcyBHZW5lcmFsIFB1YmxpYwpMaWNlbnNlIGFwcGxpZXMgdG8gbW9zdCBvZiB0 +aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uJ3Mgc29mdHdhcmUgYW5kIHRvCmFueSBvdGhlciBw +cm9ncmFtIHdob3NlIGF1dGhvcnMgY29tbWl0IHRvIHVzaW5nIGl0LiAgKFNvbWUgb3RoZXIgRnJl +ZQpTb2Z0d2FyZSBGb3VuZGF0aW9uIHNvZnR3YXJlIGlzIGNvdmVyZWQgYnkgdGhlIEdOVSBMaWJy +YXJ5IEdlbmVyYWwgUHVibGljCkxpY2Vuc2UgaW5zdGVhZC4pICBZb3UgY2FuIGFwcGx5IGl0IHRv +IHlvdXIgcHJvZ3JhbXMsIHRvby4KCldoZW4gd2Ugc3BlYWsgb2YgZnJlZSBzb2Z0d2FyZSwgd2Ug +YXJlIHJlZmVycmluZyB0byBmcmVlZG9tLCBub3QgcHJpY2UuCk91ciBHZW5lcmFsIFB1YmxpYyBM +aWNlbnNlcyBhcmUgZGVzaWduZWQgdG8gbWFrZSBzdXJlIHRoYXQgeW91IGhhdmUgdGhlCmZyZWVk +b20gdG8gZGlzdHJpYnV0ZSBjb3BpZXMgb2YgZnJlZSBzb2Z0d2FyZSAoYW5kIGNoYXJnZSBmb3Ig +dGhpcyBzZXJ2aWNlCmlmIHlvdSB3aXNoKSwgdGhhdCB5b3UgcmVjZWl2ZSBzb3VyY2UgY29kZSBv +ciBjYW4gZ2V0IGl0IGlmIHlvdSB3YW50IGl0LAp0aGF0IHlvdSBjYW4gY2hhbmdlIHRoZSBzb2Z0 +d2FyZSBvciB1c2UgcGllY2VzIG9mIGl0IGluIG5ldyBmcmVlIHByb2dyYW1zOwphbmQgdGhhdCB5 +b3Uga25vdyB5b3UgY2FuIGRvIHRoZXNlIHRoaW5ncy4KClRvIHByb3RlY3QgeW91ciByaWdodHMs +IHdlIG5lZWQgdG8gbWFrZSByZXN0cmljdGlvbnMgdGhhdCBmb3JiaWQgYW55b25lIHRvCmRlbnkg +eW91IHRoZXNlIHJpZ2h0cyBvciB0byBhc2sgeW91IHRvIHN1cnJlbmRlciB0aGUgcmlnaHRzLiAg +VGhlc2UKcmVzdHJpY3Rpb25zIHRyYW5zbGF0ZSB0byBjZXJ0YWluIHJlc3BvbnNpYmlsaXRpZXMg +Zm9yIHlvdSBpZiB5b3UKZGlzdHJpYnV0ZSBjb3BpZXMgb2YgdGhlIHNvZnR3YXJlLCBvciBpZiB5 +b3UgbW9kaWZ5IGl0LgoKRm9yIGV4YW1wbGUsIGlmIHlvdSBkaXN0cmlidXRlIGNvcGllcyBvZiBz +dWNoIGEgcHJvZ3JhbSwgd2hldGhlciBncmF0aXMgb3IKZm9yIGEgZmVlLCB5b3UgbXVzdCBnaXZl +IHRoZSByZWNpcGllbnRzIGFsbCB0aGUgcmlnaHRzIHRoYXQgeW91IGhhdmUuICBZb3UKbXVzdCBt +YWtlIHN1cmUgdGhhdCB0aGV5LCB0b28sIHJlY2VpdmUgb3IgY2FuIGdldCB0aGUgc291cmNlIGNv +ZGUuICBBbmQKeW91IG11c3Qgc2hvdyB0aGVtIHRoZXNlIHRlcm1zIHNvIHRoZXkga25vdyB0aGVp +ciByaWdodHMuCgpXZSBwcm90ZWN0IHlvdXIgcmlnaHRzIHdpdGggdHdvIHN0ZXBzOiAoMSkgY29w +eXJpZ2h0IHRoZSBzb2Z0d2FyZSwgYW5kICgyKQpvZmZlciB5b3UgdGhpcyBsaWNlbnNlIHdoaWNo +IGdpdmVzIHlvdSBsZWdhbCBwZXJtaXNzaW9uIHRvIGNvcHksCmRpc3RyaWJ1dGUgYW5kL29yIG1v +ZGlmeSB0aGUgc29mdHdhcmUuCgpBbHNvLCBmb3IgZWFjaCBhdXRob3IncyBwcm90ZWN0aW9uIGFu +ZCBvdXJzLCB3ZSB3YW50IHRvIG1ha2UgY2VydGFpbiB0aGF0CmV2ZXJ5b25lIHVuZGVyc3RhbmRz +IHRoYXQgdGhlcmUgaXMgbm8gd2FycmFudHkgZm9yIHRoaXMgZnJlZSBzb2Z0d2FyZS4gIElmCnRo +ZSBzb2Z0d2FyZSBpcyBtb2RpZmllZCBieSBzb21lb25lIGVsc2UgYW5kIHBhc3NlZCBvbiwgd2Ug +d2FudCBpdHMKcmVjaXBpZW50cyB0byBrbm93IHRoYXQgd2hhdCB0aGV5IGhhdmUgaXMgbm90IHRo +ZSBvcmlnaW5hbCwgc28gdGhhdCBhbnkKcHJvYmxlbXMgaW50cm9kdWNlZCBieSBvdGhlcnMgd2ls +bCBub3QgcmVmbGVjdCBvbiB0aGUgb3JpZ2luYWwgYXV0aG9ycycKcmVwdXRhdGlvbnMuCgpGaW5h +bGx5LCBhbnkgZnJlZSBwcm9ncmFtIGlzIHRocmVhdGVuZWQgY29uc3RhbnRseSBieSBzb2Z0d2Fy +ZSBwYXRlbnRzLgpXZSB3aXNoIHRvIGF2b2lkIHRoZSBkYW5nZXIgdGhhdCByZWRpc3RyaWJ1dG9y +cyBvZiBhIGZyZWUgcHJvZ3JhbSB3aWxsCmluZGl2aWR1YWxseSBvYnRhaW4gcGF0ZW50IGxpY2Vu +c2VzLCBpbiBlZmZlY3QgbWFraW5nIHRoZSBwcm9ncmFtCnByb3ByaWV0YXJ5LiAgVG8gcHJldmVu +dCB0aGlzLCB3ZSBoYXZlIG1hZGUgaXQgY2xlYXIgdGhhdCBhbnkgcGF0ZW50IG11c3QKYmUgbGlj +ZW5zZWQgZm9yIGV2ZXJ5b25lJ3MgZnJlZSB1c2Ugb3Igbm90IGxpY2Vuc2VkIGF0IGFsbC4KClRo +ZSBwcmVjaXNlIHRlcm1zIGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0cmlidXRpb24g +YW5kCm1vZGlmaWNhdGlvbiBmb2xsb3cuCgpcYmVnaW57Y2VudGVyfQp7XExhcmdlIFxzYyBUZXJt +cyBhbmQgQ29uZGl0aW9ucyBGb3IgQ29weWluZywgRGlzdHJpYnV0aW9uIGFuZAogIE1vZGlmaWNh +dGlvbn0KXGVuZHtjZW50ZXJ9CgoKJVxyZW5ld2NvbW1hbmR7XHRoZWVudW1pfXtcYWxwaGF7ZW51 +bWl9fQpcYmVnaW57ZW51bWVyYXRlfQoKXGFkZHRvY291bnRlcntlbnVtaX17LTF9CgpcaXRlbSAK +ClRoaXMgTGljZW5zZSBhcHBsaWVzIHRvIGFueSBwcm9ncmFtIG9yIG90aGVyIHdvcmsgd2hpY2gg +Y29udGFpbnMgYSBub3RpY2UKcGxhY2VkIGJ5IHRoZSBjb3B5cmlnaHQgaG9sZGVyIHNheWluZyBp +dCBtYXkgYmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlCnRlcm1zIG9mIHRoaXMgR2VuZXJhbCBQdWJs +aWMgTGljZW5zZS4gIFRoZSBgYFByb2dyYW0nJywgYmVsb3csIHJlZmVycyB0bwphbnkgc3VjaCBw +cm9ncmFtIG9yIHdvcmssIGFuZCBhIGBgd29yayBiYXNlZCBvbiB0aGUgUHJvZ3JhbScnIG1lYW5z +IGVpdGhlcgp0aGUgUHJvZ3JhbSBvciBhbnkgZGVyaXZhdGl2ZSB3b3JrIHVuZGVyIGNvcHlyaWdo +dCBsYXc6IHRoYXQgaXMgdG8gc2F5LCBhCndvcmsgY29udGFpbmluZyB0aGUgUHJvZ3JhbSBvciBh +IHBvcnRpb24gb2YgaXQsIGVpdGhlciB2ZXJiYXRpbSBvciB3aXRoCm1vZGlmaWNhdGlvbnMgYW5k +L29yIHRyYW5zbGF0ZWQgaW50byBhbm90aGVyIGxhbmd1YWdlLiAgKEhlcmVpbmFmdGVyLAp0cmFu +c2xhdGlvbiBpcyBpbmNsdWRlZCB3aXRob3V0IGxpbWl0YXRpb24gaW4gdGhlIHRlcm0gYGBtb2Rp +ZmljYXRpb24nJy4pCkVhY2ggbGljZW5zZWUgaXMgYWRkcmVzc2VkIGFzIGBgeW91JycuCgpBY3Rp +dml0aWVzIG90aGVyIHRoYW4gY29weWluZywgZGlzdHJpYnV0aW9uIGFuZCBtb2RpZmljYXRpb24g +YXJlIG5vdApjb3ZlcmVkIGJ5IHRoaXMgTGljZW5zZTsgdGhleSBhcmUgb3V0c2lkZSBpdHMgc2Nv +cGUuICBUaGUgYWN0IG9mCnJ1bm5pbmcgdGhlIFByb2dyYW0gaXMgbm90IHJlc3RyaWN0ZWQsIGFu +ZCB0aGUgb3V0cHV0IGZyb20gdGhlIFByb2dyYW0KaXMgY292ZXJlZCBvbmx5IGlmIGl0cyBjb250 +ZW50cyBjb25zdGl0dXRlIGEgd29yayBiYXNlZCBvbiB0aGUKUHJvZ3JhbSAoaW5kZXBlbmRlbnQg +b2YgaGF2aW5nIGJlZW4gbWFkZSBieSBydW5uaW5nIHRoZSBQcm9ncmFtKS4KV2hldGhlciB0aGF0 +IGlzIHRydWUgZGVwZW5kcyBvbiB3aGF0IHRoZSBQcm9ncmFtIGRvZXMuCgpcaXRlbSBZb3UgbWF5 +IGNvcHkgYW5kIGRpc3RyaWJ1dGUgdmVyYmF0aW0gY29waWVzIG9mIHRoZSBQcm9ncmFtJ3Mgc291 +cmNlCiAgY29kZSBhcyB5b3UgcmVjZWl2ZSBpdCwgaW4gYW55IG1lZGl1bSwgcHJvdmlkZWQgdGhh +dCB5b3UgY29uc3BpY3VvdXNseQogIGFuZCBhcHByb3ByaWF0ZWx5IHB1Ymxpc2ggb24gZWFjaCBj +b3B5IGFuIGFwcHJvcHJpYXRlIGNvcHlyaWdodCBub3RpY2UKICBhbmQgZGlzY2xhaW1lciBvZiB3 +YXJyYW50eTsga2VlcCBpbnRhY3QgYWxsIHRoZSBub3RpY2VzIHRoYXQgcmVmZXIgdG8KICB0aGlz +IExpY2Vuc2UgYW5kIHRvIHRoZSBhYnNlbmNlIG9mIGFueSB3YXJyYW50eTsgYW5kIGdpdmUgYW55 +IG90aGVyCiAgcmVjaXBpZW50cyBvZiB0aGUgUHJvZ3JhbSBhIGNvcHkgb2YgdGhpcyBMaWNlbnNl +IGFsb25nIHdpdGggdGhlIFByb2dyYW0uCgpZb3UgbWF5IGNoYXJnZSBhIGZlZSBmb3IgdGhlIHBo +eXNpY2FsIGFjdCBvZiB0cmFuc2ZlcnJpbmcgYSBjb3B5LCBhbmQgeW91Cm1heSBhdCB5b3VyIG9w +dGlvbiBvZmZlciB3YXJyYW50eSBwcm90ZWN0aW9uIGluIGV4Y2hhbmdlIGZvciBhIGZlZS4KClxp +dGVtCgpZb3UgbWF5IG1vZGlmeSB5b3VyIGNvcHkgb3IgY29waWVzIG9mIHRoZSBQcm9ncmFtIG9y +IGFueSBwb3J0aW9uCm9mIGl0LCB0aHVzIGZvcm1pbmcgYSB3b3JrIGJhc2VkIG9uIHRoZSBQcm9n +cmFtLCBhbmQgY29weSBhbmQKZGlzdHJpYnV0ZSBzdWNoIG1vZGlmaWNhdGlvbnMgb3Igd29yayB1 +bmRlciB0aGUgdGVybXMgb2YgU2VjdGlvbiAxCmFib3ZlLCBwcm92aWRlZCB0aGF0IHlvdSBhbHNv +IG1lZXQgYWxsIG9mIHRoZXNlIGNvbmRpdGlvbnM6CgpcYmVnaW57ZW51bWVyYXRlfQoKXGl0ZW0g +CgpZb3UgbXVzdCBjYXVzZSB0aGUgbW9kaWZpZWQgZmlsZXMgdG8gY2FycnkgcHJvbWluZW50IG5v +dGljZXMgc3RhdGluZyB0aGF0CnlvdSBjaGFuZ2VkIHRoZSBmaWxlcyBhbmQgdGhlIGRhdGUgb2Yg +YW55IGNoYW5nZS4KClxpdGVtCgpZb3UgbXVzdCBjYXVzZSBhbnkgd29yayB0aGF0IHlvdSBkaXN0 +cmlidXRlIG9yIHB1Ymxpc2gsIHRoYXQgaW4Kd2hvbGUgb3IgaW4gcGFydCBjb250YWlucyBvciBp +cyBkZXJpdmVkIGZyb20gdGhlIFByb2dyYW0gb3IgYW55CnBhcnQgdGhlcmVvZiwgdG8gYmUgbGlj +ZW5zZWQgYXMgYSB3aG9sZSBhdCBubyBjaGFyZ2UgdG8gYWxsIHRoaXJkCnBhcnRpZXMgdW5kZXIg +dGhlIHRlcm1zIG9mIHRoaXMgTGljZW5zZS4KClxpdGVtCklmIHRoZSBtb2RpZmllZCBwcm9ncmFt +IG5vcm1hbGx5IHJlYWRzIGNvbW1hbmRzIGludGVyYWN0aXZlbHkKd2hlbiBydW4sIHlvdSBtdXN0 +IGNhdXNlIGl0LCB3aGVuIHN0YXJ0ZWQgcnVubmluZyBmb3Igc3VjaAppbnRlcmFjdGl2ZSB1c2Ug +aW4gdGhlIG1vc3Qgb3JkaW5hcnkgd2F5LCB0byBwcmludCBvciBkaXNwbGF5IGFuCmFubm91bmNl +bWVudCBpbmNsdWRpbmcgYW4gYXBwcm9wcmlhdGUgY29weXJpZ2h0IG5vdGljZSBhbmQgYQpub3Rp +Y2UgdGhhdCB0aGVyZSBpcyBubyB3YXJyYW50eSAob3IgZWxzZSwgc2F5aW5nIHRoYXQgeW91IHBy +b3ZpZGUKYSB3YXJyYW50eSkgYW5kIHRoYXQgdXNlcnMgbWF5IHJlZGlzdHJpYnV0ZSB0aGUgcHJv +Z3JhbSB1bmRlcgp0aGVzZSBjb25kaXRpb25zLCBhbmQgdGVsbGluZyB0aGUgdXNlciBob3cgdG8g +dmlldyBhIGNvcHkgb2YgdGhpcwpMaWNlbnNlLiAgKEV4Y2VwdGlvbjogaWYgdGhlIFByb2dyYW0g +aXRzZWxmIGlzIGludGVyYWN0aXZlIGJ1dApkb2VzIG5vdCBub3JtYWxseSBwcmludCBzdWNoIGFu +IGFubm91bmNlbWVudCwgeW91ciB3b3JrIGJhc2VkIG9uCnRoZSBQcm9ncmFtIGlzIG5vdCByZXF1 +aXJlZCB0byBwcmludCBhbiBhbm5vdW5jZW1lbnQuKQoKXGVuZHtlbnVtZXJhdGV9CgoKVGhlc2Ug +cmVxdWlyZW1lbnRzIGFwcGx5IHRvIHRoZSBtb2RpZmllZCB3b3JrIGFzIGEgd2hvbGUuICBJZgpp +ZGVudGlmaWFibGUgc2VjdGlvbnMgb2YgdGhhdCB3b3JrIGFyZSBub3QgZGVyaXZlZCBmcm9tIHRo +ZSBQcm9ncmFtLAphbmQgY2FuIGJlIHJlYXNvbmFibHkgY29uc2lkZXJlZCBpbmRlcGVuZGVudCBh +bmQgc2VwYXJhdGUgd29ya3MgaW4KdGhlbXNlbHZlcywgdGhlbiB0aGlzIExpY2Vuc2UsIGFuZCBp +dHMgdGVybXMsIGRvIG5vdCBhcHBseSB0byB0aG9zZQpzZWN0aW9ucyB3aGVuIHlvdSBkaXN0cmli +dXRlIHRoZW0gYXMgc2VwYXJhdGUgd29ya3MuICBCdXQgd2hlbiB5b3UKZGlzdHJpYnV0ZSB0aGUg +c2FtZSBzZWN0aW9ucyBhcyBwYXJ0IG9mIGEgd2hvbGUgd2hpY2ggaXMgYSB3b3JrIGJhc2VkCm9u +IHRoZSBQcm9ncmFtLCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSB3aG9sZSBtdXN0IGJlIG9uIHRo +ZSB0ZXJtcyBvZgp0aGlzIExpY2Vuc2UsIHdob3NlIHBlcm1pc3Npb25zIGZvciBvdGhlciBsaWNl +bnNlZXMgZXh0ZW5kIHRvIHRoZQplbnRpcmUgd2hvbGUsIGFuZCB0aHVzIHRvIGVhY2ggYW5kIGV2 +ZXJ5IHBhcnQgcmVnYXJkbGVzcyBvZiB3aG8gd3JvdGUgaXQuCgpUaHVzLCBpdCBpcyBub3QgdGhl +IGludGVudCBvZiB0aGlzIHNlY3Rpb24gdG8gY2xhaW0gcmlnaHRzIG9yIGNvbnRlc3QKeW91ciBy +aWdodHMgdG8gd29yayB3cml0dGVuIGVudGlyZWx5IGJ5IHlvdTsgcmF0aGVyLCB0aGUgaW50ZW50 +IGlzIHRvCmV4ZXJjaXNlIHRoZSByaWdodCB0byBjb250cm9sIHRoZSBkaXN0cmlidXRpb24gb2Yg +ZGVyaXZhdGl2ZSBvcgpjb2xsZWN0aXZlIHdvcmtzIGJhc2VkIG9uIHRoZSBQcm9ncmFtLgoKSW4g +YWRkaXRpb24sIG1lcmUgYWdncmVnYXRpb24gb2YgYW5vdGhlciB3b3JrIG5vdCBiYXNlZCBvbiB0 +aGUgUHJvZ3JhbQp3aXRoIHRoZSBQcm9ncmFtIChvciB3aXRoIGEgd29yayBiYXNlZCBvbiB0aGUg +UHJvZ3JhbSkgb24gYSB2b2x1bWUgb2YKYSBzdG9yYWdlIG9yIGRpc3RyaWJ1dGlvbiBtZWRpdW0g +ZG9lcyBub3QgYnJpbmcgdGhlIG90aGVyIHdvcmsgdW5kZXIKdGhlIHNjb3BlIG9mIHRoaXMgTGlj +ZW5zZS4KClxpdGVtCllvdSBtYXkgY29weSBhbmQgZGlzdHJpYnV0ZSB0aGUgUHJvZ3JhbSAob3Ig +YSB3b3JrIGJhc2VkIG9uIGl0LAp1bmRlciBTZWN0aW9uIDIpIGluIG9iamVjdCBjb2RlIG9yIGV4 +ZWN1dGFibGUgZm9ybSB1bmRlciB0aGUgdGVybXMgb2YKU2VjdGlvbnMgMSBhbmQgMiBhYm92ZSBw +cm92aWRlZCB0aGF0IHlvdSBhbHNvIGRvIG9uZSBvZiB0aGUgZm9sbG93aW5nOgoKXGJlZ2lue2Vu +dW1lcmF0ZX0KClxpdGVtCgpBY2NvbXBhbnkgaXQgd2l0aCB0aGUgY29tcGxldGUgY29ycmVzcG9u +ZGluZyBtYWNoaW5lLXJlYWRhYmxlCnNvdXJjZSBjb2RlLCB3aGljaCBtdXN0IGJlIGRpc3RyaWJ1 +dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiBTZWN0aW9ucwoxIGFuZCAyIGFib3ZlIG9uIGEgbWVkaXVt +IGN1c3RvbWFyaWx5IHVzZWQgZm9yIHNvZnR3YXJlIGludGVyY2hhbmdlOyBvciwKClxpdGVtCgpB +Y2NvbXBhbnkgaXQgd2l0aCBhIHdyaXR0ZW4gb2ZmZXIsIHZhbGlkIGZvciBhdCBsZWFzdCB0aHJl +ZQp5ZWFycywgdG8gZ2l2ZSBhbnkgdGhpcmQgcGFydHksIGZvciBhIGNoYXJnZSBubyBtb3JlIHRo +YW4geW91cgpjb3N0IG9mIHBoeXNpY2FsbHkgcGVyZm9ybWluZyBzb3VyY2UgZGlzdHJpYnV0aW9u +LCBhIGNvbXBsZXRlCm1hY2hpbmUtcmVhZGFibGUgY29weSBvZiB0aGUgY29ycmVzcG9uZGluZyBz +b3VyY2UgY29kZSwgdG8gYmUKZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb25z +IDEgYW5kIDIgYWJvdmUgb24gYSBtZWRpdW0KY3VzdG9tYXJpbHkgdXNlZCBmb3Igc29mdHdhcmUg +aW50ZXJjaGFuZ2U7IG9yLAoKXGl0ZW0KCkFjY29tcGFueSBpdCB3aXRoIHRoZSBpbmZvcm1hdGlv +biB5b3UgcmVjZWl2ZWQgYXMgdG8gdGhlIG9mZmVyCnRvIGRpc3RyaWJ1dGUgY29ycmVzcG9uZGlu +ZyBzb3VyY2UgY29kZS4gIChUaGlzIGFsdGVybmF0aXZlIGlzCmFsbG93ZWQgb25seSBmb3Igbm9u +Y29tbWVyY2lhbCBkaXN0cmlidXRpb24gYW5kIG9ubHkgaWYgeW91CnJlY2VpdmVkIHRoZSBwcm9n +cmFtIGluIG9iamVjdCBjb2RlIG9yIGV4ZWN1dGFibGUgZm9ybSB3aXRoIHN1Y2gKYW4gb2ZmZXIs +IGluIGFjY29yZCB3aXRoIFN1YnNlY3Rpb24gYiBhYm92ZS4pCgpcZW5ke2VudW1lcmF0ZX0KCgpU +aGUgc291cmNlIGNvZGUgZm9yIGEgd29yayBtZWFucyB0aGUgcHJlZmVycmVkIGZvcm0gb2YgdGhl +IHdvcmsgZm9yCm1ha2luZyBtb2RpZmljYXRpb25zIHRvIGl0LiAgRm9yIGFuIGV4ZWN1dGFibGUg +d29yaywgY29tcGxldGUgc291cmNlCmNvZGUgbWVhbnMgYWxsIHRoZSBzb3VyY2UgY29kZSBmb3Ig +YWxsIG1vZHVsZXMgaXQgY29udGFpbnMsIHBsdXMgYW55CmFzc29jaWF0ZWQgaW50ZXJmYWNlIGRl +ZmluaXRpb24gZmlsZXMsIHBsdXMgdGhlIHNjcmlwdHMgdXNlZCB0bwpjb250cm9sIGNvbXBpbGF0 +aW9uIGFuZCBpbnN0YWxsYXRpb24gb2YgdGhlIGV4ZWN1dGFibGUuICBIb3dldmVyLCBhcyBhCnNw +ZWNpYWwgZXhjZXB0aW9uLCB0aGUgc291cmNlIGNvZGUgZGlzdHJpYnV0ZWQgbmVlZCBub3QgaW5j +bHVkZQphbnl0aGluZyB0aGF0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIChpbiBlaXRoZXIgc291 +cmNlIG9yIGJpbmFyeQpmb3JtKSB3aXRoIHRoZSBtYWpvciBjb21wb25lbnRzIChjb21waWxlciwg +a2VybmVsLCBhbmQgc28gb24pIG9mIHRoZQpvcGVyYXRpbmcgc3lzdGVtIG9uIHdoaWNoIHRoZSBl +eGVjdXRhYmxlIHJ1bnMsIHVubGVzcyB0aGF0IGNvbXBvbmVudAppdHNlbGYgYWNjb21wYW5pZXMg +dGhlIGV4ZWN1dGFibGUuCgpJZiBkaXN0cmlidXRpb24gb2YgZXhlY3V0YWJsZSBvciBvYmplY3Qg +Y29kZSBpcyBtYWRlIGJ5IG9mZmVyaW5nCmFjY2VzcyB0byBjb3B5IGZyb20gYSBkZXNpZ25hdGVk +IHBsYWNlLCB0aGVuIG9mZmVyaW5nIGVxdWl2YWxlbnQKYWNjZXNzIHRvIGNvcHkgdGhlIHNvdXJj +ZSBjb2RlIGZyb20gdGhlIHNhbWUgcGxhY2UgY291bnRzIGFzCmRpc3RyaWJ1dGlvbiBvZiB0aGUg +c291cmNlIGNvZGUsIGV2ZW4gdGhvdWdoIHRoaXJkIHBhcnRpZXMgYXJlIG5vdApjb21wZWxsZWQg +dG8gY29weSB0aGUgc291cmNlIGFsb25nIHdpdGggdGhlIG9iamVjdCBjb2RlLgoKXGl0ZW0KWW91 +IG1heSBub3QgY29weSwgbW9kaWZ5LCBzdWJsaWNlbnNlLCBvciBkaXN0cmlidXRlIHRoZSBQcm9n +cmFtCmV4Y2VwdCBhcyBleHByZXNzbHkgcHJvdmlkZWQgdW5kZXIgdGhpcyBMaWNlbnNlLiAgQW55 +IGF0dGVtcHQKb3RoZXJ3aXNlIHRvIGNvcHksIG1vZGlmeSwgc3VibGljZW5zZSBvciBkaXN0cmli +dXRlIHRoZSBQcm9ncmFtIGlzCnZvaWQsIGFuZCB3aWxsIGF1dG9tYXRpY2FsbHkgdGVybWluYXRl +IHlvdXIgcmlnaHRzIHVuZGVyIHRoaXMgTGljZW5zZS4KSG93ZXZlciwgcGFydGllcyB3aG8gaGF2 +ZSByZWNlaXZlZCBjb3BpZXMsIG9yIHJpZ2h0cywgZnJvbSB5b3UgdW5kZXIKdGhpcyBMaWNlbnNl +IHdpbGwgbm90IGhhdmUgdGhlaXIgbGljZW5zZXMgdGVybWluYXRlZCBzbyBsb25nIGFzIHN1Y2gK +cGFydGllcyByZW1haW4gaW4gZnVsbCBjb21wbGlhbmNlLgoKXGl0ZW0KWW91IGFyZSBub3QgcmVx +dWlyZWQgdG8gYWNjZXB0IHRoaXMgTGljZW5zZSwgc2luY2UgeW91IGhhdmUgbm90CnNpZ25lZCBp +dC4gIEhvd2V2ZXIsIG5vdGhpbmcgZWxzZSBncmFudHMgeW91IHBlcm1pc3Npb24gdG8gbW9kaWZ5 +IG9yCmRpc3RyaWJ1dGUgdGhlIFByb2dyYW0gb3IgaXRzIGRlcml2YXRpdmUgd29ya3MuICBUaGVz +ZSBhY3Rpb25zIGFyZQpwcm9oaWJpdGVkIGJ5IGxhdyBpZiB5b3UgZG8gbm90IGFjY2VwdCB0aGlz +IExpY2Vuc2UuICBUaGVyZWZvcmUsIGJ5Cm1vZGlmeWluZyBvciBkaXN0cmlidXRpbmcgdGhlIFBy +b2dyYW0gKG9yIGFueSB3b3JrIGJhc2VkIG9uIHRoZQpQcm9ncmFtKSwgeW91IGluZGljYXRlIHlv +dXIgYWNjZXB0YW5jZSBvZiB0aGlzIExpY2Vuc2UgdG8gZG8gc28sIGFuZAphbGwgaXRzIHRlcm1z +IGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0cmlidXRpbmcgb3IgbW9kaWZ5aW5nCnRo +ZSBQcm9ncmFtIG9yIHdvcmtzIGJhc2VkIG9uIGl0LgoKXGl0ZW0KRWFjaCB0aW1lIHlvdSByZWRp +c3RyaWJ1dGUgdGhlIFByb2dyYW0gKG9yIGFueSB3b3JrIGJhc2VkIG9uIHRoZQpQcm9ncmFtKSwg +dGhlIHJlY2lwaWVudCBhdXRvbWF0aWNhbGx5IHJlY2VpdmVzIGEgbGljZW5zZSBmcm9tIHRoZQpv +cmlnaW5hbCBsaWNlbnNvciB0byBjb3B5LCBkaXN0cmlidXRlIG9yIG1vZGlmeSB0aGUgUHJvZ3Jh +bSBzdWJqZWN0IHRvCnRoZXNlIHRlcm1zIGFuZCBjb25kaXRpb25zLiAgWW91IG1heSBub3QgaW1w +b3NlIGFueSBmdXJ0aGVyCnJlc3RyaWN0aW9ucyBvbiB0aGUgcmVjaXBpZW50cycgZXhlcmNpc2Ug +b2YgdGhlIHJpZ2h0cyBncmFudGVkIGhlcmVpbi4KWW91IGFyZSBub3QgcmVzcG9uc2libGUgZm9y +IGVuZm9yY2luZyBjb21wbGlhbmNlIGJ5IHRoaXJkIHBhcnRpZXMgdG8KdGhpcyBMaWNlbnNlLgoK +XGl0ZW0KSWYsIGFzIGEgY29uc2VxdWVuY2Ugb2YgYSBjb3VydCBqdWRnbWVudCBvciBhbGxlZ2F0 +aW9uIG9mIHBhdGVudAppbmZyaW5nZW1lbnQgb3IgZm9yIGFueSBvdGhlciByZWFzb24gKG5vdCBs +aW1pdGVkIHRvIHBhdGVudCBpc3N1ZXMpLApjb25kaXRpb25zIGFyZSBpbXBvc2VkIG9uIHlvdSAo +d2hldGhlciBieSBjb3VydCBvcmRlciwgYWdyZWVtZW50IG9yCm90aGVyd2lzZSkgdGhhdCBjb250 +cmFkaWN0IHRoZSBjb25kaXRpb25zIG9mIHRoaXMgTGljZW5zZSwgdGhleSBkbyBub3QKZXhjdXNl +IHlvdSBmcm9tIHRoZSBjb25kaXRpb25zIG9mIHRoaXMgTGljZW5zZS4gIElmIHlvdSBjYW5ub3QK +ZGlzdHJpYnV0ZSBzbyBhcyB0byBzYXRpc2Z5IHNpbXVsdGFuZW91c2x5IHlvdXIgb2JsaWdhdGlv +bnMgdW5kZXIgdGhpcwpMaWNlbnNlIGFuZCBhbnkgb3RoZXIgcGVydGluZW50IG9ibGlnYXRpb25z +LCB0aGVuIGFzIGEgY29uc2VxdWVuY2UgeW91Cm1heSBub3QgZGlzdHJpYnV0ZSB0aGUgUHJvZ3Jh +bSBhdCBhbGwuICBGb3IgZXhhbXBsZSwgaWYgYSBwYXRlbnQKbGljZW5zZSB3b3VsZCBub3QgcGVy +bWl0IHJveWFsdHktZnJlZSByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZ3JhbSBieQphbGwgdGhv +c2Ugd2hvIHJlY2VpdmUgY29waWVzIGRpcmVjdGx5IG9yIGluZGlyZWN0bHkgdGhyb3VnaCB5b3Us +IHRoZW4KdGhlIG9ubHkgd2F5IHlvdSBjb3VsZCBzYXRpc2Z5IGJvdGggaXQgYW5kIHRoaXMgTGlj +ZW5zZSB3b3VsZCBiZSB0bwpyZWZyYWluIGVudGlyZWx5IGZyb20gZGlzdHJpYnV0aW9uIG9mIHRo +ZSBQcm9ncmFtLgoKSWYgYW55IHBvcnRpb24gb2YgdGhpcyBzZWN0aW9uIGlzIGhlbGQgaW52YWxp +ZCBvciB1bmVuZm9yY2VhYmxlIHVuZGVyCmFueSBwYXJ0aWN1bGFyIGNpcmN1bXN0YW5jZSwgdGhl +IGJhbGFuY2Ugb2YgdGhlIHNlY3Rpb24gaXMgaW50ZW5kZWQgdG8KYXBwbHkgYW5kIHRoZSBzZWN0 +aW9uIGFzIGEgd2hvbGUgaXMgaW50ZW5kZWQgdG8gYXBwbHkgaW4gb3RoZXIKY2lyY3Vtc3RhbmNl +cy4KCkl0IGlzIG5vdCB0aGUgcHVycG9zZSBvZiB0aGlzIHNlY3Rpb24gdG8gaW5kdWNlIHlvdSB0 +byBpbmZyaW5nZSBhbnkKcGF0ZW50cyBvciBvdGhlciBwcm9wZXJ0eSByaWdodCBjbGFpbXMgb3Ig +dG8gY29udGVzdCB2YWxpZGl0eSBvZiBhbnkKc3VjaCBjbGFpbXM7IHRoaXMgc2VjdGlvbiBoYXMg +dGhlIHNvbGUgcHVycG9zZSBvZiBwcm90ZWN0aW5nIHRoZQppbnRlZ3JpdHkgb2YgdGhlIGZyZWUg +c29mdHdhcmUgZGlzdHJpYnV0aW9uIHN5c3RlbSwgd2hpY2ggaXMKaW1wbGVtZW50ZWQgYnkgcHVi +bGljIGxpY2Vuc2UgcHJhY3RpY2VzLiAgTWFueSBwZW9wbGUgaGF2ZSBtYWRlCmdlbmVyb3VzIGNv +bnRyaWJ1dGlvbnMgdG8gdGhlIHdpZGUgcmFuZ2Ugb2Ygc29mdHdhcmUgZGlzdHJpYnV0ZWQKdGhy +b3VnaCB0aGF0IHN5c3RlbSBpbiByZWxpYW5jZSBvbiBjb25zaXN0ZW50IGFwcGxpY2F0aW9uIG9m +IHRoYXQKc3lzdGVtOyBpdCBpcyB1cCB0byB0aGUgYXV0aG9yL2Rvbm9yIHRvIGRlY2lkZSBpZiBo +ZSBvciBzaGUgaXMgd2lsbGluZwp0byBkaXN0cmlidXRlIHNvZnR3YXJlIHRocm91Z2ggYW55IG90 +aGVyIHN5c3RlbSBhbmQgYSBsaWNlbnNlZSBjYW5ub3QKaW1wb3NlIHRoYXQgY2hvaWNlLgoKVGhp +cyBzZWN0aW9uIGlzIGludGVuZGVkIHRvIG1ha2UgdGhvcm91Z2hseSBjbGVhciB3aGF0IGlzIGJl +bGlldmVkIHRvCmJlIGEgY29uc2VxdWVuY2Ugb2YgdGhlIHJlc3Qgb2YgdGhpcyBMaWNlbnNlLgoK +XGl0ZW0KSWYgdGhlIGRpc3RyaWJ1dGlvbiBhbmQvb3IgdXNlIG9mIHRoZSBQcm9ncmFtIGlzIHJl +c3RyaWN0ZWQgaW4KY2VydGFpbiBjb3VudHJpZXMgZWl0aGVyIGJ5IHBhdGVudHMgb3IgYnkgY29w +eXJpZ2h0ZWQgaW50ZXJmYWNlcywgdGhlCm9yaWdpbmFsIGNvcHlyaWdodCBob2xkZXIgd2hvIHBs +YWNlcyB0aGUgUHJvZ3JhbSB1bmRlciB0aGlzIExpY2Vuc2UKbWF5IGFkZCBhbiBleHBsaWNpdCBn +ZW9ncmFwaGljYWwgZGlzdHJpYnV0aW9uIGxpbWl0YXRpb24gZXhjbHVkaW5nCnRob3NlIGNvdW50 +cmllcywgc28gdGhhdCBkaXN0cmlidXRpb24gaXMgcGVybWl0dGVkIG9ubHkgaW4gb3IgYW1vbmcK +Y291bnRyaWVzIG5vdCB0aHVzIGV4Y2x1ZGVkLiAgSW4gc3VjaCBjYXNlLCB0aGlzIExpY2Vuc2Ug +aW5jb3Jwb3JhdGVzCnRoZSBsaW1pdGF0aW9uIGFzIGlmIHdyaXR0ZW4gaW4gdGhlIGJvZHkgb2Yg +dGhpcyBMaWNlbnNlLgoKXGl0ZW0KVGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiBtYXkgcHVi +bGlzaCByZXZpc2VkIGFuZC9vciBuZXcgdmVyc2lvbnMKb2YgdGhlIEdlbmVyYWwgUHVibGljIExp +Y2Vuc2UgZnJvbSB0aW1lIHRvIHRpbWUuICBTdWNoIG5ldyB2ZXJzaW9ucyB3aWxsCmJlIHNpbWls +YXIgaW4gc3Bpcml0IHRvIHRoZSBwcmVzZW50IHZlcnNpb24sIGJ1dCBtYXkgZGlmZmVyIGluIGRl +dGFpbCB0bwphZGRyZXNzIG5ldyBwcm9ibGVtcyBvciBjb25jZXJucy4KCkVhY2ggdmVyc2lvbiBp +cyBnaXZlbiBhIGRpc3Rpbmd1aXNoaW5nIHZlcnNpb24gbnVtYmVyLiAgSWYgdGhlIFByb2dyYW0K +c3BlY2lmaWVzIGEgdmVyc2lvbiBudW1iZXIgb2YgdGhpcyBMaWNlbnNlIHdoaWNoIGFwcGxpZXMg +dG8gaXQgYW5kIGBgYW55CmxhdGVyIHZlcnNpb24nJywgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiBm +b2xsb3dpbmcgdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zCmVpdGhlciBvZiB0aGF0IHZlcnNpb24g +b3Igb2YgYW55IGxhdGVyIHZlcnNpb24gcHVibGlzaGVkIGJ5IHRoZSBGcmVlClNvZnR3YXJlIEZv +dW5kYXRpb24uICBJZiB0aGUgUHJvZ3JhbSBkb2VzIG5vdCBzcGVjaWZ5IGEgdmVyc2lvbiBudW1i +ZXIgb2YKdGhpcyBMaWNlbnNlLCB5b3UgbWF5IGNob29zZSBhbnkgdmVyc2lvbiBldmVyIHB1Ymxp +c2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZQpGb3VuZGF0aW9uLgoKXGl0ZW0KSWYgeW91IHdpc2gg +dG8gaW5jb3Jwb3JhdGUgcGFydHMgb2YgdGhlIFByb2dyYW0gaW50byBvdGhlciBmcmVlCnByb2dy +YW1zIHdob3NlIGRpc3RyaWJ1dGlvbiBjb25kaXRpb25zIGFyZSBkaWZmZXJlbnQsIHdyaXRlIHRv +IHRoZSBhdXRob3IKdG8gYXNrIGZvciBwZXJtaXNzaW9uLiAgRm9yIHNvZnR3YXJlIHdoaWNoIGlz +IGNvcHlyaWdodGVkIGJ5IHRoZSBGcmVlClNvZnR3YXJlIEZvdW5kYXRpb24sIHdyaXRlIHRvIHRo +ZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IHdlIHNvbWV0aW1lcwptYWtlIGV4Y2VwdGlvbnMg +Zm9yIHRoaXMuICBPdXIgZGVjaXNpb24gd2lsbCBiZSBndWlkZWQgYnkgdGhlIHR3byBnb2Fscwpv +ZiBwcmVzZXJ2aW5nIHRoZSBmcmVlIHN0YXR1cyBvZiBhbGwgZGVyaXZhdGl2ZXMgb2Ygb3VyIGZy +ZWUgc29mdHdhcmUgYW5kCm9mIHByb21vdGluZyB0aGUgc2hhcmluZyBhbmQgcmV1c2Ugb2Ygc29m +dHdhcmUgZ2VuZXJhbGx5LgoKXGJlZ2lue2NlbnRlcn0Ke1xMYXJnZVxzYwpObyBXYXJyYW50eQp9 +ClxlbmR7Y2VudGVyfQoKXGl0ZW0Ke1xzYyBCZWNhdXNlIHRoZSBwcm9ncmFtIGlzIGxpY2Vuc2Vk +IGZyZWUgb2YgY2hhcmdlLCB0aGVyZSBpcyBubyB3YXJyYW50eQpmb3IgdGhlIHByb2dyYW0sIHRv +IHRoZSBleHRlbnQgcGVybWl0dGVkIGJ5IGFwcGxpY2FibGUgbGF3LiAgRXhjZXB0IHdoZW4Kb3Ro +ZXJ3aXNlIHN0YXRlZCBpbiB3cml0aW5nIHRoZSBjb3B5cmlnaHQgaG9sZGVycyBhbmQvb3Igb3Ro +ZXIgcGFydGllcwpwcm92aWRlIHRoZSBwcm9ncmFtIGBgYXMgaXMnJyB3aXRob3V0IHdhcnJhbnR5 +IG9mIGFueSBraW5kLCBlaXRoZXIgZXhwcmVzc2VkCm9yIGltcGxpZWQsIGluY2x1ZGluZywgYnV0 +IG5vdCBsaW1pdGVkIHRvLCB0aGUgaW1wbGllZCB3YXJyYW50aWVzIG9mCm1lcmNoYW50YWJpbGl0 +eSBhbmQgZml0bmVzcyBmb3IgYSBwYXJ0aWN1bGFyIHB1cnBvc2UuICBUaGUgZW50aXJlIHJpc2sg +YXMKdG8gdGhlIHF1YWxpdHkgYW5kIHBlcmZvcm1hbmNlIG9mIHRoZSBwcm9ncmFtIGlzIHdpdGgg +eW91LiAgU2hvdWxkIHRoZQpwcm9ncmFtIHByb3ZlIGRlZmVjdGl2ZSwgeW91IGFzc3VtZSB0aGUg +Y29zdCBvZiBhbGwgbmVjZXNzYXJ5IHNlcnZpY2luZywKcmVwYWlyIG9yIGNvcnJlY3Rpb24ufQoK +XGl0ZW0Ke1xzYyBJbiBubyBldmVudCB1bmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcg +b3IgYWdyZWVkIHRvIGluIHdyaXRpbmcKd2lsbCBhbnkgY29weXJpZ2h0IGhvbGRlciwgb3IgYW55 +IG90aGVyIHBhcnR5IHdobyBtYXkgbW9kaWZ5IGFuZC9vcgpyZWRpc3RyaWJ1dGUgdGhlIHByb2dy +YW0gYXMgcGVybWl0dGVkIGFib3ZlLCBiZSBsaWFibGUgdG8geW91IGZvciBkYW1hZ2VzLAppbmNs +dWRpbmcgYW55IGdlbmVyYWwsIHNwZWNpYWwsIGluY2lkZW50YWwgb3IgY29uc2VxdWVudGlhbCBk +YW1hZ2VzIGFyaXNpbmcKb3V0IG9mIHRoZSB1c2Ugb3IgaW5hYmlsaXR5IHRvIHVzZSB0aGUgcHJv +Z3JhbSAoaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZAp0byBsb3NzIG9mIGRhdGEgb3IgZGF0YSBi +ZWluZyByZW5kZXJlZCBpbmFjY3VyYXRlIG9yIGxvc3NlcyBzdXN0YWluZWQgYnkKeW91IG9yIHRo +aXJkIHBhcnRpZXMgb3IgYSBmYWlsdXJlIG9mIHRoZSBwcm9ncmFtIHRvIG9wZXJhdGUgd2l0aCBh +bnkgb3RoZXIKcHJvZ3JhbXMpLCBldmVuIGlmIHN1Y2ggaG9sZGVyIG9yIG90aGVyIHBhcnR5IGhh +cyBiZWVuIGFkdmlzZWQgb2YgdGhlCnBvc3NpYmlsaXR5IG9mIHN1Y2ggZGFtYWdlcy59CgpcZW5k +e2VudW1lcmF0ZX0KCgpcYmVnaW57Y2VudGVyfQp7XExhcmdlXHNjIEVuZCBvZiBUZXJtcyBhbmQg +Q29uZGl0aW9uc30KXGVuZHtjZW50ZXJ9CgoKXHBhZ2VicmVha1syXQoKXHNlY3Rpb24qe0FwcGVu +ZGl4OiBIb3cgdG8gQXBwbHkgVGhlc2UgVGVybXMgdG8gWW91ciBOZXcgUHJvZ3JhbXN9CgpJZiB5 +b3UgZGV2ZWxvcCBhIG5ldyBwcm9ncmFtLCBhbmQgeW91IHdhbnQgaXQgdG8gYmUgb2YgdGhlIGdy +ZWF0ZXN0CnBvc3NpYmxlIHVzZSB0byB0aGUgcHVibGljLCB0aGUgYmVzdCB3YXkgdG8gYWNoaWV2 +ZSB0aGlzIGlzIHRvIG1ha2UgaXQKZnJlZSBzb2Z0d2FyZSB3aGljaCBldmVyeW9uZSBjYW4gcmVk +aXN0cmlidXRlIGFuZCBjaGFuZ2UgdW5kZXIgdGhlc2UKdGVybXMuCgogIFRvIGRvIHNvLCBhdHRh +Y2ggdGhlIGZvbGxvd2luZyBub3RpY2VzIHRvIHRoZSBwcm9ncmFtLiAgSXQgaXMgc2FmZXN0IHRv +CiAgYXR0YWNoIHRoZW0gdG8gdGhlIHN0YXJ0IG9mIGVhY2ggc291cmNlIGZpbGUgdG8gbW9zdCBl +ZmZlY3RpdmVseSBjb252ZXkKICB0aGUgZXhjbHVzaW9uIG9mIHdhcnJhbnR5OyBhbmQgZWFjaCBm +aWxlIHNob3VsZCBoYXZlIGF0IGxlYXN0IHRoZQogIGBgY29weXJpZ2h0JycgbGluZSBhbmQgYSBw +b2ludGVyIHRvIHdoZXJlIHRoZSBmdWxsIG5vdGljZSBpcyBmb3VuZC4KClxiZWdpbntxdW90ZX0K +b25lIGxpbmUgdG8gZ2l2ZSB0aGUgcHJvZ3JhbSdzIG5hbWUgYW5kIGEgYnJpZWYgaWRlYSBvZiB3 +aGF0IGl0IGRvZXMuIFxcCkNvcHlyaWdodCAoQykgeXl5eSAgbmFtZSBvZiBhdXRob3IgXFwKClRo +aXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQv +b3IgbW9kaWZ5Cml0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp +Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CnRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhl +ciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCihhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVy +IHZlcnNpb24uCgpUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBp +dCB3aWxsIGJlIHVzZWZ1bCwKYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4g +dGhlIGltcGxpZWQgd2FycmFudHkgb2YKTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEg +UEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQpHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBm +b3IgbW9yZSBkZXRhaWxzLgoKWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUg +R05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5v +dCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxl +IFBsYWNlIC0gU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3LCBVU0EuClxlbmR7cXVv +dGV9CgpBbHNvIGFkZCBpbmZvcm1hdGlvbiBvbiBob3cgdG8gY29udGFjdCB5b3UgYnkgZWxlY3Ry +b25pYyBhbmQgcGFwZXIgbWFpbC4KCklmIHRoZSBwcm9ncmFtIGlzIGludGVyYWN0aXZlLCBtYWtl +IGl0IG91dHB1dCBhIHNob3J0IG5vdGljZSBsaWtlIHRoaXMKd2hlbiBpdCBzdGFydHMgaW4gYW4g +aW50ZXJhY3RpdmUgbW9kZToKClxiZWdpbntxdW90ZX0KR25vbW92aXNpb24gdmVyc2lvbiA2OSwg +Q29weXJpZ2h0IChDKSB5eXl5ICBuYW1lIG9mIGF1dGhvciBcXApHbm9tb3Zpc2lvbiBjb21lcyB3 +aXRoIEFCU09MVVRFTFkgTk8gV0FSUkFOVFk7IGZvciBkZXRhaWxzIHR5cGUgYHNob3cgdycuIFxc +ClRoaXMgaXMgZnJlZSBzb2Z0d2FyZSwgYW5kIHlvdSBhcmUgd2VsY29tZSB0byByZWRpc3RyaWJ1 +dGUgaXQKdW5kZXIgY2VydGFpbiBjb25kaXRpb25zOyB0eXBlIGBzaG93IGMnIGZvciBkZXRhaWxz +LgpcZW5ke3F1b3RlfQoKClRoZSBoeXBvdGhldGljYWwgY29tbWFuZHMge1x0dCBzaG93IHd9IGFu +ZCB7XHR0IHNob3cgY30gc2hvdWxkIHNob3cgdGhlCmFwcHJvcHJpYXRlIHBhcnRzIG9mIHRoZSBH +ZW5lcmFsIFB1YmxpYyBMaWNlbnNlLiAgT2YgY291cnNlLCB0aGUgY29tbWFuZHMKeW91IHVzZSBt +YXkgYmUgY2FsbGVkIHNvbWV0aGluZyBvdGhlciB0aGFuIHtcdHQgc2hvdyB3fSBhbmQge1x0dCBz +aG93IGN9Owp0aGV5IGNvdWxkIGV2ZW4gYmUgbW91c2UtY2xpY2tzIG9yIG1lbnUgaXRlbXMtLS13 +aGF0ZXZlciBzdWl0cyB5b3VyCnByb2dyYW0uCgpZb3Ugc2hvdWxkIGFsc28gZ2V0IHlvdXIgZW1w +bG95ZXIgKGlmIHlvdSB3b3JrIGFzIGEgcHJvZ3JhbW1lcikgb3IgeW91cgpzY2hvb2wsIGlmIGFu +eSwgdG8gc2lnbiBhIGBgY29weXJpZ2h0IGRpc2NsYWltZXInJyBmb3IgdGhlIHByb2dyYW0sIGlm +Cm5lY2Vzc2FyeS4gIEhlcmUgaXMgYSBzYW1wbGU7IGFsdGVyIHRoZSBuYW1lczoKClxiZWdpbntx +dW90ZX0KWW95b2R5bmUsIEluYy4sIGhlcmVieSBkaXNjbGFpbXMgYWxsIGNvcHlyaWdodCBpbnRl +cmVzdCBpbiB0aGUgcHJvZ3JhbSBcXApgR25vbW92aXNpb24nICh3aGljaCBtYWtlcyBwYXNzZXMg +YXQgY29tcGlsZXJzKSB3cml0dGVuIGJ5IEphbWVzIEhhY2tlci4gXFwKCnNpZ25hdHVyZSBvZiBU +eSBDb29uLCAxIEFwcmlsIDE5ODkgXFwKVHkgQ29vbiwgUHJlc2lkZW50IG9mIFZpY2UKXGVuZHtx +dW90ZX0KCgpUaGlzIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZG9lcyBub3QgcGVybWl0IGluY29y +cG9yYXRpbmcgeW91ciBwcm9ncmFtCmludG8gcHJvcHJpZXRhcnkgcHJvZ3JhbXMuICBJZiB5b3Vy +IHByb2dyYW0gaXMgYSBzdWJyb3V0aW5lIGxpYnJhcnksIHlvdQptYXkgY29uc2lkZXIgaXQgbW9y +ZSB1c2VmdWwgdG8gcGVybWl0IGxpbmtpbmcgcHJvcHJpZXRhcnkgYXBwbGljYXRpb25zCndpdGgg +dGhlIGxpYnJhcnkuICBJZiB0aGlzIGlzIHdoYXQgeW91IHdhbnQgdG8gZG8sIHVzZSB0aGUgR05V +IExpYnJhcnkKR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBpbnN0ZWFkIG9mIHRoaXMgTGljZW5zZS4K +Cgo= +" ++ Glurf ++ lists:reverse(Glurf++"kalle"). diff --git a/lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl b/lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl new file mode 100644 index 0000000000..62402c10b7 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl @@ -0,0 +1,36 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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(nested_tuples_in_case_expr). +-export([nested_tuples_in_case_expr/0,t/2]). + +nested_tuples_in_case_expr() -> + ok. + +t(A, B) -> + case {{element(1, A),element(2, B)},{element(2, A),element(2, B)}} of + {Same,Same} -> ok; + {{0,1},{up,X}} -> bar(X); + {_,{X,_}} -> bar(X) + end. + +bar(X) -> X. + + + + diff --git a/lib/compiler/test/compilation_SUITE_data/on_load.erl b/lib/compiler/test/compilation_SUITE_data/on_load.erl new file mode 100644 index 0000000000..92bcf74624 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/on_load.erl @@ -0,0 +1,18 @@ +-module(on_load). +-export([?MODULE/0]). + +-on_load(do_on_load/0). + +%% Only test that the compiler is able to compile a module +%% with an on_load attribute. (There will be more thorough tests +%% of the functionality in code_SUITE in the Kernel application.) + +?MODULE() -> + ok. + +do_on_load() -> + local_function(), + true. + +local_function() -> + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/opt_crash.erl b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl new file mode 100644 index 0000000000..3a1d625c28 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl @@ -0,0 +1,65 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(opt_crash). +-export([?MODULE/0,test/0]). + +?MODULE() -> + ok. + +test() -> + URI_Before = + {absoluteURI, + {scheme,fun() -> nil end}, + {'hier-part', + {'net-path', + {srvr, + {userinfo,nil}, + fun() -> nil end}, + nil}, + {'query',nil}}}, + + {absoluteURI, + {scheme,_}, + {'hier-part', + {'net-path', + {srvr, + {userinfo,nil}, + HostportBefore}, + nil}, + {'query',nil}}} = URI_Before, + + %% ... some funky code ommitted, not relevant ... + + {absoluteURI, + {scheme,_}, + {'hier-part', + {'net-path', + {srvr, + {userinfo,nil}, + HostportAfter}, + nil}, + {'query',nil}}} = URI_Before, + %% NOTE: I intended to write URI_After instead of URI_Before + %% but the accident revealed that when you add the line below, + %% it causes internal error in v3_codegen on compilation + {hostport,{hostname,"HostName"},{port,nil}} = HostportAfter, + + ok. + + diff --git a/lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl b/lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl new file mode 100644 index 0000000000..7cb0778b95 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl @@ -0,0 +1,19 @@ +%% +%% %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(vsn_1). diff --git a/lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl b/lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl new file mode 100644 index 0000000000..3870e0704d --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl @@ -0,0 +1,24 @@ +%% +%% %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(vsn_3). + +-export([f/1]). + +f(X) -> + 2*X. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2141.erl b/lib/compiler/test/compilation_SUITE_data/otp_2141.erl new file mode 100644 index 0000000000..3e766546be --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_2141.erl @@ -0,0 +1,24 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(otp_2141). +-export([otp_2141/0]). + + +otp_2141() -> + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2173.erl b/lib/compiler/test/compilation_SUITE_data/otp_2173.erl new file mode 100644 index 0000000000..7e9d4c417b --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_2173.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(otp_2173). +-compile(export_all). + +-record(t, {a = fun(X) -> X*X end}). + +otp_2173() -> + ok. + +t() -> + #t{}. + + + diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2330.erl b/lib/compiler/test/compilation_SUITE_data/otp_2330.erl new file mode 100644 index 0000000000..f5f6717968 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_2330.erl @@ -0,0 +1,35 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(otp_2330). +-export([otp_2330/0, handle_interface/1]). + +otp_2330() -> + ok. + +handle_interface(Data)-> + Ctrl = 1, + case Data of + ok -> + case Ctrl of + [Viar]->integer_to_list(Viar); + _ -> [] + + end + end. + diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2380.erl b/lib/compiler/test/compilation_SUITE_data/otp_2380.erl new file mode 100644 index 0000000000..db2028b347 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_2380.erl @@ -0,0 +1,36 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(otp_2380). +-export([test/0, otp_2380/0]). + +otp_2380() -> + ok. + +-define(FUNC(Name), + case Name of + dpCh -> 5; + dpEvent -> 1; + dpc -> 4; + dpFm -> 6; + dpFm1 -> 6; + _ -> false + end). + +test() -> + N = ?FUNC(dpCh). diff --git a/lib/compiler/test/compilation_SUITE_data/otp_4790.erl b/lib/compiler/test/compilation_SUITE_data/otp_4790.erl new file mode 100644 index 0000000000..130ee44e80 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_4790.erl @@ -0,0 +1,63 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(otp_4790). + +-export([?MODULE/0]). + +?MODULE() -> + pan_test(). + + +% --------------------------- OTP Ticket -------------------------------- +% *Id: OTP-4790 +% *Notes: In the code below, the compiler incorrectly assumes +% wings_pref:get_value(pan_speed) returns a float, +% causing a crash at run-time. + +% The same error could cause tuple tests to be removed, +% but that would propbably only cause a crash if the +% Erlang code was incorrect or if it depended on a catch +% to catch exceptions. Therefore, I consider it unlikely +% that Erlang programs that don't use floating point +% arithmetic are likely to be bitten by this bug. +% ----------------------------------------------------------------------- + +-record(view, {pan_x,pan_y,distance}). + +pan_test() -> + pan(13, 3). + +pan(Dx0, Dy0) -> + #view{pan_x=PanX0,pan_y=PanY0,distance=D} = View = current(), + S = D*(1/8)/(51-pref_get_value(pan_speed)), + Dx = Dx0*S, + Dy = Dy0*S, + PanX = PanX0 + Dx, + PanY = PanY0 - Dy, + set_current(View#view{pan_x=PanX,pan_y=PanY}). + +current() -> + #view{pan_x=2.0,pan_y=9.75,distance=25.3}. + +set_current(#view{pan_x=X,pan_y=Y,distance=D}) + when is_float(X), is_float(Y), is_float(D) -> + io:format("X=~p Y=~p D=~p\n", [X,Y,D]). + +pref_get_value(pan_speed) -> + 32. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5076.erl b/lib/compiler/test/compilation_SUITE_data/otp_5076.erl new file mode 100644 index 0000000000..f05a4e1148 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5076.erl @@ -0,0 +1,27 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(otp_5076). +-export([?MODULE/0]). + +?MODULE() -> + [] = t(), + ok. + +t() -> + [3 || {3=4} <- []]. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5092.erl b/lib/compiler/test/compilation_SUITE_data/otp_5092.erl new file mode 100644 index 0000000000..e445e5e1e9 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5092.erl @@ -0,0 +1,39 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(otp_5092). +-export([?MODULE/0]). + +?MODULE() -> + [] = t(), + [] = t2(), + [t] = t4(), + [] = t5(), + ok. + +t() -> + [t || {C=D}={_,_} <- []]. + +t2() -> + [X || {X,{Y}={X,X}} <- []]. + +t4() -> + [t || "a"++"b" = "ab" <- ["ab"]]. + +t5() -> + [{X,Y} || {X} <- [], begin Y = X, Y =:= X end]. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5151.erl b/lib/compiler/test/compilation_SUITE_data/otp_5151.erl new file mode 100644 index 0000000000..2dccb979df --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5151.erl @@ -0,0 +1,61 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(otp_5151). + +-export([?MODULE/0]). +-export([read_variables/1,read_variables_1/1,read_variables_2/1, + read_variables_3/1,read_variables_4/1]). + +?MODULE() -> + ok. + +read_variables(Name) -> + case file:consult(Name) of + {ok,Vars} -> Vars; + {error,Reason} -> + erlang:error({bad_installation,file:format_error(Reason)}, [Name]) + end. + +read_variables_1(Name) -> + case file:consult(Name) of + {ok,Vars} -> Vars; + {error,Reason} -> + erlang:error({bad_installation,file:format_error(Reason)}) + end. + +read_variables_2(Name) -> + case file:consult(Name) of + {ok,Vars} -> Vars; + {error,Reason} -> + erlang:error({bad_installation,file:format_error(Reason)}, [Name]) + end. + +read_variables_3(Name) -> + case file:consult(Name) of + {ok,Vars} -> Vars; + {error,Reason} -> + erlang:error({bad_installation,file:format_error(Reason)}) + end. + +read_variables_4(Name) -> + case file:consult(Name) of + {ok,Vars} -> Vars; + {error,Reason} -> + exit({bad_installation,file:format_error(Reason)}) + end. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5235.erl b/lib/compiler/test/compilation_SUITE_data/otp_5235.erl new file mode 100644 index 0000000000..1c918cdf9d --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5235.erl @@ -0,0 +1,84 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(otp_5235). +-export([?MODULE/0]). + +-record(commit, {node, + decision, % presume_commit | Decision + ram_copies = [], + disc_copies = [], + disc_only_copies = [], + snmp = [], + schema_ops = [self(),make_ref()] + }). + +?MODULE() -> + process_flag(trap_exit, true), + N = 1024, + clone(N), + wait(N). + +wait(0) -> ok; +wait(N) -> + receive + {'EXIT',_,normal} -> + wait(N-1); + Other -> + exit(Other) + end. + +clone(0) -> ok; +clone(N) -> + spawn_link(fun worker/0), + clone(N-1). + +worker() -> + Seq = lists:seq(1, 10), + PidList = [{N,self()} || N <- Seq], + Commit = #commit{ram_copies=PidList,disc_copies=[], + disc_only_copies=[],snmp=[]}, + List = lists:duplicate(2, Commit), + verify(run(2, List)). + +verify([#commit{node=true,ram_copies=L}|T]) -> + verify_1(L, 1), + verify(T); +verify([]) -> ok. + +verify_1([{N,Pid}|T], N) when Pid =:= self() -> + verify_1(T, N+1); +verify_1([], _) -> ok. + +run(0, L) -> L; +run(N, L) -> run(N-1, reverse(L)). + +reverse([]) -> []; +reverse([H|R]) when record(H, commit) -> + [H#commit{ + ram_copies = lists:reverse(H#commit.ram_copies), + disc_copies = lists:reverse(H#commit.disc_copies), + disc_only_copies = lists:reverse(H#commit.disc_only_copies), + snmp = lists:reverse(H#commit.snmp), + node = erlang:yield() + } + | reverse(R)]. + + + + diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5244.erl b/lib/compiler/test/compilation_SUITE_data/otp_5244.erl new file mode 100644 index 0000000000..30849c6b5e --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5244.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(otp_5244). +-export([?MODULE/0]). + +?MODULE() -> + L = [{stretch,0,0}, + {bad,[]}, + {bad,atom}, + {bad,0}, + {bad,16#AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}, + {bad,16#555555555555555555555555555555555555555555555555555}], + remove_failure(L, unit, 0). + +remove_failure([], _Unit, _MaxFailure) -> + ok; +remove_failure([{bad,Bad}|_], _Unit, _MaxFailure) -> + Bad; +remove_failure([{stretch,_,Mi}=Stretch | Specs], Unit, _MaxFailure) -> + {MinMax,NewMaxFailure} = max_failure(), + case {MinMax,remove_failure(Specs, Unit, NewMaxFailure)} of + {min,{NewMaxFailure,Rest}} -> + {done,[{fixed,Mi} | Rest]}; + {min,_} when Specs =/= [] -> + remove_failure([Stretch|tl(Specs)], Unit, NewMaxFailure); + {min,_} -> + ok + end. + +max_failure() -> + {min,1}. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5404.erl b/lib/compiler/test/compilation_SUITE_data/otp_5404.erl new file mode 100644 index 0000000000..2de147c082 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5404.erl @@ -0,0 +1,51 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(otp_5404). +-compile(export_all). + +%% Thanks to Martin Bjorklund. + +?MODULE() -> + ok. + +-record(bar, {status, vs = []}). + +y() -> + x({foo, 1, []}). + +get_bar() -> + #bar{status = 1}. + +x(Trans) -> + {foo, Barno, _} = Trans, + case get_bar() of + Bar when Bar#bar.status /= 2 -> + if 1 == 1 -> + mnesia:dirty_delete({bar, Barno}), + Vs = [1,2] ++ Bar#bar.vs, + Bar33 = Bar#bar{status = 1}, + Bar1 = Bar#bar{status = 3, + vs = Vs}, + [{payment, Barno}]; + true -> + Barno + end; + _ -> + Trans + end. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5436.erl b/lib/compiler/test/compilation_SUITE_data/otp_5436.erl new file mode 100644 index 0000000000..4df8d50647 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5436.erl @@ -0,0 +1,201 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(otp_5436). +-compile(export_all). + +?MODULE() -> + ok. + +-record(readerState, {action_index, + log_index, + log_name, + time_period, + rec_id_period, + result_format, + action_status, + filter_type, + event_list, + sender_list, + read_status}). + +handle_call(delete,_From,State) -> + case catch debug:filter(console,logReader) of + true -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,306,console,self(),sysAssert:format_time2(erlang:now())])|"delete, State: ~p ~n"],[State]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["delete, State: ~p ~n",[State]]), + ok + end; + false -> + disabled; + {'EXIT',{undef,_}} -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,306,console,self(),sysAssert:format_time2(erlang:now())])|"delete, State: ~p ~n"],[State]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["delete, State: ~p ~n",[State]]), + ok + end; + {'EXIT',_} -> + debug:filter(console,logReader); + _ -> + exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}}) + end, + ?MODULE:clean_result(State), + {stop,normal,ok,State}; +handle_call(die,_,State) -> + {stop,normal,ok,State}; +handle_call(_Action,_From,#readerState{action_status = 2} = State) -> + {reply,error,State}; +handle_call(update_action_attr,_From,State) -> + NewState = ?MODULE:handle_update_action_attr(State), + case catch debug:filter(console,logReader) of + true -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,317,console,self(),sysAssert:format_time2(erlang:now())])|"update_action_attr, State: ~p ~n"],[NewState]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["update_action_attr, State: ~p ~n",[NewState]]), + ok + end; + false -> + disabled; + {'EXIT',{undef,_}} -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,317,console,self(),sysAssert:format_time2(erlang:now())])|"update_action_attr, State: ~p ~n"],[NewState]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["update_action_attr, State: ~p ~n",[NewState]]), + ok + end; + {'EXIT',_} -> + debug:filter(console,logReader); + _ -> + exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}}) + end, + {reply,ok,NewState}; +handle_call(update_event_filter,_From,State) -> + NewState = State#readerState{event_list = ?MODULE:get_event_list(State#readerState.action_index)}, + case catch debug:filter(console,logReader) of + true -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,323,console,self(),sysAssert:format_time2(erlang:now())])|"update_event_filter, State: ~p ~n"],[NewState]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["update_event_filter, State: ~p ~n",[NewState]]), + ok + end; + false -> + disabled; + {'EXIT',{undef,_}} -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,323,console,self(),sysAssert:format_time2(erlang:now())])|"update_event_filter, State: ~p ~n"],[NewState]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["update_event_filter, State: ~p ~n",[NewState]]), + ok + end; + {'EXIT',_} -> + debug:filter(console,logReader); + _ -> + exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}}) + end, + {reply,ok,NewState}; +handle_call(update_sender_filter,_From,State) -> + NewState = State#readerState{sender_list = ?MODULE:get_sender_list(State#readerState.action_index)}, + case catch debug:filter(console,logReader) of + true -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,329,console,self(),sysAssert:format_time2(erlang:now())])|"update_sender_filter, State: ~p ~n"],[NewState]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["update_sender_filter, State: ~p ~n",[NewState]]), + ok + end; + false -> + disabled; + {'EXIT',{undef,_}} -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,329,console,self(),sysAssert:format_time2(erlang:now())])|"update_sender_filter, State: ~p ~n"],[NewState]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["update_sender_filter, State: ~p ~n",[NewState]]), + ok + end; + {'EXIT',_} -> + debug:filter(console,logReader); + _ -> + exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}}) + end, + {reply,ok,NewState}; +handle_call(Request,_From,State) -> + case catch debug:filter(console,logReader) of + true -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,332,console,self(),sysAssert:format_time2(erlang:now())])|"Call ~p, State: ~p ~n"],[Request,State]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["Call ~p, State: ~p ~n",[Request,State]]), + ok + end; + false -> + disabled; + {'EXIT',{undef,_}} -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,332,console,self(),sysAssert:format_time2(erlang:now())])|"Call ~p, State: ~p ~n"],[Request,State]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["Call ~p, State: ~p ~n",[Request,State]]), + ok + end; + {'EXIT',_} -> + debug:filter(console,logReader); + _ -> + exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}}) + end, + {stop,{error,unknown,Request},State}. + +handle_info(Request,State) -> + case catch debug:filter(readlog,logReader) of + true -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,345,readlog,self(),sysAssert:format_time2(erlang:now())])|"Info ~p, State: ~p ~n"],[Request,State]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["Info ~p, State: ~p ~n",[Request,State]]), + ok + end; + false -> + disabled; + {'EXIT',{undef,_}} -> + case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,345,readlog,self(),sysAssert:format_time2(erlang:now())])|"Info ~p, State: ~p ~n"],[Request,State]) of + ok -> + ok; + _ -> + io:format("*** Bad format (~p, ~p) ***~n",["Info ~p, State: ~p ~n",[Request,State]]), + ok + end; + {'EXIT',_} -> + debug:filter(readlog,logReader); + _ -> + exit({badmatch,{{debug,filter,[readlog,logReader]},debug:filter(readlog,logReader)}}) + end, + {stop,{error,unknown,Request},State}. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5481.erl b/lib/compiler/test/compilation_SUITE_data/otp_5481.erl new file mode 100644 index 0000000000..5cf114ac4e --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5481.erl @@ -0,0 +1,527 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(otp_5481). + +-export([?MODULE/0,encode_cc_clpn/1,get_oper_status/2,foo/0]). + +?MODULE() -> + ok. + +-record(pchVp, {vplEntry, + vplLastChange, + vplReceiveTrafficDescrIndex = 0, + vplTransmitTrafficDescrIndex = 0, + vplConnId, + vplGroupShapingId}). + +-record(pchVc, {vclEntry, + vclLastChange, + vplConnId, + vclConnId, + vclShapingMode = 1}). +-record(spvcVpc, {spvcVpcEntry, + currentState, + spvcRerCap = false, + spvcRerStatus = false}). +-record(spvcVpcPerm, {spvcVpcEntry, + spvcVpcTargetAddress, + spvcVpcTargetSelectType, + spvcVpcUserName, + spvcVpcProviderName, + spvcVpcApplication}). +-record(spvcVcc, {spvcVccEntry, + spvcVccTargetAddress, + spvcVccTargetSelectType, + spvcVccTargetVpi, + spvcVccApplication, + spvcVccFrKey, + spvcVccTranslationMode, + spvcRerCap = false, + currentState, + spvcRerStatus = false}). +-record(spvcVccPerm, {spvcVccEntry, + spvcVccTargetAddress, + spvcVccTargetSelectType, + spvcVccTargetVpi, + spvcVccTargetType, + spvcVccApplication, + spvcVccFrKey, + spvcVccTranslationMode = 2}). +-record(spvcObj, {spvcEntry, + spvcTargetAddress, + spvcTargetSelectType, + spvcTargetVpi, + spvcTargetVci, + spvcLastReleaseCause, + spvcLastReleaseDiagnostic, + spvcRetryInterval = 1000, + spvcRetryTimer = 0, + spvcRetryThreshold = 1, + spvcRetryFailures = 0, + spvcRetryLimit = 15, + spvcFrKey, + spvcVccTranslationMode = 2, + spvcRerCap = false, + spvcRerStatus = false}). +-record(spvcTargetVc, {entry, + userName = [], + providerName = [], + opState, + rowStatus}). + +-record(spvcTargetVp, {entry, + userName = [], + providerName = [], + opState, + rowStatus}). + +-record(spvcFr, {spvcFrEntry, + spvcFrAtmEntry, + spvcFrTargetAddress, + spvcFrTargetSelectType, + spvcFrProviderName, + currentState}). + +-record(spvcFrPerm, {spvcFrEntry, + spvcFrAtmEntry, + spvcFrAtmTranslation, + spvcFrAdminStatus, + spvcFrConnect}). + +-record(hci_clpn, {hci_pci, + hci_type_of_number, + hci_numbering_plan_indicator, + hci_presentation_indicator, + hci_screening_indicator, + hci_number_digits, + hci_incomplete_indicator = 0, + hci_binary}). + +encode_cc_clpn(Spvc) when Spvc#spvcObj.spvcFrKey == undefined -> + If = case Spvc of + Spvc when record(Spvc,spvcObj) -> + case Spvc#spvcObj.spvcEntry of + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value + end; + Spvc when record(Spvc,spvcVcc) -> + {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry, + If_Value; + Spvc when record(Spvc,spvcVpc) -> + {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry, + If_Value; + Spvc when record(Spvc,spvcVpcPerm) -> + {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry, + If_Value; + Spvc when record(Spvc,spvcVccPerm) -> + {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry, + If_Value; + Spvc when record(Spvc,spvcTargetVc) -> + {If_Value,_,_} = Spvc#spvcTargetVc.entry, + If_Value; + Spvc when record(Spvc,spvcTargetVp) -> + {If_Value,_} = Spvc#spvcTargetVp.entry, + If_Value; + Spvc when record(Spvc,pchVc) -> + {If_Value,_,_} = Spvc#pchVc.vclEntry, + If_Value; + Spvc when record(Spvc,pchVp) -> + {If_Value,_} = Spvc#pchVp.vplEntry, + If_Value; + Spvc when record(Spvc,spvcFr) -> + {If_Value,_} = Spvc#spvcFr.spvcFrEntry, + If_Value; + Spvc when record(Spvc,spvcFrPerm) -> + {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry, + If_Value; + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value; + {If_Value,_} -> + If_Value; + [If_Value|_] -> + If_Value; + _ -> + error + end, + Col = [2], + SpvcAddress = case x:x(get_next,[If],Col) of + [{[2,If,20|Address],_}] -> + Address; + _ -> + lists:duplicate(20,0) + end, + #hci_clpn{hci_type_of_number = 0, + hci_numbering_plan_indicator = 2, + hci_presentation_indicator = 0, + hci_screening_indicator = 1, + hci_number_digits = SpvcAddress}; +encode_cc_clpn(Spvc) -> + {If,_} = Spvc#spvcObj.spvcFrKey, + Col = [4], + SpvcFrAddress = case x:x(get_next,[If],Col) of + [{[4,If,20|Address],_}] -> + Address; + _ -> + lists:duplicate(20,0) + end, + #hci_clpn{hci_type_of_number = 0, + hci_numbering_plan_indicator = 2, + hci_presentation_indicator = 0, + hci_screening_indicator = 1, + hci_number_digits = SpvcFrAddress}. + + + +get_oper_status(spvcVpc,Obj) when record(Obj,spvcVpc) -> + State = Obj#spvcVpc.currentState, + LinkState = get_link_opstate(case Obj of + Obj when record(Obj,spvcObj) -> + case Obj#spvcObj.spvcEntry of + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value + end; + Obj when record(Obj,spvcVcc) -> + {If_Value,_,_,_} = +Obj#spvcVcc.spvcVccEntry, + If_Value; + Obj when record(Obj,spvcVpc) -> + {If_Value,_,_} = Obj#spvcVpc.spvcVpcEntry, + If_Value; + Obj when record(Obj,spvcVpcPerm) -> + {If_Value,_,_} = +Obj#spvcVpcPerm.spvcVpcEntry, + If_Value; + Obj when record(Obj,spvcVccPerm) -> + {If_Value,_,_,_} = +Obj#spvcVccPerm.spvcVccEntry, + If_Value; + Obj when record(Obj,spvcTargetVc) -> + {If_Value,_,_} = Obj#spvcTargetVc.entry, + If_Value; + Obj when record(Obj,spvcTargetVp) -> + {If_Value,_} = Obj#spvcTargetVp.entry, + If_Value; + Obj when record(Obj,pchVc) -> + {If_Value,_,_} = Obj#pchVc.vclEntry, + If_Value; + Obj when record(Obj,pchVp) -> + {If_Value,_} = Obj#pchVp.vplEntry, + If_Value; + Obj when record(Obj,spvcFr) -> + {If_Value,_} = Obj#spvcFr.spvcFrEntry, + If_Value; + Obj when record(Obj,spvcFrPerm) -> + {If_Value,_} = Obj#spvcFrPerm.spvcFrEntry, + If_Value; + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value; + {If_Value,_} -> + If_Value; + [If_Value|_] -> + If_Value; + _ -> + error + end), + debug_disabled, + case {State,LinkState} of + {not_in_service,_} -> + 10; + {created,_} -> + 10; + {_,disabled} -> + 6; + {wait,_} -> + 2; + {outgoing_callproceeding,_} -> + 2; + {release_at_restart,_} -> + 2; + {active,_} -> + 3; + {rest_in_peace,_} -> + 4; + {_Other,_} -> + 1 + end; +get_oper_status(spvcVpc,_) -> + debug_disabled, + 1; +get_oper_status(spvcVcc,Obj) when record(Obj,spvcVcc) -> + State = Obj#spvcVcc.currentState, + LinkState = get_link_opstate(case Obj of + Obj when record(Obj,spvcObj) -> + case Obj#spvcObj.spvcEntry of + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value + end; + Obj when record(Obj,spvcVcc) -> + {If_Value,_,_,_} = +Obj#spvcVcc.spvcVccEntry, + If_Value; + Obj when record(Obj,spvcVpc) -> + {If_Value,_,_} = Obj#spvcVpc.spvcVpcEntry, + If_Value; + Obj when record(Obj,spvcVpcPerm) -> + {If_Value,_,_} = +Obj#spvcVpcPerm.spvcVpcEntry, + If_Value; + Obj when record(Obj,spvcVccPerm) -> + {If_Value,_,_,_} = +Obj#spvcVccPerm.spvcVccEntry, + If_Value; + Obj when record(Obj,spvcTargetVc) -> + {If_Value,_,_} = Obj#spvcTargetVc.entry, + If_Value; + Obj when record(Obj,spvcTargetVp) -> + {If_Value,_} = Obj#spvcTargetVp.entry, + If_Value; + Obj when record(Obj,pchVc) -> + {If_Value,_,_} = Obj#pchVc.vclEntry, + If_Value; + Obj when record(Obj,pchVp) -> + {If_Value,_} = Obj#pchVp.vplEntry, + If_Value; + Obj when record(Obj,spvcFr) -> + {If_Value,_} = Obj#spvcFr.spvcFrEntry, + If_Value; + Obj when record(Obj,spvcFrPerm) -> + {If_Value,_} = Obj#spvcFrPerm.spvcFrEntry, + If_Value; + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value; + {If_Value,_} -> + If_Value; + [If_Value|_] -> + If_Value; + _ -> + error + end), + debug_disabled, + case {State,LinkState} of + {not_in_service,_} -> + 10; + {created,_} -> + 10; + {_,disabled} -> + 6; + {wait,_} -> + 2; + {outgoing_callproceeding,_} -> + 2; + {release_at_restart,_} -> + 2; + {active,_} -> + 3; + {rest_in_peace,_} -> + 4; + {_Other,_} -> + 1 + end; +get_oper_status(spvcVcc,_) -> + debug_disabled, + 1; +get_oper_status(spvcTargetVp,Obj) when record(Obj,spvcTargetVp) -> + debug_disabled, + Key = Obj#spvcTargetVp.entry, + case get_link_opstate(case Key of + Key when record(Key,spvcObj) -> + case Key#spvcObj.spvcEntry of + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value + end; + Key when record(Key,spvcVcc) -> + {If_Value,_,_,_} = Key#spvcVcc.spvcVccEntry, + If_Value; + Key when record(Key,spvcVpc) -> + {If_Value,_,_} = Key#spvcVpc.spvcVpcEntry, + If_Value; + Key when record(Key,spvcVpcPerm) -> + {If_Value,_,_} = Key#spvcVpcPerm.spvcVpcEntry, + If_Value; + Key when record(Key,spvcVccPerm) -> + {If_Value,_,_,_} = Key#spvcVccPerm.spvcVccEntry, + If_Value; + Key when record(Key,spvcTargetVc) -> + {If_Value,_,_} = Key#spvcTargetVc.entry, + If_Value; + Key when record(Key,spvcTargetVp) -> + {If_Value,_} = Key#spvcTargetVp.entry, + If_Value; + Key when record(Key,pchVc) -> + {If_Value,_,_} = Key#pchVc.vclEntry, + If_Value; + Key when record(Key,pchVp) -> + {If_Value,_} = Key#pchVp.vplEntry, + If_Value; + Key when record(Key,spvcFr) -> + {If_Value,_} = Key#spvcFr.spvcFrEntry, + If_Value; + Key when record(Key,spvcFrPerm) -> + {If_Value,_} = Key#spvcFrPerm.spvcFrEntry, + If_Value; + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value; + {If_Value,_} -> + If_Value; + [If_Value|_] -> + If_Value; + _ -> + error + end) of + disabled -> + debug_disabled, + 4; + enabled -> + debug_disabled, + case (x:x({pchVp,Key}))#pchVp.vplConnId of + undefined -> + debug_disabled, + 3; + _ -> + debug_disabled, + 2 + end + end; +get_oper_status(spvcTargetVp,_) -> + debug_disabled, + 1; +get_oper_status(spvcTargetVc,Obj) when record(Obj,spvcTargetVc) -> + debug_disabled, + Key = Obj#spvcTargetVc.entry, + case get_link_opstate(case Key of + Key when record(Key,spvcObj) -> + case Key#spvcObj.spvcEntry of + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value + end; + Key when record(Key,spvcVcc) -> + {If_Value,_,_,_} = Key#spvcVcc.spvcVccEntry, + If_Value; + Key when record(Key,spvcVpc) -> + {If_Value,_,_} = Key#spvcVpc.spvcVpcEntry, + If_Value; + Key when record(Key,spvcVpcPerm) -> + {If_Value,_,_} = Key#spvcVpcPerm.spvcVpcEntry, + If_Value; + Key when record(Key,spvcVccPerm) -> + {If_Value,_,_,_} = Key#spvcVccPerm.spvcVccEntry, + If_Value; + Key when record(Key,spvcTargetVc) -> + {If_Value,_,_} = Key#spvcTargetVc.entry, + If_Value; + Key when record(Key,spvcTargetVp) -> + {If_Value,_} = Key#spvcTargetVp.entry, + If_Value; + Key when record(Key,pchVc) -> + {If_Value,_,_} = Key#pchVc.vclEntry, + If_Value; + Key when record(Key,pchVp) -> + {If_Value,_} = Key#pchVp.vplEntry, + If_Value; + Key when record(Key,spvcFr) -> + {If_Value,_} = Key#spvcFr.spvcFrEntry, + If_Value; + Key when record(Key,spvcFrPerm) -> + {If_Value,_} = Key#spvcFrPerm.spvcFrEntry, + If_Value; + {If_Value,_,_,_} -> + If_Value; + {If_Value,_,_} -> + If_Value; + {If_Value,_} -> + If_Value; + [If_Value|_] -> + If_Value; + _ -> + error + end) of + disabled -> + debug_disabled, + 4; + enabled -> + debug_disabled, + case (x:x({pchVc,Key}))#pchVc.vclConnId of + undefined -> + debug_disabled, + 3; + _ -> + debug_disabled, + 2 + end + end; +get_oper_status(spvcTargetVc,_) -> + debug_disabled, + 1. + +get_link_opstate(If) -> + debug_disabled, + case x:x(x:x(If),cnhChi,get_link_opstate,[If]) of + {genError,_} -> + debug_disabled, + disabled; + Return -> + debug_disabled, + Return + end. + +-record(record_A,{ + field_1, + field_2, + field_3, + field_4, + field_5 + }). +-record(record_B, { field_1 }). +-record(record_C, { }). + +foo() -> + case something of + [#record_A{} = A] -> + B = foo3(#record_C{}), + C = element(B, A), + foo2(A), + D = C#record_B.field_1, + foo4(A#record_A.field_4, + B, + #record_C{}, + D) + end. + +foo2(_) -> ok. +foo3(_) -> 1. +foo4(_,_,_,_) -> ok. + diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5553.erl b/lib/compiler/test/compilation_SUITE_data/otp_5553.erl new file mode 100644 index 0000000000..9a7004a980 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5553.erl @@ -0,0 +1,82 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(otp_5553). + +-export([?MODULE/0,test/0,handle_cast/2]). + +?MODULE() -> + ok. + +split_quoted_string([34 | _Rest]) -> %% 34 is '"' + ok. + +test() -> + %% does not start with quote + io:format("test: split_quoted_string/1 - 5~n"), + try split_quoted_string("foo \"bar\"") of + SQS_Res5 -> throw({error, test_case_failed, SQS_Res5}) + catch + error: does_not_start_with_quote -> ok + end, + + %% no ending quote + io:format("test: split_quoted_string/1 - 6~n"), + try split_quoted_string("\"foo ") of + SQS_Res6 -> throw({error, test_case_failed, SQS_Res6}) + catch + error: no_end_quote -> ok + end, + + ok. + +test2() -> + try split_quoted_string("") of + SQS_Res5 -> throw({error, test_case_failed, SQS_Res5}) + catch + error: does_not_start_with_quote -> ok + after + ok + end, + try split_quoted_string("") of + SQS_Res6 -> throw({error, test_case_failed, SQS_Res6}) + catch + error: no_end_quote -> ok + after + ok + end, + ok. + +-record(state, {connect_all, known = [], synced = [], + lockers = [], syncers = [], node_name = node(), + the_locker, the_deleter}). + +handle_cast({in_sync, Node, IsKnown}, S) -> + NewS = cancel_locker(Node, S, get({sync_tag_my, Node})), + NKnown = case lists:member(Node, Known = NewS#state.known) of + false when IsKnown == true -> +1/0, + gen_server:cast({global_name_server, Node}, + {in_sync, node(), false}), + [Node | Known]; + _ -> + Known + end. + +cancel_locker(Node, S, Tag) -> + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5632.erl b/lib/compiler/test/compilation_SUITE_data/otp_5632.erl new file mode 100644 index 0000000000..ebf8e47ca2 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5632.erl @@ -0,0 +1,230 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(otp_5632). +-export([?MODULE/0]). +-export([pstnproxy_add_headers/2,macosx_workaround/0,fast_cut/3,test/1,test2/1, + create_int_jumper_cables/1]). + +-import(lists, [foldl/3,last/1,member/2,reverse/1,reverse/2,seq/2,sort/1]). + +?MODULE() -> + ok. + +-record(request, { + header + }). + + +-record(siporigin, { + proto + }). + + +%% Test a problem in beam_jump.erl. +pstnproxy_add_headers(Request, Origin) when is_record(Request, request), + is_record(Origin, siporigin) -> + NewHeaders1 = Request#request.header, + NewHeaders2 = + case (Origin#siporigin.proto == tls) or (Origin#siporigin.proto == tls6) of + true -> + keylist:delete("X-Foo2", NewHeaders1); + false -> + keylist:delete("X-Foo2", NewHeaders1) + end, + NewHeaders3 = + case (Origin#siporigin.proto == tls) or (Origin#siporigin.proto == tls6) of + true -> + keylist:delete("X-Foo3", NewHeaders2); + false -> + keylist:delete("X-Foo3", NewHeaders2) + end, + Request#request{header = NewHeaders3}. + +%% Test a problem in beam_validator.erl. +macosx_workaround() -> + try 1.0/zero() + catch + error:_ -> ok + end. + +zero() -> 0.0. + +-record(we, {id, + perm = 0, + name, + es, + fs, + he, + vc, + vp, + mat = default, + next_id, + mode, + mirror = none, + light = none, + has_shape = true}). + +-record(edge, {vs, + ve, + a = none, + b = none, + lf, + rf, + ltpr, + ltsu, + rtpr, + rtsu}). + + +fast_cut(Edge,Pos0,We0) -> + {NewEdge = NewV,We} = wings_we:new_ids(1,We0), + #we{es = Etab0, + vc = Vct0, + vp = Vtab0, + he = Htab0} = We, + Template = gb_trees:get(Edge,Etab0), + #edge{vs = Vstart, + ve = Vend, + a = ACol, + b = BCol, + lf = Lf, + rf = Rf, + ltpr = EdgeA, + rtsu = EdgeB, + rtpr = NextBCol} = Template, + VendPos = gb_trees:get(Vend,Vtab0), + Vct1 = gb_trees:update(Vend,NewEdge,Vct0), + VstartPos = wings_vertex:pos(Vstart,Vtab0), + if + Pos0 =:= default -> + NewVPos0 = e3d_vec:average([VstartPos,VendPos]); + true -> + NewVPos0 = Pos0 + end, + NewVPos = wings_util:share(NewVPos0), + Vct = gb_trees:insert(NewV,NewEdge,Vct1), + Vtab = gb_trees:insert(NewV,NewVPos,Vtab0), + AColOther = ?MODULE:get_vtx_color(EdgeA,Lf,Etab0), + BColOther = ?MODULE:get_vtx_color(NextBCol,Rf,Etab0), + Weight = if + Pos0 == default -> + 0.500000; + true -> + ADist = e3d_vec:dist(Pos0,VstartPos), + BDist = e3d_vec:dist(Pos0,VendPos), + try + ADist / (ADist + BDist) + catch + error:badarith -> + 0.500000 + end + end, + NewColA = wings_color:mix(Weight,AColOther,ACol), + NewColB = wings_color:mix(Weight,BCol,BColOther), + NewEdgeRec = Template#edge{vs = NewV, + a = NewColA, + ltsu = Edge, + rtpr = Edge}, + Etab1 = gb_trees:insert(NewEdge,NewEdgeRec,Etab0), + Etab2 = ?MODULE:patch_edge(EdgeA,NewEdge,Edge,Etab1), + Etab3 = ?MODULE:patch_edge(EdgeB,NewEdge,Edge,Etab2), + EdgeRec = Template#edge{ve = NewV, + b = NewColB, + rtsu = NewEdge, + ltpr = NewEdge}, + Etab = gb_trees:update(Edge,EdgeRec,Etab3), + Htab = case gb_sets:is_member(Edge,Htab0) of + false -> + Htab0; + true -> + gb_sets:insert(NewEdge,Htab0) + end, + {We#we{es = Etab, + vc = Vct, + vp = Vtab, + he = Htab},NewV}. + +%% A problem in beam_bool. + +-record(a, {a,b,c}). + +test(As) -> + case As of + A when A#a.b == []; A#a.b == undefined -> + true; + _ -> + false + end. + +test2(As) -> + case As of + A when A#a.b == {a,b,c}; A#a.b == undefined -> + true; + _ -> + false + end. + +%% Record updating problems. + +-record(int_jumper_cable, {id, + connectionFieldRef, + aiuPlugInUnitRef, + connFieldConnector, + aiuConnector, + dlAttenuation = 1, + ulAttenuation = 1, + electricalDlDelay = 100, + electricalUlDelay = 100, + optionals = []}). + +create_int_jumper_cables(_Config) -> + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},637}), + ct:comment("Create IntJumperCable MO"), + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},639}), + Parent = "ManagedElement=1,Equipment=1", + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},641}), + I1 = #int_jumper_cable{id = 1, + connectionFieldRef = Parent ++ ",ConnectionField=1", + aiuPlugInUnitRef = Parent ++ ",Subrack=2,Slot=6,PlugInUnit=1", + connFieldConnector = "J1", + aiuConnector = 1}, + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},650}), + I2 = I1#int_jumper_cable{id = 2, + connFieldConnector = "H1", + aiuConnector = 2}, + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},657}), + I3 = I1#int_jumper_cable{id = 3, + aiuPlugInUnitRef = Parent ++ ",Subrack=2,Slot=9,PlugInUnit=1", + connFieldConnector = "J2"}, + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},663}), + I4 = I3#int_jumper_cable{id = 4, + connFieldConnector = "H2", + aiuConnector = 2}, + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},670}), + I5 = I1#int_jumper_cable{id = 5, + aiuPlugInUnitRef = Parent ++ ",Subrack=2,Slot=12,PlugInUnit=1", + connFieldConnector = "J3"}, + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},677}), + I6 = I5#int_jumper_cable{id = 6, + connFieldConnector = "H3", + aiuConnector = 2}, + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},684}), + [_MO1,_MO2,_MO3,_MO4,_MO5,_MO6] = mub_util:create(mp_mub,Parent,[I1,I2,I3,I4,I5,I6]), + ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},686}), + ok. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5714.erl b/lib/compiler/test/compilation_SUITE_data/otp_5714.erl new file mode 100644 index 0000000000..5aefa0a803 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5714.erl @@ -0,0 +1,46 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(otp_5714). +-export([?MODULE/0,foo/1,mktree_text/1]). +-binary(<<1,2,3>>). + +?MODULE() -> + [<<1,2,3>>] = proplists:get_value(binary, ?MODULE:module_info(attributes)), + ok. + +-record(foo_record, {key,blabla}). +foo(A) -> + hd(tl(element(2,element(2,catch erlang:error(apa))))), + case A of + A -> + B = #foo_record{ key = key1}, + C = B#foo_record{ key = key2}, + {X,Y} = {a,b} + end. + +mktree_text(Val) -> + case erlang:is_integer(Val) of + _A = IsInteger -> + _A; + _A -> + IsInteger = erlang:exit({{bug,mktree_text,4},{line,34},match,[_A]}) + end, + ok; +mktree_text(_A1) -> + erlang:exit({{bug,mktree_text,4},{line,33},function_clause,[_A1]}). diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5872.erl b/lib/compiler/test/compilation_SUITE_data/otp_5872.erl new file mode 100644 index 0000000000..cada7ad994 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_5872.erl @@ -0,0 +1,46 @@ +%% +%% %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(otp_5872). +-export([?MODULE/0,chunk_request_body/3]). + +?MODULE() -> + ok. + +chunk_request_body(Body,_ChunkSize,Acc) when Body == <<>>; Body == [] -> + LastChunk = "0\r\n", + lists:reverse(["\r\n",LastChunk|Acc]); +chunk_request_body(Body,ChunkSize,Acc) when binary(Body), size(Body) >= ChunkSize -> + <<ChunkBody:ChunkSize/binary, + Rest/binary>> = Body, + Chunk = [ibrowse_lib:dec2hex(4,ChunkSize),"\r\n",ChunkBody,"\r\n"], + chunk_request_body(Rest,ChunkSize,[Chunk|Acc]); +chunk_request_body(Body,_ChunkSize,Acc) when binary(Body) -> + BodySize = size(Body), + Chunk = [ibrowse_lib:dec2hex(4,BodySize),"\r\n",Body,"\r\n"], + LastChunk = "0\r\n", + lists:reverse(["\r\n",LastChunk,Chunk|Acc]); +chunk_request_body(Body,ChunkSize,Acc) when list(Body), length(Body) >= ChunkSize -> + {ChunkBody,Rest} = ?MODULE:split_list_at(Body,ChunkSize), + Chunk = [ibrowse_lib:dec2hex(4,ChunkSize),"\r\n",ChunkBody,"\r\n"], + chunk_request_body(Rest,ChunkSize,[Chunk|Acc]); +chunk_request_body(Body,_ChunkSize,Acc) when list(Body) -> + BodySize = length(Body), + Chunk = [ibrowse_lib:dec2hex(4,BodySize),"\r\n",Body,"\r\n"], + LastChunk = "0\r\n", + lists:reverse(["\r\n",LastChunk,Chunk|Acc]). diff --git a/lib/compiler/test/compilation_SUITE_data/otp_6121.erl b/lib/compiler/test/compilation_SUITE_data/otp_6121.erl new file mode 100644 index 0000000000..c71f7806a0 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_6121.erl @@ -0,0 +1,48 @@ +%% +%% %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(otp_6121). +-export([?MODULE/0]). + +?MODULE() -> + 42 = digit_map_timer(<<1>>, 42), + test(), + Beam = code:which(?MODULE), + Sz = filelib:file_size(Beam), + io:format("Size of Beam file: ~p\n", [Sz]), + if + 100 < Sz, Sz < 100000 -> + ok + end. + +test() -> + %% Make sure that the compiler does not make an unreasonable + %% expansion when trying to optimize the following expressions. + <<0:(8*128*1024)>> = id(<<0:(8*128*1024)>>), + <<100:(8*128*1024)>> = id(<<100:(8*128*1024)>>), + <<1009797879398749873879789879388:(8*128*1024)>> = + id(<<1009797879398749873879789879388:(8*128*1024)>>), + <<7:(8*128*1024)/little>> = id(<<7:(8*128*1024)/little>>), + ok. + +id(I) -> I. + +digit_map_timer(<<_:8>>, Int) when is_integer(Int) andalso Int >= 0 -> + Int; +digit_map_timer(_, _) -> + error. diff --git a/lib/compiler/test/compilation_SUITE_data/otp_6121a.erl b/lib/compiler/test/compilation_SUITE_data/otp_6121a.erl new file mode 100644 index 0000000000..caed631aa2 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_6121a.erl @@ -0,0 +1,32 @@ +%% +%% %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(otp_6121a). +-export([?MODULE/0]). + +%% Thanks to Martin Bjorklund. + +?MODULE() -> + G = fun() -> ok end, + try + fun() -> ok end + after + fun({A, B}) -> A + B end + end, + ok. + diff --git a/lib/compiler/test/compilation_SUITE_data/otp_6121b.erl b/lib/compiler/test/compilation_SUITE_data/otp_6121b.erl new file mode 100644 index 0000000000..967f078942 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_6121b.erl @@ -0,0 +1,33 @@ +%% +%% %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(otp_6121b). +-export([?MODULE/0]). + +%% Thanks to Tim Rath. + +?MODULE() -> + A = {6}, + try + io:fwrite("") + after + fun () -> + fun () -> {B} = A end + end + end. + diff --git a/lib/compiler/test/compilation_SUITE_data/otp_7202.erl b/lib/compiler/test/compilation_SUITE_data/otp_7202.erl new file mode 100644 index 0000000000..9dca244aa5 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/otp_7202.erl @@ -0,0 +1,48 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-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(otp_7202). +-export([?MODULE/0]). + +?MODULE() -> + test(). + +test() -> + List = [a], + Error = case func() of + no_value -> true; + {ok, V} -> V + end, + %% Liveness calculation for the make_fun2 instruction was wrong - + %% it looked like Error would not be needed by the make_fun2 instruction. + lists:foreach(fun(_E) -> + case Error of + true -> + ok; + false -> + ok + end + end, List). + +func() -> + no_value. + + + + + diff --git a/lib/compiler/test/compilation_SUITE_data/pattern_expr.erl b/lib/compiler/test/compilation_SUITE_data/pattern_expr.erl new file mode 100644 index 0000000000..02eacced81 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/pattern_expr.erl @@ -0,0 +1,30 @@ +%% +%% %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(pattern_expr). + +-export(pattern_expr/0). + +pattern_expr() -> + f(). + +f() -> + case 4 of + 2+2 -> + ok + end. diff --git a/lib/compiler/test/compilation_SUITE_data/trycatch_4.erl b/lib/compiler/test/compilation_SUITE_data/trycatch_4.erl new file mode 100644 index 0000000000..7ea710856f --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/trycatch_4.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(trycatch_4). +-export([trycatch_4/0]). +-record(state, {foo}). + +trycatch_4() -> + handle_info({foo}, #state{}), + ok. + +handle_info({_}, State) -> + foo(), + State#state{foo = bar}, + case ok of + _ -> + case catch foo() of + ok -> + {stop, State} + end + end; +handle_info(_, State) -> + (catch begin + foo(), + State#state{foo = bar} + end), + case ok of + _ -> + case catch foo() of + ok -> + {stop, State} + end + end. + +foo() -> ok. diff --git a/lib/compiler/test/compilation_SUITE_data/vsn_1.erl b/lib/compiler/test/compilation_SUITE_data/vsn_1.erl new file mode 100644 index 0000000000..a9e23f7c25 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/vsn_1.erl @@ -0,0 +1,21 @@ +%% +%% %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(vsn_1). + +-hubbub(himmap). diff --git a/lib/compiler/test/compilation_SUITE_data/vsn_2.erl b/lib/compiler/test/compilation_SUITE_data/vsn_2.erl new file mode 100644 index 0000000000..4833458cf4 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/vsn_2.erl @@ -0,0 +1,21 @@ +%% +%% %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(vsn_2). + +-vsn(34). diff --git a/lib/compiler/test/compilation_SUITE_data/vsn_3.erl b/lib/compiler/test/compilation_SUITE_data/vsn_3.erl new file mode 100644 index 0000000000..7b970b2b75 --- /dev/null +++ b/lib/compiler/test/compilation_SUITE_data/vsn_3.erl @@ -0,0 +1,22 @@ +%% +%% %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(vsn_3). + +f(X) -> + 2*X. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl new file mode 100644 index 0000000000..7c3990a855 --- /dev/null +++ b/lib/compiler/test/compile_SUITE.erl @@ -0,0 +1,722 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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(compile_SUITE). + +%% Tests compile:file/1 and compile:file/2 with various options. + +-include("test_server.hrl"). + +-export([all/1, + app_test/1, + file_1/1, module_mismatch/1, big_file/1, outdir/1, + binary/1, cond_and_ifdef/1, listings/1, listings_big/1, + other_output/1, package_forms/1, encrypted_abstr/1, + bad_record_use/1, bad_record_use1/1, bad_record_use2/1, strict_record/1, + missing_testheap/1, cover/1, env/1, core/1, asm/1]). + +-export([init/3]). + + +%% To cover the stripping of 'type' and 'spec' in beam_asm. +-type all_return_type() :: [atom()]. +-spec all('suite' | [_]) -> all_return_type(). + +all(suite) -> + test_lib:recompile(?MODULE), + [app_test, + file_1, module_mismatch, big_file, outdir, binary, + cond_and_ifdef, listings, listings_big, + other_output, package_forms, + encrypted_abstr, + bad_record_use, strict_record, + missing_testheap, cover, env, core, asm]. + + +%% Test that the Application file has no `basic' errors."; +app_test(Config) when is_list(Config) -> + ?line ?t:app_test(compiler). + +%% Tests that we can compile and run a simple Erlang program, +%% using compile:file/1. + +file_1(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(5)), + ?line {Simple, Target} = files(Config, "file_1"), + ?line {ok, Cwd} = file:get_cwd(), + ?line ok = file:set_cwd(filename:dirname(Target)), + ?line {ok,simple} = compile:file(Simple), %Smoke test only. + ?line {ok,simple} = compile:file(Simple, [slim]), %Smoke test only. + ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test. + ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. + ?line {ok,simple} = compile:file(Simple, [debug_info]), + ?line ok = file:set_cwd(Cwd), + ?line true = exists(Target), + ?line passed = run(Target, test, []), + + %% Cleanup. + ?line ok = file:delete(Target), + ?line ok = file:del_dir(filename:dirname(Target)), + ?line test_server:timetrap_cancel(Dog), + ok. + +module_mismatch(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line File = filename:join(DataDir, "wrong_module_name.erl"), + ?line {error,[{"wrong_module_name.beam", + [{compile,{module_name,arne,"wrong_module_name"}}]}], + []} = compile:file(File, [return]), + ?line error = compile:file(File, [report]), + + ?line {ok,arne,[]} = compile:file(File, + [return,no_error_module_mismatch]), + + ok. + +big_file(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(5)), + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Big = filename:join(DataDir, "big.erl"), + ?line Target = filename:join(PrivDir, "big.beam"), + ?line ok = file:set_cwd(PrivDir), + ?line {ok,big} = compile:file(Big, []), + ?line {ok,big} = compile:file(Big, [r9,debug_info]), + ?line {ok,big} = compile:file(Big, [no_postopt]), + ?line true = exists(Target), + + %% Cleanup. + ?line ok = file:delete(Target), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that the {outdir, Dir} option works. + +outdir(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line {Simple, Target} = files(Config, "outdir"), + ?line {ok, simple} = compile:file(Simple, [{outdir, filename:dirname(Target)}]), + ?line true = exists(Target), + ?line passed = run(Target, test, []), + ?line ok = file:delete(Target), + ?line ok = file:del_dir(filename:dirname(Target)), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that the binary option works. + +binary(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line {Simple, Target} = files(Config, "binary"), + ?line {ok, simple, Binary} = compile:file(Simple, [binary]), + ?line code:load_binary(simple, Target, Binary), + ?line passed = simple:test(), + ?line true = code:delete(simple), + ?line false = code:purge(simple), + ?line ok = file:del_dir(filename:dirname(Target)), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that conditional compilation, defining values, including files work. + +cond_and_ifdef(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line {Simple, Target} = files(Config, "cond_and_ifdef"), + ?line IncludeDir = filename:join(filename:dirname(Simple), "include"), + ?line Options = [{outdir, filename:dirname(Target)}, + {d, need_foo}, {d, foo_value, 42}, + {i, IncludeDir}, report], + ?line {ok, simple} = compile:file(Simple, Options), + ?line true = exists(Target), + ?line {hiker, 42} = run(Target, foo, []), + ?line ok = file:delete(Target), + ?line ok = file:del_dir(filename:dirname(Target)), + ?line test_server:timetrap_cancel(Dog), + ok. + +listings(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(8)), + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Simple = filename:join(DataDir, simple), + ?line TargetDir = filename:join(PrivDir, listings), + ?line ok = file:make_dir(TargetDir), + + %% Test all dedicated listing options. + ?line do_listing(Simple, TargetDir, 'S'), + ?line do_listing(Simple, TargetDir, 'E'), + ?line do_listing(Simple, TargetDir, 'P'), + ?line do_listing(Simple, TargetDir, dpp, ".pp"), + ?line do_listing(Simple, TargetDir, dabstr, ".abstr"), + ?line do_listing(Simple, TargetDir, dexp, ".expand"), + ?line do_listing(Simple, TargetDir, dcore, ".core"), + ?line do_listing(Simple, TargetDir, doldinline, ".oldinline"), + ?line do_listing(Simple, TargetDir, dinline, ".inline"), + ?line do_listing(Simple, TargetDir, dcore, ".core"), + ?line do_listing(Simple, TargetDir, dcopt, ".copt"), + ?line do_listing(Simple, TargetDir, dsetel, ".dsetel"), + ?line do_listing(Simple, TargetDir, dkern, ".kernel"), + ?line do_listing(Simple, TargetDir, dlife, ".life"), + ?line do_listing(Simple, TargetDir, dcg, ".codegen"), + ?line do_listing(Simple, TargetDir, dblk, ".block"), + ?line do_listing(Simple, TargetDir, dbool, ".bool"), + ?line do_listing(Simple, TargetDir, dtype, ".type"), + ?line do_listing(Simple, TargetDir, ddead, ".dead"), + ?line do_listing(Simple, TargetDir, djmp, ".jump"), + ?line do_listing(Simple, TargetDir, dclean, ".clean"), + ?line do_listing(Simple, TargetDir, dpeep, ".peep"), + ?line do_listing(Simple, TargetDir, dopt, ".optimize"), + + %% First clean up. + ?line Listings = filename:join(PrivDir, listings), + ?line lists:foreach(fun(F) -> ok = file:delete(F) end, + filelib:wildcard(filename:join(Listings, "*"))), + + %% Test options that produce a listing file if 'binary' is not given. + ?line do_listing(Simple, TargetDir, to_pp, ".P"), + ?line do_listing(Simple, TargetDir, to_exp, ".E"), + ?line do_listing(Simple, TargetDir, to_core0, ".core"), + ?line ok = file:delete(filename:join(Listings, "simple.core")), + ?line do_listing(Simple, TargetDir, to_core, ".core"), + ?line do_listing(Simple, TargetDir, to_kernel, ".kernel"), + + %% Final clean up. + ?line lists:foreach(fun(F) -> ok = file:delete(F) end, + filelib:wildcard(filename:join(Listings, "*"))), + ?line ok = file:del_dir(Listings), + ?line test_server:timetrap_cancel(Dog), + ok. + +listings_big(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(10)), + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Big = filename:join(DataDir, big), + ?line TargetDir = filename:join(PrivDir, listings_big), + ?line ok = file:make_dir(TargetDir), + ?line do_listing(Big, TargetDir, 'S'), + ?line do_listing(Big, TargetDir, 'E'), + ?line do_listing(Big, TargetDir, 'P'), + ?line do_listing(Big, TargetDir, dkern, ".kernel"), + + ?line Target = filename:join(TargetDir, big), + ?line {ok,big} = compile:file(Target, [asm,{outdir,TargetDir}]), + + %% Cleanup. + ?line ok = file:delete(Target ++ ".beam"), + ?line lists:foreach(fun(F) -> ok = file:delete(F) end, + filelib:wildcard(filename:join(TargetDir, "*"))), + ?line ok = file:del_dir(TargetDir), + ?line test_server:timetrap_cancel(Dog), + ok. + +other_output(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(8)), + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Simple = filename:join(DataDir, simple), + ?line TargetDir = filename:join(PrivDir, other_output), + ?line ok = file:make_dir(TargetDir), + + io:put_chars("to_pp"), + ?line {ok,[],PP} = compile:file(Simple, [to_pp,binary,time]), + ?line [] = [E || E <- PP, + begin + case element(1, E) of + attribute -> false; + function -> false; + eof -> false + end + end], + + io:put_chars("to_exp (file)"), + ?line {ok,simple,Expand} = compile:file(Simple, [to_exp,binary,time]), + ?line case Expand of + {simple,Exports,Forms} when is_list(Exports), is_list(Forms) -> ok + end, + io:put_chars("to_exp (forms)"), + ?line {ok,simple,Expand} = compile:forms(PP, [to_exp,binary,time]), + + io:put_chars("to_core (file)"), + ?line {ok,simple,Core} = compile:file(Simple, [to_core,binary,time]), + ?line c_module = element(1, Core), + ?line {ok,_} = core_lint:module(Core), + io:put_chars("to_core (forms)"), + ?line {ok,simple,Core} = compile:forms(PP, [to_core,binary,time]), + + io:put_chars("to_kernel (file)"), + ?line {ok,simple,Kernel} = compile:file(Simple, [to_kernel,binary,time]), + ?line k_mdef = element(1, Kernel), + io:put_chars("to_kernel (forms)"), + ?line {ok,simple,Kernel} = compile:forms(PP, [to_kernel,binary,time]), + + io:put_chars("to_asm (file)"), + ?line {ok,simple,Asm} = compile:file(Simple, [to_asm,binary,time]), + ?line {simple,_,_,_,_} = Asm, + io:put_chars("to_asm (forms)"), + ?line {ok,simple,Asm} = compile:forms(PP, [to_asm,binary,time]), + + ?line test_server:timetrap_cancel(Dog), + ok. + +package_forms(Config) when is_list(Config) -> + Fs = [{attribute,1,file,{"./p.erl",1}}, + {attribute,1,module,[p,p]}, + {attribute,3,compile,export_all}, + {attribute,1,file, + {"/clearcase/otp/erts/lib/stdlib/include/qlc.hrl",1}}, + {attribute,6,file,{"./p.erl",6}}, + {function,7,q,0, + [{clause,7,[],[], + [{call,8, + {remote,8,{atom,8,qlc},{atom,8,q}}, + [{tuple,-8, + [{atom,-8,qlc_lc}, + {'fun',-8, + {clauses, + [{clause,-8,[],[], + [{tuple,-8, + [{atom,-8,simple_v1}, + {atom,-8,'X'}, + {'fun',-8,{clauses,[{clause,-8,[],[],[{nil,8}]}]}}, + {integer,-8,8}]}]}]}}, + {atom,-8,undefined}]}]}]}]}, + {eof,9}], + {ok,'p.p',_} = compile:forms(Fs, ['S',report]), + ok. + +encrypted_abstr(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(10)), + ?line {Simple,Target} = files(Config, "encrypted_abstr"), + + Res = case has_crypto() of + no -> + %% No crypto. + ?line encrypted_abstr_no_crypto(Simple, Target), + {comment,"The crypto application is missing or broken"}; + yes -> + %% Simulate not having crypto by removing + %% the crypto application from the path. + ?line OldPath = code:get_path(), + try + ?line NewPath = OldPath -- [filename:dirname(code:which(crypto))], + ?line (catch crypto:stop()), + ?line code:delete(crypto), + ?line code:purge(crypto), + ?line code:set_path(NewPath), + ?line encrypted_abstr_no_crypto(Simple, Target) + after + code:set_path(OldPath) + end, + + %% Now run the tests that require crypto. + ?line encrypted_abstr_1(Simple, Target), + ?line ok = file:delete(Target), + ?line ok = file:del_dir(filename:dirname(Target)) + end, + + %% Cleanup. + ?line test_server:timetrap_cancel(Dog), + Res. + +encrypted_abstr_1(Simple, Target) -> + ?line TargetDir = filename:dirname(Target), + ?line Key = "ablurf123BX#$;3", + ?line install_crypto_key(Key), + ?line {ok,simple} = compile:file(Simple, + [debug_info,{debug_info_key,Key}, + {outdir,TargetDir}]), + ?line verify_abstract(Target), + + ?line {ok,simple} = compile:file(Simple, + [{debug_info_key,Key}, + {outdir,TargetDir}]), + ?line verify_abstract(Target), + + ?line {ok,simple} = compile:file(Simple, + [debug_info,{debug_info_key,{des3_cbc,Key}}, + {outdir,TargetDir}]), + ?line verify_abstract(Target), + + ?line {ok,{simple,[{compile_info,CInfo}]}} = + beam_lib:chunks(Target, [compile_info]), + ?line {value,{_,Opts}} = lists:keysearch(options, 1, CInfo), + ?line {value,{_,'********'}} = lists:keysearch(debug_info_key, 1, Opts), + + %% Try some illegal forms of crypto keys. + ?line error = compile:file(Simple, + [debug_info,{debug_info_key,{blurf,"ss"}},report]), + ?line error = compile:file(Simple, + [debug_info,{debug_info_key,{blurf,1,"ss"}},report]), + ?line error = compile:file(Simple, + [debug_info,{debug_info_key,42},report]), + + %% Place the crypto key in .erlang.crypt. + ?line beam_lib:clear_crypto_key_fun(), + ?line {ok,OldCwd} = file:get_cwd(), + ?line ok = file:set_cwd(TargetDir), + + ?line error = compile:file(Simple, [encrypt_debug_info,report]), + + ?line NewKey = "better use another key here", + ?line write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]), + ?line {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]), + ?line verify_abstract("simple.beam"), + ?line ok = file:delete(".erlang.crypt"), + ?line beam_lib:clear_crypto_key_fun(), + ?line {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} = + beam_lib:chunks("simple.beam", [abstract_code]), + ?line ok = file:set_cwd(OldCwd), + ok. + + +write_crypt_file(Contents0) -> + Contents = list_to_binary([Contents0]), + io:format("~s\n", [binary_to_list(Contents)]), + ok = file:write_file(".erlang.crypt", Contents). + +encrypted_abstr_no_crypto(Simple, Target) -> + ?line TargetDir = filename:dirname(Target), + ?line Key = "ablurf123BX#$;3", + ?line error = compile:file(Simple, + [debug_info,{debug_info_key,Key}, + {outdir,TargetDir},report]), + ok. + +verify_abstract(Target) -> + {ok,{simple,[Chunk]}} = beam_lib:chunks(Target, [abstract_code]), + {abstract_code,{raw_abstract_v1,_}} = Chunk. + +has_crypto() -> + try + crypto:start(), + crypto:info(), + crypto:stop(), + yes + catch + error:_ -> no + end. + +install_crypto_key(Key) -> + F = fun (init) -> ok; + ({debug_info,des3_cbc,_,_}) -> Key; + (clear) -> ok + end, + ok = beam_lib:crypto_key_fun(F). + +%% Miscellanous tests, mainly to get better coverage. +cover(Config) when is_list(Config) -> + ?line io:format("~p\n", [compile:options()]), + ok. + +do_listing(Source, TargetDir, Type) -> + do_listing(Source, TargetDir, Type, "." ++ atom_to_list(Type)). + +do_listing(Source, TargetDir, Type, Ext) -> + io:format("Source: ~p TargetDir: ~p\n Type: ~p Ext: ~p\n", + [Source, TargetDir, Type, Ext]), + case compile:file(Source, [Type, time, {outdir, TargetDir}]) of + {ok, _} -> ok; + Other -> test_server:fail({unexpected_result, Other}) + end, + SourceBase = filename:rootname(filename:basename(Source)), + + Target = filename:join(TargetDir, SourceBase ++ Ext), + true = exists(Target). + +files(Config, Name) -> + ?line code:delete(simple), + ?line code:purge(simple), + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Simple = filename:join(DataDir, "simple"), + ?line TargetDir = filename:join(PrivDir, Name), + ?line ok = file:make_dir(TargetDir), + ?line Target = filename:join(TargetDir, "simple"++code:objfile_extension()), + {Simple, Target}. + + +run(Target, Func, Args) -> + ?line Module = list_to_atom(filename:rootname(filename:basename(Target))), + ?line {module, Module} = code:load_abs(filename:rootname(Target)), + ?line Result = (catch apply(Module, Func, Args)), + ?line true = code:delete(Module), + ?line false = code:purge(Module), + Result. + +exists(Name) -> + case file:read_file_info(Name) of + {ok, _} -> true; + {error, _} -> false + end. + +bad_record_use(suite) -> [bad_record_use1, bad_record_use2]. + +%% Tests that the compiler does not accept +%% bad use of records. +bad_record_use1(Config) when is_list(Config) -> + ?line {ok, Cwd} = file:get_cwd(), + ?line file:set_cwd(?config(data_dir, Config)), + ?line true=exists("bad_record_use.erl"), + ?line Ret=c:c(bad_record_use), + ?line file:set_cwd(Cwd), + ?line error=Ret, + ok. + +%% Tests that the compiler does not accept +%% bad use of records. +bad_record_use2(Config) when is_list(Config) -> + ?line {ok, Cwd} = file:get_cwd(), + ?line file:set_cwd(?config(data_dir, Config)), + ?line true=exists("bad_record_use2.erl"), + ?line Ret=c:c(bad_record_use), + ?line file:set_cwd(Cwd), + ?line error=Ret, + ok. + +strict_record(Config) when is_list(Config) -> + ?line Priv = ?config(priv_dir, Config), + ?line file:set_cwd(?config(data_dir, Config)), + ?line Opts = [{outdir,Priv},report_errors], + M = record_access, + + ?line {ok,M} = c:c(M, [strict_record_tests|Opts]), + ?line Turtle = test_strict(), + + ?line {ok,M} = c:c(M, [no_strict_record_tests|Opts]), + ?line Turtle = test_sloppy(), + + %% The option first given wins. + ?line {ok,M} = c:c(M, [no_strict_record_tests,strict_record_tests|Opts]), + ?line Turtle = test_sloppy(), + ?line {ok,M} = c:c(M, [strict_record_tests,no_strict_record_tests|Opts]), + ?line Turtle = test_strict(), + + %% Default (possibly influenced by ERL_COMPILER_OPTIONS). + ?line {ok,M} = c:c(M, [{outdir,Priv},report_errors]), + ?line try + {1,2} = record_access:test(Turtle), + {comment,"Default: no_strict_record_tests"} + catch + error:{badrecord,tortoise} -> + {comment,"Default: strict_record_tests"} + end. + +test_strict() -> + Turtle = record_access:turtle(), + ?line try + record_access:test(Turtle) + catch + error:{badrecord,tortoise} -> + ok + end, + Turtle. + +test_sloppy() -> + Turtle = record_access:turtle(), + {1,2} = record_access:test(Turtle), + Turtle. + +missing_testheap(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + Opts = [{outdir,PrivDir}], + OldPath = code:get_path(), + try + code:add_patha(PrivDir), + c:c(filename:join(DataDir, "missing_testheap1"), Opts), + c:c(filename:join(DataDir, "missing_testheap2"), Opts), + ?line ok = test(fun() -> + missing_testheap1:f({a,self()},{state,true,b}) + end, {a,b}), + ?line ok = test(fun() -> + missing_testheap2:f({a,self()},16#80000000) end, + bigger) + after + code:set_path(OldPath), + file:delete(filename:join(PrivDir, "missing_testheap1.beam")), + file:delete(filename:join(PrivDir, "missing_testheap2.beam")) + end, + ok. + +test(Fun, Result) -> + test(500, Fun, Result, []). + +test(0, _, _, _) -> + ok; +test(Iter, Fun, Result, Filler) -> + spawn(?MODULE, init, [self(), Fun, list_to_tuple(Filler)]), + receive + {result, Result} -> + test(Iter-1, Fun, Result, [0|Filler]); + {result, Other} -> + io:format("Expected ~p; got ~p~n", [Result, Other]), + test_server:fail() + end. + +init(ReplyTo, Fun, _Filler) -> + ReplyTo ! {result, Fun()}. + +env(Config) when is_list(Config) -> + ?line {Simple,Target} = files(Config, "file_1"), + ?line {ok,Cwd} = file:get_cwd(), + ?line ok = file:set_cwd(filename:dirname(Target)), + + true = os:putenv("ERL_COMPILER_OPTIONS", "binary"), + try + env_1(Simple, Target) + after + true = os:putenv("ERL_COMPILER_OPTIONS", "ignore_me"), + file:set_cwd(Cwd), + file:delete(Target), + file:del_dir(filename:dirname(Target)) + end, + ok. + +env_1(Simple, Target) -> + %% file + ?line {ok,simple,<<_/binary>>} = compile:file(Simple), + ?line {ok,simple} = compile:noenv_file(Simple, [debug_info]), + ?line true = exists(Target), + ?line {ok,{simple,[{abstract_code,Abstr0}]}} = + beam_lib:chunks(Target, [abstract_code]), + ?line {raw_abstract_v1,Forms} = Abstr0, + + %% forms + ?line true = os:putenv("ERL_COMPILER_OPTIONS", "strong_validation"), + ?line {ok,simple} = compile:forms(Forms), + ?line {ok,simple,<<"FOR1",_/binary>>} = compile:noenv_forms(Forms, []), + + %% output_generated + ?line false = compile:output_generated([]), + ?line true = compile:noenv_output_generated([]), + + ?line ok = file:delete(Target), + + ok. + +%% Test pretty-printing in Core Erlang format and then try to +%% compile the generated Core Erlang files. + +core(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(5)), + ?line PrivDir = ?config(priv_dir, Config), + ?line Outdir = filename:join(PrivDir, "core"), + ?line ok = file:make_dir(Outdir), + + ?line Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), + ?line TestBeams = filelib:wildcard(Wc), + ?line Abstr = [begin {ok,{Mod,[{abstract_code, + {raw_abstract_v1,Abstr}}]}} = + beam_lib:chunks(Beam, [abstract_code]), + {Mod,Abstr} end || Beam <- TestBeams], + ?line Res = p_run(fun(F) -> do_core(F, Outdir) end, Abstr), + ?line test_server:timetrap_cancel(Dog), + Res. + + +do_core({M,A}, Outdir) -> + try + {ok,M,Core} = compile:forms(A, [to_core,report]), + CoreFile = filename:join(Outdir, atom_to_list(M)++".core"), + CorePP = core_pp:format(Core), + ok = file:write_file(CoreFile, CorePP), + case compile:file(CoreFile, [clint,from_core,binary]) of + {ok,M,_} -> + ok = file:delete(CoreFile); + Other -> + io:format("*** core_lint failure '~p' for ~s\n", + [Other,CoreFile]), + error + end + catch Class:Error -> + io:format("~p: ~p ~p\n~p\n", + [M,Class,Error,erlang:get_stacktrace()]), + error + end. + +%% Compile to Beam assembly language (.S) and the try to +%% run .S throught the compiler again. + +asm(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(20)), + ?line PrivDir = ?config(priv_dir, Config), + ?line Outdir = filename:join(PrivDir, "asm"), + ?line ok = file:make_dir(Outdir), + + ?line Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), + ?line TestBeams = filelib:wildcard(Wc), + ?line Res = p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams), + ?line test_server:timetrap_cancel(Dog), + Res. + + +do_asm(Beam, Outdir) -> + {ok,{M,[{abstract_code,{raw_abstract_v1,A}}]}} = + beam_lib:chunks(Beam, [abstract_code]), + try + {ok,M,Asm} = compile:forms(A, ['S']), + AsmFile = filename:join(Outdir, atom_to_list(M)++".S"), + {ok,Fd} = file:open(AsmFile, [write]), + beam_listing:module(Fd, Asm), + ok = file:close(Fd), + case compile:file(AsmFile, [from_asm,no_postopt,binary,report]) of + {ok,M,_} -> + ok = file:delete(AsmFile); + Other -> + io:format("*** failure '~p' for ~s\n", + [Other,AsmFile]), + error + end + catch Class:Error -> + io:format("~p: ~p ~p\n~p\n", + [M,Class,Error,erlang:get_stacktrace()]), + error + end. + +%% p_run(fun() -> ok|error, List) -> ok +%% Will fail the test case if there were any errors. + +p_run(Test, List) -> + N = erlang:system_info(schedulers) + 1, + p_run_loop(Test, List, N, [], 0, 0). + +p_run_loop(_, [], _, [], Errors, Ws) -> + case Errors of + 0 -> + case Ws of + 0 -> ok; + 1 -> {comment,"1 core_lint failure"}; + N -> {comment,integer_to_list(N)++" core_lint failures"} + end; + N -> ?t:fail({N,errors}) + end; +p_run_loop(Test, [H|T], N, Refs, Errors, Ws) when length(Refs) < N -> + {_,Ref} = erlang:spawn_monitor(fun() -> exit(Test(H)) end), + p_run_loop(Test, T, N, [Ref|Refs], Errors, Ws); +p_run_loop(Test, List, N, Refs0, Errors0, Ws0) -> + receive + {'DOWN',Ref,process,_,Res} -> + {Errors,Ws} = case Res of + ok -> {Errors0,Ws0}; + error -> {Errors0+1,Ws0}; + warning -> {Errors0,Ws0+1} + end, + Refs = Refs0 -- [Ref], + p_run_loop(Test, List, N, Refs, Errors, Ws) + end. diff --git a/lib/compiler/test/compile_SUITE_data/bad_record_use.erl b/lib/compiler/test/compile_SUITE_data/bad_record_use.erl new file mode 100644 index 0000000000..c2adbfa8de --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/bad_record_use.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(bad_record_use). +-export([test/0]). + +-record(bad_use, {a=undefined, + b=undefined, + c=undefined}). + +test() -> + NewRecord=#bad_use{a=1, b=2, a=2}. + diff --git a/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl b/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl new file mode 100644 index 0000000000..1de44b2df4 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl @@ -0,0 +1,29 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(bad_record_use2). +-export([test/0]). + +-record(bad_use, {a=undefined, + b=undefined, + c=undefined}). + +test() -> + R=#bad_use{a=1, b=2}, + R2=R#bad_use{a=1, b=2, a=2}, + ok. diff --git a/lib/compiler/test/compile_SUITE_data/big.erl b/lib/compiler/test/compile_SUITE_data/big.erl new file mode 100644 index 0000000000..4cd8e15f13 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/big.erl @@ -0,0 +1,742 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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(big). +-compile([export_all]). + +compiler_1() -> ok. + +-define(log(Format,Args),mnesia_test_lib:log(Format,Args,?FILE,?LINE)). +-define(warning(Format,Args),?log("<WARNING> " ++ Format,Args)). +-define(error(Format,Args), + mnesia_test_lib:note_error(Format,Args,?FILE,?LINE), + ?log("<ERROR> " ++ Format,Args)). + +-define(match(ExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + ExpectedRes -> + ?log("ok, result as expected: ~p~n",[AcTuAlReS]), + {success,AcTuAlReS}; + _ -> + ?error("actual result was: ~p~n",[AcTuAlReS]), + {fail,AcTuAlReS} + end + end()). + +-define(match_inverse(NotExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + NotExpectedRes -> + ?error("actual result was: ~p~n",[AcTuAlReS]), + {fail,AcTuAlReS}; + _ -> + ?log("ok, result as expected: ~p~n",[AcTuAlReS]), + {success,AcTuAlReS} + end + end()). + +-define(match_receive(ExpectedMsg), + ?match(ExpectedMsg,mnesia_test_lib:pick_msg())). + +%% ExpectedMsgs must be completely bound +-define(match_multi_receive(ExpectedMsgs), + fun() -> + TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs), + ?match(TmPeXpCtEdMsGs, + lists:sort(lists:map(fun(_) -> + mnesia_test_lib:pick_msg() + end, + TmPeXpCtEdMsGs))) + end()). + +-define(setup(), mnesia_test_lib:setup(?FILE,?LINE)). + +-define(start_activities(Nodes), + fun() -> + AcTiViTyPiDs = + lists:map(fun(Node) -> + spawn_link(Node, + mnesia_test_lib, + activity_evaluator, + [self()]) + end, + Nodes), + ?match_multi_receive(AcTiViTyPiDs) + end()). + +-define(start_transactions(Pids), + ?match_multi_receive(lists:map(fun(Pid) -> + Pid ! begin_trans, + {Pid,begin_trans} + end, + Pids))). + +-define(acquire_nodes(N,Nodes), + mnesia_test_lib:acquire_nodes(N,Nodes,?FILE,?LINE)). + + + +%%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories +%%% Author: Hakan Mattsson [email protected] +%%% Purpose: Evil usage of the API +%%% +%%% Invoke all functions in the API and try to cover all legal uses +%%% cases as well the illegal dito. This is a complement to the +%%% other more explicit test cases. +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% show/0 +%%% +%%% Prints out the complete test case structure +%%% +%%% show/1 +%%% +%%% Prints out parts of the test case structure +%%% +%%% test/0 +%%% +%%% Run the complete test suite. +%%% Reads Nodes from nodes.profile and starts them if neccessary. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/1 +%%% +%%% Run parts of the test suite. +%%% Reads Nodes from nodes.profile and starts them if neccessary. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/2 +%%% +%%% Run parts of the test suite on the given Nodes, +%%% assuming that the nodes are up and running. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/3 +%%% +%%% Run parts of the test suite on permutations of the given Nodes, +%%% assuming that the nodes are up and running. Uses test/2. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% See the module mnesia_test_lib for further information. +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +show() -> mnesia_test_lib:show([{?MODULE,all}]). +show(TestCases) -> mnesia_test_lib:show([{?MODULE,TestCases}]). +test() -> mnesia_test_lib:test([{?MODULE,all}]). +test(TestCases) -> mnesia_test_lib:test([{?MODULE,TestCases}]). +test(TestCases,Nodes) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes). +test(TestCases,Nodes,Config) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes,Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +old_all(suite) -> + [ + system_info, table_info, error_description, + db_node_lifecycle, start_and_stop, transaction, checkpoint, backup, + table_lifecycle, replica_management, replica_location, index_lifecycle, + trans_access, dirty_access, table_sync, snmp_access, debug_support + ]. + +trans_access(suite) -> + [ {mnesia_dirty_access_test,all} ]. + +dirty_access(suite) -> + [ {mnesia_trans_access_test,all} ]. + +%% Get meta info about Mnesia +system_info(suite) -> []; +system_info(Nodes) -> + ?match(yes,mnesia:system_info(is_running)), + ?match(Nodes,mnesia:system_info(db_nodes)), + ?match(Nodes,mnesia:system_info(running_db_nodes)), + ?match(true,mnesia:system_info(have_disc)), + ?match(A when atom(A),mnesia:system_info(debug)), + ?match(L when list(L),mnesia:system_info(directory)), + ?match(L when list(L),mnesia:system_info(log_version)), + ?match({_,_},mnesia:system_info(schema_version)), + ?match(L when list(L),mnesia:system_info(tables)), + ?match(L when list(L),mnesia:system_info(local_tables)), + ?match(L when list(L),mnesia:system_info(held_locks)), + ?match(L when list(L),mnesia:system_info(lock_queue)), + ?match(L when list(L),mnesia:system_info(transactions)), + ?match(I when integer(I),mnesia:system_info(transaction_failures)), + ?match(I when integer(I),mnesia:system_info(transaction_commits)), + ?match(I when integer(I),mnesia:system_info(transaction_restarts)), + ?match(L when list(L),mnesia:system_info(checkpoints)), + ?match(A when atom(A),mnesia:system_info(backup_module)), + ?match(true,mnesia:system_info(auto_repair)), + ?match({_,_},mnesia:system_info(dump_log_interval)), + ?match(A when atom(A),mnesia:system_info(dump_log_update_in_place)), + ?match(I when integer(I),mnesia:system_info(transaction_log_writes)), + ?match({'EXIT',{aborted,badarg}},mnesia:system_info(ali_baba)), + done. + +%% Get meta info about table +table_info(suite) -> []; +table_info(Nodes) -> + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + + Tab = table_info, + Type = bag, + ValPos = 3, + Attrs = [k,v], + Arity = length(Attrs) +1, + Schema = [{name,Tab},{type,Type},{attributes,Attrs},{index,[ValPos]}, + {disc_only_copies,[Node1]},{ram_copies,[Node2]},{disc_copies,[Node3]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + + Size = 10, + Keys = lists:seq(1,Size), + Records = [{Tab,A,7} || A <- Keys], + lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), + ?match(Mem when integer(Mem),mnesia:table_info(Tab,memory)), + ?match(Size,mnesia:table_info(Tab,size)), + ?match(Type,mnesia:table_info(Tab,type)), + ?match([Node3],mnesia:table_info(Tab,disc_copies)), + ?match([Node2],mnesia:table_info(Tab,ram_copies)), + ?match([Node1],mnesia:table_info(Tab,disc_only_copies)), + Read = [Node1,Node2,Node3], + ?match(true,lists:member(mnesia:table_info(Tab,where_to_read),Read)), + Write = lists:sort([Node1,Node2,Node3]), + ?match(Write,lists:sort(mnesia:table_info(Tab,where_to_write))), + WriteLock = lists:sort([Node2,Node3]), + ?match([ValPos],mnesia:table_info(Tab,index)), + ?match(Arity,mnesia:table_info(Tab,arity)), + ?match(Attrs,mnesia:table_info(Tab,attributes)), + ?match({Tab,'_','_'},mnesia:table_info(Tab,wild_pattern)), + ?match({atomic,Attrs}, mnesia:transaction(fun() -> + mnesia:table_info(Tab,attributes) end)), + + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add and drop db nodes + +db_node_lifecycle(suite) -> []; +db_node_lifecycle(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + Tab = db_node_lifecycle, + + Schema = [{name,Tab},{ram_copies,[Node1,Node2]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ?match({aborted,active}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + + ?match([], mnesia_test_lib:stop_mnesia(Nodes)), + ?match(ok, mnesia:delete_schema(Nodes)), + ?match({error,_}, mnesia:create_schema(foo)), + ?match({error,_}, mnesia:create_schema([foo])), + ?match({error,_}, mnesia:create_schema([foo@bar])), + ?match({error,_}, mnesia:start()), + + ?match(ok, mnesia:create_schema(Nodes)), + ?match([],mnesia_test_lib:start_mnesia(Nodes)), + ?match({atomic,ok}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo@bar])), + + ?match([], mnesia_test_lib:stop_mnesia([Node2])), + ?match(ok,mnesia:delete_schema([Node2])), + AddFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:add_db_node(Node2)), ok end, + ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[AddFun])), + DelFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:del_db_node(Node2)), ok end, + ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[DelFun])), + + ?match({atomic,ok}, rpc:call(Node1,mnesia,add_db_node,[Node2])), + ?match({aborted,already_exists}, rpc:call(Node1,mnesia,add_db_node,[Node2])), + ?match([],mnesia_test_lib:start_mnesia([Node2])), + ?match({atomic,ok}, mnesia:create_table(Schema)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Start and stop the system + +start_and_stop(suite) -> []; +start_and_stop(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match({started,_}, rpc:call(Node1,mnesia,start,[])), + ?match({started,_}, rpc:call(Node1,mnesia,start,[])), + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match([],mnesia_test_lib:start_mnesia(Nodes)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Checkpoints and backup management + +checkpoint(suite) -> []; +checkpoint(Nodes) -> + OneNode = ?acquire_nodes(1,Nodes), + checkpoint(OneNode,Nodes), + TwoNodes = ?acquire_nodes(2,Nodes), + checkpoint(TwoNodes,Nodes). + +checkpoint(TabNodes,Nodes) -> + [Node1] = ?acquire_nodes(1,TabNodes), + CreateTab = fun(Type,N,Ns) -> + Tab0 = lists:concat(["local_checkpoint_",Type,N]), + Tab = list_to_atom(Tab0), + Schema = [{name,Tab},{Type,Ns}], + ?match({atomic,ok},mnesia:delete_table(Tab)), + ?match({atomic,ok},mnesia:create_table(Schema)), + Tab + end, + CreateTabs = fun(Type) -> + CreateTab(Type,1,hd(TabNodes)), + CreateTab(Type,2,TabNodes), + CreateTab(Type,3,lists:last(TabNodes)) + end, + Types = [ram_copies,disc_copies,disc_only_copies], + Tabs = lists:append(lists:map(CreateTabs,Types)), + Recs = lists:sort([{T,N,N} || T <- Tabs,N <- lists:seq(1,10)]), + lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs), + + CpName = a_checkpoint_name, + MinArgs = [{name,CpName},{min,Tabs},{allow_remote,false}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[MinArgs])), + ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + MaxArgs = [{name,CpName},{max,Tabs},{allow_remote,true}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[MaxArgs])), + ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + Args = [{name,CpName},{min,Tabs},{allow_remote,false}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[Args])), + Recs2 = lists:sort([{T,K,0} || {T,K,_} <- Recs]), + lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs2), + ?match({atomic,ok},rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + ?match({error,no_exists},mnesia:deactivate_checkpoint(CpName)), + ?match({error,badarg},mnesia:activate_checkpoint(foo)), + ?match({error,badarg},mnesia:activate_checkpoint([{foo,foo}])), + ?match({error,badarg},mnesia:activate_checkpoint([{max,foo}])), + ?match({error,badarg},mnesia:activate_checkpoint([{min,foo}])), + ?match({error,no_exists},mnesia:activate_checkpoint([{min,[foo@bar]}])), + ?match({error,badarg},mnesia:activate_checkpoint([{allow_remote,foo}])), + + Fun = fun(Tab) -> ?match({atomic,ok},mnesia:delete_table(Tab)) end, + lists:foreach(Fun,Tabs), + done. + +backup(suite) -> + [ + backup_schema, restore_schema, backup_checkpoint, restore_tables + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Use and misuse transactions + +transaction(suite) -> []; +transaction(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + ?match({atomic,ali_baba}, mnesia:transaction(fun() -> ali_baba end)), + ?match({aborted,_}, mnesia:transaction(no_fun)), + ?match({aborted,_}, mnesia:transaction(?MODULE,no_fun,[foo])), + + {success,[A,B,C,D,E,F,G,H]} = ?start_activities(lists:duplicate(8,Node1)), + ?start_transactions([A,B,C,D,E,F,G,H]), + + A ! fun() -> mnesia:abort(abort_bad_trans) end, + ?match_receive({A,{aborted,abort_bad_trans}}), + + B ! fun() -> 1 = 2 end, + ?match_receive({B,{aborted,_}}), + + C ! fun() -> throw(throw_bad_trans) end, + ?match_receive({C,{aborted,{throw,throw_bad_trans}}}), + + D ! fun() -> exit(exit_bad_trans) end, + ?match_receive({D,{aborted,exit_bad_trans}}), + + E ! fun() -> exit(normal) end, + ?match_receive({E,{aborted,normal}}), + + F ! fun() -> exit(abnormal) end, + ?match_receive({F,{aborted,abnormal}}), + + G ! fun() -> exit(G,abnormal) end, + ?match_receive({'EXIT',G,abnormal}), + + H ! fun() -> exit(H,kill) end, + ?match_receive({'EXIT',H,killed}), + + ?match({atomic,ali_baba}, + mnesia:transaction(fun() -> ali_baba end,infinity)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,1)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,0)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,-1)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,foo)), + Fun = fun() -> ?match({aborted,nested_transaction}, + mnesia:transaction(fun() -> ok end)), ok end, + ?match({atomic,ok},mnesia:transaction(Fun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create and delete tables + +%% Get meta info about table + +replica_location(suite) -> []; +replica_location(Nodes) -> + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + Tab = replica_location, + + %% Create three replicas + Schema = [{name,Tab},{disc_only_copies,[Node1]}, + {ram_copies,[Node2]},{disc_copies,[Node3]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[Node2],[Node3],Nodes), + + %% Delete one replica + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node3],Nodes), + + %% Move one replica + ?match({atomic,ok}, mnesia:move_table_copy(Tab, Node1, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node3],Nodes), + + %% Change replica type + ?match({atomic,ok}, mnesia:change_table_copy_type(Tab, Node2,ram_copies)), + mnesia_test_lib:verify_replica_location(Tab,[],[Node2],[Node3],Nodes), + + done. + +table_lifecycle(suite) -> []; +table_lifecycle(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + + ?match({atomic,ok}, mnesia:create_table([{type,bag}, + {ram_copies,[Node1]}, + {attributes,[rajtan,tajtan]}, + {name,order_of_args}])), + ?match([],mnesia:dirty_read({order_of_args,4711})), + ?match({atomic,ok}, mnesia:create_table([{name,already_exists}, + {ram_copies,[Node1]}])), + ?match({aborted,already_exists}, + mnesia:create_table([{name,already_exists},{ram_copies,[Node1]}])), + ?match({aborted,not_a_db_node}, + mnesia:create_table([{name,no_node},{ram_copies,[foo]}])), + ?match({aborted,not_a_db_node}, + mnesia:create_table([{name,no_host},{ram_copies,[foo@bar]}])), + ?match({aborted,badarg}, + mnesia:create_table([{name,zero_arity},{attributes,[]}])), + ?match({aborted,badarg}, mnesia:create_table([])), + ?match({aborted,badarg}, mnesia:create_table(atom)), + ?match({aborted,badarg}, + mnesia:create_table({cstruct,table_name_as_atom})), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{ram_copies,foo}])), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{disc_only_copies,foo}])), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{disc_copies,foo}])), + + CreateFun = + fun() -> ?match({aborted,nested_transaction}, + mnesia:create_table([{name,nested_trans}])), ok + end, + ?match({atomic,ok},mnesia:transaction(CreateFun)), + ?match({atomic,ok},mnesia:create_table([{name,remote_tab}, + {ram_copies,[Node2]}])), + + ?match({atomic,ok}, mnesia:create_table([{name,a_brand_new_tab}, + {ram_copies,[Node1]}])), + ?match([],mnesia:dirty_read({a_brand_new_tab,4711})), + ?match({atomic,ok}, mnesia:delete_table(a_brand_new_tab)), + ?match({'EXIT',{aborted,no_exists}}, + mnesia:dirty_read({a_brand_new_tab,4711})), + ?match({aborted,no_exists}, mnesia:delete_table(a_brand_new_tab)), + ?match({aborted,badarg}, mnesia:create_table([])), + + ?match({atomic,ok}, mnesia:create_table([{name,nested_del_trans}, + {ram_copies,[Node1]}])), + DeleteFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:delete_table(nested_del_trans)), ok end, + ?match({atomic,ok}, mnesia:transaction(DeleteFun)), + + ?match({aborted,bad_type}, + mnesia:create_table([{name,create_with_index},{index,2}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[-1]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[0]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[1]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[2]}])), + ?match({atomic,ok}, + mnesia:create_table([{name,create_with_index},{index,[3]}, + {ram_copies,[Node1]}])), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add, drop and move replicas, change storage types +%% Change table layout (only arity change supported) + +replica_management(suite) -> []; +replica_management(Nodes) -> + %% add_table_copy/3, del_table_copy/2, move_table_copy/3, + %% change_table_copy_type/3, transform_table/3 + + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + + Tab = replica_management, + Attrs = [k,v], + + %% + %% Add, delete and change replicas + %% + ?match({atomic,ok}, + mnesia:create_table([{name,Tab},{attributes,Attrs}, + {ram_copies,[Node1]}])), + mnesia_test_lib:verify_replica_location(Tab,[],[Node1],[],Nodes), + %% R - - + ?match({aborted,combine_error}, + mnesia:add_table_copy(Tab, Node2, disc_copies)), + ?match({aborted,combine_error}, + mnesia:change_table_copy_type(Tab, Node1, disc_copies)), + ?match({atomic,ok}, mnesia:del_table_copy(Tab,Node1)), + mnesia_test_lib:verify_replica_location(Tab,[],[],[],Nodes), + %% - - - + ?match({aborted,no_exists}, + mnesia:add_table_copy(Tab, Node3, ram_copies)), + + ?match({atomic,ok}, mnesia:create_table([{name,Tab}, + {attributes,Attrs}, + {disc_copies,[Node1]}])), + mnesia_test_lib:verify_replica_location(Tab,[],[],[Node1],Nodes), + %% D - - + ?match({aborted,badarg}, + mnesia:add_table_copy(Tab, Node2, bad_storage_type)), + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node1],Nodes), + %% D DO - + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), + %% D DO R + ?match({atomic,ok}, + mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node1,Node2],[Node3],[],Nodes), + %% DO DO R + ?match({aborted,already_exists}, + mnesia:add_table_copy(Tab, Node3, ram_copies)), + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node1)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[],Nodes), + %% - DO R + ?match({aborted,_}, mnesia:del_table_copy(Tab, Node1)), + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), + %% D DO R + ?match({atomic,ok}, + mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2,Node3],[],[Node1],Nodes), + %% D DO DO + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node1],Nodes), + %% D - DO + ?match({aborted,already_exists}, + mnesia:change_table_copy_type(Tab, Node1, disc_copies)), + + %% + %% Move replica + %% + ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node1,Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],Nodes), + %% - D DO + ?match({aborted,_}, mnesia:move_table_copy(Tab,Node1,Node2)), + ?match([], mnesia_test_lib:stop_mnesia([Node3])), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2], + Nodes -- [Node3]), + %% - D DO + ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node3,Node1)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2], + Nodes -- [Node3]), + %% DO D - + ?match([],mnesia_test_lib:start_mnesia([Node3])), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],Nodes), + %% DO D - + + %% + %% Transformer + %% + + NewAttrs = Attrs ++ [extra], + Transformer = + fun(Rec) -> list_to_tuple(tuple_to_list(Rec) ++ [initial_value]) end, + ?match({atomic,ok}, mnesia:transform_table(Tab, Transformer,NewAttrs)), + ?match({atomic,ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, 0)), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, -1)), + ?match({aborted,badarg}, mnesia:transform_table(Tab, Transformer, [])), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, no_fun, NewAttrs)), + + NestedFun = + fun() -> + ?match({aborted,_}, + mnesia:move_table_copy(Tab,Node1,Node2)), + ?match({aborted,_}, + mnesia:add_table_copy(Tab,Node1,ram_copies)), + ?match({aborted,_}, + mnesia:del_table_copy(Tab,Node1)), + T = fun(_) -> 4711 end, + ?match({aborted,_}, + mnesia:transform_table(Tab,Transformer, T)), + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add and drop indecies + +index_lifecycle(suite) -> + [ add_table_index, create_live_table_index, del_table_index ]. + +%% Add table index + +add_table_index(suite) -> []; +add_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = add_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,BadValPos)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,2)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,1)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,0)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,-1)), + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + ?match({aborted,already_exists}, mnesia:add_table_index(Tab,ValPos)), + + NestedFun = fun() -> + ?match({aborted,nested_transaction}, + mnesia:add_table_index(Tab,ValPos)), + + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +create_live_table_index(suite) -> []; +create_live_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = create_live_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + mnesia:dirty_write({Tab,1,2}), + + Fun = fun() -> + ?match(ok, mnesia:write({Tab,2,2})), + ok + end, + ?match({atomic,ok},mnesia:transaction(Fun)), + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + done. + +%% Drop table index + +del_table_index(suite) ->[]; +del_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = del_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + ?match({aborted,no_exists}, + mnesia:del_table_index(Tab,BadValPos)), + ?match({atomic,ok}, mnesia:del_table_index(Tab,ValPos)), + + NestedFun = + fun() -> + ?match({aborted,nested_transaction}, + mnesia:del_table_index(Tab,ValPos)), + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Syncronize table with log or disc +%% +table_sync(suite) -> + [ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ]. + +%% Dump ram tables on disc +dump_tables(suite) -> []; +dump_tables(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + Tab = dump_tables, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node2]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + + %% Dump 10 records + Size = 10, + Keys = lists:seq(1,Size), + Records = [{Tab,A,7} || A <- Keys], + lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), + AllKeys = fun() -> lists:sort(mnesia:all_keys(Tab)) end, + + ?match({atomic,Keys}, mnesia:transaction(AllKeys)), + ?match(ok, mnesia:dump_tables(Tab)), + + %% Delete one record + ?match(ok,mnesia:dirty_delete({Tab,5})), + Keys2 = lists:delete(5,Keys), + ?match({atomic,Keys2}, mnesia:transaction(AllKeys)), + + %% Check that all 10 is restored after a stop + ?match([], mnesia_test_lib:stop_mnesia([Node1,Node2])), + ?match([],mnesia_test_lib:start_mnesia([Node1,Node2])), + ?match(ok,mnesia:wait_for_tables([Tab],infinity)), + ?match({atomic,Keys}, mnesia:transaction(AllKeys)), + + ?match(ok, mnesia:dump_tables([foo])), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make Mnesia table accessible via SNMP + +snmp_access(suite) -> + [ + snmp_open_table, snmp_close_table, + snmp_get_row, snmp_get_next_index, snmp_get_mnesia_key + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Check that the debug support has not decayed + +debug_support(suite) -> + [ info, schema, schema, kill, lkill ]. + diff --git a/lib/compiler/test/compile_SUITE_data/include/simple.hrl b/lib/compiler/test/compile_SUITE_data/include/simple.hrl new file mode 100644 index 0000000000..cbe6e4f1a4 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/include/simple.hrl @@ -0,0 +1,19 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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% +%% +-define(included_value, hiker). diff --git a/lib/compiler/test/compile_SUITE_data/missing_testheap1.erl b/lib/compiler/test/compile_SUITE_data/missing_testheap1.erl new file mode 100644 index 0000000000..65ee11541d --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/missing_testheap1.erl @@ -0,0 +1,35 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(missing_testheap1). + +-compile(export_all). +%%-export([Function/Arity, ...]). +-record(state,{e1,e2}). + +f({a,DpId},State) when State == +#state{e1=true, + e2=a} -> + {a,a}; + +f({a,DpId},State) when State == +#state{e1=true, + e2=b} -> + {a,b}. + + diff --git a/lib/compiler/test/compile_SUITE_data/missing_testheap2.erl b/lib/compiler/test/compile_SUITE_data/missing_testheap2.erl new file mode 100644 index 0000000000..014210fa5a --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/missing_testheap2.erl @@ -0,0 +1,29 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(missing_testheap2). + +-compile(export_all). + +f({a,DpId},16#7fffffff) -> + big; + +f({a,DpId},16#80000000) -> + bigger. + + diff --git a/lib/compiler/test/compile_SUITE_data/record_access.erl b/lib/compiler/test/compile_SUITE_data/record_access.erl new file mode 100644 index 0000000000..c89f9ad7c7 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/record_access.erl @@ -0,0 +1,29 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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(record_access). +-export([turtle/0,test/1]). + +-record(turtle, {a,b,c}). +-record(tortoise, {a,b,c}). + +turtle() -> + #turtle{a=1,b=2,c=3}. + +test(T) -> + {T#tortoise.a,T#tortoise.b}. diff --git a/lib/compiler/test/compile_SUITE_data/simple.erl b/lib/compiler/test/compile_SUITE_data/simple.erl new file mode 100644 index 0000000000..2021056388 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/simple.erl @@ -0,0 +1,39 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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(simple). + +-export([test/0]). + +-ifdef(need_foo). +-export([foo/0]). +-endif. + +test() -> + passed. + +%% Conditional inclusion. +%% Compile with [{d, need_foo}, {d, foo_value, 42}]. + +-ifdef(need_foo). +-include("simple.hrl"). + +foo() -> + {?included_value, ?foo_value}. + +-endif. diff --git a/lib/compiler/test/compile_SUITE_data/wrong_module_name.erl b/lib/compiler/test/compile_SUITE_data/wrong_module_name.erl new file mode 100644 index 0000000000..ea437556a4 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/wrong_module_name.erl @@ -0,0 +1,23 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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(arne). +-export([?MODULE/0]). + +?MODULE() -> + ok. diff --git a/lib/compiler/test/compiler.cover b/lib/compiler/test/compiler.cover new file mode 100644 index 0000000000..5ec2408a35 --- /dev/null +++ b/lib/compiler/test/compiler.cover @@ -0,0 +1,3 @@ +%% -*- erlang -*- +{exclude,[sys_pre_attributes,core_parse]}. + diff --git a/lib/compiler/test/compiler.dynspec b/lib/compiler/test/compiler.dynspec new file mode 100644 index 0000000000..7e452cef6c --- /dev/null +++ b/lib/compiler/test/compiler.dynspec @@ -0,0 +1,10 @@ +%% -*- erlang -*- +%% You can test this file using this command. +%% file:script("compiler.dynspec", [{'Os',"Unix"}]). + +case Os of + "VxWorks" -> + [{skip,{compile_SUITE,listings,"VxWorks filesystem too slow"}}]; + _ -> + [] +end. diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl new file mode 100644 index 0000000000..54cf799057 --- /dev/null +++ b/lib/compiler/test/core_SUITE.erl @@ -0,0 +1,59 @@ +%% +%% %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(core_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + dehydrated_itracer/1,nested_tries/1]). + +-include("test_server.hrl"). + +-define(comp(N), + N(Config) when is_list(Config) -> try_it(N, Config)). + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = test_server:timetrap(?t:minutes(5)), + [{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), + [dehydrated_itracer,nested_tries]. + +?comp(dehydrated_itracer). +?comp(nested_tries). + +try_it(Mod, Conf) -> + ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)), + ?line Out = ?config(priv_dir,Conf), + ?line io:format("Compiling: ~s\n", [Src]), + ?line CompRc0 = compile:file(Src, [from_core,{outdir,Out},report,time]), + ?line io:format("Result: ~p\n",[CompRc0]), + ?line {ok,Mod} = CompRc0, + + ?line {module,Mod} = code:load_abs(filename:join(Out, Mod)), + ?line ok = Mod:Mod(), + ok. + + + + diff --git a/lib/compiler/test/core_SUITE_data/dehydrated_itracer.core b/lib/compiler/test/core_SUITE_data/dehydrated_itracer.core new file mode 100644 index 0000000000..e64e981edc --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/dehydrated_itracer.core @@ -0,0 +1,99 @@ +module 'dehydrated_itracer' ['dehydrated_itracer'/0, + 'module_info'/0, + 'module_info'/1] + attributes [] +'dehydrated_itracer'/0 = + %% Line 5 + fun () -> + case <> of + <> when 'true' -> + %% Line 6 + case apply 'itracer'/0 + () of + <{'vector',65536}> when 'true' -> + %% Line 7 + 'ok' + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + primop 'match_fail' + ({'function_clause'}) + -| ['compiler_generated'] ) + end +'itracer'/0 = + %% Line 8 + fun () -> + let <Dir> = + %% Line 9 + apply 'vcreate'/3 + (0, 0, 256) + in %% Line 10 + apply 'initialize'/1 + (Dir) +'initialize'/1 = + %% Line 12 + fun (_cor0) -> + %% Line 23 + case _cor0 of + <{'vector',_pre0}> when 'true' -> + let <_cor4> = + call 'erlang':'*' + (_pre0, 2) + in let <Up2> = {'vector',_cor4} + in case Up2 of + <{'vector',_pre0}> when 'true' -> + let <_cor4> = + call 'erlang':'*' + (_pre0, -1) + in let <Down> = {'vector',_cor4} + in case _cor0 of +%%% The case would be optimized away, and pre0 would be used directly, +%%% only it would be the wrong pre0. + <{'vector',_pre0}> when 'true' -> + let <_cor4> = + call 'erlang':'*' + (_pre0, 256) + in {'vector',_cor4} + <_cor7> when 'true' -> + call 'erlang':'error' + ({'badrecord','vector'}) + end + <_cor7> when 'true' -> + call 'erlang':'error' + ({'badrecord','vector'}) + end + <_cor7> when 'true' -> + call 'erlang':'error' + ({'badrecord','vector'}) + end +'vcreate'/3 = + %% Line 19 + fun (_cor2,_cor1,_cor0) -> + %% Line 20 + {'vector',_cor0} +'mul'/2 = + %% Line 22 + fun (_cor1,_cor0) -> + %% Line 23 + case _cor0 of + <{'vector',_pre0}> when 'true' -> + let <_cor4> = + call 'erlang':'*' + (_pre0, _cor1) + in {'vector',_cor4} + <_cor7> when 'true' -> + call 'erlang':'error' + ({'badrecord','vector'}) + end +'module_info'/0 = + fun () -> + call 'erlang':'get_module_info' + ('dehydrated_itracer') +'module_info'/1 = + fun (_cor0) -> + call 'erlang':'get_module_info' + ('dehydrated_itracer', _cor0) +end
\ No newline at end of file diff --git a/lib/compiler/test/core_SUITE_data/nested_tries.core b/lib/compiler/test/core_SUITE_data/nested_tries.core new file mode 100644 index 0000000000..d9010b808b --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/nested_tries.core @@ -0,0 +1,36 @@ +module 'nested_tries' ['nested_tries'/0, 'reg'/2] + attributes [] + +'nested_tries'/0 = + fun () -> 'ok' + +'reg'/2 = + fun (_cor1,_cor0) -> + let <_X_var__238> = 1 + in case %% Line 4 + <_cor1,_cor0> of + <Id,Pid> + when call 'erlang':'and' + (try 'true' + of <_X_var__235> -> _X_var__235 + catch <_X_var__236,_X_var__237> -> 'false', + try + let <_cor2> = + try + call 'erlang':'and' + ('true', + call 'erlang':'is_integer'(call 'erlang':'element'(3, Pid))) + of <_X_var__232> -> _X_var__232 + catch <_X_var__233,_X_var__234> -> 'false' + in let <_cor4> = call 'erlang':'element'(2, Pid) + in let <_cor3> = _X_var__238 + in let <_cor5> = call 'erlang':'=='(_cor4, _cor3) + in call 'erlang':'and'(_cor2, _cor5) + of <Try> -> Try + catch <T,R> -> 'false') -> 'true' + <_cor7,_cor6> when 'true' -> + primop 'match_fail' + ({( 'function_clause' + -| [{'name',{'reg',2}}] ),_cor7,_cor6}) + end +end diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl new file mode 100644 index 0000000000..5f2c905d4a --- /dev/null +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -0,0 +1,233 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-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(core_fold_SUITE). + +-export([all/1, + t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1, + eq/1,nested_call_in_case/1,coverage/1]). + +-export([foo/0,foo/1,foo/2,foo/3]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [t_element,setelement,t_length,append,t_apply,bifs, + eq,nested_call_in_case,coverage]. + +t_element(Config) when is_list(Config) -> + X = make_ref(), + ?line X = id(element(1, {X,y,z})), + ?line b = id(element(2, {a,b,c,d})), + + %% No optimization, but should work. + Tuple = id({x,y,z}), + Pos = id(3), + ?line x = id(element(1, Tuple)), + ?line c = id(element(Pos, {a,b,c,d})), + ?line X = id(element(Pos, {a,b,X,d})), + ?line z = id(element(Pos, Tuple)), + + %% Calls that will fail. + ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})), + ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})), + ?line {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})), + case id({a,b,c}) of + {_,_,_}=Tup -> + ?line {'EXIT',{badarg,_}} = (catch element(4, Tup)) + end, + + ok. + +setelement(Config) when is_list(Config) -> + X = id(b), + New = id([1,2,3]), + ?line {y,b,c} = id(setelement(1, {a,b,c}, y)), + ?line {y,b,c} = id(setelement(1, {a,X,c}, y)), + ?line {a,y,c} = id(setelement(2, {a,X,c}, y)), + ?line {a,[1,2,3],c} = id(setelement(2, {a,b,c}, New)), + ?line {a,[1,2,3],c} = id(setelement(2, {a,X,c}, New)), + ?line {a,b,[1,2,3]} = id(setelement(3, {a,b,c}, New)), + ?line {a,b,[1,2,3]} = id(setelement(3, {a,X,c}, New)), + + ?line {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})), + ?line error = setelement_crash_2({a,b,c,d,e,f}, <<42>>), + ok. + +setelement_crash(Tuple) -> + %% Used to crash the compiler because sys_core_dsetel did not notice that + %% X1 was used in bit syntax construction. + X1 = setelement(5, Tuple, new), + X2 = setelement(3, X1, new), + {X2,<<X1>>}. + +setelement_crash_2(Tuple, Bin) -> + %% Used to crash the compiler because sys_core_dsetel did not notice that + %% X1 was used as a size field in bit syntax matching. + X1 = setelement(5, Tuple, new), + X2 = setelement(3, X1, new), + case Bin of + <<42:X1>> -> X2; + _ -> error + end. + +t_length(Config) when is_list(Config) -> + Blurf = id({blurf,a,b}), + Tail = id([42,43,44,45]), + ?line 0 = id(length([])), + ?line 1 = id(length([x])), + ?line 2 = id(length([x,Blurf])), + ?line 4 = id(length([x,Blurf,a,b])), + + %% No or partial optimization. + ?line 4 = length(Tail), + ?line 5 = id(length([x|Tail])), + + %% Will fail. + ?line {'EXIT',{badarg,_}} = (catch id(length([a,b|c]))), + ?line {'EXIT',{badarg,_}} = (catch id(length([a,Blurf|c]))), + ?line {'EXIT',{badarg,_}} = (catch id(length(atom))), + + ok. + +-define(APPEND(A, B), (fun(Res) -> + Res = lists:append(A, B), + Res = erlang:append(A, B), + Res = erlang:'++'(A, B) + end)(A++B)). + +append(Config) when is_list(Config) -> + A = id(0), + ?line [a,b,c,d,e,f,g,h,i,j,k] = id(?APPEND([a,b,c,d,e,f],[g,h,i,j,k])), + ?line [a,b,c,d,e] = id(?APPEND([a,b,c],id([d,e]))), + ?line [0,1,2,3,4,5,6] = id(?APPEND([A,1,2,3],[4,5,6])), + ?line {'EXIT',{badarg,_}} = (catch id(?APPEND([A|blurf],[4,5,6]))), + ok. + +t_apply(Config) when is_list(Config) -> + ?line ok = apply(?MODULE, foo, []), + ?line 4 = apply(?MODULE, foo, [3]), + ?line 7 = apply(?MODULE, foo, [3,4]), + ?line 12 = apply(?MODULE, foo, [id(8),4]), + ?line 21 = apply(?MODULE, foo, [8,id(9),4]), + ?line 20 = apply(?MODULE, foo, [8,8,id(4)]), + ?line 24 = apply(?MODULE, foo, [id(10),10,4]), + + M = id(?MODULE), + ?line ok = apply(M, foo, []), + ?line 4 = apply(M, foo, [3]), + ?line 16.0 = apply(M, foo, [12.0,4]), + + %% Will fail. + ?line {'EXIT',{badarg,_}} = (catch apply([a,b,c], foo, [])), + ?line {'EXIT',{badarg,_}} = (catch apply(42, foo, [])), + ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, 45, [xx])), + ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, {a,b})), + ?line {'EXIT',{badarg,_}} = (catch apply(M, M, [1009|10010])), + ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, [10000|9999])), + ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, a)), + + ok. + +foo() -> + ok. + +foo(A) -> + A+1. + +foo(A, B) -> + A + B. + +foo(A, B, C) -> + A + B + C. + +bifs(Config) when is_list(Config) -> + ?line <<1,2,3,4>> = id(list_to_binary([1,2,3,4])), + ok. + +-define(CMP_SAME(A0, B), (fun(A) -> true = A == B, false = A /= B end)(id(A0))). +-define(CMP_DIFF(A0, B), (fun(A) -> false = A == B, true = A /= B end)(id(A0))). + +eq(Config) when is_list(Config) -> + ?line ?CMP_SAME([a,b,c], [a,b,c]), + ?line ?CMP_SAME([42.0], [42.0]), + ?line ?CMP_SAME([42], [42]), + ?line ?CMP_SAME([42.0], [42]), + + ?line ?CMP_DIFF(a, [a]), + ?line ?CMP_DIFF(a, {1,2,3}), + + ok. + +%% OTP-7117. +nested_call_in_case(Config) when is_list(Config) -> + ?line PrivDir = ?config(priv_dir, Config), + ?line Dir = filename:dirname(code:which(?MODULE)), + ?line Core = filename:join(Dir, "nested_call_in_case"), + ?line Opts = [from_core,{outdir,PrivDir}|test_lib:opt_opts(?MODULE)], + ?line io:format("~p", [Opts]), + ?line {ok,Mod} = c:c(Core, Opts), + ?line yes = Mod:a([1,2,3], 2), + ?line no = Mod:a([1,2,3], 4), + ?line {'EXIT',_} = (catch Mod:a(not_a_list, 42)), + ok. + +coverage(Config) when is_list(Config) -> + ?line {'EXIT',{{case_clause,{a,b,c}},_}} = + (catch cover_will_match_list_type({a,b,c})), + ?line {'EXIT',{{case_clause,{a,b,c,d}},_}} = + (catch cover_will_match_list_type({a,b,c,d})), + ?line a = cover_remove_non_vars_alias({a,b,c}), + ?line error = cover_will_match_lit_list(), + + %% Make sure that we don't attempt to make literals + %% out of pids. (Putting a pid into a #c_literal{} + %% would crash later compiler passes.) + case list_to_pid("<0.42.0>") of + Pid when is_pid(Pid) -> ok + end, + ok. + +cover_will_match_list_type(A) -> + case A of + {a,_,_} -> %Set type of A to {a,_,_}. + case A of + {a,_,_,_} -> ok %Compare type and pattern. + end + end. + +%% Make sure the remove_non_vars/4 can handle aliases in the type argument. +cover_remove_non_vars_alias(X) -> + case X of + {a=Y,_,_} -> %Set type of A to {a=Y,_,_}. + case X of + {_,_,_} -> %Compare type and pattern. + Y + end + end. + +cover_will_match_lit_list() -> + case {1,2,3} of %Literal case expression. + {_,$A,$A} -> %Pattern that does not match. + ok; + _ -> + error + end. + +id(I) -> I. diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl new file mode 100644 index 0000000000..477730c3ac --- /dev/null +++ b/lib/compiler/test/error_SUITE.erl @@ -0,0 +1,114 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(error_SUITE). + +-include("test_server.hrl"). + +-export([all/1, + head_mismatch_line/1,r11b_binaries/1]). + +all(suite) -> + test_lib:recompile(?MODULE), + [head_mismatch_line,r11b_binaries]. + +%% Tests that a head mismatch is reported on the correct line (OTP-2125). +head_mismatch_line(Config) when is_list(Config) -> + ?line [E|_] = get_compilation_errors(Config, "head_mismatch_line"), + ?line {26, Mod, Reason} = E, + ?line Mod:format_error(Reason), + ok. + +%% Compiles a test file and returns the list of errors. + +get_compilation_errors(Config, Filename) -> + ?line DataDir = ?config(data_dir, Config), + ?line File = filename:join(DataDir, Filename), + ?line {error, [{_Name, E}|_], []} = compile:file(File, [return_errors]), + E. + +r11b_binaries(Config) when is_list(Config) -> + Ts = [{r11b_binaries, + <<" + t1(Bin) -> + case Bin of + _ when size(Bin) > 20 -> erlang:error(too_long); + <<_,T/binary>> -> t1(T); + <<>> -> ok + end. + + t2(<<_,T/bytes>>) -> + split_binary(T, 4). + + t3(X) -> + <<42,X/binary>>. + + t4(X) -> + <<N:32>> = X, + N. + ">>, + [r11], + {error, + [{5,v3_core,no_binaries}, + {6,v3_core,no_binaries}, + {9,v3_core,no_binaries}, + {13,v3_core,no_binaries}, + {16,v3_core,no_binaries}], + []} }], + ?line [] = run(Config, Ts), + ok. + + +run(Config, Tests) -> + F = fun({N,P,Ws,E}, BadL) -> + case catch run_test(Config, P, Ws) of + E -> + BadL; + Bad -> + ?t:format("~nTest ~p failed. Expected~n ~p~n" + "but got~n ~p~n", [N, E, Bad]), + fail() + end + end, + lists:foldl(F, [], Tests). + + +%% Compiles a test module and returns the list of errors and warnings. + +run_test(Conf, Test0, Warnings) -> + Filename = 'errors_test.erl', + ?line DataDir = ?config(priv_dir, Conf), + ?line Test = ["-module(errors_test). ", Test0], + ?line File = filename:join(DataDir, Filename), + ?line Opts = [binary,export_all,return|Warnings], + ?line ok = file:write_file(File, Test), + + %% Compile once just to print all errors and warnings. + ?line compile:file(File, [binary,export_all,report|Warnings]), + + %% Test result of compilation. + ?line Res = case compile:file(File, Opts) of + {error,[{_File,Es}],Ws} -> + {error,Es,Ws} + end, + file:delete(File), + Res. + +fail() -> + io:format("failed~n"), + ?t:fail(). diff --git a/lib/compiler/test/error_SUITE_data/head_mismatch_line.erl b/lib/compiler/test/error_SUITE_data/head_mismatch_line.erl new file mode 100644 index 0000000000..619c1329a4 --- /dev/null +++ b/lib/compiler/test/error_SUITE_data/head_mismatch_line.erl @@ -0,0 +1,30 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(head_mismatch_line). + +-export([foo/1, bar/2]). + +foo(a) -> + ok; + +bar(x) -> % The mismatch should be here. + ok; +bar(y) -> + ok. + diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl new file mode 100644 index 0000000000..3d2dbf47e9 --- /dev/null +++ b/lib/compiler/test/float_SUITE.erl @@ -0,0 +1,120 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-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(float_SUITE). +-export([all/1,pending/1,bif_calls/1,math_functions/1,mixed_float_and_int/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [pending,bif_calls,math_functions,mixed_float_and_int]. + +%% Thanks to Tobias Lindahl <[email protected]> +%% Shows the effect of pending exceptions on the x86. + +pending(Config) when is_list(Config) -> + ?line case catch float_mul(1, 1.1e300, 3.14e300) of + {'EXIT',{badarith,_}} -> ok; + Other -> ?t:fail({expected_exception,Other}) + end, + ?line 0.0 = float_sub(2.0). + +float_sub(A)-> + catch A - 2.0. + +float_mul(0, _, _)-> + ok; +float_mul(Iter, A, B) when is_float(A), is_float(B) -> + A*B, + float_mul(Iter-1, A, B). + +%% Thanks to Mikael Pettersson and Tobias Lindahl (HiPE). + +bif_calls(Config) when is_list(Config) -> + ?line {'EXIT',{badarith,_}} = (catch bad_arith(2.0, 1.7)), + ?line {'EXIT',{badarith,_}} = (catch bad_arith_again(2.0, [])), + ?line {'EXIT',{badarith,_}} = (catch bad_arith_xor(2.0, [])), + ?line {'EXIT',{badarith,_}} = (catch bad_arith_hd(2.0, [])), + ?line {'EXIT',{badarith,_}} = (catch bad_negate(2.0, 1.7)), + ok. + +bad_arith(X, Y) when is_float(X) -> + X1 = X * 1.7e+308, + X2 = X1 + 1.0, + Y1 = Y * 2, %Calls erts_mixed_times/2. + %(A BIF call.) + {X2, Y1}. + +bad_arith_xor(X, Y) when is_float(X) -> + X1 = X * 1.7e+308, + Y1 = Y xor true, %A failing BIF call. + {X1 + 1.0, Y1}. + +bad_arith_hd(X, Y) when is_float(X) -> + X1 = X * 1.7e+308, + Y1 = hd(Y), %A failing BIF call. + {X1 + 1.0, Y1}. + +bad_arith_again(X, Y) when is_float(X) -> + X1 = X * 1.7e+308, + Y1 = element(1, Y), %A failing BIF call. + {X1 + 1.0, Y1}. + +bad_negate(X, Y) when is_float(X) -> + X1 = X * 1.7e+308, + X2 = X1 + 1.0, + Y1 = -Y, %BIF call. + {X2, Y1}. + +math_functions(Config) when is_list(Config) -> + %% Mostly silly coverage. + ?line 0.0 = math:tan(0), + ?line 0.0 = math:atan2(0, 1), + ?line 0.0 = math:sinh(0), + ?line 1.0 = math:cosh(0), + ?line 0.0 = math:tanh(0), + ?line 1.0 = math:log10(10), + ?line -1.0 = math:cos(math:pi()), + ?line 1.0 = math:exp(0), + ?line 1.0 = math:pow(math:pi(), 0), + + ?line 0.0 = math:tan(id(0)), + ?line 0.0 = math:atan2(id(0), 1), + ?line 0.0 = math:sinh(id(0)), + ?line 1.0 = math:cosh(id(0)), + ?line 0.0 = math:tanh(id(0)), + ?line 1.0 = math:log10(id(10)), + ?line 1.0 = math:exp(id(0)), + + %% Only for coverage (of beam_type.erl). + ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0)), + ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)), + ?line {'EXIT',{badarg,_}} = (catch float(kalle)), + ?line {'EXIT',{badarith,_}} = (catch name/1), + ok. + +mixed_float_and_int(Config) when is_list(Config) -> + ?line 129.0 = pc(77, 23, 5), + ok. + +pc(Cov, NotCov, X) -> + round(Cov/(Cov+NotCov)*100) + 42 + 2.0*X. + +id(I) -> I. + diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl new file mode 100644 index 0000000000..fb2667245a --- /dev/null +++ b/lib/compiler/test/fun_SUITE.erl @@ -0,0 +1,136 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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(fun_SUITE). + +-export([all/1, + test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [test1,overwritten_fun,otp_7202,bif_fun]. + +%%% The help functions below are copied from emulator:bs_construct_SUITE. + +-define(T(B, L), {B, ??B, L}). + +l1() -> + [ + ?T((begin A = 3, F = fun(A) -> 1; (_) -> 2 end, F(2) end), 1), + ?T((begin G = fun(1=0) -> ok end, {'EXIT',_} = (catch G(2)), ok end), ok) + ]. + +test1(suite) -> []; +test1(Config) when is_list(Config) -> + ?line lists:foreach(fun one_test/1, eval_list(l1(), [])), + ok. + +evaluate(Str, Vars) -> + {ok,Tokens,_} = + erl_scan:string(Str ++ " . "), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + case erl_eval:expr(Expr, Vars) of + {value, Result, _} -> + Result + end. + +eval_list([], _Vars) -> + []; +eval_list([{C_bin, Str, Bytes} | Rest], Vars) -> + case catch evaluate(Str, Vars) of + {'EXIT', Error} -> + io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]), + exit(Error); + E_bin -> + [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)] + end. + +one_test({C, E, Str, Correct}) -> + io:format(" ~s, ~p~n", [Str, Correct]), + if + C == Correct -> + ok; + true -> + io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", + [Str, Correct, C]), + test_server:fail(comp) + end, + if + E == Correct -> + ok; + true -> + io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", + [Str, Correct, E]), + test_server:fail(comp) + end. + +-record(b, {c}). + +%% OTP-7102. (Thanks to Simon Cornish.) + +overwritten_fun(Config) when is_list(Config) -> + ?line {a2,a} = overwritten_fun_1(a), + ?line {a2,{b,c}} = overwritten_fun_1(#b{c=c}), + ?line one = overwritten_fun_1(#b{c=[]}), + ok. + +overwritten_fun_1(A) -> + F = fun() -> + {ok, A} + end, + if A#b.c == [] -> + one; + true -> + case F() of + {ok, A2} -> + {a2, A2}; + _ -> + three + end + end. + +%% OTP-7202. The liveness calculation for the make_fun2 instruction was wrong. + +otp_7202(Config) when is_list(Config) -> + otp_7202(). + +otp_7202() -> + List = [a], + Error = case otp_7202_func() of + no_value -> true; + {ok, V} -> V + end, + lists:foreach(fun(_E) -> + case Error of + true -> + ok; + false -> + ok + end + end, List). + +otp_7202_func() -> + no_value. + +bif_fun(Config) when is_list(Config) -> + ?line F = fun abs/1, + ?line 5 = F(-5), + ok. + diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl new file mode 100644 index 0000000000..5ae41f13e7 --- /dev/null +++ b/lib/compiler/test/guard_SUITE.erl @@ -0,0 +1,1376 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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(guard_SUITE). + +-include("test_server.hrl"). + +-export([all/1, + misc/1,const_cond/1,basic_not/1,complex_not/1,nested_nots/1, + semicolon/1,complex_semicolon/1,comma/1, + or_guard/1,more_or_guards/1, + complex_or_guards/1,and_guard/1, + xor_guard/1,more_xor_guards/1, + old_guard_tests/1, + build_in_guard/1,gbif/1, + t_is_boolean/1,is_function_2/1, + tricky/1,rel_ops/1,literal_type_tests/1, + basic_andalso_orelse/1,traverse_dcd/1, + check_qlc_hrl/1,andalso_semi/1,tuple_size/1]). + +all(suite) -> + test_lib:recompile(?MODULE), + [misc,const_cond,basic_not,complex_not,nested_nots, + semicolon,complex_semicolon, + comma,or_guard,more_or_guards, + complex_or_guards,and_guard, + xor_guard,more_xor_guards, + build_in_guard,old_guard_tests,gbif, + t_is_boolean,is_function_2,tricky,rel_ops,literal_type_tests, + basic_andalso_orelse,traverse_dcd,check_qlc_hrl,andalso_semi, + tuple_size]. + +misc(Config) when is_list(Config) -> + ?line 42 = case id(42) of + X when -X -> ok; + X -> X + end, + ?line {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]), + ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]), + ?line none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]), + ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]), + + ?line {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf), + ?line {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf), + ?line {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf), + ?line error = get_data({o,false,raw}, 42, buf), + ?line {ok,buf,<<>>} = get_data({o,true,0}, 0, buf), + ?line {ok,buf,<<>>} = get_data({o,true,0}, 42, buf), + ?line {ok,buf,<<>>} = get_data({o,false,0}, 0, buf), + ?line error = get_data({o,false,0}, 42, buf), + ok. + + +misc_1([{W},{X},{Y},{Z}]) -> + if + X > Y andalso abs(Z) =:= 2 -> + id(W); + true -> + none + end. + +get_data({o,Active,Raw}, BytesToRead, Buffer) + when Raw =:= raw; Raw =:= 0 -> + if + Active =/= false orelse BytesToRead =:= 0 -> + {ok,Buffer,<<>>}; + true -> + error + end. + +const_cond(Config) when is_list(Config) -> + ?line ok = const_cond({}, 0), + ?line ok = const_cond({a}, 1), + ?line error = const_cond({a,b}, 3), + ?line error = const_cond({a}, 0), + ?line error = const_cond({a,b}, 1), + ok. + +const_cond(T, Sz) -> + case T of + _X when false -> never; + _X when tuple(T), eq == eq, tuple_size(T) == Sz -> ok; + _X when tuple(T), eq == leq, tuple_size(T) =< Sz -> ok; + _X -> error + end. + +basic_not(Config) when is_list(Config) -> + True = id(true), + False = id(false), + Glurf = id(glurf), + A = id(5), + B = id(37.5), + C = id(-1), + D = id(5), + ATuple = {False,True,Glurf}, + + ?line check(fun() -> if not false -> ok; true -> error end end, ok), + ?line check(fun() -> if not true -> ok; true -> error end end, error), + ?line check(fun() -> if not False -> ok; true -> error end end, ok), + ?line check(fun() -> if not True -> ok; true -> error end end, error), + + ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt), + ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt), + ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq), + + ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge; + not (7 == 453) -> ne; true -> eq end end, le), + ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge; + not (7 == -8) -> ne; true -> eq end end, ge), + ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge; + not (7 == 7) -> ne; true -> eq end end, le), + + ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge; + not (A == B) -> ne; true -> eq end end, le), + ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge; + not (A == C) -> ne; true -> eq end end, ge), + ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge; + not (A == D) -> ne; true -> eq end end, le), + + ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok), + ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error), + ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error), + + ?line check(fun() -> if not glurf -> ok; true -> error end end, error), + ?line check(fun() -> if not Glurf -> ok; true -> error end end, error), + + ok. + +complex_not(Config) when is_list(Config) -> + ATuple = id({false,true,gurka}), + ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok), + ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error), + + ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok; + true -> error end end, error), + ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok; + true -> error end end, ok), + + ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok; + true -> error end end, ok), + ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok; + true -> error end end, error), + + ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok; + true -> error end end, error), + + %% orelse + ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok; + true -> error end end, error), + + ok. + +nested_nots(Config) when is_list(Config) -> + ?line true = nested_not_1(0, 0), + ?line true = nested_not_1(0, 1), + ?line true = nested_not_1(a, b), + ?line true = nested_not_1(10, 0), + ?line false = nested_not_1(z, a), + ?line false = nested_not_1(3.4, {anything,goes}), + ?line false = nested_not_1(3.4, atom), + ?line true = nested_not_1(3.0, [list]), + + ?line true = nested_not_2(false, false, 42), + ?line true = nested_not_2(false, true, 42), + ?line true = nested_not_2(true, false, 42), + ?line true = nested_not_2(true, true, 42), + ?line true = nested_not_2(false, false, atom), + ?line false = nested_not_2(false, true, atom), + ?line false = nested_not_2(true, false, atom), + ?line false = nested_not_2(true, true, atom), + ok. + +nested_not_1(X, Y) when not (((X>Y) or not(is_atom(X))) and + (is_atom(Y) or (X==3.4))) -> + true; +nested_not_1(_, _) -> + false. + +nested_not_2(X, Y, Z) -> + nested_not_2(X, Y, Z, true). + +nested_not_2(X, Y, Z, True) + when not(True and not((not(X) and not(Y)) or not(is_atom(Z)))) -> + true; +nested_not_2(_, _, _, _) -> + false. + +semicolon(Config) when is_list(Config) -> + + %% True/false combined using ';' (literal atoms). + + ?line check(fun() -> if true; false -> ok end end, ok), + ?line check(fun() -> if false; true -> ok end end, ok), + ?line check(fun() -> if true; true -> ok end end, ok), + ?line check(fun() -> if false; false -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false; false -> ok end), + exit + end, exit), + + %% True/false combined used ';'. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True; False -> ok end end, ok), + ?line check(fun() -> if False; True -> ok end end, ok), + ?line check(fun() -> if True; True -> ok end end, ok), + ?line check(fun() -> if False; False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False; False -> ok end), + exit + end, exit), + + %% Combine true/false with a non-boolean value. + Glurf = id(glurf), + + + ?line check(fun() -> if True; Glurf -> ok end end, ok), + ?line check(fun() -> if Glurf; True -> ok end end, ok), + ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end), + exit + end, exit), + + %% Combine true/false with errors. + + ATuple = id({false,true,gurka}), + + ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if False; element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if element(42, ATuple); + False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if element(42, ATuple); + element(42, ATuple) -> ok end), + exit + end, exit), + + ok. + +complex_semicolon(Config) when is_list(Config) -> + ?line ok = csemi1(int, {blurf}), + ?line ok = csemi1(string, {blurf}), + ?line ok = csemi1(float, [a]), + ?line error = csemi1(35, 42), + + %% 2 + ?line ok = csemi2({}, {a,b,c}), + ?line ok = csemi2({1,3.5}, {a,b,c}), + ?line ok = csemi2(dum, {a,b,c}), + + ?line ok = csemi2({45,-19.3}, {}), + ?line ok = csemi2({45,-19.3}, {dum}), + ?line ok = csemi2({45,-19.3}, {dum,dum}), + + ?line error = csemi2({45}, {dum}), + ?line error = csemi2([], {dum}), + ?line error = csemi2({dum}, []), + ?line error = csemi2([], []), + + %% 3 + ?line csemi3(fun csemi3a/4), + ?line csemi3(fun csemi3b/4), + ?line csemi3(fun csemi3c/4), + + %% 4 + ?line csemi4(fun csemi4a/4), + ?line csemi4(fun csemi4b/4), + ?line csemi4(fun csemi4c/4), + ?line csemi4(fun csemi4d/4), + + %% 4, 'orelse' instead of 'or' + ?line csemi4_orelse(fun csemi4_orelse_a/4), + ?line csemi4_orelse(fun csemi4_orelse_b/4), + ?line csemi4_orelse(fun csemi4_orelse_c/4), + ?line csemi4_orelse(fun csemi4_orelse_d/4), + + %% 5 + ?line error = csemi5(0, 0), + ?line ok = csemi5(5, 0), + ?line ok = csemi5(4, -4), + ?line ok = csemi5(10, -4), + + %% 6 + ?line error = csemi6({a}, 0), + ?line ok = csemi6({a,b}, 0), + ?line ok = csemi6({}, 3), + ?line ok = csemi6({a,b,c}, 3), + + ok. + +csemi1(Type, Val) when is_list(Val), Type == float; + Type == int; Type == string -> ok; +csemi1(_, _) -> error. + +csemi2(A, B) when tuple_size(A) > 1; tuple_size(B) > 2 -> ok; +csemi2(_, _) -> error. + +csemi3(Csemi3) -> + ok = Csemi3({}, {a,b,c}, [0], [0]), + ok = Csemi3({1,3.5}, {a,b,c}, -1, -1), + ok = Csemi3(dum, {a,b,c}, 0.0, 0.0), + ok = Csemi3(dum, {c}, b, a), + ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0), + ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1), + + ok = Csemi3({45,-19.3}, {}, [], []), + ok = Csemi3({45,-19.3}, {dum}, 42, 42), + ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33), + + ok = Csemi3({45}, {dum}, 1.0, 0), + ok = Csemi3([a], {dum}, 1.0, 0), + ok = Csemi3({dum}, [], 1.0, 0), + ok = Csemi3([], [], 1.0, 0), + ok = Csemi3(blurf, {dum}, 1.0, 0), + ok = Csemi3({a}, blurf, 1.0, 0), + ok = Csemi3([a], [dum], 1.0, 0), + ok = Csemi3({dum}, [], 1.0, 0), + ok = Csemi3([], [], 1.0, 0), + + error = Csemi3({45}, {dum}, 0, 0), + error = Csemi3([a], {dum}, 0, 0), + error = Csemi3({dum}, [], 0, 0), + error = Csemi3([], [], 0, 0), + + ok. + +csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok; +csemi3a(_, _, _, _) -> error. + +csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok; +csemi3b(_, _, _, _) -> error. + +csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok; +csemi3c(_, _, _, _) -> error. + + +csemi4(Test) -> + ok = Test({a,b}, 2, {c,d}, 2), + ok = Test({1,2,3}, 0, [], 0), + ok = Test({}, 2, blurf, 0), + ok = Test({}, 2, {1}, 2), + + error = Test([], 4, {}, 0), + error = Test({}, 0, [a,b], 4), + error = Test({}, 0, [a,b], 0), + error = Test([], 0, {}, 0), + error = Test({}, 0, {}, 0), + + ok. + +csemi4a(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1); + (tuple_size(B) > 1) or (Y > 1) -> ok; +csemi4a(_, _, _, _) -> error. + +csemi4b(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1); + (tuple_size(B) > 1) or (Y > 1) -> ok; +csemi4b(_, _, _, _) -> error. + +csemi4c(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1); + (Y > 1) or (tuple_size(B) > 1) -> ok; +csemi4c(_, _, _, _) -> error. + +csemi4d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1); + (Y > 1) or (tuple_size(B) > 1) -> ok; +csemi4d(_, _, _, _) -> error. + + +csemi4_orelse(Test) -> + ok = Test({a,b}, 2, {c,d}, 2), + ok = Test({1,2,3}, 0, [], 0), + ok = Test({}, 2, blurf, 0), + ok = Test({}, 2, {1}, 2), + + ?line error = Test([], 1, {}, 0), + + ok. + +csemi4_orelse_a(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1); + (tuple_size(B) > 1) orelse (Y > 1) -> ok; +csemi4_orelse_a(_, _, _, _) -> error. + +csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (tuple_size(A) > 1); + (tuple_size(B) > 1) orelse (Y > 1) -> ok; +csemi4_orelse_b(_, _, _, _) -> error. + +csemi4_orelse_c(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1); + (Y > 1) orelse (tuple_size(B) > 1) -> ok; +csemi4_orelse_c(_, _, _, _) -> error. + +csemi4_orelse_d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1); + (Y > 1) or (tuple_size(B) > 1) -> ok; +csemi4_orelse_d(_, _, _, _) -> error. + +csemi5(A, B) when hd([A+B]) > 1; abs(B) > 2 -> ok; +csemi5(_, _) -> error. + +csemi6(A, B) when hd([tuple_size(A)]) > 1; abs(B) > 2 -> ok; +csemi6(_, _) -> error. + +comma(Config) when is_list(Config) -> + + %% ',' combinations of literal true/false. + + ?line check(fun() -> if true, false -> ok; true -> error end end, error), + ?line check(fun() -> if false, true -> ok; true -> error end end, error), + ?line check(fun() -> if true, true -> ok end end, ok), + ?line check(fun() -> if false, false -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if true, false -> ok; + false, true -> ok; + false, false -> ok + end), + exit + end, exit), + + %% ',' combinations of true/false in variables. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True, False -> ok; true -> error end end, error), + ?line check(fun() -> if False, True -> ok; true -> error end end, error), + ?line check(fun() -> if True, True -> ok end end, ok), + ?line check(fun() -> if False, False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, False -> ok; + False, True -> ok; + False, False -> ok + end), + exit + end, exit), + + %% ',' combinations of true/false, and non-boolean in variables. + + Glurf = id(glurf), + + ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error), + ?line check(fun() -> if True, True -> ok end end, ok), + ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, Glurf -> ok; + Glurf, True -> ok; + Glurf, Glurf -> ok + end), + exit + end, exit), + + %% ',' combinations of true/false with errors. + ATuple = id({a,b,c}), + + ?line check(fun() -> if True, element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if element(42, ATuple), True -> ok; + true -> error end end, error), + ?line check(fun() -> if True, True -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, element(42, ATuple) -> ok; + element(42, ATuple), True -> ok; + element(42, ATuple), element(42, ATuple) -> ok + end), + exit + end, exit), + + ok. + +or_guard(Config) when is_list(Config) -> + True = id(true), + False = id(false), + Glurf = id(glurf), + + %% 'or' combinations of literal true/false. + ?line check(fun() -> if true or false -> ok end end, ok), + ?line check(fun() -> if false or true -> ok end end, ok), + ?line check(fun() -> if true or true -> ok end end, ok), + ?line check(fun() -> if false or false -> ok; true -> error end end, error), + + ?line check(fun() -> if glurf or true -> ok; true -> error end end, error), + ?line check(fun() -> if true or glurf -> ok; true -> error end end, error), + ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error), + + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false or false -> ok end), + exit + end, exit), + + + %% 'or' combinations using variables containing true/false. + ?line check(fun() -> if True or False -> ok end end, ok), + ?line check(fun() -> if False or True -> ok end end, ok), + ?line check(fun() -> if True or True -> ok end end, ok), + ?line check(fun() -> if False or False -> ok; true -> error end end, error), + + ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error), + + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False or False -> ok end), + exit + end, exit), + + ok. + +more_or_guards(Config) when is_list(Config) -> + True = id(true), + False = id(false), + ATuple = id({false,true,gurka}), + + ?line check(fun() -> + if element(42, ATuple) or False -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if False or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(18, ATuple) or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if True or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(42, ATuple) or True -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(1, ATuple) or element(42, ATuple) or True -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(1, ATuple) or True or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if + (<<False:8>> == <<0>>) or element(2, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if + element(2, ATuple) or (<<True:8>> == <<1>>) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(2, ATuple) or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if + element(1, ATuple) or + element(2, ATuple) or + element(19, ATuple) -> ok; + true -> error end + end, error), + ok. + +complex_or_guards(Config) when is_list(Config) -> + %% complex_or_1/2 + ?line ok = complex_or_1({a,b,c,d}, {1,2,3}), + ?line ok = complex_or_1({a,b,c,d}, {1}), + ?line ok = complex_or_1({a}, {1,2,3}), + ?line error = complex_or_1({a}, {1}), + + ?line error = complex_or_1(1, 2), + ?line error = complex_or_1([], {a,b,c,d}), + ?line error = complex_or_1({a,b,c,d}, []), + + + %% complex_or_2/1 + ?line ok = complex_or_2({true,{}}), + ?line ok = complex_or_2({false,{a}}), + ?line ok = complex_or_2({false,{a,b,c}}), + ?line ok = complex_or_2({true,{a,b,c,d}}), + + ?line error = complex_or_2({blurf,{a,b,c}}), + + ?line error = complex_or_2({true}), + ?line error = complex_or_2({true,no_tuple}), + ?line error = complex_or_2({true,[]}), + + %% complex_or_3/2 + ?line ok = complex_or_3({true}, {}), + ?line ok = complex_or_3({false}, {a}), + ?line ok = complex_or_3({false}, {a,b,c}), + ?line ok = complex_or_3({true}, {a,b,c,d}), + ?line ok = complex_or_3({false}, <<1,2,3>>), + ?line ok = complex_or_3({true}, <<1,2,3,4>>), + + ?line error = complex_or_3(blurf, {a,b,c}), + + ?line error = complex_or_3({false}, <<1,2,3,4>>), + ?line error = complex_or_3([], <<1,2>>), + ?line error = complex_or_3({true}, 45), + ?line error = complex_or_3(<<>>, <<>>), + + %% complex_or_4/2 + ?line ok = complex_or_4(<<1,2,3>>, {true}), + ?line ok = complex_or_4(<<1,2,3>>, {false}), + ?line ok = complex_or_4(<<1,2,3>>, {true}), + ?line ok = complex_or_4({1,2,3}, {true}), + ?line error = complex_or_4({1,2,3,4}, {false}), + + ?line error = complex_or_4(<<1,2,3,4>>, []), + ?line error = complex_or_4([], {true}), + + %% complex_or_5/2 + ?line ok = complex_or_5(<<1>>, {false}), + ?line ok = complex_or_5(<<1,2,3>>, {true}), + ?line ok = complex_or_5(<<1,2,3,4>>, {false}), + ?line ok = complex_or_5({1,2,3}, {false}), + ?line ok = complex_or_5({1,2,3,4}, {false}), + + ?line error = complex_or_5(blurf, {false}), + ?line error = complex_or_5(<<1>>, klarf), + ?line error = complex_or_5(blurf, klarf), + + %% complex_or_6/2 + ?line ok = complex_or_6({true,true}, {1,2,3,4}), + ?line ok = complex_or_6({true,true}, <<1,2,3,4>>), + ?line ok = complex_or_6({false,false}, <<1,2,3,4>>), + ?line ok = complex_or_6({false,true}, <<1>>), + ?line ok = complex_or_6({true,false}, {1}), + ?line ok = complex_or_6({true,true}, {1}), + + ?line error = complex_or_6({false,false}, {1}), + + ?line error = complex_or_6({true}, {1,2,3,4}), + ?line error = complex_or_6({}, {1,2,3,4}), + ?line error = complex_or_6([], {1,2,3,4}), + ?line error = complex_or_6([], {1,2,3,4}), + ?line error = complex_or_6({true,false}, klurf), + + ok. + +complex_or_1(A, B) -> + if + ((3 < tuple_size(A)) and (tuple_size(A) < 9)) or + ((2 < tuple_size(B)) and (tuple_size(B) < 7)) -> ok; + true -> error + end. + +complex_or_2(Tuple) -> + if + element(1, Tuple) or not (tuple_size(element(2, Tuple)) > 3) -> ok; + true -> error + end. + +complex_or_3(A, B) -> + if + not (size(B) > 3) or element(1, A) -> ok; + true -> error + end. + +complex_or_4(A, B) -> + if + not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok; + true -> error + end. + +complex_or_5(A, B) -> + if + not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok; + true -> error + end. + +complex_or_6(A, B) -> + if + not (not element(1, A) and not element(2, A)) or + not (not (size(B) > 3)) -> ok; + true -> error + end. + +and_guard(Config) when is_list(Config) -> + + %% 'and' combinations of literal true/false. + + ?line check(fun() -> if true and false -> ok; true -> error end end, error), + ?line check(fun() -> if false and true -> ok; true -> error end end, error), + ?line check(fun() -> if true and true -> ok end end, ok), + ?line check(fun() -> if false and false -> ok; true -> error end end, error), + + ?line check(fun() -> if glurf and true -> ok; true -> error end end, error), + ?line check(fun() -> if true and glurf -> ok; true -> error end end, error), + ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error), + + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if true and false -> ok; + false and true -> ok; + false and false -> ok + end), + exit + end, exit), + + %% 'and' combinations of true/false in variables. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True and False -> ok; true -> error end end, error), + ?line check(fun() -> if False and True -> ok; true -> error end end, error), + ?line check(fun() -> if True and True -> ok end end, ok), + ?line check(fun() -> if False and False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and False -> ok; + False and True -> ok; + False and False -> ok + end), + exit + end, exit), + + %% 'and' combinations of true/false and a non-boolean in variables. + + Glurf = id(glurf), + + ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error), + ?line check(fun() -> if True and True -> ok end end, ok), + ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and Glurf -> ok; + Glurf and True -> ok; + Glurf and Glurf -> ok + end), + exit + end, exit), + + %% 'and' combinations of true/false with errors. + ATuple = id({a,b,c}), + + ?line check(fun() -> if True and element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if element(42, ATuple) and True -> ok; + true -> error end end, error), + ?line check(fun() -> if True and True -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and element(42, ATuple) -> ok; + element(42, ATuple) and True -> ok; + element(42, ATuple) and element(42, ATuple) -> ok + end), + exit + end, exit), + + ?line ok = relprod({'Set',a,b}, {'Set',a,b}), + + ok. + +relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') -> + ok. + + +xor_guard(Config) when is_list(Config) -> + + %% 'xor' combinations of literal true/false. + ?line check(fun() -> if true xor false -> ok end end, ok), + ?line check(fun() -> if false xor true -> ok end end, ok), + ?line check(fun() -> if true xor true -> ok; true -> error end end, error), + ?line check(fun() -> if false xor false -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end), + exit + end, exit), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end), + exit + end, exit), + + + %% 'xor' combinations using variables containing true/false. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True xor False -> ok end end, ok), + ?line check(fun() -> if False xor True -> ok end end, ok), + ?line check(fun() -> if True xor True -> ok; true -> error end end, error), + ?line check(fun() -> if False xor False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end), + exit + end, exit), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end), + exit + end, exit), + + ok. + +more_xor_guards(Config) when is_list(Config) -> + True = id(true), + False = id(false), + ATuple = id({false,true,gurka}), + + ?line check(fun() -> + if element(42, ATuple) xor False -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if False xor element(42, ATuple) xor False -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(18, ATuple) xor element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if True xor element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(42, ATuple) xor True -> ok; + true -> error end + end, error), + ok. + +build_in_guard(Config) when is_list(Config) -> + SubBin = <<5.0/float>>, + ?line B = <<1,SubBin/binary,3.5/float>>, + ?line if + B =:= <<1,SubBin/binary,3.5/float>> -> ok + end. + +old_guard_tests(Config) when list(Config) -> + %% Check that all the old guard tests are still recognized. + ?line list = og(Config), + ?line atom = og(an_atom), + ?line binary = og(<<1,2>>), + ?line float = og(3.14), + ?line integer = og(43), + ?line a_function = og(fun() -> ok end), + ?line pid = og(self()), + ?line reference = og(make_ref()), + ?line tuple = og({}), + + ?line number = on(45.333), + ?line number = on(-19), + ok. + +og(V) when atom(V) -> atom; +og(V) when binary(V) -> binary; +og(V) when float(V) -> float; +og(V) when integer(V) -> integer; +og(V) when function(V) -> a_function; +og(V) when list(V) -> list; +og(V) when pid(V) -> pid; +og(V) when port(V) -> port; +og(V) when reference(V) -> reference; +og(V) when tuple(V) -> tuple; +og(_) -> what. + +on(V) when number(V) -> number; +on(_) -> not_number. + +gbif(Config) when is_list(Config) -> + ?line error = gbif_1(1, {false,true}), + ?line ok = gbif_1(2, {false,true}), + ok. + +gbif_1(P, T) when element(P, T) -> ok; +gbif_1(_, _) -> error. + + +t_is_boolean(Config) when is_list(Config) -> + ?line true = is_boolean(true), + ?line true = is_boolean(false), + ?line true = is_boolean(id(true)), + ?line true = is_boolean(id(false)), + + ?line false = is_boolean(glurf), + ?line false = is_boolean(id(glurf)), + + ?line false = is_boolean([]), + ?line false = is_boolean(id([])), + ?line false = is_boolean(42), + ?line false = is_boolean(id(-42)), + + ?line false = is_boolean(math:pi()), + ?line false = is_boolean(384793478934378924978439789873478934897), + + ?line false = is_boolean(id(self())), + ?line false = is_boolean(id({x,y,z})), + ?line false = is_boolean(id([a,b,c])), + ?line false = is_boolean(id(make_ref())), + ?line false = is_boolean(id(<<1,2,3>>)), + ?line false = is_boolean({id(x),y,z}), + ?line false = is_boolean([id(a),b,c]), + + ?line ok = bool(true), + ?line ok = bool(false), + ?line ok = bool(id(true)), + ?line ok = bool(id(false)), + + ?line error = bool(glurf), + ?line error = bool(id(glurf)), + + ?line error = bool([]), + ?line error = bool(id([])), + ?line error = bool(42), + ?line error = bool(id(-42)), + + ?line error = bool(math:pi()), + ?line error = bool(384793478934378924978439789873478934897), + + ?line error = bool(id(self())), + ?line error = bool(id({x,y,z})), + ?line error = bool(id([a,b,c])), + ?line error = bool(id(make_ref())), + ?line error = bool(id(<<1,2,3>>)), + + ?line true = my_is_bool(true), + ?line true = my_is_bool(false), + ?line false = my_is_bool([]), + ?line false = my_is_bool([1,2,3,4]), + ?line false = my_is_bool({a,b,c}), + + ok. + +bool(X) when is_boolean(X) -> ok; +bool(_) -> error. + +my_is_bool(V) -> + Res = my_is_bool_a(V), + Res = my_is_bool_b(V). + +my_is_bool_a(V) -> + case V of + true -> true; + false -> true; + _ -> false + end. + +my_is_bool_b(V) -> + case V of + false -> true; + true -> true; + _ -> false + end. + +is_function_2(Config) when is_list(Config) -> + true = is_function(id(fun ?MODULE:all/1), 1), + true = is_function(id(fun() -> ok end), 0), + false = is_function(id(fun ?MODULE:all/1), 0), + false = is_function(id(fun() -> ok end), 1), + + F = fun(_) -> ok end, + if + is_function(F, 1) -> ok + end. + +tricky(Config) when is_list(Config) -> + ?line not_ok = tricky_1(1, 2), + ?line not_ok = tricky_1(1, blurf), + ?line not_ok = tricky_1(foo, 2), + ?line not_ok = tricky_1(a, b), + + ?line error = tricky_2(0.5), + ?line error = tricky_2(a), + ?line error = tricky_2({a,b,c}), + + ?line false = rb(100000, [1], 42), + ?line true = rb(100000, [], 42), + ?line true = rb(555, [a,b,c], 19), + ok. + +tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok; +tricky_1(_, _) -> not_ok. + +tricky_2(X) when float(X) or float(X) -> ok; +tricky_2(_) -> error. + +%% From dets_v9:read_buckets/11, simplified. + +rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true; +rb(_, _, _) -> false. + + +-define(T(Op,A,B), + ok = if A Op B -> ok; true -> error end, + ok = if not (A Op B) -> error; true -> ok end, + (fun(X, Y, True, False) -> + ok = if X Op Y -> ok; true -> error end, + ok = if False; X Op Y; False -> ok; true -> error end, + ok = if X Op Y, True -> ok; true -> error end, + ok = if not (X Op Y) -> error; true -> ok end, + ok = if False; not (X Op Y); False -> error; true -> ok end + end)(id(A), id(B), id(true), id(false))). + +-define(F(Op,A,B), + ok = if A Op B -> error; true -> ok end, + ok = if not (A Op B) -> ok; true -> error end, + (fun(X, Y, True, False) -> + ok = if X Op Y -> error; true -> ok end, + ok = if False; X Op Y; False -> error; true -> ok end, + ok = if not (X Op Y); False -> ok; true -> error end, + ok = if not (X Op Y), True -> ok; true -> error end + end)(id(A), id(B), id(true), id(false))). + + +rel_ops(Config) when is_list(Config) -> + ?line ?T(=/=, 1, 1.0), + ?line ?F(=/=, 2, 2), + ?line ?F(=/=, {a}, {a}), + + ?line ?F(/=, a, a), + ?line ?F(/=, 0, 0.0), + ?line ?T(/=, 0, 1), + ?line ?F(/=, {a}, {a}), + + ?line ?T(==, 1, 1.0), + ?line ?F(==, a, {}), + + ?line ?F(=:=, 1, 1.0), + ?line ?T(=:=, 42.0, 42.0), + + ?line ?F(>, a, b), + ?line ?T(>, 42, 1.0), + ?line ?F(>, 42, 42.0), + + ?line ?T(<, a, b), + ?line ?F(<, 42, 1.0), + ?line ?F(<, 42, 42.0), + + ?line ?T(=<, 1.5, 5), + ?line ?F(=<, -9, -100.344), + ?line ?T(=<, 42, 42.0), + + ?line ?T(>=, 42, 42.0), + ?line ?F(>=, a, b), + ?line ?T(>=, 1.0, 0), + + %% Coverage of beam_block:is_exact_eq_ok/1 and collect/1. + ?line true = any_atom /= id(42), + ?line true = [] /= id(42), + + ok. + +-undef(TestOp). + + +%% Test type tests on literal values. (From emulator test suites.) +literal_type_tests(Config) when is_list(Config) -> + case ?MODULE of + guard_SUITE -> literal_type_tests_1(Config); + _ -> {skip,"Enough to run this case once."} + end. + +literal_type_tests_1(Config) -> + %% Generate an Erlang module with all different type of type tests. + ?line Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++ + [{is_function,L1,L2} || + L1 <- literals(), L2 <- 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 smoke_disasm(Config, Mod, Code1), + ?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 smoke_disasm(Config, Mod, Code2), + ?line {module,Mod} = code:load_binary(Mod, Mod, Code2), + ?line Mod:test(), + ?line true = code:delete(Mod), + ?line code:purge(Mod), + ok. + +make_test([{T,L1,L2}|Ts]) -> + [test(T, L1, L2)|make_test(Ts)]; +make_test([{T,L}|Ts]) -> + [test(T, L)|make_test(Ts)]; +make_test([]) -> []. + +test(T, L) -> + S0 = io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T,L,T,L]), + S = lists:flatten(S0), + {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, L1, L2) -> + S0 = io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ", [T,L1,L2,T,L1,L2]), + S = lists:flatten(S0), + {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)}. + +smoke_disasm(Config, Mod, Bin) -> + Priv = ?config(priv_dir, Config), + File = filename:join(Priv, atom_to_list(Mod)++".beam"), + ok = file:write_file(File, Bin), + test_lib:smoke_disasm(File). + +literals() -> + [42, + 3.14, + -3, + 32982724987789283473473838474, + [], + xxxx, + {a,b,c}, + [a,list], + <<1,2,3>>, + <<42:17>>]. + +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]. + +basic_andalso_orelse(Config) when is_list(Config) -> + ?line T = id({type,integers,23,42}), + ?line 65 = if + ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso + element(2, T)) == integers -> + element(3, T) + element(4, T); + true -> error + end, + ?line 65 = case [] of + [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso + element(2, T)) == integers -> + element(3, T) + element(4, T) + end, + + ?line 42 = basic_rt({type,integers,40,2}), + ?line 5.0 = basic_rt({vector,{3.0,4.0}}), + ?line 20 = basic_rt(['+',3,7]), + ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}), + ?line 12 = basic_rt({klurf,4}), + + ?line error = basic_rt({type,integers,40,2,3}), + ?line error = basic_rt({kalle,integers,40,2}), + ?line error = basic_rt({kalle,integers,40,2}), + ?line error = basic_rt({1,2}), + ?line error = basic_rt([]), + + RelProdBody = + fun(R1, R2) -> + if + (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'), + (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') -> + ok + end + end, + + ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}), + + %% 'andalso'/'orelse' with calls known to fail already at compile time. + %% Used to crash the code generator. + error = (fun() -> + R = {vars,true}, + if + is_record(R, vars, 2) andalso element(99, R) -> ok; + true -> error + end + end)(), + error = (fun(X) -> + L = {a,b,c}, + if + is_list(X) andalso length(L) > 4 -> ok; + true -> error + end + end)([]), + ok. + +basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 4 andalso element(1, T) =:= type andalso + element(2, T) == integers -> + element(3, T) + element(4, T); +basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= vector -> + {X,Y} = element(2, T), + if + is_float(X), is_float(Y) -> + math:sqrt(X*X+Y*Y) + end; +basic_rt(['+',A,B]) -> + 2*id(A+B); +basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set', + erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' -> + R1 = id(R1), + R2 = id(R2), + R1; +basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= klurf -> + 3*id(element(2, T)); +basic_rt(_) -> + error. + +traverse_dcd(Config) when is_list(Config) -> + L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c}, + {log_header,dcd_log,"0.0",a,b,c},blurf], + {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} = + traverse_dcd({cont,L0}, log, funny), + L1 = [{log_header,dcd_log,"1.0"}], + {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny), + L2 = [{a,tuple}], + {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny), + ok. + +%% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}. +%% The outer match of a two tuple will places the first element in {x,3} and +%% second in {x,4}. The guard for the first clause must make ensure that all of those +%% registers are restored before entering the second clause. +%% +%% (From mnesia_checkpoint.erl, modified.) + +traverse_dcd({Cont,[LogH|Rest]},Log,Fun) + when is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header +andalso erlang:element(2,LogH) == dcd_log, +is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header +andalso erlang:element(3,LogH) >= "1.0" -> + traverse_dcd({Cont,Rest},Log,Fun); +traverse_dcd({Cont,Recs},Log,Fun) -> + {Cont,Recs,Log,Fun}. + + +check_qlc_hrl(Config) when is_list(Config) -> + St = {r1,false,dum}, + ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St), + ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St), + ?line St = cqlc(qlc, q, [], St), + ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St), + ?line St = cqlc(q, q, [{lc,1,2,3},b], St), + ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St), + ?line St = cqlc(qlc, q, [a,b], St), + ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}), + ok. + +%% From erl_lint.erl; original name was check_qlc_hrl/4. +cqlc(M, F, As, St) -> + Arity = length(As), + case As of + [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q, + Arity < 3, + not (((element(1, St) =:= r1) orelse fail) and (tuple_size(St) =:= 3) and element(2, St)) -> + foo; + _ -> + St + end. + +%% OTP-7679: Thanks to Hunter Morris. +andalso_semi(Config) when is_list(Config) -> + ?line ok = andalso_semi_foo(0), + ?line ok = andalso_semi_foo(1), + ?line {'EXIT',{function_clause,_}} = (catch andalso_semi_foo(2)), + + ?line ok = andalso_semi_bar([a,b,c]), + ?line ok = andalso_semi_bar(1), + ?line {'EXIT',{function_clause,_}} = (catch andalso_semi_bar([a,b])), + ok. + +andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 -> + ok. + +andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 -> + ok. + + +tuple_size(Config) when is_list(Config) -> + ?line 10 = do_tuple_size({1,2,3,4}), + ?line {'EXIT',{function_clause,_}} = (catch do_tuple_size({1,2,3})), + ?line {'EXIT',{function_clause,_}} = (catch do_tuple_size(42)), + + ?line error = ludicrous_tuple_size({a,b,c}), + ?line error = ludicrous_tuple_size([a,b,c]), + + %% Test the "unsafe case" - the register assigned the tuple size is + %% not killed. + ?line DataDir = test_lib:get_data_dir(Config), + ?line File = filename:join(DataDir, "guard_SUITE_tuple_size"), + ?line {ok,Mod,Code} = compile:file(File, [from_asm,binary]), + ?line code:load_binary(Mod, File, Code), + ?line 14 = Mod:t({1,2,3,4}), + + ok. + +do_tuple_size(T) when tuple_size(T) =:= 4 -> + {A,B,C,D} = T, + A+B+C+D. + +ludicrous_tuple_size(T) + when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok; +ludicrous_tuple_size(T) + when tuple_size(T) =:= 16#10000000000000000 -> ok; +ludicrous_tuple_size(T) + when tuple_size(T) =:= (1 bsl 64) - 1 -> ok; +ludicrous_tuple_size(T) + when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok; +ludicrous_tuple_size(_) -> error. + + +%% Call this function to turn off constant propagation. +id(I) -> I. + +check(F, Result) -> + case F() of + Result -> ok; + Other -> + io:format("Expected: ~p\n", [Result]), + io:format(" Got: ~p\n", [Other]), + test_server:fail() + end. diff --git a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S new file mode 100644 index 0000000000..c0bf04ed8f --- /dev/null +++ b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S @@ -0,0 +1,30 @@ +{module, guard_SUITE_tuple_size}. %% version = 0 + +{exports, [{t,1}]}. + +{attributes, []}. + +{labels, 5}. + + +{function, t, 1, 2}. + {label,1}. + {func_info,{atom,guard_SUITE_tuple_size},{atom,t},1}. + {label,2}. + {bif,tuple_size,{f,4},[{x,0}],{x,1}}. + {test,is_eq_exact,{f,4},[{x,1},{integer,4}]}. + {test,is_tuple,{f,3},[{x,0}]}. + {test,test_arity,{f,3},[{x,0},4]}. + {get_tuple_element,{x,0},0,{x,5}}. + {get_tuple_element,{x,0},1,{x,2}}. + {get_tuple_element,{x,0},2,{x,3}}. + {get_tuple_element,{x,0},3,{x,4}}. + {gc_bif,'+',{f,0},5,[{x,1},{x,2}],{x,0}}. + {gc_bif,'+',{f,0},5,[{x,0},{x,3}],{x,0}}. + {gc_bif,'+',{f,0},5,[{x,0},{x,4}],{x,0}}. + {gc_bif,'+',{f,0},5,[{x,0},{x,5}],{x,0}}. + return. + {label,3}. + {badmatch,{x,0}}. + {label,4}. + {jump,{f,1}}. diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl new file mode 100644 index 0000000000..396fb450b7 --- /dev/null +++ b/lib/compiler/test/inline_SUITE.erl @@ -0,0 +1,280 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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% +%% +%%% Purpose : Tests inlining. + +-module(inline_SUITE). + +-include("test_server.hrl"). + +-compile(export_all). +-compile({inline,[badarg/2]}). + +%% Needed by test case `lists'. +-compile(inline_list_funcs). + +all(suite) -> + test_lib:recompile(?MODULE), + [attribute,bsdecode,bsdes,barnes2,decode1,smith,itracer,pseudoknot,lists, + really_inlined,otp_7223,coverage]. + +attribute(Config) when is_list(Config) -> + Name = "attribute", + ?line Src = filename:join(?config(data_dir, Config), Name), + ?line Out = ?config(priv_dir,Config), + + ?line {ok,attribute=Mod} = compile:file(Src, [{outdir,Out},report,time]), + ?line Outfile = filename:join(Out, Name++".beam"), + ?line {ok,{Mod,[{locals,Locals}]}} = beam_lib:chunks(Outfile, [locals]), + ?line io:format("locals: ~p\n", [Locals]), + + %% The inliner should have removed all local functions. + ?line [] = Locals, + + ok. + +-define(comp(Name), + Name(Config) when list(Config) -> + try_inline(Name, Config)). + +?comp(bsdecode). +?comp(bsdes). +?comp(barnes2). +?comp(decode1). +?comp(smith). +?comp(itracer). +?comp(pseudoknot). + +try_inline(Mod, Config) -> + ?line Src = filename:join(?config(data_dir, Config), atom_to_list(Mod)), + ?line Out = ?config(priv_dir,Config), + + %% Normal compilation. + ?line io:format("Compiling: ~s\n", [Src]), + ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]), + + ?line Dog = test_server:timetrap(test_server:minutes(10)), + ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)), + ?line {ok,Node} = start_node(compiler, Pa), + ?line NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), + ?line test_server:timetrap_cancel(Dog), + + %% Inlining. + ?line io:format("Compiling with old inliner: ~s\n", [Src]), + ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info, + {inline,1000},clint]), + + %% Run inlined code. + ?line Dog3 = test_server:timetrap(test_server:minutes(10)), + ?line OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), + ?line test_server:timetrap_cancel(Dog3), + + %% Compare results. + ?line compare(NormalResult, OldInlinedResult), + ?line NormalResult = OldInlinedResult, + + %% Inlining. + ?line io:format("Compiling with new inliner: ~s\n", [Src]), + ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report, + bin_opt_info,inline,clint]), + + %% Run inlined code. + ?line Dog4 = test_server:timetrap(test_server:minutes(10)), + ?line InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), + ?line test_server:timetrap_cancel(Dog4), + + %% Compare results. + ?line compare(NormalResult, InlinedResult), + ?line NormalResult = InlinedResult, + + %% Delete Beam file. + ?line ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())), + + ?line ?t:stop_node(Node), + ok. + +compare(Same, Same) -> ok; +compare([Same|T1], [Same|T2]) -> + compare(T1, T2); +compare([{X,Y,RGB1}|T1], [{X,Y,RGB2}|T2]) -> + io:format("X = ~p, Y = ~p, RGB normal = ~p, RGB inlined ~p\n", [X,Y,RGB1,RGB2]), + compare(T1, T2); +compare([H1|_], [H2|_]) -> + io:format("Normal = ~p, Inlined = ~p\n", [H1,H2]), + ?t:fail(); +compare([], []) -> ok. + +start_node(Name, Args) -> + case test_server:start_node(Name, slave, [{args,Args}]) of + {ok,Node} -> {ok, Node}; + Error -> ?line test_server:fail(Error) + end. + +load_and_call(Out, Module) -> + ?line io:format("Loading...\n",[]), + ?line code:purge(Module), + ?line LoadRc = code:load_abs(filename:join(Out, Module)), + ?line {module,Module} = LoadRc, + + ?line io:format("Calling...\n",[]), + ?line {Time,CallResult} = timer:tc(Module, Module, []), + ?line io:format("Time: ~p\n", [Time]), + CallResult. + +%% Macros used by lists/1 below. + +-define(TestHighOrder_2(Name, Body, List), + begin + put(?MODULE, []), + (fun({Res,Res2}) -> + {Res,Res2} = my_apply(lists, Name, [Body,List], []) + end)(begin + (fun(R) -> + {R,get(?MODULE)} + end)(lists:Name(Body, List)) + end) + end). + +-define(TestHighOrder_3(Name, Body, Init, List), + begin + put(?MODULE, []), + (fun({Res,Res2}) -> + {Res,Res2} = my_apply(lists, Name, [Body,Init,List], []) + end)(begin + (fun(R) -> + {R,get(?MODULE)} + end)(lists:Name(Body, Init, List)) + end) + end). + +%% For each high order function in the lists module, verify +%% that the inlined version produces the same result and is evaluated +%% in the same order as the function in the lists module. +%% +%% Note: This module must be compiled with the inline_lists_funcs option. + +lists(Config) when is_list(Config) -> + ?line List = lists:seq(1, 20), + + %% lists:map/2 + ?line ?TestHighOrder_2(map, (fun(E) -> + R = E band 16#ff, + put(?MODULE, [E|get(?MODULE)]), + R + end), List), + + %% lists:flatmap/2 + ?line ?TestHighOrder_2(flatmap, (fun(E) -> + R = lists:duplicate(E, E), + put(?MODULE, [E|get(?MODULE)]), + R + end), List), + + %% lists:foreach/2 + ?line ?TestHighOrder_2(foreach, + (fun(E) -> + put(?MODULE, [E bor 7|get(?MODULE)]) + end), List), + + %% lists:filter/2 + ?line ?TestHighOrder_2(filter, (fun(E) -> + put(?MODULE, [E|get(?MODULE)]), + (E bsr 1) band 1 =/= 0 + end), List), + + %% lists:any/2 + ?line ?TestHighOrder_2(any, (fun(E) -> + put(?MODULE, [E|get(?MODULE)]), + false %Force it to go through all. + end), List), + + %% lists:all/2 + ?line ?TestHighOrder_2(all, (fun(E) -> + put(?MODULE, [E|get(?MODULE)]), + true %Force it to go through all. + end), List), + + %% lists:foldl/3 + ?line ?TestHighOrder_3(foldl, (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + A bxor E + end), 0, List), + + %% lists:foldr/3 + ?line ?TestHighOrder_3(foldr, (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + A bxor (bnot E) + end), 0, List), + + %% lists:mapfoldl/3 + ?line ?TestHighOrder_3(mapfoldl, (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + {bnot E,A bxor (bnot E)} + end), 0, List), + + %% lists:mapfoldr/3 + ?line ?TestHighOrder_3(mapfoldr, (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + {bnot E,A bxor (bnot E)} + end), 0, List), + + %% Cleanup. + erase(?MODULE), + ok. + +my_apply(M, F, A, Init) -> + put(?MODULE, Init), + Res = apply(M, F, A), + {Res,get(?MODULE)}. + +really_inlined(Config) when is_list(Config) -> + %% Make sure that badarg/2 really gets inlined. + {'EXIT',{badarg,[{?MODULE,fail_me_now,[]}|_]}} = (catch fail_me_now()), + ok. + +fail_me_now() -> + badarg(foo(bar), []). + +foo(_X) -> + badarg. + +%% Inlined. +badarg(badarg, A) -> + erlang:error(badarg, A); +badarg(Reply, _A) -> + Reply. + +otp_7223(Config) when is_list(Config) -> + ?line {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)), + ok. + +-compile({inline,[{otp_7223_1,1}]}). +otp_7223_1(X) -> + otp_7223_2(X). + +-compile({inline,[{otp_7223_2,1}]}). +otp_7223_2({a}) -> + 1. + +coverage(Config) when is_list(Config) -> + ?line Src = filename:join(?config(data_dir, Config), bsdecode), + ?line Out = ?config(priv_dir,Config), + ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,{inline,0},clint]), + ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,{inline,20},verbose,clint]), + ?line ok = file:delete(filename:join(Out, "bsdecode"++code:objfile_extension())), + ok. diff --git a/lib/compiler/test/inline_SUITE_data/attribute.erl b/lib/compiler/test/inline_SUITE_data/attribute.erl new file mode 100644 index 0000000000..961086a888 --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/attribute.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(attribute). +-export([test/1]). +-compile(inline). + +%% If -compile(inline) above is recognized, the local function add/2 +%% will not be present in the Beam file. + +test(X) -> add(X, 2). + +add(X, Y) -> X+Y. + + + diff --git a/lib/compiler/test/inline_SUITE_data/barnes2.erl b/lib/compiler/test/inline_SUITE_data/barnes2.erl new file mode 100644 index 0000000000..a986331060 --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/barnes2.erl @@ -0,0 +1,160 @@ +% file: "barnes.erl" + +-module(barnes2). +-export([?MODULE/0]). + +?MODULE() -> + Stars = create_scenario(1000, 1.0), + R = hd(loop(10,1000.0,Stars,0)), + Str = lists:flatten(io:lib_format("~s", [R])), + {R,Str =:= {1.00000,-1.92269e+4,-1.92269e+4,2.86459e-2,2.86459e-2}}. + +create_scenario(N, M) -> + create_scenario0(0, 0, trunc(math:sqrt(N)), M). + +create_scenario0(_X, _SN, _SN, _M) -> + []; +create_scenario0(SN, Y, SN, M) -> + create_scenario0(0, Y+1, SN, M); +create_scenario0(X, Y, SN, M) -> + XPos0 = (((20000.0 * 2) / SN) * X) - 20000.0, + YPos0 = (((20000.0 * 2) / SN) * Y) - 20000.0, + Calibrate = ((20000.0 * 2) / SN) / 2, + XPos = XPos0 + Calibrate, + YPos = YPos0 + Calibrate, + [{M, XPos, YPos, 0.0, 0.0} | create_scenario0(X+1, Y, SN, M)]. + +relpos_to_quadrant(DX, DY) when DX >= 0 -> + if + DY >= 0 -> 0; + true -> 3 + end; +relpos_to_quadrant(_, DY) -> + if + DY >= 0 -> 1; + true -> 2 + end. + +quadrant_to_dx(0, D) -> D; +quadrant_to_dx(1, D) -> -D; +quadrant_to_dx(2, D) -> -D; +quadrant_to_dx(3, D) -> D. + +quadrant_to_dy(Q,D) -> + if + Q < 2 -> D; + true -> -D + end. + +create_tree(Stars) -> + create_tree0(Stars, empty). + +create_tree0([],Tree) -> + Tree; +create_tree0([{M,X,Y,_,_} | Stars], Tree) -> + create_tree0(Stars, insert_tree_element(Tree, M, X, Y, 0.0, 0.0, 20000.0)). + +insert_tree_element(empty, M, X, Y, _OX, _OY, _D) -> + {body,M,X,Y}; +insert_tree_element({branch,M0,SubTree}, M, X, Y, OX, OY, D) -> + Q = relpos_to_quadrant(X-OX,Y-OY), + D2 = D / 2, + DX = quadrant_to_dx(Q,D2), + DY = quadrant_to_dy(Q,D2), + {branch,M0+M,setelement(Q+1,SubTree, + insert_tree_element(element(Q+1,SubTree), + M, X, Y, OX+DX, OY+DY,D2))}; +insert_tree_element({body,M0,X0,Y0},M,X,Y,OX,OY,D) -> + resolve_body_conflict(M,X,Y,M0,X0,Y0,OX,OY,D). + +resolve_body_conflict(M0, X0, Y0, M1, X1, Y1, OX, OY, D) -> + T = {empty,empty,empty,empty}, + Q0 = relpos_to_quadrant(X0-OX,Y0-OY), + Q1 = relpos_to_quadrant(X1-OX,Y1-OY), + D2 = D / 2, + if + Q0 == Q1 -> DX = quadrant_to_dx(Q0,D2), + DY = quadrant_to_dy(Q1,D2), + {branch,M0+M1,setelement(Q0+1,T, + resolve_body_conflict(M0,X0,Y0, + M1,X1,Y1, + OX+DX,OY+DY, + D2))} ; + true -> {branch,M0+M1, setelement(Q1+1, + setelement(Q0+1,T,{body,M0,X0,Y0}), + {body,M1,X1,Y1})} + end. + +compute_acceleration(empty, _, _, _, _, _,L) -> + {{0.0, 0.0},L+1}; +compute_acceleration({body,BM,BX,BY}, _D, _OX, _OY, X, Y,L) -> + DX = BX - X, + DY = BY - Y, + R2 = (DX * DX) + (DY * DY), + Divisor = R2 * math:sqrt(R2), + if + Divisor < 0.000001 -> % was: Divisor < ?EPSILON -> + {{0.0, 0.0},L+1}; + true -> + Expr = BM / Divisor, + {{DX * Expr, DY * Expr},L+1} + end; +compute_acceleration({branch,M,SubTree}, D, OX, OY, X, Y,L) -> + DX = OX - X, + DY = OY - Y, + R2 = (DX * DX) + (DY * DY), + DD = D*D, + R2_THETA2 = 0.09 * R2, % TRY 2.0 *R2, !!! was: R2_THETA2 = ?THETA2*R2, + if + % Ok to approximate? + DD < R2_THETA2 -> + Divisor = R2 * math:sqrt(R2), + if + Divisor < 0.000001 -> + {{0.0,0.0},L}; + true -> + Expr = M / Divisor, + {{DX*Expr, DY*Expr},L+1} + end; + % Not ok to approximate... + true -> + D2 = D / 2, + {{AX0, AY0},L1} = compute_acceleration(element(1,SubTree), + D2, OX + quadrant_to_dx(0,D2), + OY + quadrant_to_dy(0,D2),X,Y,L), + {{AX1, AY1},L2} = compute_acceleration(element(2,SubTree), + D2, OX + quadrant_to_dx(1,D2), + OY + quadrant_to_dy(1,D2),X,Y,L1), + {{AX2, AY2},L3} = compute_acceleration(element(3,SubTree), + D2,OX + quadrant_to_dx(2,D2), + OY + quadrant_to_dy(2,D2),X,Y,L2), + {{AX3, AY3},L4} = compute_acceleration(element(4,SubTree), + D2, OX + quadrant_to_dx(3,D2), + OY + quadrant_to_dy(3,D2),X,Y,L3), + {{AX0+AX1+AX2+AX3, AY0+AY1+AY2+AY3},L4+1} + end. + +compute_star_accelerations(_Tree,[],L) -> + {[],L}; +compute_star_accelerations(Tree,[{_,X, Y,_,_}|Stars],L) -> + {A,AL} = compute_acceleration(Tree, 20000.0, 0.0, 0.0, X, Y,L), + {B,BL} = compute_star_accelerations(Tree, Stars,AL), + {[A | B],BL}. + +compute_next_state([],_,_) -> + []; +compute_next_state([{M,X,Y,VX,VY}|Stars],[{AX,AY}|Accs],Time) -> + VX0 = VX + (AX * Time), + VY0 = VY + (AY * Time), + [{M,X+(VX*Time),Y+(VY*Time),VX0,VY0} | compute_next_state(Stars,Accs,Time)]. + +advance_time(Time,Stars,L) -> + Tree = create_tree(Stars), + {Acc,NL} = compute_star_accelerations(Tree, Stars,L), + {compute_next_state(Stars, Acc, Time),NL}. + +loop(0,_Time,Stars,_L) -> + Stars; +loop(N,Time,Stars,L) -> + {NS,NL} = advance_time(Time,Stars,L), + loop(N-1,Time,NS,NL). diff --git a/lib/compiler/test/inline_SUITE_data/bsdecode.erl b/lib/compiler/test/inline_SUITE_data/bsdecode.erl new file mode 100644 index 0000000000..ae134ad02e --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/bsdecode.erl @@ -0,0 +1,1188 @@ +%% +%% %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(bsdecode). +-export([?MODULE/0]). + +-record(protocolErrors, {invalidManIE = false, + outOfSequence = false, + incorrectOptIE = false}). + +-record(mvsT_msisdn, {value}). + + +-record(mvsgT_pdpAddressType, {pdpTypeNbr, + address}). + +-record(mvsgT_ipAddress, {version, + a1, + a2, + a3, + a4, + a5, + a6, + a7, + a8}). + +-record(mvsgT_imsi, {value}). + +-record(mvsgT_tid, {imsi, + nsapi}). + +-record(sesT_qualityOfServiceV0, {delayClass, + reliabilityClass, + peakThroughput, + precedenceClass, + meanThroughput}). + +-record(sesT_deleteReqV0, {tid}). + +-record(sesT_deleteResV0, {tid, + cause}). + +-record(sesT_createReqV0, {tid, + tidRaw, + qos, + recovery, + selMode, + flowLblData, + flowLblSig, + endUserAdd, + accPointName, + protConOpt, + sgsnAddSig, + sgsnAddUser, + msisdn}). + +-record(sesT_updateReqV0, {tid, + tidRaw, + qos, + recovery, + flowLblData, + flowLblSig, + sgsnAddSig, + sgsnAddUser}). + +-record(masT_ipcpData, {type, + ipAddress, + rawMessage}). + +-record(masT_ipcp, {exists, + code, + id, + ipcpList}). + +-record(masT_pap, {exists, + code, + id, + username, + password}). + +-record(masT_chap, {code, + id, + value, + name}). + +-record(masT_protocolConfigOptions, {chap, + pap, + ipcp}). + +?MODULE() -> + Res = test(), + {Res,Res =:= + {ok,{sesT_createReqV0,{mvsgT_tid,{mvsgT_imsi,<<81,67,101,7,0,0,0,240>>},6}, + [81,67,101,7,0,0,0,96], + {sesT_qualityOfServiceV0,1,4,9,2,18},0, + subscribed,0,0,{mvsgT_pdpAddressType,ietf_ipv4,[]}, + [<<97,112,110,48,49,51,97>>,<<101,114,105,99,115,115,111,110>>,<<115,101>>], + {masT_protocolConfigOptions,[], + {masT_pap,true,1,5,[117,115,101,114,53],[112,97,115,115,53]},[]}, + {mvsgT_ipAddress,ipv4,172,28,12,1,0,0,0,0}, + {mvsgT_ipAddress,ipv4,172,28,12,3,0,0,0,0}, + {mvsT_msisdn,<<145,148,113,129,0,0,0,0>>}},1}}. + +test() -> + Pdu = <<30, + 16, + 0, + 90, + 0, + 1, + 0, + 0, + 255, + 255, + 255, + 255, + 81, + 67, + 101, + 7, + 0, + 0, + 0, + 96, + 6, + 12, + 146, + 18, + 14, + 0, + 15, + 252, + 16, + 0, + 0, + 17, + 0, + 0, + 128, + 0, + 2, + 241, + 33, + 131, + 0, + 20, + 7, + 97, + 112, + 110, + 48, + 49, + 51, + 97, + 8, + 101, + 114, + 105, + 99, + 115, + 115, + 111, + 110, + 2, + 115, + 101, + 132, + 0, + 20, + 128, + 192, + 35, + 16, + 1, + 5, + 0, + 16, + 5, + 117, + 115, + 101, + 114, + 53, + 5, + 112, + 97, + 115, + 115, + 53, + 133, + 0, + 4, + 172, + 28, + 12, + 1, + 133, + 0, + 4, + 172, + 28, + 12, + 3, + 134, + 0, + 8, + 145, + 148, + 113, + 129, + 0, + 0, + 0, + 0>>, + decode_v0_opt(10,Pdu). + +decode_v0_opt(0,Pdu) -> + decode_gtpc_msg(Pdu); +decode_v0_opt(N,Pdu) -> + decode_gtpc_msg(Pdu), + decode_v0_opt(N - 1,Pdu). + +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 16:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + InformationElements/binary>>) -> + Errors = #protocolErrors{}, + {ok,TID2} = tid_internal_storage(TID,[]), + EmptyCreateReq = #sesT_createReqV0{tid = TID2, + tidRaw = binary_to_list(TID)}, + case catch decode_ie_create(InformationElements,0,Errors,EmptyCreateReq) of + {ok,CreateReq} -> + {ok,CreateReq,SequenceNumber}; + {fault,Cause,CreateReq} -> + {fault,Cause,CreateReq,SequenceNumber}; + {'EXIT',_Reason} -> + {fault,193,EmptyCreateReq,SequenceNumber} + end; +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 18:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + InformationElements/binary>>) -> + io:format("hej",[]), + Errors = #protocolErrors{}, + {ok,TID2} = tid_internal_storage(TID,[]), + EmptyUpdateReq = #sesT_updateReqV0{tid = TID2, + tidRaw = binary_to_list(TID)}, + case catch decode_ie_update(InformationElements,0,Errors,EmptyUpdateReq) of + {ok,UpdateReq} -> + {ok,UpdateReq,SequenceNumber}; + {fault,Cause,UpdateReq} -> + {fault,Cause,UpdateReq,SequenceNumber}; + {'EXIT',Reason} -> + io:format("hej",[]), + {fault,193,EmptyUpdateReq,SequenceNumber,Reason} + end; +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 20:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + _InformationElements/binary>>) -> + {ok,TID2} = tid_internal_storage(TID,[]), + DeleteReq = #sesT_deleteReqV0{tid = TID2}, + {ok,DeleteReq,SequenceNumber}; +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 21:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + InformationElements/binary>>) -> + Errors = #protocolErrors{}, + {ok,TID2} = tid_internal_storage(TID,[]), + EmptyDeleteRes = #sesT_deleteResV0{tid = TID2}, + case catch decode_ie_delete_res(InformationElements,0,Errors,EmptyDeleteRes) of + {ok,DeleteRes} -> + {ok,DeleteRes,SequenceNumber}; + {fault,Cause,DeleteRes} -> + {fault,Cause,DeleteRes,SequenceNumber}; + {'EXIT',_Reason} -> + {fault,193,EmptyDeleteRes,SequenceNumber} + end; +decode_gtpc_msg(_GTP_C_Message) -> + {fault}. + +decode_ie_create(<<>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 1917 /= 1917 -> + {fault,202,CreateReq}; + true -> + case Errors of + #protocolErrors{invalidManIE = true} -> + {fault,201,CreateReq}; + #protocolErrors{outOfSequence = true} -> + {fault,193,CreateReq}; + #protocolErrors{incorrectOptIE = true} -> + {fault,203,CreateReq}; + _ -> + {ok,CreateReq} + end + end; +decode_ie_create(<<6:8, + QoSElement:3/binary-unit:8, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 1 == 1 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 1 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{qos = QoS}, + decode_ie_create(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedCreateReq); + true -> + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{qos = QoS}, + decode_ie_create(Rest,PresentIEs bor 1,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<14:8, + Recovery:8, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 2 == 2 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 2 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{recovery = Recovery}, + decode_ie_create(Rest,PresentIEs bor 2,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{recovery = Recovery}, + decode_ie_create(Rest,PresentIEs bor 2,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<15:8, + _:6, + SelectionMode:2, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 4 == 4 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 4 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{selMode = selection_mode_internal_storage(SelectionMode)}, + decode_ie_create(Rest,PresentIEs bor 4,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{selMode = selection_mode_internal_storage(SelectionMode)}, + decode_ie_create(Rest,PresentIEs bor 4,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<16:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 8 == 8 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 8 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblData = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 8,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblData = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 8,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<17:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 16 == 16 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 16 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblSig = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 16,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblSig = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 16,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<128:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<PDPElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 32 == 32 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 32 -> + case pdp_addr_internal_storage(PDPElement) of + {ok,PDPAddress} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{endUserAdd = PDPAddress}, + decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,CreateReq) + end; + true -> + case pdp_addr_internal_storage(PDPElement) of + {ok,PDPAddress} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{endUserAdd = PDPAddress}, + decode_ie_create(Rest,PresentIEs bor 32,Errors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<131:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<APNElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 64 == 64 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 64 -> + case catch apn_internal_storage(APNElement,[]) of + {ok,APN} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{accPointName = APN}, + decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true, + invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,CreateReq) + end; + true -> + case catch apn_internal_storage(APNElement,[]) of + {ok,APN} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{accPointName = APN}, + decode_ie_create(Rest,PresentIEs bor 64,Errors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<132:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<ConfigurationElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 128 == 128 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 128 -> + case catch pco_internal_storage(ConfigurationElement) of + {ok,PCO} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{protConOpt = PCO}, + decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true, + incorrectOptIE = true}, + decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,CreateReq) + end; + true -> + case catch pco_internal_storage(ConfigurationElement) of + {ok,PCO} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{protConOpt = PCO}, + decode_ie_create(Rest,PresentIEs bor 128,Errors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{incorrectOptIE = true}, + decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<133:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<AddressElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 768 == 768 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 512 -> + if + PresentIEs band 256 == 0 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddSig = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,CreateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddUser = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,CreateReq) + end + end; + PresentIEs < 256 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddSig = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 256,Errors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,CreateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddUser = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 512,Errors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<134:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<MSISDNElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 1024 == 1024 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 1024 -> + case msisdn_internal_storage(MSISDNElement,[]) of + {ok,MSISDN} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{msisdn = MSISDN}, + decode_ie_create(Rest,PresentIEs bor 1024,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true, + invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 1024,UpdatedErrors,CreateReq) + end; + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{msisdn = #mvsT_msisdn{value = MSISDNElement}}, + decode_ie_create(Rest,PresentIEs bor 1024,Errors,UpdatedCreateReq) + end; +decode_ie_create(UnexpectedIE,PresentIEs,Errors,CreateReq) -> + case check_ie(UnexpectedIE) of + {defined_ie,Rest} -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + {handled_ie,Rest} -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + {unhandled_ie} -> + {fault,193,CreateReq} + end. + +decode_ie_update(<<>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 61 /= 61 -> + {fault,202,UpdateReq}; + true -> + case Errors of + #protocolErrors{invalidManIE = true} -> + {fault,201,UpdateReq}; + #protocolErrors{outOfSequence = true} -> + {fault,193,UpdateReq}; + #protocolErrors{incorrectOptIE = true} -> + {fault,203,UpdateReq}; + _ -> + {ok,UpdateReq} + end + end; +decode_ie_update(<<6:8, + QoSElement:3/binary-unit:8, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 1 == 1 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 1 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{qos = QoS}, + decode_ie_update(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedUpdateReq); + true -> + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{qos = QoS}, + decode_ie_update(Rest,PresentIEs bor 1,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<14:8, + Recovery:8, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 2 == 2 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 2 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{recovery = Recovery}, + decode_ie_update(Rest,PresentIEs bor 2,UpdatedErrors,UpdatedUpdateReq); + true -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{recovery = Recovery}, + decode_ie_update(Rest,PresentIEs bor 2,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<16:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 4 == 4 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 4 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblData = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 4,UpdatedErrors,UpdatedUpdateReq); + true -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblData = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 4,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<17:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 8 == 8 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 8 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblSig = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 8,UpdatedErrors,UpdatedUpdateReq); + true -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblSig = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 8,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<133:8, + Length:16, + More/binary>>,PresentIEs,Errors,UpdateReq) -> + <<AddressElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 48 == 48 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 32 -> + if + PresentIEs band 16 == 0 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddSig = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddUser = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdateReq) + end + end; + PresentIEs < 16 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddSig = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 16,Errors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddUser = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 32,Errors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdateReq) + end + end; +decode_ie_update(UnexpectedIE,PresentIEs,Errors,UpdateReq) -> + case check_ie(UnexpectedIE) of + {defined_ie,Rest} -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + {handled_ie,Rest} -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + {unhandled_ie} -> + {fault,193,UpdateReq} + end. + +decode_ie_delete_res(<<>>,PresentIEs,Errors,DeleteRes) -> + if + PresentIEs band 1 /= 1 -> + {fault,202,DeleteRes}; + true -> + case Errors of + #protocolErrors{invalidManIE = true} -> + {fault,201,DeleteRes}; + #protocolErrors{outOfSequence = true} -> + {fault,193,DeleteRes}; + #protocolErrors{incorrectOptIE = true} -> + {fault,203,DeleteRes}; + _ -> + {ok,DeleteRes} + end + end; +decode_ie_delete_res(<<1:8, + Cause:8, + Rest/binary>>,PresentIEs,Errors,DeleteRes) -> + if + PresentIEs band 1 == 1 -> + decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes); + PresentIEs > 1 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedDeleteRes = DeleteRes#sesT_deleteResV0{cause = Cause}, + decode_ie_delete_res(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedDeleteRes); + true -> + UpdatedDeleteRes = DeleteRes#sesT_deleteResV0{cause = Cause}, + decode_ie_delete_res(Rest,PresentIEs bor 1,Errors,UpdatedDeleteRes) + end; +decode_ie_delete_res(UnexpectedIE,PresentIEs,Errors,DeleteRes) -> + case check_ie(UnexpectedIE) of + {defined_ie,Rest} -> + decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes); + {handled_ie,Rest} -> + decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes); + {unhandled_ie} -> + {fault,193,DeleteRes} + end. + +check_ie(<<1:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<2:8, + _:8/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<3:8, + _:6/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<4:8, + _:4/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<5:8, + _:4/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<6:8, + _:3/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<8:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<9:8, + _:28/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<11:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<12:8, + _:3/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<13:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<14:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<15:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<16:8, + _:16, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<17:8, + _:16, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<18:8, + _:32, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<19:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<127:8, + _:4/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<1:1, + _:7, + Length:16, + More/binary>>) -> + if + Length > size(More) -> + {unhandled_ie}; + true -> + <<_:Length/binary-unit:8, + Rest/binary>> = More, + {handled_ie,Rest} + end; +check_ie(_UnhandledIE) -> + {unhandled_ie}. + +tid_internal_storage(Bin,_) -> + Size = size(Bin) - 1, + <<Front:Size/binary, + NSAPI:4, + DigitN:4>> = Bin, + Result = case DigitN of + 15 -> + #mvsgT_tid{imsi = #mvsgT_imsi{value = Front}, + nsapi = NSAPI}; + _ -> + #mvsgT_tid{imsi = #mvsgT_imsi{value = <<Front/binary, + 15:4, + DigitN:4>>}, + nsapi = NSAPI} + end, + {ok,Result}. + +selection_mode_internal_storage(0) -> + subscribed; +selection_mode_internal_storage(1) -> + msRequested; +selection_mode_internal_storage(2) -> + sgsnSelected; +selection_mode_internal_storage(3) -> + sgsnSelected. + +pdp_addr_internal_storage(<<_:4, + 0:4, + 1:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = etsi_ppp, + address = []}}; +pdp_addr_internal_storage(<<_:4, + 0:4, + 2:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = etsi_osp_ihoss, + address = []}}; +pdp_addr_internal_storage(<<_:4, + 1:4, + 33:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv4, + address = []}}; +pdp_addr_internal_storage(<<_:4, + 1:4, + 33:8, + IP_A:8, + IP_B:8, + IP_C:8, + IP_D:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv4, + address = [IP_A,IP_B,IP_C,IP_D]}}; +pdp_addr_internal_storage(<<_:4, + 1:4, + 87:8, + IP_A:16, + IP_B:16, + IP_C:16, + IP_D:16, + IP_E:16, + IP_F:16, + IP_G:16, + IP_H:16>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv6, + address = [IP_A,IP_B,IP_C,IP_D,IP_E,IP_F,IP_G,IP_H]}}; +pdp_addr_internal_storage(_PDP_ADDR) -> + {fault}. + +apn_internal_storage(<<>>,APN) -> + {ok,lists:reverse(APN)}; +apn_internal_storage(<<Length:8, + Rest/binary>>,APN) -> + <<Label:Length/binary-unit:8, + MoreAPNLabels/binary>> = Rest, + apn_internal_storage(MoreAPNLabels,[Label|APN]). + +pco_internal_storage(<<1:1, + _:4, + 0:3, + PPPConfigurationOptions/binary>>) -> + case ppp_configuration_options(PPPConfigurationOptions,#masT_pap{exists = false},[],[]) of + {ok,PAP,CHAP,IPCP} -> + {ok,#masT_protocolConfigOptions{pap = PAP, + chap = CHAP, + ipcp = IPCP}}; + {fault} -> + {fault} + end; +pco_internal_storage(<<1:1, + _:4, + 1:3, + _OSP_IHOSSConfigurationOptions/binary>>) -> + {ok,osp_ihoss}; +pco_internal_storage(_UnknownConfigurationOptions) -> + {fault}. + +ppp_configuration_options(<<>>,PAP,CHAP,IPCP) -> + {ok,PAP,CHAP,IPCP}; +ppp_configuration_options(<<49185:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<_LCP:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(<<49187:16, + _Length:8, + 1:8, + Identifier:8, + DataLength:16, + More/binary>>,_PAP,CHAP,IPCP) -> + ActualDataLength = DataLength - 4, + <<Data:ActualDataLength/binary-unit:8, + Rest/binary>> = More, + <<PeerIDLength:8, + PeerData/binary>> = Data, + <<PeerID:PeerIDLength/binary-unit:8, + PasswdLength:8, + PasswordData/binary>> = PeerData, + <<Password:PasswdLength/binary, + _Padding/binary>> = PasswordData, + ppp_configuration_options(Rest,#masT_pap{exists = true, + code = 1, + id = Identifier, + username = binary_to_list(PeerID), + password = binary_to_list(Password)},CHAP,IPCP); +ppp_configuration_options(<<49187:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<PAP:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(<<49699:16, + _Length:8, + 1:8, + Identifier:8, + DataLength:16, + More/binary>>,PAP,CHAP,IPCP) -> + ActualDataLength = DataLength - 4, + <<Data:ActualDataLength/binary-unit:8, + Rest/binary>> = More, + <<ValueSize:8, + ValueAndName/binary>> = Data, + <<Value:ValueSize/binary-unit:8, + Name/binary>> = ValueAndName, + ppp_configuration_options(Rest,PAP,[#masT_chap{code = 1, + id = Identifier, + value = binary_to_list(Value), + name = binary_to_list(Name)}|CHAP],IPCP); +ppp_configuration_options(<<49699:16, + _Length:8, + 2:8, + Identifier:8, + DataLength:16, + More/binary>>,PAP,CHAP,IPCP) -> + ActualDataLength = DataLength - 4, + <<Data:ActualDataLength/binary-unit:8, + Rest/binary>> = More, + <<ValueSize:8, + ValueAndName/binary>> = Data, + <<Value:ValueSize/binary-unit:8, + Name/binary>> = ValueAndName, + ppp_configuration_options(Rest,PAP,[#masT_chap{code = 2, + id = Identifier, + value = binary_to_list(Value), + name = binary_to_list(Name)}|CHAP],IPCP); +ppp_configuration_options(<<49699:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<CHAP:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(<<32801:16, + _Length:8, + 1:8, + Identifier:8, + OptionsLength:16, + More/binary>>,PAP,CHAP,IPCP) -> + ActualOptionsLength = OptionsLength - 4, + <<Options:ActualOptionsLength/binary-unit:8, + Rest/binary>> = More, + case Options of + <<3:8, + 6:8, + A1:8, + A2:8, + A3:8, + A4:8>> -> + ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true, + code = 1, + id = Identifier, + ipcpList = [#masT_ipcpData{type = 3, + ipAddress = #mvsgT_ipAddress{version = ipv4, + a1 = A1, + a2 = A2, + a3 = A3, + a4 = A4, + a5 = 0, + a6 = 0, + a7 = 0, + a8 = 0}, + rawMessage = binary_to_list(Options)}]}|IPCP]); + <<129:8, + 6:8, + B1:8, + B2:8, + B3:8, + B4:8>> -> + ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true, + code = 1, + id = Identifier, + ipcpList = [#masT_ipcpData{type = 129, + ipAddress = #mvsgT_ipAddress{version = ipv4, + a1 = B1, + a2 = B2, + a3 = B3, + a4 = B4}, + rawMessage = binary_to_list(Options)}]}|IPCP]); + <<131:8, + 6:8, + C1:8, + C2:8, + C3:8, + C4:8>> -> + ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true, + code = 1, + id = Identifier, + ipcpList = [#masT_ipcpData{type = 131, + ipAddress = #mvsgT_ipAddress{version = ipv4, + a1 = C1, + a2 = C2, + a3 = C3, + a4 = C4}, + rawMessage = binary_to_list(Options)}]}|IPCP]); + _ -> + ppp_configuration_options(Rest,PAP,CHAP,IPCP) + end; +ppp_configuration_options(<<_UnknownProtocolID:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<_Skipped:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(_Unhandled,_PAP,_CHAP,_IPCP) -> + {fault}. + +gsn_addr_internal_storage(<<IP_A:8, + IP_B:8, + IP_C:8, + IP_D:8>>) -> + {ok,#mvsgT_ipAddress{version = ipv4, + a1 = IP_A, + a2 = IP_B, + a3 = IP_C, + a4 = IP_D, + a5 = 0, + a6 = 0, + a7 = 0, + a8 = 0}}; +gsn_addr_internal_storage(<<IP_A:16, + IP_B:16, + IP_C:16, + IP_D:16, + IP_E:16, + IP_F:16, + IP_G:16, + IP_H:16>>) -> + {ok,#mvsgT_ipAddress{version = ipv6, + a1 = IP_A, + a2 = IP_B, + a3 = IP_C, + a4 = IP_D, + a5 = IP_E, + a6 = IP_F, + a7 = IP_G, + a8 = IP_H}}; +gsn_addr_internal_storage(_GSN_ADDR) -> + {fault}. + +msisdn_internal_storage(<<>>,MSISDN) -> + {ok,#mvsT_msisdn{value = lists:reverse(MSISDN)}}; +msisdn_internal_storage(<<255:8, + _Rest/binary>>,MSISDN) -> + {ok,#mvsT_msisdn{value = lists:reverse(MSISDN)}}; +msisdn_internal_storage(<<15:4, + DigitN:4, + _Rest/binary>>,MSISDN) when DigitN < 10 -> + {ok,#mvsT_msisdn{value = lists:reverse([DigitN bor 240|MSISDN])}}; +msisdn_internal_storage(<<DigitNplus1:4, + DigitN:4, + Rest/binary>>,MSISDN) when DigitNplus1 < 10, DigitN < 10 -> + NewMSISDN = [DigitNplus1 bsl 4 bor DigitN|MSISDN], + msisdn_internal_storage(Rest,NewMSISDN); +msisdn_internal_storage(_Rest,_MSISDN) -> + {fault}. diff --git a/lib/compiler/test/inline_SUITE_data/bsdes.erl b/lib/compiler/test/inline_SUITE_data/bsdes.erl new file mode 100644 index 0000000000..8d2d1a8287 --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/bsdes.erl @@ -0,0 +1,747 @@ +%% +%% %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(bsdes). +-export([?MODULE/0]). + +-define(ITERATIONS, 100). %% for benchmarking use a higher number + +?MODULE() -> + Res = test(), + {Res,Res =:= <<0,0,0,0,0,0,0,1>>}. + +test() -> + Bin = <<1:64>>, + Size= size(Bin), + Key = <<4704650607608769871263876:64>>, + Jumbled = run_encode(?ITERATIONS, Bin, Key), + Unjumbled = run_decode(?ITERATIONS, Jumbled, Key), + <<Bin:Size/binary,_/binary>> = Unjumbled. + +run_encode(1, Bin, Key) -> + encode(Bin, Key); +run_encode(N, Bin, Key) -> + encode(Bin, Key), + run_encode(N-1, Bin, Key). + +run_decode(1, Bin, Key) -> + decode(Bin, Key); +run_decode(N, Bin, Key) -> + decode(Bin, Key), + run_decode(N-1, Bin, Key). + +encode(Data, Key) -> + Keys = schedule(Key), + list_to_binary(encode_data(Data, Keys)). + +decode(Data, Key) -> + Keys = lists:reverse(schedule(Key)), + list_to_binary(decode_data(Data, Keys)). + +encode_data(<<Data:8/binary, Rest/binary>>, Keys) -> + [ipinv(des_core(ip(Data), Keys))|encode_data(Rest, Keys)]; +encode_data(<<Rest/binary>>, Keys) -> + case size(Rest) of + 0 -> []; + X -> + Y = 8-X, + Data = <<Rest/binary, 0:Y/integer-unit:8>>, + [ipinv(des_core(ip(Data), Keys))] + end. + +decode_data(<<Data:8/binary, Rest/binary>>, Keys) -> + [ipinv(dechiper(ip(Data), Keys))|decode_data(Rest, Keys)]; +decode_data(_, _Keys) -> + []. + +schedule(Key) -> + NewKey=pc1(Key), + subkeys(NewKey, 1). + +subkeys(_Key, 17) -> + []; +subkeys(Key, N) -> + TmpKey = + case rotate(N) of + 1 -> + <<X1:1, L:27, X2:1, R:27>> = Key, + <<L:27, X1:1, R:27, X2:1>>; + 2 -> + <<X1:2, L:26, X2:2, R:26>> = Key, + <<L:26, X1:2, R:26, X2:2>>; + _ -> + error + end, + [pc2(TmpKey)|subkeys(TmpKey, N+1)]. + +pc2(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1, + _I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1, + I17:1, _I18:1, I19:1, I20:1, I21:1, _I22:1, I23:1, I24:1, + _I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1, + I33:1, I34:1, _I35:1, I36:1, I37:1, _I38:1, I39:1, I40:1, + I41:1, I42:1, _I43:1, I44:1, I45:1, I46:1, I47:1, I48:1, + I49:1, I50:1, I51:1, I52:1, I53:1, _I54:1, I55:1, I56:1>>) -> + <<I14:1, I17:1, I11:1, I24:1, I1:1, I5:1, I3:1, I28:1, + I15:1, I6:1, I21:1, I10:1, I23:1, I19:1, I12:1, I4:1, + I26:1, I8:1, I16:1, I7:1, I27:1, I20:1, I13:1, I2:1, + I41:1, I52:1, I31:1, I37:1, I47:1, I55:1, I30:1, I40:1, + I51:1, I45:1, I33:1, I48:1, I44:1, I49:1, I39:1, I56:1, + I34:1, I53:1, I46:1, I42:1, I50:1, I36:1, I29:1, I32:1>>. + +pc1(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, _:1, + I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, _:1, + I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, _:1, + I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, _:1, + I33:1, I34:1, I35:1, I36:1, I37:1, I38:1, I39:1, _:1, + I41:1, I42:1, I43:1, I44:1, I45:1, I46:1, I47:1, _:1, + I49:1, I50:1, I51:1, I52:1, I53:1, I54:1, I55:1, _:1, + I57:1, I58:1, I59:1, I60:1, I61:1, I62:1, I63:1, _:1>>) -> + <<I57:1, I49:1, I41:1, I33:1, I25:1, I17:1, I9:1, I1:1, + I58:1, I50:1, I42:1, I34:1, I26:1, I18:1, I10:1, I2:1, + I59:1, I51:1, I43:1, I35:1, I27:1, I19:1, I11:1, I3:1, + I60:1, I52:1, I44:1, I36:1, I63:1, I55:1, I47:1, I39:1, + I31:1, I23:1, I15:1, I7:1, I62:1, I54:1, I46:1, I38:1, + I30:1, I22:1, I14:1, I6:1, I61:1, I53:1, I45:1, I37:1, + I29:1, I21:1, I13:1, I5:1, I28:1, I20:1, I12:1, I4:1>>. + +ip(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1, + I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1, + I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, I24:1, + I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1, + I33:1, I34:1, I35:1, I36:1, I37:1, I38:1, I39:1, I40:1, + I41:1, I42:1, I43:1, I44:1, I45:1, I46:1, I47:1, I48:1, + I49:1, I50:1, I51:1, I52:1, I53:1, I54:1, I55:1, I56:1, + I57:1, I58:1, I59:1, I60:1, I61:1, I62:1, I63:1, I64:1>>) -> + <<I58:1, I50:1, I42:1, I34:1, I26:1, I18:1, I10:1, I2:1, + I60:1, I52:1, I44:1, I36:1, I28:1, I20:1, I12:1, I4:1, + I62:1, I54:1, I46:1, I38:1, I30:1, I22:1, I14:1, I6:1, + I64:1, I56:1, I48:1, I40:1, I32:1, I24:1, I16:1, I8:1, + I57:1, I49:1, I41:1, I33:1, I25:1, I17:1, I9:1, I1:1, + I59:1, I51:1, I43:1, I35:1, I27:1, I19:1, I11:1, I3:1, + I61:1, I53:1, I45:1, I37:1, I29:1, I21:1, I13:1, I5:1, + I63:1, I55:1, I47:1, I39:1, I31:1, I23:1, I15:1, I7:1>>. + +ipinv(<<I58:1, I50:1, I42:1, I34:1, I26:1, I18:1, I10:1, I2:1, + I60:1, I52:1, I44:1, I36:1, I28:1, I20:1, I12:1, I4:1, + I62:1, I54:1, I46:1, I38:1, I30:1, I22:1, I14:1, I6:1, + I64:1, I56:1, I48:1, I40:1, I32:1, I24:1, I16:1, I8:1, + I57:1, I49:1, I41:1, I33:1, I25:1, I17:1, I9:1, I1:1, + I59:1, I51:1, I43:1, I35:1, I27:1, I19:1, I11:1, I3:1, + I61:1, I53:1, I45:1, I37:1, I29:1, I21:1, I13:1, I5:1, + I63:1, I55:1, I47:1, I39:1, I31:1, I23:1, I15:1, I7:1>>) -> + <<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1, + I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1, + I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, I24:1, + I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1, + I33:1, I34:1, I35:1, I36:1, I37:1, I38:1, I39:1, I40:1, + I41:1, I42:1, I43:1, I44:1, I45:1, I46:1, I47:1, I48:1, + I49:1, I50:1, I51:1, I52:1, I53:1, I54:1, I55:1, I56:1, + I57:1, I58:1, I59:1, I60:1, I61:1, I62:1, I63:1, I64:1>>. + +dechiper(<<L:4/binary, R:4/binary>>, Keys) -> + dechiper(L, R, Keys, 16). + +dechiper(L, R, [], 0) -> + <<L:4/binary, R:4/binary>>; +dechiper(L, R, [Key|Rest], I) -> + NewL=ebit(L), + XorL=xor48(NewL, Key), + Sboxed=sboxing(XorL), + Ped=p(Sboxed), + EndL = xor32(Ped, R), + dechiper(EndL,L,Rest,I-1). + +des_core(<<L:4/binary, R:4/binary>>, Keys) -> + des_core(L, R, Keys, 0). + +des_core(L, R, [], 16) -> + <<L:4/binary, R:4/binary>>; +des_core(L, R, [Key|Rest], I) when I<16 -> + NewR=ebit(R), + XorR=xor48(NewR, Key), + Sboxed=sboxing(XorR), + Ped=p(Sboxed), + EndR = xor32(Ped, L), + des_core(R, EndR, Rest, I+1). + +ebit(<<I1:1, I2:2, I3:2,I4:2,I5:2,I6:2, + I7:2,I8:2,I9:2,I10:2,I11:2,I12:2, + I13:2,I14:2,I15:2,I16:2,I17:1>>) -> + <<I17:1, I1:1, I2:2, I3:2, I3:2, + I4:2, I5:2, I5:2, I6:2, + I7:2, I7:2, I8:2, I9:2, + I9:2, I10:2, I11:2, I11:2, + I12:2, I13:2, I13:2, I14:2, + I15:2, I15:2, I16:2, I17:1, I1:1>>. + +p(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1, + I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1, + I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, I24:1, + I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1>>) -> + <<I16:1, I7:1, I20:1, I21:1, I29:1, I12:1, I28:1, I17:1, + I1:1, I15:1, I23:1, I26:1, I5:1, I18:1, I31:1, I10:1, + I2:1, I8:1, I24:1, I14:1, I32:1, I27:1, I3:1, I9:1, + I19:1, I13:1, I30:1, I6:1, I22:1, I11:1, I4:1, I25:1>>. + +rotate(1) -> 1; +rotate(2) -> 1; +rotate(9) -> 1; +rotate(16) -> 1; +rotate(N) when N>0, N<17 -> 2. + +%xor64(<<I1:16, I2:16, I3:16, I4:16>>,<<J1:16, J2:16, J3:16, J4:16>>) -> +% K1 = I1 bxor J1, +% K2 = I2 bxor J2, +% K3 = I3 bxor J3, +% K4 = I4 bxor J4, +% <<K1:16, K2:16, K3:16, K4:16>>. + +xor48(<<I1:16, I2:16, I3:16>>,<<J1:16, J2:16, J3:16>>) -> + K1 = I1 bxor J1, + K2 = I2 bxor J2, + K3 = I3 bxor J3, + <<K1:16, K2:16, K3:16>>. + +xor32(<<I1:16, I2:16>>,<<J1:16, J2:16>>) -> + K1 = I1 bxor J1, + K2 = I2 bxor J2, + <<K1:16, K2:16>>. + +sboxing(<<A1:6, A2:6, A3:6, A4:6, A5:6, A6:6, A7:6, A8:6>>) -> + S1=sbox(A1, 1), + S2=sbox(A2, 2), + S3=sbox(A3, 3), + S4=sbox(A4, 4), + S5=sbox(A5, 5), + S6=sbox(A6, 6), + S7=sbox(A7, 7), + S8=sbox(A8, 8), + <<S1:4,S2:4,S3:4,S4:4,S5:4,S6:4,S7:4,S8:4>>. + +sbox(0,1) -> 14; +sbox(1,1) -> 0; +sbox(2,1) -> 4; +sbox(3,1) -> 15; +sbox(4,1) -> 13; +sbox(5,1) -> 7; +sbox(6,1) -> 1; +sbox(7,1) -> 4; +sbox(8,1) -> 2; +sbox(9,1) -> 14; +sbox(10,1) -> 15; +sbox(11,1) -> 2; +sbox(12,1) -> 11; +sbox(13,1) -> 13; +sbox(14,1) -> 8; +sbox(15,1) -> 1; +sbox(16,1) -> 3; +sbox(17,1) -> 10; +sbox(18,1) -> 10; +sbox(19,1) -> 6; +sbox(20,1) -> 6; +sbox(21,1) -> 12; +sbox(22,1) -> 12; +sbox(23,1) -> 11; +sbox(24,1) -> 5; +sbox(25,1) -> 9; +sbox(26,1) -> 9; +sbox(27,1) -> 5; +sbox(28,1) -> 0; +sbox(29,1) -> 3; +sbox(30,1) -> 7; +sbox(31,1) -> 8; +sbox(32,1) -> 4; +sbox(33,1) -> 15; +sbox(34,1) -> 1; +sbox(35,1) -> 12; +sbox(36,1) -> 14; +sbox(37,1) -> 8; +sbox(38,1) -> 8; +sbox(39,1) -> 2; +sbox(40,1) -> 13; +sbox(41,1) -> 4; +sbox(42,1) -> 6; +sbox(43,1) -> 9; +sbox(44,1) -> 2; +sbox(45,1) -> 1; +sbox(46,1) -> 11; +sbox(47,1) -> 7; +sbox(48,1) -> 15; +sbox(49,1) -> 5; +sbox(50,1) -> 12; +sbox(51,1) -> 11; +sbox(52,1) -> 9; +sbox(53,1) -> 3; +sbox(54,1) -> 7; +sbox(55,1) -> 14; +sbox(56,1) -> 3; +sbox(57,1) -> 10; +sbox(58,1) -> 10; +sbox(59,1) -> 0; +sbox(60,1) -> 5; +sbox(61,1) -> 6; +sbox(62,1) -> 0; +sbox(63,1) -> 13; +sbox(0,2) -> 15; +sbox(1,2) -> 3; +sbox(2,2) -> 1; +sbox(3,2) -> 13; +sbox(4,2) -> 8; +sbox(5,2) -> 4; +sbox(6,2) -> 14; +sbox(7,2) -> 7; +sbox(8,2) -> 6; +sbox(9,2) -> 15; +sbox(10,2) -> 11; +sbox(11,2) -> 2; +sbox(12,2) -> 3; +sbox(13,2) -> 8; +sbox(14,2) -> 4; +sbox(15,2) -> 14; +sbox(16,2) -> 9; +sbox(17,2) -> 12; +sbox(18,2) -> 7; +sbox(19,2) -> 0; +sbox(20,2) -> 2; +sbox(21,2) -> 1; +sbox(22,2) -> 13; +sbox(23,2) -> 10; +sbox(24,2) -> 12; +sbox(25,2) -> 6; +sbox(26,2) -> 0; +sbox(27,2) -> 9; +sbox(28,2) -> 5; +sbox(29,2) -> 11; +sbox(30,2) -> 10; +sbox(31,2) -> 5; +sbox(32,2) -> 0; +sbox(33,2) -> 13; +sbox(34,2) -> 14; +sbox(35,2) -> 8; +sbox(36,2) -> 7; +sbox(37,2) -> 10; +sbox(38,2) -> 11; +sbox(39,2) -> 1; +sbox(40,2) -> 10; +sbox(41,2) -> 3; +sbox(42,2) -> 4; +sbox(43,2) -> 15; +sbox(44,2) -> 13; +sbox(45,2) -> 4; +sbox(46,2) -> 1; +sbox(47,2) -> 2; +sbox(48,2) -> 5; +sbox(49,2) -> 11; +sbox(50,2) -> 8; +sbox(51,2) -> 6; +sbox(52,2) -> 12; +sbox(53,2) -> 7; +sbox(54,2) -> 6; +sbox(55,2) -> 12; +sbox(56,2) -> 9; +sbox(57,2) -> 0; +sbox(58,2) -> 3; +sbox(59,2) -> 5; +sbox(60,2) -> 2; +sbox(61,2) -> 14; +sbox(62,2) -> 15; +sbox(63,2) -> 9; +sbox(0,3) -> 10; +sbox(1,3) -> 13; +sbox(2,3) -> 0; +sbox(3,3) -> 7; +sbox(4,3) -> 9; +sbox(5,3) -> 0; +sbox(6,3) -> 14; +sbox(7,3) -> 9; +sbox(8,3) -> 6; +sbox(9,3) -> 3; +sbox(10,3) -> 3; +sbox(11,3) -> 4; +sbox(12,3) -> 15; +sbox(13,3) -> 6; +sbox(14,3) -> 5; +sbox(15,3) -> 10; +sbox(16,3) -> 1; +sbox(17,3) -> 2; +sbox(18,3) -> 13; +sbox(19,3) -> 8; +sbox(20,3) -> 12; +sbox(21,3) -> 5; +sbox(22,3) -> 7; +sbox(23,3) -> 14; +sbox(24,3) -> 11; +sbox(25,3) -> 12; +sbox(26,3) -> 4; +sbox(27,3) -> 11; +sbox(28,3) -> 2; +sbox(29,3) -> 15; +sbox(30,3) -> 8; +sbox(31,3) -> 1; +sbox(32,3) -> 13; +sbox(33,3) -> 1; +sbox(34,3) -> 6; +sbox(35,3) -> 10; +sbox(36,3) -> 4; +sbox(37,3) -> 13; +sbox(38,3) -> 9; +sbox(39,3) -> 0; +sbox(40,3) -> 8; +sbox(41,3) -> 6; +sbox(42,3) -> 15; +sbox(43,3) -> 9; +sbox(44,3) -> 3; +sbox(45,3) -> 8; +sbox(46,3) -> 0; +sbox(47,3) -> 7; +sbox(48,3) -> 11; +sbox(49,3) -> 4; +sbox(50,3) -> 1; +sbox(51,3) -> 15; +sbox(52,3) -> 2; +sbox(53,3) -> 14; +sbox(54,3) -> 12; +sbox(55,3) -> 3; +sbox(56,3) -> 5; +sbox(57,3) -> 11; +sbox(58,3) -> 10; +sbox(59,3) -> 5; +sbox(60,3) -> 14; +sbox(61,3) -> 2; +sbox(62,3) -> 7; +sbox(63,3) -> 12; +sbox(0,4) -> 7; +sbox(1,4) -> 13; +sbox(2,4) -> 13; +sbox(3,4) -> 8; +sbox(4,4) -> 14; +sbox(5,4) -> 11; +sbox(6,4) -> 3; +sbox(7,4) -> 5; +sbox(8,4) -> 0; +sbox(9,4) -> 6; +sbox(10,4) -> 6; +sbox(11,4) -> 15; +sbox(12,4) -> 9; +sbox(13,4) -> 0; +sbox(14,4) -> 10; +sbox(15,4) -> 3; +sbox(16,4) -> 1; +sbox(17,4) -> 4; +sbox(18,4) -> 2; +sbox(19,4) -> 7; +sbox(20,4) -> 8; +sbox(21,4) -> 2; +sbox(22,4) -> 5; +sbox(23,4) -> 12; +sbox(24,4) -> 11; +sbox(25,4) -> 1; +sbox(26,4) -> 12; +sbox(27,4) -> 10; +sbox(28,4) -> 4; +sbox(29,4) -> 14; +sbox(30,4) -> 15; +sbox(31,4) -> 9; +sbox(32,4) -> 10; +sbox(33,4) -> 3; +sbox(34,4) -> 6; +sbox(35,4) -> 15; +sbox(36,4) -> 9; +sbox(37,4) -> 0; +sbox(38,4) -> 0; +sbox(39,4) -> 6; +sbox(40,4) -> 12; +sbox(41,4) -> 10; +sbox(42,4) -> 11; +sbox(43,4) -> 1; +sbox(44,4) -> 7; +sbox(45,4) -> 13; +sbox(46,4) -> 13; +sbox(47,4) -> 8; +sbox(48,4) -> 15; +sbox(49,4) -> 9; +sbox(50,4) -> 1; +sbox(51,4) -> 4; +sbox(52,4) -> 3; +sbox(53,4) -> 5; +sbox(54,4) -> 14; +sbox(55,4) -> 11; +sbox(56,4) -> 5; +sbox(57,4) -> 12; +sbox(58,4) -> 2; +sbox(59,4) -> 7; +sbox(60,4) -> 8; +sbox(61,4) -> 2; +sbox(62,4) -> 4; +sbox(63,4) -> 14; +sbox(0,5) -> 2; +sbox(1,5) -> 14; +sbox(2,5) -> 12; +sbox(3,5) -> 11; +sbox(4,5) -> 4; +sbox(5,5) -> 2; +sbox(6,5) -> 1; +sbox(7,5) -> 12; +sbox(8,5) -> 7; +sbox(9,5) -> 4; +sbox(10,5) -> 10; +sbox(11,5) -> 7; +sbox(12,5) -> 11; +sbox(13,5) -> 13; +sbox(14,5) -> 6; +sbox(15,5) -> 1; +sbox(16,5) -> 8; +sbox(17,5) -> 5; +sbox(18,5) -> 5; +sbox(19,5) -> 0; +sbox(20,5) -> 3; +sbox(21,5) -> 15; +sbox(22,5) -> 15; +sbox(23,5) -> 10; +sbox(24,5) -> 13; +sbox(25,5) -> 3; +sbox(26,5) -> 0; +sbox(27,5) -> 9; +sbox(28,5) -> 14; +sbox(29,5) -> 8; +sbox(30,5) -> 9; +sbox(31,5) -> 6; +sbox(32,5) -> 4; +sbox(33,5) -> 11; +sbox(34,5) -> 2; +sbox(35,5) -> 8; +sbox(36,5) -> 1; +sbox(37,5) -> 12; +sbox(38,5) -> 11; +sbox(39,5) -> 7; +sbox(40,5) -> 10; +sbox(41,5) -> 1; +sbox(42,5) -> 13; +sbox(43,5) -> 14; +sbox(44,5) -> 7; +sbox(45,5) -> 2; +sbox(46,5) -> 8; +sbox(47,5) -> 13; +sbox(48,5) -> 15; +sbox(49,5) -> 6; +sbox(50,5) -> 9; +sbox(51,5) -> 15; +sbox(52,5) -> 12; +sbox(53,5) -> 0; +sbox(54,5) -> 5; +sbox(55,5) -> 9; +sbox(56,5) -> 6; +sbox(57,5) -> 10; +sbox(58,5) -> 3; +sbox(59,5) -> 4; +sbox(60,5) -> 0; +sbox(61,5) -> 5; +sbox(62,5) -> 14; +sbox(63,5) -> 3; +sbox(0,6) -> 12; +sbox(1,6) -> 10; +sbox(2,6) -> 1; +sbox(3,6) -> 15; +sbox(4,6) -> 10; +sbox(5,6) -> 4; +sbox(6,6) -> 15; +sbox(7,6) -> 2; +sbox(8,6) -> 9; +sbox(9,6) -> 7; +sbox(10,6) -> 2; +sbox(11,6) -> 12; +sbox(12,6) -> 6; +sbox(13,6) -> 9; +sbox(14,6) -> 8; +sbox(15,6) -> 5; +sbox(16,6) -> 0; +sbox(17,6) -> 6; +sbox(18,6) -> 13; +sbox(19,6) -> 1; +sbox(20,6) -> 3; +sbox(21,6) -> 13; +sbox(22,6) -> 4; +sbox(23,6) -> 14; +sbox(24,6) -> 14; +sbox(25,6) -> 0; +sbox(26,6) -> 7; +sbox(27,6) -> 11; +sbox(28,6) -> 5; +sbox(29,6) -> 3; +sbox(30,6) -> 11; +sbox(31,6) -> 8; +sbox(32,6) -> 9; +sbox(33,6) -> 4; +sbox(34,6) -> 14; +sbox(35,6) -> 3; +sbox(36,6) -> 15; +sbox(37,6) -> 2; +sbox(38,6) -> 5; +sbox(39,6) -> 12; +sbox(40,6) -> 2; +sbox(41,6) -> 9; +sbox(42,6) -> 8; +sbox(43,6) -> 5; +sbox(44,6) -> 12; +sbox(45,6) -> 15; +sbox(46,6) -> 3; +sbox(47,6) -> 10; +sbox(48,6) -> 7; +sbox(49,6) -> 11; +sbox(50,6) -> 0; +sbox(51,6) -> 14; +sbox(52,6) -> 4; +sbox(53,6) -> 1; +sbox(54,6) -> 10; +sbox(55,6) -> 7; +sbox(56,6) -> 1; +sbox(57,6) -> 6; +sbox(58,6) -> 13; +sbox(59,6) -> 0; +sbox(60,6) -> 11; +sbox(61,6) -> 8; +sbox(62,6) -> 6; +sbox(63,6) -> 13; +sbox(0,7) -> 4; +sbox(1,7) -> 13; +sbox(2,7) -> 11; +sbox(3,7) -> 0; +sbox(4,7) -> 2; +sbox(5,7) -> 11; +sbox(6,7) -> 14; +sbox(7,7) -> 7; +sbox(8,7) -> 15; +sbox(9,7) -> 4; +sbox(10,7) -> 0; +sbox(11,7) -> 9; +sbox(12,7) -> 8; +sbox(13,7) -> 1; +sbox(14,7) -> 13; +sbox(15,7) -> 10; +sbox(16,7) -> 3; +sbox(17,7) -> 14; +sbox(18,7) -> 12; +sbox(19,7) -> 3; +sbox(20,7) -> 9; +sbox(21,7) -> 5; +sbox(22,7) -> 7; +sbox(23,7) -> 12; +sbox(24,7) -> 5; +sbox(25,7) -> 2; +sbox(26,7) -> 10; +sbox(27,7) -> 15; +sbox(28,7) -> 6; +sbox(29,7) -> 8; +sbox(30,7) -> 1; +sbox(31,7) -> 6; +sbox(32,7) -> 1; +sbox(33,7) -> 6; +sbox(34,7) -> 4; +sbox(35,7) -> 11; +sbox(36,7) -> 11; +sbox(37,7) -> 13; +sbox(38,7) -> 13; +sbox(39,7) -> 8; +sbox(40,7) -> 12; +sbox(41,7) -> 1; +sbox(42,7) -> 3; +sbox(43,7) -> 4; +sbox(44,7) -> 7; +sbox(45,7) -> 10; +sbox(46,7) -> 14; +sbox(47,7) -> 7; +sbox(48,7) -> 10; +sbox(49,7) -> 9; +sbox(50,7) -> 15; +sbox(51,7) -> 5; +sbox(52,7) -> 6; +sbox(53,7) -> 0; +sbox(54,7) -> 8; +sbox(55,7) -> 15; +sbox(56,7) -> 0; +sbox(57,7) -> 14; +sbox(58,7) -> 5; +sbox(59,7) -> 2; +sbox(60,7) -> 9; +sbox(61,7) -> 3; +sbox(62,7) -> 2; +sbox(63,7) -> 12; +sbox(0,8) -> 13; +sbox(1,8) -> 1; +sbox(2,8) -> 2; +sbox(3,8) -> 15; +sbox(4,8) -> 8; +sbox(5,8) -> 13; +sbox(6,8) -> 4; +sbox(7,8) -> 8; +sbox(8,8) -> 6; +sbox(9,8) -> 10; +sbox(10,8) -> 15; +sbox(11,8) -> 3; +sbox(12,8) -> 11; +sbox(13,8) -> 7; +sbox(14,8) -> 1; +sbox(15,8) -> 4; +sbox(16,8) -> 10; +sbox(17,8) -> 12; +sbox(18,8) -> 9; +sbox(19,8) -> 5; +sbox(20,8) -> 3; +sbox(21,8) -> 6; +sbox(22,8) -> 14; +sbox(23,8) -> 11; +sbox(24,8) -> 5; +sbox(25,8) -> 0; +sbox(26,8) -> 0; +sbox(27,8) -> 14; +sbox(28,8) -> 12; +sbox(29,8) -> 9; +sbox(30,8) -> 7; +sbox(31,8) -> 2; +sbox(32,8) -> 7; +sbox(33,8) -> 2; +sbox(34,8) -> 11; +sbox(35,8) -> 1; +sbox(36,8) -> 4; +sbox(37,8) -> 14; +sbox(38,8) -> 1; +sbox(39,8) -> 7; +sbox(40,8) -> 9; +sbox(41,8) -> 4; +sbox(42,8) -> 12; +sbox(43,8) -> 10; +sbox(44,8) -> 14; +sbox(45,8) -> 8; +sbox(46,8) -> 2; +sbox(47,8) -> 13; +sbox(48,8) -> 0; +sbox(49,8) -> 15; +sbox(50,8) -> 6; +sbox(51,8) -> 12; +sbox(52,8) -> 10; +sbox(53,8) -> 9; +sbox(54,8) -> 13; +sbox(55,8) -> 0; +sbox(56,8) -> 15; +sbox(57,8) -> 3; +sbox(58,8) -> 3; +sbox(59,8) -> 5; +sbox(60,8) -> 5; +sbox(61,8) -> 6; +sbox(62,8) -> 8; +sbox(63,8) -> 11. diff --git a/lib/compiler/test/inline_SUITE_data/decode1.erl b/lib/compiler/test/inline_SUITE_data/decode1.erl new file mode 100644 index 0000000000..d51bedcb2e --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/decode1.erl @@ -0,0 +1,402 @@ +%% +%% %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% +%% +%---------------------------------------------------------------------- +% decode1.erl (new version) +%---------------------------------------------------------------------- +% -*- Erlang -*- +% File: decode1.erl (~jb/decode/decode1.erl) +% Author: Johan Bevemyr +% Created: Tue Jan 14 09:33:49 1997 +% Purpose: +% Notes: Rewritten for use in ETOS. (Happi) + +-module(decode1). + +-export([?MODULE/0, + decode_ie_heads_setup/1, + run_dummy/2, + run_orig/2]). + +?MODULE() -> + FrameList = [89,128,0,8,132,0,26,133,133,0,38,148,94, + 128,0,2,129,128,92,128,0,2,0,0,112,128,0, + 10,194,69,0,0,0,0,0,18,52,95], + Frame = concat_binary([list_to_binary([89]),list_to_binary([128]), + list_to_binary([0]),list_to_binary([8]), + list_to_binary([132]),list_to_binary([0]), + list_to_binary([26]),list_to_binary([133]), + list_to_binary([133]),list_to_binary([0]), + list_to_binary([38]),list_to_binary([148]), + list_to_binary([94]),list_to_binary([128]), + list_to_binary([0]),list_to_binary([2]), + list_to_binary([129]),list_to_binary([128]), + list_to_binary([92]),list_to_binary([128]), + list_to_binary([0]),list_to_binary([2]), + list_to_binary([0]),list_to_binary([0]), + list_to_binary([112]),list_to_binary([128]), + list_to_binary([0]),list_to_binary([10]), + list_to_binary([194]),list_to_binary([69]), + list_to_binary([0]),list_to_binary([0]), + list_to_binary([0]),list_to_binary([0]), + list_to_binary([0]),list_to_binary([18]), + list_to_binary([52]),list_to_binary([95])]), + + R = loop(2,0,Frame), + {R,R =:= {0,[{ie,112,itu_t_standard,ignore,10,<<194,69,0,0,0,0,0,18,52,95>>}, + {ie,92,itu_t_standard,ignore,2,<<0,0>>}, + {ie,94,itu_t_standard,ignore,2,<<129,128>>}, + {ie,89,itu_t_standard,ignore,8,<<132,0,26,133,133,0,38,148>>}]}}. + +loop(0,R,_) -> R; +loop(N,R,Frame) -> loop(N-1, decode1:decode_ie_heads_setup(Frame),Frame). + +run_dummy(0,Frame) -> + done; +run_dummy(N,Frame) -> + parse_dummy(Frame), + run_dummy(N-1,Frame). + +parse_dummy(Frame) -> true. + +run_orig(0,Frame) -> + done; +run_orig(N,Frame) -> + decode1:decode_ie_heads_setup(Frame), + run_orig(N-1,Frame). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Macros +% + +-define(VALID_ACTION(Flag), if ((Flag) band 16#10) == 16#10 -> true; + true -> false + end). +-define(GET_ACTION(Flag), ((Flag) band 16#03)). + +-define(getint16(X1,X0), (16#100*X1 + X0)). + +-define(IS_EXTENDED(X), (if ((X) band 16#80) == 16#80 -> false; + true -> true + end)). + + +%%% ---------------------------------------------------------- +%%% # ie +%%% Description: Used to encapsulate the ie head +%%% ---------------------------------------------------------- + + +-record(ie,{identifier, + coding, + action_ind, + length, + ie_body = binary}). + +%%% ---------------------------------------------------------- +%%% # bbc +%%% Description: BROADBAND BEARER CAPABILITY +%%% ---------------------------------------------------------- + +-record(scct_bbc, + {scct_pci, % parameter compatibility info + scct_bearer_class, + scct_atm_transfer_capability, + scct_user_plane_connection_configuration, + scct_susceptibility_to_clipping}). + + +%%% ---------------------------------------------------------- +%%% # cause +%%% Description: CAUSE +%%% ---------------------------------------------------------- + +-record(scct_cause, + {scct_pci, % parameter compatibility info + scct_location, + scct_cause_value, + scct_diagnostics_list = []}). + + +%%% ---------------------------------------------------------- +%%% # release_complete_uni +%%% Description: +%%% ---------------------------------------------------------- + +-record(release_complete_uni, + {scct_cause_list=[], % Cause IE's in a list where each element + % is a record of scct_cause{} + scct_geidt_list=[]}). % Generic Identifier Transport IE's in a list + % where each element is a record of scct_geidt{} + + +-define(IE_BB_BEARER_CAPABILITY, 16#5e). +-define(SCCT_PUB_NETW_SERV_LOCAL_USR, 2). +-define(SCCT_ERR_INVALID_IE_CONT, 100). +-define(DECRES_THROW_RELCOMP, error_throw_relcomp). + +-define(SCCT_P_TO_P, 0). +-define(SCCT_P_TO_MP, 1). + +-define(IE_ENDPT_REF, 16#54). +-define(IE_BB_REPEAT_INDICATOR, 16#63). + +-define(SCCT_ERR_MAND_IE_MISSING, 96). + +-define(A_CLEAR_CALL, 0). +-define(A_DISCARD_PROCEED, 1). +-define(A_DISCARD_PROCEED_STATUS, 2). + +-define(SCCT_BCOB_A, 1). +-define(SCCT_BCOB_C, 3). +-define(SCCT_BCOB_X, 16). +-define(SCCT_TRANSP_VP_SERV, 24). + +-define(SCCT_CBR, 5). +-define(SCCT_CBR_WITH_CLR_CLP_0_1, 7). +-define(SCCT_RT_VBR, 9). +-define(SCCT_RT_VBR_WITH_CLR_CLP_0_1, 19). +-define(SCCT_NON_RT_VBR, 10). +-define(SCCT_NON_RT_VBR_WITH_CLR_CLP_0_1, 11). +-define(SCCT_ABR, 12). +-define(SCCT_NOT_SUSCEPT_TO_CLIPPING, 0). +-define(SCCT_SUSCEPT_TO_CLIPPING, 1). + + + +%%% ---------------------------------------------------------- +%%% -type decode_ie_heads_setup(Bin)-> +%%% +%%% Input: Binary to body of incoming Message +%%% Output: +%%% +%%% Exceptions: +%%% Description:decode_ie_heads_setup is used both p-p and p-mp setup +%%% Never fails. Needs to be exported to be able to check +%%% if setup is p-p or p-mp. +%%% Note that if broadband rep indicator is present +%%% order must be incoming IE's must be preserved, this +%%% only applicable in msg setup +%%% ---------------------------------------------------------- +decode_ie_heads_setup(Bin)-> + decode_ie_heads_setup(Bin,no_bbc_ie,no_epr,[],no_brep). + +decode_ie_heads_setup(Bin,TypeOfCall,EprFlag,IEList,BrepFlag) when is_binary(Bin),size(Bin) >= 4 -> + {Bin1,Bin2} = split_binary(Bin,4), + [Id,F,L1,L0]= binary_to_list(Bin1), + Action = decode_action(F), + Coding = decode_ie_coding(F), + case ?getint16(L1,L0) of + Len when Len >0 -> + %%catch needed we cannot trust indata + case catch split_binary(Bin2,Len) of + {'EXIT',_} -> %%binary unpacked as far as possible + decode_ie_heads_setup(not_a_binary,TypeOfCall,EprFlag, + IEList,BrepFlag); + {Bin3,Bin4} -> + IE= #ie {identifier = Id, + coding = Coding, + action_ind= Action, + length= Len, + ie_body= Bin3}, + case Id of + ?IE_BB_BEARER_CAPABILITY -> + BbcRec=#scct_bbc{}, + %%catch needed we cannot trust indata + case catch + dec_bearer_capability(BbcRec, + binary_to_list(Bin3)) of + {'EXIT',_} -> %mand content error + CauseRec=#scct_cause{scct_location= + ?SCCT_PUB_NETW_SERV_LOCAL_USR, + scct_cause_value= + ?SCCT_ERR_INVALID_IE_CONT, + scct_diagnostics_list= + [?IE_BB_BEARER_CAPABILITY]}, + RelCompUniMsg = + #release_complete_uni{scct_cause_list= + [CauseRec]}, + {?DECRES_THROW_RELCOMP,RelCompUniMsg}; + NewBbcRec -> + case NewBbcRec + #scct_bbc.scct_user_plane_connection_configuration of + ?SCCT_P_TO_P -> + decode_ie_heads_setup(Bin4, + ?SCCT_P_TO_P, + EprFlag, + [IE|IEList], + BrepFlag); + ?SCCT_P_TO_MP -> + decode_ie_heads_setup(Bin4, + ?SCCT_P_TO_MP, + EprFlag, + [IE|IEList], + BrepFlag) + end + end; + ?IE_ENDPT_REF -> + decode_ie_heads_setup(Bin4,TypeOfCall,yes_epr, + [IE|IEList],BrepFlag); + ?IE_BB_REPEAT_INDICATOR -> + decode_ie_heads_setup(Bin4,TypeOfCall,EprFlag, + [IE|IEList],yes_brep); + _ -> + decode_ie_heads_setup(Bin4,TypeOfCall,EprFlag, + [IE|IEList],BrepFlag) + end + end; + Len when Len == 0 ->%ie body empty, treat as if whole ie was missing + decode_ie_heads_setup(Bin2,TypeOfCall,EprFlag,IEList,BrepFlag) + end; +decode_ie_heads_setup(_,?SCCT_P_TO_MP,yes_epr,IEList,no_brep) -> + {?SCCT_P_TO_MP,IEList}; +decode_ie_heads_setup(_,?SCCT_P_TO_MP,yes_epr,IEList,yes_brep) -> +%Order of incoming IEs must be preserved since BroadB Repeat Ind is present + {?SCCT_P_TO_MP,reverse(IEList)}; +decode_ie_heads_setup(_,?SCCT_P_TO_MP,no_epr,_,no_brep) -> + CauseRec=#scct_cause{scct_location=?SCCT_PUB_NETW_SERV_LOCAL_USR, + scct_cause_value=?SCCT_ERR_MAND_IE_MISSING, + scct_diagnostics_list=[?IE_ENDPT_REF]}, + RelCompUniMsg =#release_complete_uni{scct_cause_list=[CauseRec]}, + {?DECRES_THROW_RELCOMP,RelCompUniMsg}; +decode_ie_heads_setup(_,?SCCT_P_TO_P,_,IEList,no_brep) -> + {?SCCT_P_TO_P,IEList}; +decode_ie_heads_setup(_,?SCCT_P_TO_P,_,IEList,yes_brep) -> +%Order of incoming IEs must be preserved since BrodB Repeat Ind is present + {?SCCT_P_TO_P,reverse(IEList)}; +decode_ie_heads_setup(_,no_bbc_ie,_,_,_) -> + CauseRec=#scct_cause{scct_location=?SCCT_PUB_NETW_SERV_LOCAL_USR, + scct_cause_value=?SCCT_ERR_MAND_IE_MISSING, + scct_diagnostics_list=[?IE_BB_BEARER_CAPABILITY]}, + RelCompUniMsg =#release_complete_uni{scct_cause_list=[CauseRec]}, + {?DECRES_THROW_RELCOMP,RelCompUniMsg}. + + + +%%% +%%% Decode message type and header +%%% + +decode_action(Flag) -> + case ?VALID_ACTION(Flag) of + true -> + case ?GET_ACTION(Flag) of + ?A_CLEAR_CALL -> clear_call; + ?A_DISCARD_PROCEED -> discard_proceed; + ?A_DISCARD_PROCEED_STATUS -> discard_proceed_status; + _ -> undefined + end; + false -> + ignore + end. + + +%%% +%%% Decode ie coding +%%% + +decode_ie_coding(F) -> + case F band 16#60 of + 0 -> itu_t_standard; + 16#60 -> atm_forum_specific; + _ -> undefined + end. + + +%%% -------------------------------------------------------------------------- +%%% +%%% Decode of INFORMATION ELEMENT: Broadband Bearer Capability +%%% +%%% -------------------------------------------------------------------------- + +dec_bearer_capability(BbcRec, [Octet5 | Rest]) -> + NewBbcRec = + case Octet5 band 16#1f of + 16#01 -> + BbcRec#scct_bbc{scct_bearer_class = ?SCCT_BCOB_A}; + 16#03 -> + BbcRec#scct_bbc{scct_bearer_class = ?SCCT_BCOB_C}; + 16#10 -> + BbcRec#scct_bbc{scct_bearer_class = ?SCCT_BCOB_X}; + 16#18 -> + BbcRec#scct_bbc{scct_bearer_class = ?SCCT_TRANSP_VP_SERV} + end, + + case ?IS_EXTENDED(Octet5) of + true -> + dec_bearer_capability_5a(NewBbcRec, Rest); + false -> + dec_bearer_capability_6(NewBbcRec, Rest) + end. + +dec_bearer_capability_5a(BbcRec,[Octet5a | Rest]) -> + NewBbcRec = + case Octet5a band 16#7f of + 16#05 -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_CBR}; + 16#07 -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_CBR_WITH_CLR_CLP_0_1}; + 16#09 -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_RT_VBR}; + 16#13 -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_RT_VBR_WITH_CLR_CLP_0_1}; + 16#0a -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_NON_RT_VBR}; + 16#0b -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_NON_RT_VBR_WITH_CLR_CLP_0_1}; + 16#0c -> + BbcRec#scct_bbc{scct_atm_transfer_capability = + ?SCCT_ABR} + end, + dec_bearer_capability_6(NewBbcRec,Rest). + + +dec_bearer_capability_6(BbcRec, [Octet6]) -> + STC = + case (Octet6 bsr 5) band 16#03 of + 16#00 -> + ?SCCT_NOT_SUSCEPT_TO_CLIPPING; + 16#01 -> + ?SCCT_SUSCEPT_TO_CLIPPING + end, + + UPCC = + case Octet6 band 16#03 of + 16#00 -> + ?SCCT_P_TO_P; + 16#01 -> + ?SCCT_P_TO_MP + end, + + NewBbcRec = BbcRec#scct_bbc{scct_susceptibility_to_clipping = STC, + scct_user_plane_connection_configuration = UPCC}. + + +reverse(L) -> + reverse(L,[]). + +reverse([E|Rest],Acc) -> + reverse(Rest,[E|acc]); +reverse([],Acc) -> Acc. diff --git a/lib/compiler/test/inline_SUITE_data/itracer.erl b/lib/compiler/test/inline_SUITE_data/itracer.erl new file mode 100644 index 0000000000..93f24e9bb1 --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/itracer.erl @@ -0,0 +1,407 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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(itracer). +-export([itracer/0]). + +%%%--------------------------------------------------------------------------- +%%% +%%% This is a little raytracer. +%%% +%%%--------------------------------------------------------------------------- + + +%%---------------------------------------------------------------------------- +%% Constructors. +%%---------------------------------------------------------------------------- + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +itracer() -> + C1 = ccreate(), + C2 = set_width(C1,100), + C3 = set_height(C2,100), + C4 = initialize(C3), + Sphere1 = screate(40,vcreate(35,10,0),{1,0,0}), + Sphere2 = screate(35,vcreate(-25,-25,50),{0,1,0}), + PL = traceloop(C4,50,50,[Sphere1,Sphere2]). + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +overflow_prevent(A) when A<1 -> A; +overflow_prevent(_) -> 1. + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +traceloop(Camera,Width,Height,Scene) -> + traceloop(Camera,Width,Height,0,0,Scene,[]). + + +traceloop(_,_,Height,_,Y,_,PL) when Height=<Y -> + PL; + +traceloop(Camera,Width,Height,X,Y,Scene,PL) when Width=<X -> + traceloop(Camera,Width,Height,0,Y+1,Scene,PL); + +traceloop(Camera,Width,Height,X,Y,Scene,PL) -> + Ray = ray(Camera,X/Width,Y/Height), + {R1,G1,B1} = traceray(Ray,Scene,1), + R2 = overflow_prevent(R1), + G2 = overflow_prevent(G1), + B2 = overflow_prevent(B1), + P = {trunc(R2*255), trunc(G2*255), trunc(B2*255)}, + traceloop(Camera,Width,Height,X+1,Y,Scene,[{X,Y,P}|PL]). + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +traceray(Ray,Scene,Level) -> + Hit = findintersection(Ray,Scene,Level), + case Hit of + nohit -> {0,0,0}; + {[T|Ts],Object} -> shaderay(Ray,Scene,Level,T,Object) + end. + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +% Here we loop through all the objects in the scene to find the +% closest intersection. + +findintersection(_,[],_) -> nohit; + +findintersection(Ray,[Object|Objects],Level) -> + Ts = intersection(Object,Ray), + Hit1 = findintersection(Ray,Objects,Level), + Hit2 = closesthit(Ts,Object,Hit1). + + +closesthit(nohit,_,nohit) -> nohit; +closesthit(nohit,_,{[T|Ts],Obj}) when T>0 -> {[T|Ts],Obj}; +closesthit(nohit,_,_) -> nohit; +closesthit([T|Ts],Obj,nohit) when T>0 -> {[T|Ts],Obj}; +closesthit(_,_,nohit) -> nohit; +closesthit([T1|Ts1],Obj1,{[T2|Ts2],Obj2}) when T1>0,T1<T2 -> {[T1|Ts1],Obj1}; +closesthit([T1|Ts1],Obj1,{[T2|Ts2],Obj2}) when T2>0,T2<T1 -> {[T2|Ts2],Obj2}; +closesthit(_,_,_) -> nohit. + + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +shaderay(Ray,Scene,Level,T,Object) -> + Direction = get_direction(Ray), + Origin = get_origin(Ray), + Point = add(Origin, mul(T, Direction)), + Normal = calcnormal(Object, Point), + Diffuse = -dot(Normal, Direction), + ReflectionVector = reflection(Ray,Normal), + NewOrigin = add(Point, mul(0.0001, Normal)), + ReflectionRay = rcreate(NewOrigin,ReflectionVector), + {Red1,Green1,Blue1} = get_color(Object), + if + Level<4, Diffuse>0 -> + {Red2,Green2,Blue2} = traceray(ReflectionRay,Scene,Level+1), + {Diffuse*Red1 + 0.5*Red2, + Diffuse*Green1 + 0.5*Green2, + Diffuse*Blue1 + 0.5*Blue2}; + Level<4, Diffuse<0 -> + {0,0,0}; + true -> + {0,0,0} + end. + + +%%---------------------------------------------------------------------------- +%% Har nedan foljer bara ett gang testfunktioner.... +%%---------------------------------------------------------------------------- +-record(camera,{width,height,zoom,position,lookat,up,right,down,corner}). + +%%%--------------------------------------------------------------------------- +%%% +%%% Useful camera operations. +%%% +%%%--------------------------------------------------------------------------- + + +%%---------------------------------------------------------------------------- +%% Constructors. +%%---------------------------------------------------------------------------- + +ccreate() -> + #camera{width=100, height=100, zoom=256, + position = vcreate(0,0,-256), + lookat = vcreate(0,0,0), + up = vcreate(0,1,0)}. + + + +%%---------------------------------------------------------------------------- +%% Selectors and modifiers. +%%---------------------------------------------------------------------------- + +set_width(C,Width) -> C#camera{width=Width}. +set_height(C,Height) -> C#camera{height=Height}. +set_zoom(C,Zoom) -> C#camera{zoom=Zoom}. +cset_position(C,Pos) -> C#camera{position=Pos}. +set_lookat(C,Lookat) -> C#camera{lookat=Lookat}. +set_up(C,Up) -> C#camera{up=Up}. + +get_width(C) -> C#camera.width. +get_height(C) -> C#camera.height. +get_zoom(C) -> C#camera.zoom. +cget_position(C) -> C#camera.position. +get_lookat(C) -> C#camera.lookat. +get_up(C) -> C#camera.up. + + + +%%---------------------------------------------------------------------------- +%% Operators. +%%---------------------------------------------------------------------------- + +initialize(C) -> + Dir = normalize(sub(C#camera.lookat, C#camera.position)), + Up1 = normalize(C#camera.up), + D = dot(Up1, Dir), + Up2 = normalize(sub(Up1, mul(D, Dir))), + Down = mul(-1, Up2), + Right = normalize(cross(Up2,Dir)), + Corner1 = mul(C#camera.zoom, Dir), + Corner2 = add(Corner1, mul(-C#camera.width/2, Right)), + Corner3 = add(Corner2, mul(-C#camera.height/2, Down)), + C2 = C#camera{down=Down, right=Right, corner=Corner3}. + + +% +% X och Y ska ligga i intervallet [0..1] +% +ray(C,X,Y) -> + Right = mul(C#camera.width*X, C#camera.right), + Down = mul(C#camera.height*Y, C#camera.down), + Point = add(C#camera.corner, add(Right,Down)), + rcreate(C#camera.position,normalize(Point)). + + + +%%---------------------------------------------------------------------------- +%% E N D O F F I L E +%%---------------------------------------------------------------------------- +-record(vector,{x,y,z}). + + +%%%--------------------------------------------------------------------------- +%%% +%%% Useful vector operations. +%%% +%%%--------------------------------------------------------------------------- + + +%%---------------------------------------------------------------------------- +%% Constructors. +%%---------------------------------------------------------------------------- + +vcreate() -> + #vector{x=0,y=0,z=0}. + + +vcreate(X,Y,Z) -> + #vector{x=X,y=Y,z=Z}. + + + +%%---------------------------------------------------------------------------- +%% Selectors and modifiers. +%%---------------------------------------------------------------------------- + +set_x(V,X) -> V#vector{x=X}. +set_y(V,Y) -> V#vector{y=Y}. +set_z(V,Z) -> V#vector{z=Z}. + +get_x(V) -> V#vector.x. +get_y(V) -> V#vector.y. +get_z(V) -> V#vector.z. + + + +%%---------------------------------------------------------------------------- +%% Operators. +%%---------------------------------------------------------------------------- + +add(A,B) -> + #vector{x=A#vector.x+B#vector.x, + y=A#vector.y+B#vector.y, + z=A#vector.z+B#vector.z}. + + +sub(A,B) -> + #vector{x=A#vector.x-B#vector.x, + y=A#vector.y-B#vector.y, + z=A#vector.z-B#vector.z}. + + +mul(T,A) -> + #vector{x=A#vector.x * T, + y=A#vector.y * T, + z=A#vector.z * T}. + + +dot(A,B) -> + A#vector.x*B#vector.x + + A#vector.y*B#vector.y + + A#vector.z*B#vector.z. + + +normalize(A) -> + S = 1 / math:sqrt(dot(A,A)), + vcreate(A#vector.x * S, A#vector.y * S, A#vector.z * S). + + +cross(A,B) -> + #vector{x = A#vector.y*B#vector.z - A#vector.z*B#vector.y, + y = A#vector.z*B#vector.x - A#vector.x*B#vector.z, + z = A#vector.x*B#vector.y - A#vector.y*B#vector.x}. + + +%%---------------------------------------------------------------------------- +%% E N D O F F I L E +%%---------------------------------------------------------------------------- +-record(ray,{origin,direction}). + +%%%--------------------------------------------------------------------------- +%%% +%%% Useful ray stuff. +%%% +%%%--------------------------------------------------------------------------- + + +%%---------------------------------------------------------------------------- +%% Constructors. +%%---------------------------------------------------------------------------- + +rcreate() -> + #ray{origin=vcreate(0,0,0), direction=vcreate(0,0,1)}. + + +rcreate(Origin,Direction) -> + #ray{origin=Origin, direction=Direction}. + + + +%%---------------------------------------------------------------------------- +%% Selectors and modifiers. +%%---------------------------------------------------------------------------- + +set_origin(R,Origin) -> R#ray{origin=Origin}. +set_direction(R,Direction) -> R#ray{direction=Direction}. + +get_origin(R) -> R#ray.origin. +get_direction(R) -> R#ray.direction. + + + +%%---------------------------------------------------------------------------- +%% +%%---------------------------------------------------------------------------- + +reflection(R,N) -> + A = mul(2*dot(N, R#ray.direction), N), + normalize(sub(R#ray.direction, A)). + + + +%%---------------------------------------------------------------------------- +%% E N D O F F I L E +%%---------------------------------------------------------------------------- +-record(sphere,{radius,position,color}). + +%%%--------------------------------------------------------------------------- +%%% +%%% Useful sphere operations. +%%% +%%%--------------------------------------------------------------------------- + + +%%---------------------------------------------------------------------------- +%% Constructors. +%%---------------------------------------------------------------------------- + +screate() -> + #sphere{radius=1, position=vcreate(0,0,0), color={1,1,1}}. + + +screate(Radius,Position,Color) -> + #sphere{radius=Radius, position=Position, color=Color}. + + + +%%---------------------------------------------------------------------------- +%% Selectors and modifiers. +%%---------------------------------------------------------------------------- + +set_radius(S,Radius) -> S#sphere{radius=Radius}. +sset_position(S,Position) -> S#sphere{position=Position}. +set_color(S,Color) -> S#sphere{color=Color}. + +get_radius(S) -> S#sphere.radius. +sget_position(S) -> S#sphere.position. +get_color(S) -> S#sphere.color. + + + +%%---------------------------------------------------------------------------- +%% Calculates the intersection between a ray and the sphere. +%%---------------------------------------------------------------------------- + +intersection(S,Ray) -> + SR = sub(S#sphere.position,get_origin(Ray)), + B = dot(SR,get_direction(Ray)), + C = dot(SR,SR), + Root = B*B-C + S#sphere.radius * S#sphere.radius, + if + Root>0 -> + SquareRoot = math:sqrt(Root), + [B-SquareRoot,B+SquareRoot]; + true -> + nohit + end. + +calcnormal(S,P) -> + normalize(sub(P, S#sphere.position)). + %mul(1/S#sphere.radius, sub(P, S#sphere.position)). + + + +%%---------------------------------------------------------------------------- +%% E N D O F F I L E +%%---------------------------------------------------------------------------- diff --git a/lib/compiler/test/inline_SUITE_data/pseudoknot.erl b/lib/compiler/test/inline_SUITE_data/pseudoknot.erl new file mode 100644 index 0000000000..5b2bf1694a --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/pseudoknot.erl @@ -0,0 +1,2575 @@ +-module(pseudoknot). + +-export([?MODULE/0]). + +?MODULE() -> + R = loop(1, 0), + abs(R-33.7976) < 0.0001. + +append([H|T], Z) -> + [H|append(T, Z)]; +append([], X) -> + X. + +atan2(Y,X) when X>0.0 -> + math:atan(Y/X); +atan2(Y,X) when Y<0.0 -> + if + X == 0.0 -> -1.57079632679489661923; + true -> math:atan(Y/X) - 3.14159265358979323846 + end; +atan2(Y,X) -> + if + X == 0.0 -> 1.57079632679489661923; + true -> math:atan(Y/X) + 3.14159265358979323846 + end. + +% -- POINTS ------------------------------------------------------------------ + +%pt ::= {X, Y, Z} where X,Y,Z are floats + +pt_sub({X1, Y1, Z1}, {X2, Y2, Z2}) + when is_float(X1), is_float(Y1), is_float(Z1), + is_float(X2), is_float(Y2), is_float(Z2) -> + {X1 - X2, Y1 - Y2, Z1 - Z2}. + +pt_dist({X1, Y1, Z1}, {X2, Y2, Z2}) + when is_float(X1), is_float(Y1), is_float(Z1), + is_float(X2), is_float(Y2), is_float(Z2) -> + Dx = X1 - X2, + Dy = Y1 - Y2, + Dz = Z1 - Z2, + math:sqrt(Dx * Dx + Dy * Dy + Dz * Dz). + +pt_phi({X, Y, Z}) + when is_float(X), is_float(Z) -> + B = atan2(X, Z), + atan2(math:cos(B) * Z + math:sin(B) * X, Y). + +pt_theta ({X, _, Z}) -> + atan2(X, Z). + +% -- COORDINATE TRANSFORMATIONS ---------------------------------------------- + +% The notation for the transformations follows "Paul, R.P. (1981) Robot +% Manipulators. MIT Press." with the exception that our transformation +% matrices don't have the perspective terms and are the transpose of +% Paul's one. See also "M\"antyl\"a, M. (1985) An Introduction to +% Solid Modeling, Computer Science Press" Appendix A. +% +% The components of a transformation matrix are named like this: +% +% a b c +% d e f +% g h i +% tx ty tz +% +% The components tx, ty, and tz are the translation vector. + +%tfo ::= {A,B,C,D,E,F,G,H,I,Tx,Ty,Tz} where all elements are floats + +tfo_id() -> {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}. + +% The function "tfo-apply" multiplies a transformation matrix, tfo, by a +% point vector, p. The result is a new point. + +tfo_apply ({A,B,C,D,E,F,G,H,I,Tx,Ty,Tz}, {X,Y,Z}) + when is_float(A), is_float(B), is_float(C), is_float(D), is_float(E), + is_float(F), is_float(G), is_float(H), is_float(I), + is_float(Tx), is_float(Ty), is_float(Tz), is_float(X), is_float(Y), is_float(Z) -> + {X * A + Y * D + Z * G + Tx, + X * B + Y * E + Z * H + Ty, + X * C + Y * F + Z * I + Tz}. + +% The function "tfo-combine" multiplies two transformation matrices A and B. +% The result is a new matrix which cumulates the transformations described +% by A and B. + +tfo_combine({A_a,A_b,A_c,A_d,A_e,A_f,A_g,A_h,A_i,A_tx,A_ty,A_tz}, + {B_a,B_b,B_c,B_d,B_e,B_f,B_g,B_h,B_i,B_tx,B_ty,B_tz}) + when is_float(A_a), is_float(A_b), is_float(A_c), is_float(A_d), is_float(A_e), + is_float(A_f), is_float(A_g), is_float(A_h), is_float(A_i), is_float(A_tx), + is_float(A_ty), is_float(A_tz), + is_float(B_a), is_float(B_b), is_float(B_c), is_float(B_d), is_float(B_e), + is_float(B_f), is_float(B_g), is_float(B_h), is_float(B_i), is_float(B_tx), + is_float(B_ty), is_float(B_tz) -> + {A_a * B_a + A_b * B_d + A_c * B_g, + A_a * B_b + A_b * B_e + A_c * B_h, + A_a * B_c + A_b * B_f + A_c * B_i, + A_d * B_a + A_e * B_d + A_f * B_g, + A_d * B_b + A_e * B_e + A_f * B_h, + A_d * B_c + A_e * B_f + A_f * B_i, + A_g * B_a + A_h * B_d + A_i * B_g, + A_g * B_b + A_h * B_e + A_i * B_h, + A_g * B_c + A_h * B_f + A_i * B_i, + A_tx * B_a + A_ty * B_d + A_tz * B_g + B_tx, + A_tx * B_b + A_ty * B_e + A_tz * B_h + B_ty, + A_tx * B_c + A_ty * B_f + A_tz * B_i + B_tz}. + +% The function "tfo-inv-ortho" computes the inverse of a homogeneous +% transformation matrix. + +tfo_inv_ortho({A,B,C,D,E,F,G,H,I,Tx,Ty,Tz}) + when is_float(A), is_float(B), is_float(C), is_float(D), is_float(E), is_float(F), + is_float(G), is_float(H), is_float(I), is_float(Tx), is_float(Ty), is_float(Tz) -> + {A,D,G, + B,E,H, + C,F,I, + -(A * Tx + B * Ty + C * Tz), + -(D * Tx + E * Ty + F * Tz), + -(G * Tx + H * Ty + I * Tz)}. + +% Given three points p1, p2, and p3, the function "tfo-align" computes +% a transformation matrix such that point p1 gets mapped to (0,0,0), p2 gets +% mapped to the Y axis and p3 gets mapped to the YZ plane. + +tfo_align({X1,Y1,Z1},{X2,Y2,Z2},{X3,Y3,Z3}) + when is_float(X1), is_float(Y1), is_float(Z1), + is_float(X2), is_float(Y2), is_float(Z2), + is_float(X3), is_float(Y3), is_float(Z3) -> + X31 = X3 - X1, + Y31 = Y3 - Y1, + Z31 = Z3 - Z1, + Rotpy = pt_sub({X2,Y2,Z2},{X1,Y1,Z1}), + Phi = pt_phi(Rotpy), + Theta = pt_theta(Rotpy), + Sinp = math:sin(Phi), + Sint = math:sin(Theta), + Cosp = math:cos(Phi), + Cost = math:cos(Theta), + Sinpsint = Sinp * Sint, + Sinpcost = Sinp * Cost, + Cospsint = Cosp * Sint, + Cospcost = Cosp * Cost, + Rotpz = {Cost * X31 - Sint * Z31, + Sinpsint * X31 + Cosp * Y31 + Sinpcost * Z31, + Cospsint * X31 - Sinp * Y31 + Cospcost * Z31}, + Rho = pt_theta(Rotpz), + Cosr = math:cos(Rho), + Sinr = math:sin(Rho), + X = Z1 * Sint - X1 * Cost, + Y = -X1 * Sinpsint - Y1 * Cosp - Z1 * Sinpcost, + Z = Y1 * Sinp - Z1 * Cospcost - X1 * Cospsint, + {Cost * Cosr - Cospsint * Sinr, + Sinpsint, + Cost * Sinr + Cospsint * Cosr, + Sinp * Sinr, + Cosp, + -Sinp * Cosr, + -Sint * Cosr - Cospcost * Sinr, + Sinpcost, + Cospcost * Cosr - Sint * Sinr, + X * Cosr - Z * Sinr, + Y, + X * Sinr + Z * Cosr}. + +% -- NUCLEIC ACID CONFORMATIONS DATA BASE ------------------------------------ + +% Numbering of atoms follows the paper: +% +% IUPAC-IUB Joint Commission on Biochemical Nomenclature (JCBN) +% (1983) Abbreviations and Symbols for the Description of +% Conformations of Polynucleotide Chains. Eur. J. Biochem 131, +% 9-15. + +% Define part common to all 4 nucleotide types. + +%nuc ::= { +% tfo,tfo,tfo,tfo, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% A/C/G/U, +% nuc_specific +% } + +% dgf_base_tfo ; defines the standard position for wc and wc_dumas +% p_o3'_275_tfo ; defines the standard position for the connect function +% p_o3'_180_tfo +% p_o3'_60_tfo +% p o1p o2p o5' c5' h5' h5'' c4' h4' o4' c1' h1' c2' h2'' o2' h2' c3' +% h3' o3' n1 n3 c2 c4 c5 c6 + +type({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,X, + _}) -> X. + +nuc_C1_({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,X,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_C2({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,X,_,_,_,_, + _}) -> X. + +nuc_C3_({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + X,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_C4({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,X,_,_,_, + _}) -> X. + +nuc_C4_({_,_,_,_,_,_,_,_,_,_, + _,X,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_N1({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,X,_,_,_,_,_,_, + _}) -> X. + +nuc_O3_({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,X,_,_,_,_,_,_,_, + _}) -> X. + +nuc_P({_,_,_,_,X,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_dgf_base_tfo({X,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_p_o3__180_tfo({_,_,X,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_p_o3__275_tfo({_,X,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_p_o3__60_tfo({_,_,_,X,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +rA_N9({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,a, + {_,_,X,_,_,_,_,_}}) -> X. + +rG_N9({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,g, + {_,_,X,_,_,_,_,_,_}}) -> X. + + +%nuc ::= { +% tfo,tfo,tfo,tfo, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% A/C/G/U, +% nuc_specific +% } + +% Define remaining atoms for each nucleotide type. + +%nuc_specific +% a {N6,N7,N9,C8,H2,H61,H62,H8} +% c {N4,O2,H41,H42,H5,H6} +% g {N2,N7,N9,C8,O6,H1,H21,H22,H8} +% u {O2,O4,H3,H5,H6} + +% Database of nucleotide conformations: + +rA() -> + { + {-0.0018, -0.8207, 0.5714, % dgf_base_tfo + 0.2679, -0.5509, -0.7904, + 0.9634, 0.1517, 0.2209, + 0.0073, 8.4030, 0.6232}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4550, 8.2120, -2.8810}, % C5' + {5.4546, 8.8508, -1.9978}, % H5' + {5.7588, 8.6625, -3.8259}, % H5'' + {6.4970, 7.1480, -2.5980}, % C4' + {7.4896, 7.5919, -2.5214}, % H4' + {6.1630, 6.4860, -1.3440}, % O4' + {6.5400, 5.1200, -1.4190}, % C1' + {7.2763, 4.9681, -0.6297}, % H1' + {7.1940, 4.8830, -2.7770}, % C2' + {6.8667, 3.9183, -3.1647}, % H2'' + {8.5860, 5.0910, -2.6140}, % O2' + {8.9510, 4.7626, -1.7890}, % H2' + {6.5720, 6.0040, -3.6090}, % C3' + {5.5636, 5.7066, -3.8966}, % H3' + {7.3801, 6.3562, -4.7350}, % O3' + {4.7150, 0.4910, -0.1360}, % N1 + {6.3490, 2.1730, -0.6020}, % N3 + {5.9530, 0.9650, -0.2670}, % C2 + {5.2900, 2.9790, -0.8260}, % C4 + {3.9720, 2.6390, -0.7330}, % C5 + {3.6770, 1.3160, -0.3660}, % C6 + a, { + {2.4280, 0.8450, -0.2360}, % N6 + {3.1660, 3.7290, -1.0360}, % N7 + {5.3170, 4.2990, -1.1930}, % N9 + {4.0100, 4.6780, -1.2990}, % C8 + {6.6890, 0.1903, -0.0518}, % H2 + {1.6470, 1.4460, -0.4040}, % H61 + {2.2780, -0.1080, -0.0280}, % H62 + {3.4421, 5.5744, -1.5482}} % H8 + }. + +rA01() -> + { + {-0.0043, -0.8175, 0.5759, % dgf_base_tfo + 0.2617, -0.5567, -0.7884, + 0.9651, 0.1473, 0.2164, + 0.0359, 8.3929, 0.5532}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4352, 8.2183, -2.7757}, % C5' + {5.3830, 8.7883, -1.8481}, % H5' + {5.7729, 8.7436, -3.6691}, % H5'' + {6.4830, 7.1518, -2.5252}, % C4' + {7.4749, 7.5972, -2.4482}, % H4' + {6.1626, 6.4620, -1.2827}, % O4' + {6.5431, 5.0992, -1.3905}, % C1' + {7.2871, 4.9328, -0.6114}, % H1' + {7.1852, 4.8935, -2.7592}, % C2' + {6.8573, 3.9363, -3.1645}, % H2'' + {8.5780, 5.1025, -2.6046}, % O2' + {8.9516, 4.7577, -1.7902}, % H2' + {6.5522, 6.0300, -3.5612}, % C3' + {5.5420, 5.7356, -3.8459}, % H3' + {7.3487, 6.4089, -4.6867}, % O3' + {4.7442, 0.4514, -0.1390}, % N1 + {6.3687, 2.1459, -0.5926}, % N3 + {5.9795, 0.9335, -0.2657}, % C2 + {5.3052, 2.9471, -0.8125}, % C4 + {3.9891, 2.5987, -0.7230}, % C5 + {3.7016, 1.2717, -0.3647}, % C6 + a, { + {2.4553, 0.7925, -0.2390}, % N6 + {3.1770, 3.6859, -1.0198}, % N7 + {5.3247, 4.2695, -1.1710}, % N9 + {4.0156, 4.6415, -1.2759}, % C8 + {6.7198, 0.1618, -0.0547}, % H2 + {1.6709, 1.3900, -0.4039}, % H61 + {2.3107, -0.1627, -0.0373}, % H62 + {3.4426, 5.5361, -1.5199}} % H8 + }. + +rA02() -> + { + {0.5566, 0.0449, 0.8296, % dgf_base_tfo + 0.5125, 0.7673, -0.3854, + -0.6538, 0.6397, 0.4041, + -9.1161, -3.7679, -2.9968}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.5778, 6.6594, -4.0364}, % C5' + {4.9220, 7.1963, -4.9204}, % H5' + {3.7996, 5.9091, -4.1764}, % H5'' + {5.7873, 5.8869, -3.5482}, % C4' + {6.0405, 5.0875, -4.2446}, % H4' + {6.9135, 6.8036, -3.4310}, % O4' + {7.7293, 6.4084, -2.3392}, % C1' + {8.7078, 6.1815, -2.7624}, % H1' + {7.1305, 5.1418, -1.7347}, % C2' + {7.2040, 5.1982, -0.6486}, % H2'' + {7.7417, 4.0392, -2.3813}, % O2' + {8.6785, 4.1443, -2.5630}, % H2' + {5.6666, 5.2728, -2.1536}, % C3' + {5.1747, 5.9805, -1.4863}, % H3' + {4.9997, 4.0086, -2.1973}, % O3' + {10.3245, 8.5459, 1.5467}, % N1 + {9.8051, 6.9432, -0.1497}, % N3 + {10.5175, 7.4328, 0.8408}, % C2 + {8.7523, 7.7422, -0.4228}, % C4 + {8.4257, 8.9060, 0.2099}, % C5 + {9.2665, 9.3242, 1.2540}, % C6 + a, { + {9.0664, 10.4462, 1.9610}, % N6 + {7.2750, 9.4537, -0.3428}, % N7 + {7.7962, 7.5519, -1.3859}, % N9 + {6.9479, 8.6157, -1.2771}, % C8 + {11.4063, 6.9047, 1.1859}, % H2 + {8.2845, 11.0341, 1.7552}, % H61 + {9.6584, 10.6647, 2.7198}, % H62 + {6.0430, 8.9853, -1.7594}} % H8 + }. + +rA03() -> + { + {-0.5021, 0.0731, 0.8617, % dgf_base_tfo + -0.8112, 0.3054, -0.4986, + -0.2996, -0.9494, -0.0940, + 6.4273, -5.1944, -3.7807}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.1214, 6.7116, -1.9049}, % C5' + {3.3465, 5.9610, -2.0607}, % H5' + {4.0789, 7.2928, -0.9837}, % H5'' + {5.4170, 5.9293, -1.8186}, % C4' + {5.4506, 5.3400, -0.9023}, % H4' + {5.5067, 5.0417, -2.9703}, % O4' + {6.8650, 4.9152, -3.3612}, % C1' + {7.1090, 3.8577, -3.2603}, % H1' + {7.7152, 5.7282, -2.3894}, % C2' + {8.5029, 6.2356, -2.9463}, % H2'' + {8.1036, 4.8568, -1.3419}, % O2' + {8.3270, 3.9651, -1.6184}, % H2' + {6.7003, 6.7565, -1.8911}, % C3' + {6.5898, 7.5329, -2.6482}, % H3' + {7.0505, 7.2878, -0.6105}, % O3' + {9.6740, 4.7656, -7.6614}, % N1 + {9.0739, 4.3013, -5.3941}, % N3 + {9.8416, 4.2192, -6.4581}, % C2 + {7.9885, 5.0632, -5.6446}, % C4 + {7.6822, 5.6856, -6.8194}, % C5 + {8.5831, 5.5215, -7.8840}, % C6 + a, { + {8.4084, 6.0747, -9.0933}, % N6 + {6.4857, 6.3816, -6.7035}, % N7 + {6.9740, 5.3703, -4.7760}, % N9 + {6.1133, 6.1613, -5.4808}, % C8 + {10.7627, 3.6375, -6.4220}, % H2 + {7.6031, 6.6390, -9.2733}, % H61 + {9.1004, 5.9708, -9.7893}, % H62 + {5.1705, 6.6830, -5.3167}} % H8 + }. + +rA04() -> + { + {-0.5426, -0.8175, 0.1929, % dgf_base_tfo + 0.8304, -0.5567, -0.0237, + 0.1267, 0.1473, 0.9809, + -0.5075, 8.3929, 0.2229}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4352, 8.2183, -2.7757}, % C5' + {5.3830, 8.7883, -1.8481}, % H5' + {5.7729, 8.7436, -3.6691}, % H5'' + {6.4830, 7.1518, -2.5252}, % C4' + {7.4749, 7.5972, -2.4482}, % H4' + {6.1626, 6.4620, -1.2827}, % O4' + {6.5431, 5.0992, -1.3905}, % C1' + {7.2871, 4.9328, -0.6114}, % H1' + {7.1852, 4.8935, -2.7592}, % C2' + {6.8573, 3.9363, -3.1645}, % H2'' + {8.5780, 5.1025, -2.6046}, % O2' + {8.9516, 4.7577, -1.7902}, % H2' + {6.5522, 6.0300, -3.5612}, % C3' + {5.5420, 5.7356, -3.8459}, % H3' + {7.3487, 6.4089, -4.6867}, % O3' + {3.6343, 2.6680, 2.0783}, % N1 + {5.4505, 3.9805, 1.2446}, % N3 + {4.7540, 3.3816, 2.1851}, % C2 + {4.8805, 3.7951, 0.0354}, % C4 + {3.7416, 3.0925, -0.2305}, % C5 + {3.0873, 2.4980, 0.8606}, % C6 + a, { + {1.9600, 1.7805, 0.7462}, % N6 + {3.4605, 3.1184, -1.5906}, % N7 + {5.3247, 4.2695, -1.1710}, % N9 + {4.4244, 3.8244, -2.0953}, % C8 + {5.0814, 3.4352, 3.2234}, % H2 + {1.5423, 1.6454, -0.1520}, % H61 + {1.5716, 1.3398, 1.5392}, % H62 + {4.2675, 3.8876, -3.1721}} % H8 + }. + +rA05() -> + { + {-0.5891, 0.0449, 0.8068, % dgf_base_tfo + 0.5375, 0.7673, 0.3498, + -0.6034, 0.6397, -0.4762, + -0.3019, -3.7679, -9.5913}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.5778, 6.6594, -4.0364}, % C5' + {4.9220, 7.1963, -4.9204}, % H5' + {3.7996, 5.9091, -4.1764}, % H5'' + {5.7873, 5.8869, -3.5482}, % C4' + {6.0405, 5.0875, -4.2446}, % H4' + {6.9135, 6.8036, -3.4310}, % O4' + {7.7293, 6.4084, -2.3392}, % C1' + {8.7078, 6.1815, -2.7624}, % H1' + {7.1305, 5.1418, -1.7347}, % C2' + {7.2040, 5.1982, -0.6486}, % H2'' + {7.7417, 4.0392, -2.3813}, % O2' + {8.6785, 4.1443, -2.5630}, % H2' + {5.6666, 5.2728, -2.1536}, % C3' + {5.1747, 5.9805, -1.4863}, % H3' + {4.9997, 4.0086, -2.1973}, % O3' + {10.2594, 10.6774, -1.0056}, % N1 + {9.7528, 8.7080, -2.2631}, % N3 + {10.4471, 9.7876, -1.9791}, % C2 + {8.7271, 8.5575, -1.3991}, % C4 + {8.4100, 9.3803, -0.3580}, % C5 + {9.2294, 10.5030, -0.1574}, % C6 + a, { + {9.0349, 11.3951, 0.8250}, % N6 + {7.2891, 8.9068, 0.3121}, % N7 + {7.7962, 7.5519, -1.3859}, % N9 + {6.9702, 7.8292, -0.3353}, % C8 + {11.3132, 10.0537, -2.5851}, % H2 + {8.2741, 11.2784, 1.4629}, % H61 + {9.6733, 12.1368, 0.9529}, % H62 + {6.0888, 7.3990, 0.1403}} % H8 + }. + +rA06() -> + { + {-0.9815, 0.0731, -0.1772, % dgf_base_tfo + 0.1912, 0.3054, -0.9328, + -0.0141, -0.9494, -0.3137, + 5.7506, -5.1944, 4.7470}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.1214, 6.7116, -1.9049}, % C5' + {3.3465, 5.9610, -2.0607}, % H5' + {4.0789, 7.2928, -0.9837}, % H5'' + {5.4170, 5.9293, -1.8186}, % C4' + {5.4506, 5.3400, -0.9023}, % H4' + {5.5067, 5.0417, -2.9703}, % O4' + {6.8650, 4.9152, -3.3612}, % C1' + {7.1090, 3.8577, -3.2603}, % H1' + {7.7152, 5.7282, -2.3894}, % C2' + {8.5029, 6.2356, -2.9463}, % H2'' + {8.1036, 4.8568, -1.3419}, % O2' + {8.3270, 3.9651, -1.6184}, % H2' + {6.7003, 6.7565, -1.8911}, % C3' + {6.5898, 7.5329, -2.6482}, % H3' + {7.0505, 7.2878, -0.6105}, % O3' + {6.6624, 3.5061, -8.2986}, % N1 + {6.5810, 3.2570, -5.9221}, % N3 + {6.5151, 2.8263, -7.1625}, % C2 + {6.8364, 4.5817, -5.8882}, % C4 + {7.0116, 5.4064, -6.9609}, % C5 + {6.9173, 4.8260, -8.2361}, % C6 + a, { + {7.0668, 5.5163, -9.3763}, % N6 + {7.2573, 6.7070, -6.5394}, % N7 + {6.9740, 5.3703, -4.7760}, % N9 + {7.2238, 6.6275, -5.2453}, % C8 + {6.3146, 1.7741, -7.3641}, % H2 + {7.2568, 6.4972, -9.3456}, % H61 + {7.0437, 5.0478, -10.2446}, % H62 + {7.4108, 7.6227, -4.8418}} % H8 + }. + +rA07() -> + { + {0.2379, 0.1310, -0.9624, % dgf_base_tfo + -0.5876, -0.7696, -0.2499, + -0.7734, 0.6249, -0.1061, + 30.9870, -26.9344, 42.6416}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.3505, 8.4697, 42.6565}, % C5' + {39.1377, 7.5433, 42.1230}, % H5' + {39.7203, 9.3119, 42.0717}, % H5'' + {38.0405, 8.9195, 43.2869}, % C4' + {37.3687, 9.3036, 42.5193}, % H4' + {37.4319, 7.8146, 43.9387}, % O4' + {37.1959, 8.1354, 45.3237}, % C1' + {36.1788, 8.5202, 45.3970}, % H1' + {38.1721, 9.2328, 45.6504}, % C2' + {39.1555, 8.7939, 45.8188}, % H2'' + {37.7862, 10.0617, 46.7013}, % O2' + {37.3087, 9.6229, 47.4092}, % H2' + {38.1844, 10.0268, 44.3367}, % C3' + {39.1578, 10.5054, 44.2289}, % H3' + {37.0547, 10.9127, 44.3441}, % O3' + {34.8811, 4.2072, 47.5784}, % N1 + {35.1084, 6.1336, 46.1818}, % N3 + {34.4108, 5.1360, 46.7207}, % C2 + {36.3908, 6.1224, 46.6053}, % C4 + {36.9819, 5.2334, 47.4697}, % C5 + {36.1786, 4.1985, 48.0035}, % C6 + a, { + {36.6103, 3.2749, 48.8452}, % N6 + {38.3236, 5.5522, 47.6595}, % N7 + {37.3887, 7.0024, 46.2437}, % N9 + {38.5055, 6.6096, 46.9057}, % C8 + {33.3553, 5.0152, 46.4771}, % H2 + {37.5730, 3.2804, 49.1507}, % H61 + {35.9775, 2.5638, 49.1828}, % H62 + {39.5461, 6.9184, 47.0041}} % H8 + }. + +rA08() -> + { + {0.1084, -0.0895, -0.9901, % dgf_base_tfo + 0.9789, -0.1638, 0.1220, + -0.1731, -0.9824, 0.0698, + -2.9039, 47.2655, 33.0094}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.4850, 8.9301, 44.6977}, % C5' + {39.0638, 9.8199, 44.2296}, % H5' + {40.0757, 9.0713, 45.6029}, % H5'' + {38.3102, 8.0414, 45.0789}, % C4' + {37.7842, 8.4637, 45.9351}, % H4' + {37.4200, 7.9453, 43.9769}, % O4' + {37.2249, 6.5609, 43.6273}, % C1' + {36.3360, 6.2168, 44.1561}, % H1' + {38.4347, 5.8414, 44.1590}, % C2' + {39.2688, 5.9974, 43.4749}, % H2'' + {38.2344, 4.4907, 44.4348}, % O2' + {37.6374, 4.0386, 43.8341}, % H2' + {38.6926, 6.6079, 45.4637}, % C3' + {39.7585, 6.5640, 45.6877}, % H3' + {37.8238, 6.0705, 46.4723}, % O3' + {33.9162, 6.2598, 39.7758}, % N1 + {34.6709, 6.5759, 42.0215}, % N3 + {33.7257, 6.5186, 41.0858}, % C2 + {35.8935, 6.3324, 41.5018}, % C4 + {36.2105, 6.0601, 40.1932}, % C5 + {35.1538, 6.0151, 39.2537}, % C6 + a, { + {35.3088, 5.7642, 37.9649}, % N6 + {37.5818, 5.8677, 40.0507}, % N7 + {37.0932, 6.3197, 42.1810}, % N9 + {38.0509, 6.0354, 41.2635}, % C8 + {32.6830, 6.6898, 41.3532}, % H2 + {36.2305, 5.5855, 37.5925}, % H61 + {34.5056, 5.7512, 37.3528}, % H62 + {39.1318, 5.8993, 41.2285}} % H8 + }. + +rA09() -> + { + {0.8467, 0.4166, -0.3311, % dgf_base_tfo + -0.3962, 0.9089, 0.1303, + 0.3552, 0.0209, 0.9346, + -42.7319, -26.6223, -29.8163}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.3505, 8.4697, 42.6565}, % C5' + {39.1377, 7.5433, 42.1230}, % H5' + {39.7203, 9.3119, 42.0717}, % H5'' + {38.0405, 8.9195, 43.2869}, % C4' + {37.6479, 8.1347, 43.9335}, % H4' + {38.2691, 10.0933, 44.0524}, % O4' + {37.3999, 11.1488, 43.5973}, % C1' + {36.5061, 11.1221, 44.2206}, % H1' + {37.0364, 10.7838, 42.1836}, % C2' + {37.8636, 11.0489, 41.5252}, % H2'' + {35.8275, 11.3133, 41.7379}, % O2' + {35.6214, 12.1896, 42.0714}, % H2' + {36.9316, 9.2556, 42.2837}, % C3' + {37.1778, 8.8260, 41.3127}, % H3' + {35.6285, 8.9334, 42.7926}, % O3' + {38.1482, 15.2833, 46.4641}, % N1 + {37.3641, 13.0968, 45.9007}, % N3 + {37.5032, 14.1288, 46.7300}, % C2 + {37.9570, 13.3377, 44.7113}, % C4 + {38.6397, 14.4660, 44.3267}, % C5 + {38.7473, 15.5229, 45.2609}, % C6 + a, { + {39.3720, 16.6649, 45.0297}, % N6 + {39.1079, 14.3351, 43.0223}, % N7 + {38.0132, 12.4868, 43.6280}, % N9 + {38.7058, 13.1402, 42.6620}, % C8 + {37.0731, 14.0857, 47.7306}, % H2 + {39.8113, 16.8281, 44.1350}, % H61 + {39.4100, 17.3741, 45.7478}, % H62 + {39.0412, 12.9660, 41.6397}} % H8 + }. + +rA10() -> + { + {0.7063, 0.6317, -0.3196, % dgf_base_tfo + -0.0403, -0.4149, -0.9090, + -0.7068, 0.6549, -0.2676, + 6.4402, -52.1496, 30.8246}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.4850, 8.9301, 44.6977}, % C5' + {39.0638, 9.8199, 44.2296}, % H5' + {40.0757, 9.0713, 45.6029}, % H5'' + {38.3102, 8.0414, 45.0789}, % C4' + {37.7099, 7.8166, 44.1973}, % H4' + {38.8012, 6.8321, 45.6380}, % O4' + {38.2431, 6.6413, 46.9529}, % C1' + {37.3505, 6.0262, 46.8385}, % H1' + {37.8484, 8.0156, 47.4214}, % C2' + {38.7381, 8.5406, 47.7690}, % H2'' + {36.8286, 8.0368, 48.3701}, % O2' + {36.8392, 7.3063, 48.9929}, % H2' + {37.3576, 8.6512, 46.1132}, % C3' + {37.5207, 9.7275, 46.1671}, % H3' + {35.9985, 8.2392, 45.9032}, % O3' + {39.9117, 2.2278, 48.8527}, % N1 + {38.6207, 3.6941, 47.4757}, % N3 + {38.9872, 2.4888, 47.9057}, % C2 + {39.2961, 4.6720, 48.1174}, % C4 + {40.2546, 4.5307, 49.0912}, % C5 + {40.5932, 3.2189, 49.4985}, % C6 + a, { + {41.4938, 2.9317, 50.4229}, % N6 + {40.7195, 5.7755, 49.5060}, % N7 + {39.1730, 6.0305, 47.9170}, % N9 + {40.0413, 6.6250, 48.7728}, % C8 + {38.5257, 1.5960, 47.4838}, % H2 + {41.9907, 3.6753, 50.8921}, % H61 + {41.6848, 1.9687, 50.6599}, % H62 + {40.3571, 7.6321, 49.0452}} % H8 + }. + +rAs() -> [rA01(),rA02(),rA03(),rA04(),rA05(),rA06(),rA07(), + rA08(),rA09(),rA10()]. + +rC() -> + { + {-0.0359, -0.8071, 0.5894, % dgf_base_tfo + -0.2669, 0.5761, 0.7726, + -0.9631, -0.1296, -0.2361, + 0.1584, 8.3434, 0.5434}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2430, -8.2420, 2.8260}, % C5' + {5.1974, -8.8497, 1.9223}, % H5' + {5.5548, -8.7348, 3.7469}, % H5'' + {6.3140, -7.2060, 2.5510}, % C4' + {7.2954, -7.6762, 2.4898}, % H4' + {6.0140, -6.5420, 1.2890}, % O4' + {6.4190, -5.1840, 1.3620}, % C1' + {7.1608, -5.0495, 0.5747}, % H1' + {7.0760, -4.9560, 2.7270}, % C2' + {6.7770, -3.9803, 3.1099}, % H2'' + {8.4500, -5.1930, 2.5810}, % O2' + {8.8309, -4.8755, 1.7590}, % H2' + {6.4060, -6.0590, 3.5580}, % C3' + {5.4021, -5.7313, 3.8281}, % H3' + {7.1570, -6.4240, 4.7070}, % O3' + {5.2170, -4.3260, 1.1690}, % N1 + {4.2960, -2.2560, 0.6290}, % N3 + {5.4330, -3.0200, 0.7990}, % C2 + {2.9930, -2.6780, 0.7940}, % C4 + {2.8670, -4.0630, 1.1830}, % C5 + {3.9570, -4.8300, 1.3550}, % C6 + c, { + {2.0187, -1.8047, 0.5874}, % N4 + {6.5470, -2.5560, 0.6290}, % O2 + {1.0684, -2.1236, 0.7109}, % H41 + {2.2344, -0.8560, 0.3162}, % H42 + {1.8797, -4.4972, 1.3404}, % H5 + {3.8479, -5.8742, 1.6480}} % H6 + }. + +rC01() -> + { + {-0.0137, -0.8012, 0.5983, % dgf_base_tfo + -0.2523, 0.5817, 0.7733, + -0.9675, -0.1404, -0.2101, + 0.2031, 8.3874, 0.4228}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {4.3777, -2.2062, 0.7229}, % N3 + {5.5069, -2.9779, 0.9088}, % C2 + {3.0693, -2.6246, 0.8500}, % C4 + {2.9279, -4.0146, 1.2149}, % C5 + {4.0101, -4.7892, 1.4017}, % C6 + c, { + {2.1040, -1.7437, 0.6331}, % N4 + {6.6267, -2.5166, 0.7728}, % O2 + {1.1496, -2.0600, 0.7287}, % H41 + {2.3303, -0.7921, 0.3815}, % H42 + {1.9353, -4.4465, 1.3419}, % H5 + {3.8895, -5.8371, 1.6762}} % H6 + }. + +rC02() -> + { + {0.5141, 0.0246, 0.8574, % dgf_base_tfo + -0.5547, -0.7529, 0.3542, + 0.6542, -0.6577, -0.3734, + -9.1111, -3.4598, -3.2939}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.6945, -8.7046, -0.2857}, % N3 + {8.6943, -7.6514, 0.6066}, % C2 + {7.7426, -9.6987, -0.3801}, % C4 + {6.6642, -9.5742, 0.5722}, % C5 + {6.6391, -8.5592, 1.4526}, % C6 + c, { + {7.9033, -10.6371, -1.3010}, % N4 + {9.5840, -6.8186, 0.6136}, % O2 + {7.2009, -11.3604, -1.3619}, % H41 + {8.7058, -10.6168, -1.9140}, % H42 + {5.8585, -10.3083, 0.5822}, % H5 + {5.8197, -8.4773, 2.1667}} % H6 + }. + +rC03() -> + { + {-0.4993, 0.0476, 0.8651, % dgf_base_tfo + 0.8078, -0.3353, 0.4847, + 0.3132, 0.9409, 0.1290, + 6.2989, -5.2303, -3.8577}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {7.9218, -5.5700, 6.8877}, % N3 + {7.8908, -5.0886, 5.5944}, % C2 + {6.9789, -6.3827, 7.4823}, % C4 + {5.8742, -6.7319, 6.6202}, % C5 + {5.8182, -6.2769, 5.3570}, % C6 + c, { + {7.1702, -6.7511, 8.7402}, % N4 + {8.7747, -4.3728, 5.1568}, % O2 + {6.4741, -7.3461, 9.1662}, % H41 + {7.9889, -6.4396, 9.2429}, % H42 + {5.0736, -7.3713, 6.9922}, % H5 + {4.9784, -6.5473, 4.7170}} % H6 + }. + +rC04() -> + { + {-0.5669, -0.8012, 0.1918, % dgf_base_tfo + -0.8129, 0.5817, 0.0273, + -0.1334, -0.1404, -0.9811, + -0.3279, 8.3874, 0.3355}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {3.8961, -3.0896, -0.1893}, % N3 + {5.0095, -3.8907, -0.0346}, % C2 + {3.0480, -2.6632, 0.8116}, % C4 + {3.4093, -3.1310, 2.1292}, % C5 + {4.4878, -3.9124, 2.3088}, % C6 + c, { + {2.0216, -1.8941, 0.4804}, % N4 + {5.7005, -4.2164, -0.9842}, % O2 + {1.4067, -1.5873, 1.2205}, % H41 + {1.8721, -1.6319, -0.4835}, % H42 + {2.8048, -2.8507, 2.9918}, % H5 + {4.7491, -4.2593, 3.3085}} % H6 + }. + +rC05() -> + { + {-0.6298, 0.0246, 0.7763, % dgf_base_tfo + -0.5226, -0.7529, -0.4001, + 0.5746, -0.6577, 0.4870, + -0.0208, -3.4598, -9.6882}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.5977, -9.5977, 0.7329}, % N3 + {8.5951, -8.5745, 1.6594}, % C2 + {7.7372, -9.7371, -0.3364}, % C4 + {6.7596, -8.6801, -0.4476}, % C5 + {6.7338, -7.6721, 0.4408}, % C6 + c, { + {7.8849, -10.7881, -1.1289}, % N4 + {9.3993, -8.5377, 2.5743}, % O2 + {7.2499, -10.8809, -1.9088}, % H41 + {8.6122, -11.4649, -0.9468}, % H42 + {6.0317, -8.6941, -1.2588}, % H5 + {5.9901, -6.8809, 0.3459}} % H6 + }. + +rC06() -> + { + {-0.9837, 0.0476, -0.1733, % dgf_base_tfo + -0.1792, -0.3353, 0.9249, + -0.0141, 0.9409, 0.3384, + 5.7793, -5.2303, 4.5997}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {6.6920, -5.0495, 7.1354}, % N3 + {6.6201, -4.5500, 5.8506}, % C2 + {6.9254, -6.3614, 7.4926}, % C4 + {7.1046, -7.2543, 6.3718}, % C5 + {7.0391, -6.7951, 5.1106}, % C6 + c, { + {6.9614, -6.6648, 8.7815}, % N4 + {6.4083, -3.3696, 5.6340}, % O2 + {7.1329, -7.6280, 9.0324}, % H41 + {6.8204, -5.9469, 9.4777}, % H42 + {7.2954, -8.3135, 6.5440}, % H5 + {7.1753, -7.4798, 4.2735}} % H6 + }. + +rC07() -> + { + {0.0033, 0.2720, -0.9623, % dgf_base_tfo + 0.3013, -0.9179, -0.2584, + -0.9535, -0.2891, -0.0850, + 43.0403, 13.7233, 34.5710}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {30.8152, 11.1619, 46.2003}, % C5' + {30.4519, 10.9454, 45.1957}, % H5' + {31.0379, 12.2016, 46.4400}, % H5'' + {29.7081, 10.7448, 47.1428}, % C4' + {28.8710, 11.4416, 47.0982}, % H4' + {29.2550, 9.4394, 46.8162}, % O4' + {29.3907, 8.5625, 47.9460}, % C1' + {28.4416, 8.5669, 48.4819}, % H1' + {30.4468, 9.2031, 48.7952}, % C2' + {31.4222, 8.9651, 48.3709}, % H2'' + {30.3701, 8.9157, 50.1624}, % O2' + {30.0652, 8.0304, 50.3740}, % H2' + {30.1622, 10.6879, 48.6120}, % C3' + {31.0952, 11.2399, 48.7254}, % H3' + {29.1076, 11.1535, 49.4702}, % O3' + {29.7883, 7.2209, 47.5235}, % N1 + {29.1825, 5.0438, 46.8275}, % N3 + {28.8008, 6.2912, 47.2263}, % C2 + {30.4888, 4.6890, 46.7186}, % C4 + {31.5034, 5.6405, 47.0249}, % C5 + {31.1091, 6.8691, 47.4156}, % C6 + c, { + {30.8109, 3.4584, 46.3336}, % N4 + {27.6171, 6.5989, 47.3189}, % O2 + {31.7923, 3.2301, 46.2638}, % H41 + {30.0880, 2.7857, 46.1215}, % H42 + {32.5542, 5.3634, 46.9395}, % H5 + {31.8523, 7.6279, 47.6603}} % H6 + }. + +rC08() -> + { + {0.0797, -0.6026, -0.7941, % dgf_base_tfo + 0.7939, 0.5201, -0.3150, + 0.6028, -0.6054, 0.5198, + -36.8341, 41.5293, 1.6628}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {31.8779, 9.9369, 47.8760}, % C5' + {31.3239, 10.6931, 48.4322}, % H5' + {32.8647, 9.6624, 48.2489}, % H5'' + {31.0429, 8.6773, 47.9401}, % C4' + {31.0779, 8.2331, 48.9349}, % H4' + {29.6956, 8.9669, 47.5983}, % O4' + {29.2784, 8.1700, 46.4782}, % C1' + {28.8006, 7.2731, 46.8722}, % H1' + {30.5544, 7.7940, 45.7875}, % C2' + {30.8837, 8.6410, 45.1856}, % H2'' + {30.5100, 6.6007, 45.0582}, % O2' + {29.6694, 6.4168, 44.6326}, % H2' + {31.5146, 7.5954, 46.9527}, % C3' + {32.5255, 7.8261, 46.6166}, % H3' + {31.3876, 6.2951, 47.5516}, % O3' + {28.3976, 8.9302, 45.5933}, % N1 + {26.2155, 9.6135, 44.9910}, % N3 + {27.0281, 8.8961, 45.8192}, % C2 + {26.7044, 10.3489, 43.9595}, % C4 + {28.1088, 10.3837, 43.7247}, % C5 + {28.8978, 9.6708, 44.5535}, % C6 + c, { + {25.8715, 11.0249, 43.1749}, % N4 + {26.5733, 8.2371, 46.7484}, % O2 + {26.2707, 11.5609, 42.4177}, % H41 + {24.8760, 10.9939, 43.3427}, % H42 + {28.5089, 10.9722, 42.8990}, % H5 + {29.9782, 9.6687, 44.4097}} % H6 + }. + +rC09() -> + { + {0.8727, 0.4760, -0.1091, % dgf_base_tfo + -0.4188, 0.6148, -0.6682, + -0.2510, 0.6289, 0.7359, + -8.1687, -52.0761, -25.0726}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {30.8152, 11.1619, 46.2003}, % C5' + {30.4519, 10.9454, 45.1957}, % H5' + {31.0379, 12.2016, 46.4400}, % H5'' + {29.7081, 10.7448, 47.1428}, % C4' + {29.4506, 9.6945, 47.0059}, % H4' + {30.1045, 10.9634, 48.4885}, % O4' + {29.1794, 11.8418, 49.1490}, % C1' + {28.4388, 11.2210, 49.6533}, % H1' + {28.5211, 12.6008, 48.0367}, % C2' + {29.1947, 13.3949, 47.7147}, % H2'' + {27.2316, 13.0683, 48.3134}, % O2' + {27.0851, 13.3391, 49.2227}, % H2' + {28.4131, 11.5507, 46.9391}, % C3' + {28.4451, 12.0512, 45.9713}, % H3' + {27.2707, 10.6955, 47.1097}, % O3' + {29.8751, 12.7405, 50.0682}, % N1 + {30.7172, 13.1841, 52.2328}, % N3 + {30.0617, 12.3404, 51.3847}, % C2 + {31.1834, 14.3941, 51.8297}, % C4 + {30.9913, 14.8074, 50.4803}, % C5 + {30.3434, 13.9610, 49.6548}, % C6 + c, { + {31.8090, 15.1847, 52.6957}, % N4 + {29.6470, 11.2494, 51.7616}, % O2 + {32.1422, 16.0774, 52.3606}, % H41 + {31.9392, 14.8893, 53.6527}, % H42 + {31.3632, 15.7771, 50.1491}, % H5 + {30.1742, 14.2374, 48.6141}} % H6 + }. + +rC10() -> + { + {0.1549, 0.8710, -0.4663, % dgf_base_tfo + 0.6768, -0.4374, -0.5921, + -0.7197, -0.2239, -0.6572, + 25.2447, -14.1920, 50.3201}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {31.8779, 9.9369, 47.8760}, % C5' + {31.3239, 10.6931, 48.4322}, % H5' + {32.8647, 9.6624, 48.2489}, % H5'' + {31.0429, 8.6773, 47.9401}, % C4' + {30.0440, 8.8473, 47.5383}, % H4' + {31.6749, 7.6351, 47.2119}, % O4' + {31.9159, 6.5022, 48.0616}, % C1' + {31.0691, 5.8243, 47.9544}, % H1' + {31.9300, 7.0685, 49.4493}, % C2' + {32.9024, 7.5288, 49.6245}, % H2'' + {31.5672, 6.1750, 50.4632}, % O2' + {31.8416, 5.2663, 50.3200}, % H2' + {30.8618, 8.1514, 49.3749}, % C3' + {31.1122, 8.9396, 50.0850}, % H3' + {29.5351, 7.6245, 49.5409}, % O3' + {33.1890, 5.8629, 47.7343}, % N1 + {34.4004, 4.2636, 46.4828}, % N3 + {33.2062, 4.8497, 46.7851}, % C2 + {35.5600, 4.6374, 47.0822}, % C4 + {35.5444, 5.6751, 48.0577}, % C5 + {34.3565, 6.2450, 48.3432}, % C6 + c, { + {36.6977, 4.0305, 46.7598}, % N4 + {32.1661, 4.5034, 46.2348}, % O2 + {37.5405, 4.3347, 47.2259}, % H41 + {36.7033, 3.2923, 46.0706}, % H42 + {36.4713, 5.9811, 48.5428}, % H5 + {34.2986, 7.0426, 49.0839}} % H6 + }. + +rCs() -> [rC01(),rC02(),rC03(),rC04(),rC05(),rC06(),rC07(), + rC08(),rC09(),rC10()]. + +rG() -> + { + {-0.0018, -0.8207, 0.5714, % dgf_base_tfo + 0.2679, -0.5509, -0.7904, + 0.9634, 0.1517, 0.2209, + 0.0073, 8.4030, 0.6232}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4550, 8.2120, -2.8810}, % C5' + {5.4546, 8.8508, -1.9978}, % H5' + {5.7588, 8.6625, -3.8259}, % H5'' + {6.4970, 7.1480, -2.5980}, % C4' + {7.4896, 7.5919, -2.5214}, % H4' + {6.1630, 6.4860, -1.3440}, % O4' + {6.5400, 5.1200, -1.4190}, % C1' + {7.2763, 4.9681, -0.6297}, % H1' + {7.1940, 4.8830, -2.7770}, % C2' + {6.8667, 3.9183, -3.1647}, % H2'' + {8.5860, 5.0910, -2.6140}, % O2' + {8.9510, 4.7626, -1.7890}, % H2' + {6.5720, 6.0040, -3.6090}, % C3' + {5.5636, 5.7066, -3.8966}, % H3' + {7.3801, 6.3562, -4.7350}, % O3' + {4.7150, 0.4910, -0.1360}, % N1 + {6.3490, 2.1730, -0.6020}, % N3 + {5.9530, 0.9650, -0.2670}, % C2 + {5.2900, 2.9790, -0.8260}, % C4 + {3.9720, 2.6390, -0.7330}, % C5 + {3.6770, 1.3160, -0.3660}, % C6 + g, { + {6.8426, 0.0056, -0.0019}, % N2 + {3.1660, 3.7290, -1.0360}, % N7 + {5.3170, 4.2990, -1.1930}, % N9 + {4.0100, 4.6780, -1.2990}, % C8 + {2.4280, 0.8450, -0.2360}, % O6 + {4.6151, -0.4677, 0.1305}, % H1 + {6.6463, -0.9463, 0.2729}, % H21 + {7.8170, 0.2642, -0.0640}, % H22 + {3.4421, 5.5744, -1.5482}} % H8 + }. + +rU() -> + { + {-0.0359, -0.8071, 0.5894, % dgf_base_tfo + -0.2669, 0.5761, 0.7726, + -0.9631, -0.1296, -0.2361, + 0.1584, 8.3434, 0.5434}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2430, -8.2420, 2.8260}, % C5' + {5.1974, -8.8497, 1.9223}, % H5' + {5.5548, -8.7348, 3.7469}, % H5'' + {6.3140, -7.2060, 2.5510}, % C4' + {7.2954, -7.6762, 2.4898}, % H4' + {6.0140, -6.5420, 1.2890}, % O4' + {6.4190, -5.1840, 1.3620}, % C1' + {7.1608, -5.0495, 0.5747}, % H1' + {7.0760, -4.9560, 2.7270}, % C2' + {6.7770, -3.9803, 3.1099}, % H2'' + {8.4500, -5.1930, 2.5810}, % O2' + {8.8309, -4.8755, 1.7590}, % H2' + {6.4060, -6.0590, 3.5580}, % C3' + {5.4021, -5.7313, 3.8281}, % H3' + {7.1570, -6.4240, 4.7070}, % O3' + {5.2170, -4.3260, 1.1690}, % N1 + {4.2960, -2.2560, 0.6290}, % N3 + {5.4330, -3.0200, 0.7990}, % C2 + {2.9930, -2.6780, 0.7940}, % C4 + {2.8670, -4.0630, 1.1830}, % C5 + {3.9570, -4.8300, 1.3550}, % C6 + u, { + {6.5470, -2.5560, 0.6290}, % O2 + {2.0540, -1.9000, 0.6130}, % O4 + {4.4300, -1.3020, 0.3600}, % H3 + {1.9590, -4.4570, 1.3250}, % H5 + {3.8460, -5.7860, 1.6240}} % H6 + }. + +rU01() -> + { + {-0.0137, -0.8012, 0.5983, % dgf_base_tfo + -0.2523, 0.5817, 0.7733, + -0.9675, -0.1404, -0.2101, + 0.2031, 8.3874, 0.4228}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {4.3777, -2.2062, 0.7229}, % N3 + {5.5069, -2.9779, 0.9088}, % C2 + {3.0693, -2.6246, 0.8500}, % C4 + {2.9279, -4.0146, 1.2149}, % C5 + {4.0101, -4.7892, 1.4017}, % C6 + u, { + {6.6267, -2.5166, 0.7728}, % O2 + {2.1383, -1.8396, 0.6581}, % O4 + {4.5223, -1.2489, 0.4716}, % H3 + {2.0151, -4.4065, 1.3290}, % H5 + {3.8886, -5.7486, 1.6535}} % H6 + }. + +rU02() -> + { + {0.5141, 0.0246, 0.8574, % dgf_base_tfo + -0.5547, -0.7529, 0.3542, + 0.6542, -0.6577, -0.3734, + -9.1111, -3.4598, -3.2939}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.6945, -8.7046, -0.2857}, % N3 + {8.6943, -7.6514, 0.6066}, % C2 + {7.7426, -9.6987, -0.3801}, % C4 + {6.6642, -9.5742, 0.5722}, % C5 + {6.6391, -8.5592, 1.4526}, % C6 + u, { + {9.5840, -6.8186, 0.6136}, % O2 + {7.8505, -10.5925, -1.2223}, % O4 + {9.4601, -8.7514, -0.9277}, % H3 + {5.9281, -10.2509, 0.5782}, % H5 + {5.8831, -8.4931, 2.1028}} % H6 + }. + +rU03() -> + { + {-0.4993, 0.0476, 0.8651, % dgf_base_tfo + 0.8078, -0.3353, 0.4847, + 0.3132, 0.9409, 0.1290, + 6.2989, -5.2303, -3.8577}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {7.9218, -5.5700, 6.8877}, % N3 + {7.8908, -5.0886, 5.5944}, % C2 + {6.9789, -6.3827, 7.4823}, % C4 + {5.8742, -6.7319, 6.6202}, % C5 + {5.8182, -6.2769, 5.3570}, % C6 + u, { + {8.7747, -4.3728, 5.1568}, % O2 + {7.1154, -6.7509, 8.6509}, % O4 + {8.7055, -5.3037, 7.4491}, % H3 + {5.1416, -7.3178, 6.9665}, % H5 + {5.0441, -6.5310, 4.7784}} % H6 + }. + +rU04() -> + { + {-0.5669, -0.8012, 0.1918, % dgf_base_tfo + -0.8129, 0.5817, 0.0273, + -0.1334, -0.1404, -0.9811, + -0.3279, 8.3874, 0.3355}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {3.8961, -3.0896, -0.1893}, % N3 + {5.0095, -3.8907, -0.0346}, % C2 + {3.0480, -2.6632, 0.8116}, % C4 + {3.4093, -3.1310, 2.1292}, % C5 + {4.4878, -3.9124, 2.3088}, % C6 + u, { + {5.7005, -4.2164, -0.9842}, % O2 + {2.0800, -1.9458, 0.5503}, % O4 + {3.6834, -2.7882, -1.1190}, % H3 + {2.8508, -2.8721, 2.9172}, % H5 + {4.7188, -4.2247, 3.2295}} % H6 + }. + +rU05() -> + { + {-0.6298, 0.0246, 0.7763, % dgf_base_tfo + -0.5226, -0.7529, -0.4001, + 0.5746, -0.6577, 0.4870, + -0.0208, -3.4598, -9.6882}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.5977, -9.5977, 0.7329}, % N3 + {8.5951, -8.5745, 1.6594}, % C2 + {7.7372, -9.7371, -0.3364}, % C4 + {6.7596, -8.6801, -0.4476}, % C5 + {6.7338, -7.6721, 0.4408}, % C6 + u, { + {9.3993, -8.5377, 2.5743}, % O2 + {7.8374, -10.6990, -1.1008}, % O4 + {9.2924, -10.3081, 0.8477}, % H3 + {6.0932, -8.6982, -1.1929}, % H5 + {6.0481, -6.9515, 0.3446}} % H6 + }. + +rU06() -> + { + {-0.9837, 0.0476, -0.1733, % dgf_base_tfo + -0.1792, -0.3353, 0.9249, + -0.0141, 0.9409, 0.3384, + 5.7793, -5.2303, 4.5997}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {6.6920, -5.0495, 7.1354}, % N3 + {6.6201, -4.5500, 5.8506}, % C2 + {6.9254, -6.3614, 7.4926}, % C4 + {7.1046, -7.2543, 6.3718}, % C5 + {7.0391, -6.7951, 5.1106}, % C6 + u, { + {6.4083, -3.3696, 5.6340}, % O2 + {6.9679, -6.6901, 8.6800}, % O4 + {6.5626, -4.3957, 7.8812}, % H3 + {7.2781, -8.2254, 6.5350}, % H5 + {7.1657, -7.4312, 4.3503}} % H6 + }. + +rU07() -> + { + {-0.9434, 0.3172, 0.0971, % dgf_base_tfo + 0.2294, 0.4125, 0.8816, + 0.2396, 0.8539, -0.4619, + 8.3625, -52.7147, 1.3745}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {21.5037, 16.8594, 43.7323}, % C5' + {20.8147, 17.6663, 43.9823}, % H5' + {21.1086, 16.0230, 43.1557}, % H5'' + {22.5654, 17.4874, 42.8616}, % C4' + {22.1584, 17.7243, 41.8785}, % H4' + {23.0557, 18.6826, 43.4751}, % O4' + {24.4788, 18.6151, 43.6455}, % C1' + {24.9355, 19.0840, 42.7739}, % H1' + {24.7958, 17.1427, 43.6474}, % C2' + {24.5652, 16.7400, 44.6336}, % H2'' + {26.1041, 16.8773, 43.2455}, % O2' + {26.7516, 17.5328, 43.5149}, % H2' + {23.8109, 16.5979, 42.6377}, % C3' + {23.5756, 15.5686, 42.9084}, % H3' + {24.2890, 16.7447, 41.2729}, % O3' + {24.9420, 19.2174, 44.8923}, % N1 + {25.2655, 20.5636, 44.8883}, % N3 + {25.1663, 21.2219, 43.8561}, % C2 + {25.6911, 21.1219, 46.0494}, % C4 + {25.8051, 20.4068, 47.2048}, % C5 + {26.2093, 20.9962, 48.2534}, % C6 + u, { + {25.4692, 19.0221, 47.2053}, % O2 + {25.0502, 18.4827, 46.0370}, % O4 + {25.9599, 22.1772, 46.0966}, % H3 + {25.5545, 18.4409, 48.1234}, % H5 + {24.7854, 17.4265, 45.9883}} % H6 + }. + +rU08() -> + { + {-0.0080, -0.7928, 0.6094, % dgf_base_tfo + -0.7512, 0.4071, 0.5197, + -0.6601, -0.4536, -0.5988, + 44.1482, 30.7036, 2.1088}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {23.5096, 16.1227, 44.5783}, % C5' + {23.5649, 15.8588, 43.5222}, % H5' + {23.9621, 15.4341, 45.2919}, % H5'' + {24.2805, 17.4138, 44.7151}, % C4' + {25.3492, 17.2309, 44.6030}, % H4' + {23.8497, 18.3471, 43.7208}, % O4' + {23.4090, 19.5681, 44.3321}, % C1' + {24.2595, 20.2496, 44.3524}, % H1' + {23.0418, 19.1813, 45.7407}, % C2' + {22.0532, 18.7224, 45.7273}, % H2'' + {23.1307, 20.2521, 46.6291}, % O2' + {22.8888, 21.1051, 46.2611}, % H2' + {24.0799, 18.1326, 46.0700}, % C3' + {23.6490, 17.4370, 46.7900}, % H3' + {25.3329, 18.7227, 46.5109}, % O3' + {22.2515, 20.1624, 43.6698}, % N1 + {22.4760, 21.0609, 42.6406}, % N3 + {23.6229, 21.3462, 42.3061}, % C2 + {21.3986, 21.6081, 42.0236}, % C4 + {20.1189, 21.3012, 42.3804}, % C5 + {19.1599, 21.8516, 41.7578}, % C6 + u, { + {19.8919, 20.3745, 43.4387}, % O2 + {20.9790, 19.8423, 44.0440}, % O4 + {21.5235, 22.3222, 41.2097}, % H3 + {18.8732, 20.1200, 43.7312}, % H5 + {20.8545, 19.1313, 44.8608}} % H6 + }. + +rU09() -> + { + {-0.0317, 0.1374, 0.9900, % dgf_base_tfo + -0.3422, -0.9321, 0.1184, + 0.9391, -0.3351, 0.0765, + -32.1929, 25.8198, -28.5088}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {21.5037, 16.8594, 43.7323}, % C5' + {20.8147, 17.6663, 43.9823}, % H5' + {21.1086, 16.0230, 43.1557}, % H5'' + {22.5654, 17.4874, 42.8616}, % C4' + {23.0565, 18.3036, 43.3915}, % H4' + {23.5375, 16.5054, 42.4925}, % O4' + {23.6574, 16.4257, 41.0649}, % C1' + {24.4701, 17.0882, 40.7671}, % H1' + {22.3525, 16.9643, 40.5396}, % C2' + {21.5993, 16.1799, 40.6133}, % H2'' + {22.4693, 17.4849, 39.2515}, % O2' + {23.0899, 17.0235, 38.6827}, % H2' + {22.0341, 18.0633, 41.5279}, % C3' + {20.9509, 18.1709, 41.5846}, % H3' + {22.7249, 19.3020, 41.2100}, % O3' + {23.8580, 15.0648, 40.5757}, % N1 + {25.1556, 14.5982, 40.4523}, % N3 + {26.1047, 15.3210, 40.7448}, % C2 + {25.3391, 13.3315, 40.0020}, % C4 + {24.2974, 12.5148, 39.6749}, % C5 + {24.5450, 11.3410, 39.2610}, % C6 + u, { + {22.9633, 12.9979, 39.8053}, % O2 + {22.8009, 14.2648, 40.2524}, % O4 + {26.3414, 12.9194, 39.8855}, % H3 + {22.1227, 12.3533, 39.5486}, % H5 + {21.7989, 14.6788, 40.3650}} % H6 + }. + +rU10() -> + { + {-0.9674, 0.1021, -0.2318, % dgf_base_tfo + -0.2514, -0.2766, 0.9275, + 0.0306, 0.9555, 0.2933, + 27.8571, -42.1305, -24.4563}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {23.5096, 16.1227, 44.5783}, % C5' + {23.5649, 15.8588, 43.5222}, % H5' + {23.9621, 15.4341, 45.2919}, % H5'' + {24.2805, 17.4138, 44.7151}, % C4' + {23.8509, 18.1819, 44.0720}, % H4' + {24.2506, 17.8583, 46.0741}, % O4' + {25.5830, 18.0320, 46.5775}, % C1' + {25.8569, 19.0761, 46.4256}, % H1' + {26.4410, 17.1555, 45.7033}, % C2' + {26.3459, 16.1253, 46.0462}, % H2'' + {27.7649, 17.5888, 45.6478}, % O2' + {28.1004, 17.9719, 46.4616}, % H2' + {25.7796, 17.2997, 44.3513}, % C3' + {25.9478, 16.3824, 43.7871}, % H3' + {26.2154, 18.4984, 43.6541}, % O3' + {25.7321, 17.6281, 47.9726}, % N1 + {25.5136, 18.5779, 48.9560}, % N3 + {25.2079, 19.7276, 48.6503}, % C2 + {25.6482, 18.1987, 50.2518}, % C4 + {25.9847, 16.9266, 50.6092}, % C5 + {26.0918, 16.6439, 51.8416}, % C6 + u, { + {26.2067, 15.9515, 49.5943}, % O2 + {26.0713, 16.3497, 48.3080}, % O4 + {25.4890, 18.9105, 51.0618}, % H3 + {26.4742, 14.9310, 49.8682}, % H5 + {26.2346, 15.6394, 47.4975}} % H6 + }. + +rUs() -> [rU01(),rU02(),rU03(),rU04(),rU05(),rU06(),rU07(), + rU08(),rU09(),rU10()]. + +rG_() -> + { + {-0.2067, -0.0264, 0.9780, % dgf_base_tfo + 0.9770, -0.0586, 0.2049, + 0.0519, 0.9979, 0.0379, + 1.0331, -46.8078, -36.4742}, + {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo + -0.0427, 0.2409, -0.9696, + 0.5010, -0.8345, -0.2294, + 4.0167, 54.5377, 12.4779}, + {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo + -0.2867, -0.7872, -0.5460, + 0.8834, 0.0032, -0.4686, + -52.9020, 18.6313, -0.6709}, + {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo + 0.9040, -0.4236, -0.0582, + -0.1007, -0.0786, -0.9918, + -7.6624, -25.2080, 49.5181}, + {31.3810, 0.1400, 47.5810}, % P + {29.9860, 0.6630, 47.6290}, % O1P + {31.7210, -0.6460, 48.8090}, % O2P + {32.4940, 1.2540, 47.2740}, % O5' + {32.1610, 2.2370, 46.2560}, % C5' + {31.2986, 2.8190, 46.5812}, % H5' + {32.0980, 1.7468, 45.2845}, % H5'' + {33.3476, 3.1959, 46.1947}, % C4' + {33.2668, 3.8958, 45.3630}, % H4' + {33.3799, 3.9183, 47.4216}, % O4' + {34.6515, 3.7222, 48.0398}, % C1' + {35.2947, 4.5412, 47.7180}, % H1' + {35.1756, 2.4228, 47.4827}, % C2' + {34.6778, 1.5937, 47.9856}, % H2'' + {36.5631, 2.2672, 47.4798}, % O2' + {37.0163, 2.6579, 48.2305}, % H2' + {34.6953, 2.5043, 46.0448}, % C3' + {34.5444, 1.4917, 45.6706}, % H3' + {35.6679, 3.3009, 45.3487}, % O3' + {37.4804, 4.0914, 52.2559}, % N1 + {36.9670, 4.1312, 49.9281}, % N3 + {37.8045, 4.2519, 50.9550}, % C2 + {35.7171, 3.8264, 50.3222}, % C4 + {35.2668, 3.6420, 51.6115}, % C5 + {36.2037, 3.7829, 52.6706}, % C6 + g, { + {39.0869, 4.5552, 50.7092}, % N2 + {33.9075, 3.3338, 51.6102}, % N7 + {34.6126, 3.6358, 49.5108}, % N9 + {33.5805, 3.3442, 50.3425}, % C8 + {35.9958, 3.6512, 53.8724}, % O6 + {38.2106, 4.2053, 52.9295}, % H1 + {39.8218, 4.6863, 51.3896}, % H21 + {39.3420, 4.6857, 49.7407}, % H22 + {32.5194, 3.1070, 50.2664}} % H8 + }. + +rU_() -> + { + {-0.0109, 0.5907, 0.8068, % dgf_base_tfo + 0.2217, -0.7853, 0.5780, + 0.9751, 0.1852, -0.1224, + -1.4225, -11.0956, -2.5217}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2430, -8.2420, 2.8260}, % C5' + {5.1974, -8.8497, 1.9223}, % H5' + {5.5548, -8.7348, 3.7469}, % H5'' + {6.3140, -7.2060, 2.5510}, % C4' + {5.8744, -6.2116, 2.4731}, % H4' + {7.2798, -7.2260, 3.6420}, % O4' + {8.5733, -6.9410, 3.1329}, % C1' + {8.9047, -6.0374, 3.6446}, % H1' + {8.4429, -6.6596, 1.6327}, % C2' + {9.2880, -7.1071, 1.1096}, % H2'' + {8.2502, -5.2799, 1.4754}, % O2' + {8.7676, -4.7284, 2.0667}, % H2' + {7.1642, -7.4416, 1.3021}, % C3' + {7.4125, -8.5002, 1.2260}, % H3' + {6.5160, -6.9772, 0.1267}, % O3' + {9.4531, -8.1107, 3.4087}, % N1 + {11.5931, -9.0015, 3.6357}, % N3 + {10.8101, -7.8950, 3.3748}, % C2 + {11.1439, -10.2744, 3.9206}, % C4 + {9.7056, -10.4026, 3.9332}, % C5 + {8.9192, -9.3419, 3.6833}, % C6 + u, { + {11.3013, -6.8063, 3.1326}, % O2 + {11.9431, -11.1876, 4.1375}, % O4 + {12.5840, -8.8673, 3.6158}, % H3 + {9.2891, -11.2898, 4.1313}, % H5 + {7.9263, -9.4537, 3.6977}} % H6 + }. + + +% -- PARTIAL INSTANTIATIONS -------------------------------------------------- + +%var ::= {Int, Tfo, Nuc} + +absolute_pos({_I,T,_N}, P) -> tfo_apply(T, P). + +atom_pos(Atom, {I,T,N}) -> + absolute_pos({I,T,N}, p_apply(Atom, N)). + +get_var(Id,[{Id,T,N}|_]) -> {Id,T,N}; +get_var(Id,[_|Lst]) -> get_var(Id,Lst). + + +% -- SEARCH ------------------------------------------------------------------ + +% Sequential backtracking algorithm + +search(Partial_inst,[],_) -> + [Partial_inst]; +search(Partial_inst,[{F,Arg0,Arg1}|T],Constraint) -> + try_assignments(p_apply(F, Arg0,Arg1,Partial_inst), + Constraint, + Partial_inst, + T); +search(Partial_inst,[{F,Arg0,Arg1,Arg2}|T],Constraint) -> + try_assignments(p_apply(F, Arg0,Arg1,Arg2,Partial_inst), + Constraint, + Partial_inst, + T). + +try_assignments([],_,_,_) -> []; +try_assignments([V|Vs], Constraint, Partial_inst,T) -> + case p_apply(Constraint, V, Partial_inst) of + true -> append(search([V|Partial_inst],T,Constraint), + try_assignments(Vs, Constraint, Partial_inst,T)); + _ -> try_assignments(Vs, Constraint, Partial_inst,T) + end. + + +% -- DOMAINS ----------------------------------------------------------------- + +% Primary structure: strand A CUGCCACGUCUG, strand B CAGACGUGGCAG +% +% Secondary structure: strand A CUGCCACGUCUG +% |||||| +% GACGGUGCAGAC strand B +% +% Tertiary structure: +% +% 5' end of strand A C1----G12 3' end of strand B +% U2-------A11 +% G3-------C10 +% C4-----G9 +% C5---G8 +% A6 +% G6-C7 +% C5----G8 +% A4-------U9 +% G3--------C10 +% A2-------U11 +% 5' end of strand B C1----G12 3' end of strand A +% +% "helix", "stacked" and "connected" describe the spatial relationship +% between two consecutive nucleotides. E.g. the nucleotides C1 and U2 +% from the strand A. +% +% "wc" (stands for Watson-Crick and is a type of base-pairing), +% and "wc-dumas" describe the spatial relationship between +% nucleotides from two chains that are growing in opposite directions. +% E.g. the nucleotides C1 from strand A and G12 from strand B. + +% Dynamic Domains + +% Given, +% "ref" a nucleotide which is already positioned, +% "nuc" the nucleotide to be placed, +% and "tfo" a transformation matrix which expresses the desired +% relationship between "ref" and "nuc", +% the function "dgf-base" computes the transformation matrix that +% places the nucleotide "nuc" in the given relationship to "ref". + +dgf_base(Tfo, V, Nuc) -> + {_I,_T,N} = V, + tfo_combine(nuc_dgf_base_tfo(Nuc), + tfo_combine(Tfo,tfo_inv_ortho(process_type(type(N),V)))). + +process_type(a,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(rA_N9, V),atom_pos(nuc_C4, V)); +process_type(c,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(nuc_N1, V),atom_pos(nuc_C2, V)); +process_type(g,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(rG_N9, V),atom_pos(nuc_C4, V)); +process_type(_,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(nuc_N1, V),atom_pos(nuc_C2, V)). + + +% Placement of first nucleotide. + +reference(Nuc,I,_) -> + [{I,tfo_id(),Nuc}]. + +% The transformation matrix for wc is from: +% +% Chandrasekaran R. et al (1989) A Re-Examination of the Crystal +% Structure of A-DNA Using Fiber Diffraction Data. J. Biomol. +% Struct. & Dynamics 6(6):1189-1202. + +wc_tfo() -> + { + -1.0000, 0.0028, -0.0019, + 0.0028, 0.3468, -0.9379, + -0.0019, -0.9379, -0.3468, + -0.0080, 6.0730, 8.7208 + }. + +wc(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(wc_tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +wc_dumas_tfo() -> + { + -0.9737, -0.1834, 0.1352, + -0.1779, 0.2417, -0.9539, + 0.1422, -0.9529, -0.2679, + 0.4837, 6.2649, 8.0285 + }. + +wc_dumas(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(wc_dumas_tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +helix5__tfo() -> + { + 0.9886, -0.0961, 0.1156, + 0.1424, 0.8452, -0.5152, + -0.0482, 0.5258, 0.8492, + -3.8737, 0.5480, 3.8024 + }. + +helix5_(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(helix5__tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +helix3__tfo() -> + { + 0.9886, 0.1424, -0.0482, + -0.0961, 0.8452, 0.5258, + 0.1156, -0.5152, 0.8492, + 3.4426, 2.0474, -3.7042 + }. + +helix3_(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(helix3__tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +g37_a38_tfo() -> + { + 0.9991, 0.0164, -0.0387, + -0.0375, 0.7616, -0.6470, + 0.0189, 0.6478, 0.7615, + -3.3018, 0.9975, 2.5585 + }. + +g37_a38(Nuc,I,J,Partial_inst) -> + {I,dgf_base(g37_a38_tfo(),get_var(J,Partial_inst),Nuc),Nuc}. + +stacked5_(Nuc,I,J,Partial_inst) -> + [g37_a38(Nuc,I,J,Partial_inst) | helix5_(Nuc,I,J,Partial_inst)]. + +a38_g37_tfo() -> + { + 0.9991, -0.0375, 0.0189, + 0.0164, 0.7616, 0.6478, + -0.0387, -0.6470, 0.7615, + 3.3819, 0.7718, -2.5321 + }. + +a38_g37(Nuc,I,J,Partial_inst) -> + {I,dgf_base(a38_g37_tfo(),get_var(J,Partial_inst),Nuc),Nuc}. + +stacked3_(Nuc,I,J,Partial_inst) -> + [a38_g37(Nuc,I,J,Partial_inst) | helix3_(Nuc,I,J,Partial_inst)]. + +p_o3_(Nucs,I,J,Partial_inst) -> + generate([],Nucs,I,J,Partial_inst). + + +generate(Domains,[],_,_,_) -> + Domains; +generate(Domains,[N|Ns],I,J,Partial_inst) -> + Ref = get_var(J,Partial_inst), + Align = tfo_inv_ortho(tfo_align(atom_pos(nuc_O3_,Ref), + atom_pos(nuc_C3_,Ref), + atom_pos(nuc_C4_,Ref))), + generate([{I,tfo_combine(nuc_p_o3__60_tfo(N),Align),N}, + {I,tfo_combine(nuc_p_o3__180_tfo(N),Align),N}, + {I,tfo_combine(nuc_p_o3__275_tfo(N),Align),N} | Domains], + Ns,I,J,Partial_inst). + + +% -- PROBLEM STATEMENT ------------------------------------------------------- + +% Define anticodon problem -- Science 253:1255 Figure 3a, 3b and 3c + +% anticodon_domains() -> +% [ +% {reference, rC(), 27}, +% {helix5_, rC(), 28, 27}, +% {helix5_, rA(), 29, 28}, +% {helix5_, rG(), 30, 29}, +% {helix5_, rA(), 31, 30}, +% {wc, rU(), 39, 31}, +% {helix5_, rC(), 40, 39}, +% {helix5_, rU(), 41, 40}, +% {helix5_, rG(), 42, 41}, +% {helix5_, rG(), 43, 42}, +% {stacked3_, rA(), 38, 39}, +% {stacked3_, rG(), 37, 38}, +% {stacked3_, rA(), 36, 37}, +% {stacked3_, rA(), 35, 36}, +% {stacked3_, rG(), 34, 35}, %<-. Distance +% {p_o3_, rCs(), 32, 31}, % | Constraint +% {p_o3_, rUs(), 33, 32} %<-' 3.0 Angstroms +% ]. + +% Anticodon constraint + +anticodon_constraint({33,T,N},Partial_inst) -> + check0(dist(34,{33,T,N},Partial_inst)); +anticodon_constraint(_,_) -> true. + +check0(Dist) when is_float(Dist), Dist =< 3.0 -> true; +check0(_) -> false. + +dist(J,V,Partial_inst) -> + pt_dist(atom_pos(nuc_P, get_var(J,Partial_inst)), + atom_pos(nuc_O3_,V)). + +% anticodon() -> search([], anticodon_domains(), anticodon_constraint). + +% Define pseudoknot problem -- Science 253:1255 Figure 4a and 4b +pseudoknot_domains() -> + [ + {reference, rA(), 23}, + {wc_dumas, rU(), 8, 23}, + {helix3_, rG(), 22, 23}, + {wc_dumas, rC(), 9, 22}, + {helix3_, rG(), 21, 22}, + {wc_dumas, rC(), 10, 21}, + {helix3_, rC(), 20, 21}, + {wc_dumas, rG(), 11, 20}, + {helix3_, rU_(), 19, 20}, %<-. + {wc_dumas, rA(), 12, 19}, % | Distance +% % | Constraint +% Helix 1 % | 4.0 Angstroms + {helix3_, rC(), 3, 19}, % | + {wc_dumas, rG(), 13, 3}, % | + {helix3_, rC(), 2, 3}, % | + {wc_dumas, rG(), 14, 2}, % | + {helix3_, rC(), 1, 2}, % | + {wc_dumas, rG_(), 15, 1}, % | +% % | +% L2 LOOP % | + {p_o3_, rUs(), 16, 15}, % | + {p_o3_, rCs(), 17, 16}, % | + {p_o3_, rAs(), 18, 17}, %<-' +% +% L1 LOOP + {helix3_, rU(), 7, 8}, %<-. + {p_o3_, rCs(), 4, 3}, % | Constraint + {stacked5_, rU(), 5, 4}, % | 4.5 Angstroms + {stacked5_, rC(), 6, 5} %<-' + ]. + +% Pseudoknot constraint + +pseudoknot_constraint({18,T,N}, Partial_inst) -> + check1(dist(19, {18,T,N}, Partial_inst)); +pseudoknot_constraint({6,T,N}, Partial_inst) -> + check2(dist(7, {6,T,N}, Partial_inst)); +pseudoknot_constraint(_,_) -> true. + +check1(Dist) when is_float(Dist), Dist =< 4.0 -> true; +check1(_) -> false. + +check2(Dist) when is_float(Dist), Dist =< 4.5 -> true; +check2(_) -> false. + +do_pseudoknot() -> search([], pseudoknot_domains(), pseudoknot_constraint). + +% -- TESTING ----------------------------------------------------------------- + +list_of_atoms(N) -> + append(list_of_common_atoms(N),list_of_specific_atoms(N)). + +list_of_common_atoms + ({ + _,_,_,_, + P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, + C3_,H3_,O3_,N1,N3,C2,C4,C5,C6, + _,_ + }) -> + [P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, + C3_,H3_,O3_,N1,N3,C2,C4,C5,C6]. + +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,a, + {N6,N7,N9,C8,H2,H61,H62,H8}}) -> + [N6,N7,N9,C8,H2,H61,H62,H8]; +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,c, + {N4,O2,H41,H42,H5,H6}}) -> + [N4,O2,H41,H42,H5,H6]; +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,g, + {N2,N7,N9,C8,O6,H1,H21,H22,H8}}) -> + [N2,N7,N9,C8,O6,H1,H21,H22,H8]; +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,u, + {O2,O4,H3,H5,H6}}) -> + [O2,O4,H3,H5,H6]. + +var_most_distant_atom(V) -> + {_,_,N} = V, + maximum(map(distance,V,list_of_atoms(N))). + +distance(V,P) -> + {X,Y,Z} = absolute_pos(V,P), + distance(X,Y,Z). + +distance(X,Y,Z) when is_float(X), is_float(Y), is_float(Z) -> + math:sqrt(X * X + Y * Y + Z * Z). + +sol_most_distant_atom(S) -> + maximum(map(var_most_distant_atom,S)). + +most_distant_atom(Sols) -> + maximum(map(sol_most_distant_atom, Sols)). + +maximum([H|T]) -> + max(T,H). + +max([H|T],M) when is_float(H), is_float(M), H > M -> + max(T,H); +max([_|T],M) -> + max(T,M); +max([],M) -> M. + +%% +%% The map/2,3 functions rewritten to use a list comprehension, +%% just to cover the letrec handling in the inliner. +%% +map(Func, L) -> + [p_apply(Func, H) || H <- L]. + +map(Func, Arg, L) -> + [p_apply(Func, Arg, H) || H <- L]. + +% p_apply implements higher order functions +p_apply(sol_most_distant_atom, S) -> sol_most_distant_atom(S); +p_apply(var_most_distant_atom, V) -> var_most_distant_atom(V); +p_apply(nuc_C1_, X) -> nuc_C1_(X); +p_apply(nuc_C2, X) -> nuc_C2(X); +p_apply(nuc_C3_, X) -> nuc_C3_(X); +p_apply(nuc_C4, X) -> nuc_C4(X); +p_apply(nuc_C4_, X) -> nuc_C4_(X); +p_apply(nuc_N1, X) -> nuc_N1(X); +p_apply(nuc_O3_, X) -> nuc_O3_(X); +p_apply(nuc_P, X) -> nuc_P(X); +p_apply(nuc_dgf_base_tfo, X) -> nuc_dgf_base_tfo(X); +p_apply(nuc_p_o3__180_tfo, X) -> nuc_p_o3__180_tfo(X); +p_apply(nuc_p_o3__275_tfo, X) -> nuc_p_o3__275_tfo(X); +p_apply(nuc_p_o3__60_tfo, X) -> nuc_p_o3__60_tfo(X); +p_apply(rA_N9, X) -> rA_N9(X); +p_apply(rG_N9, X) -> rG_N9(X). + +p_apply(anticodon_constraint, V, P) -> anticodon_constraint(V, P); +p_apply(pseudoknot_constraint, V, P) -> pseudoknot_constraint(V, P); +p_apply(distance, V, P) -> distance(V, P). + +p_apply(reference, A1, A2, A3) -> reference(A1, A2, A3). + +p_apply(helix5_, A1, A2, A3, A4) -> helix5_(A1, A2, A3, A4); +p_apply(wc, A1, A2, A3, A4) -> wc(A1, A2, A3, A4); +p_apply(stacked3_, A1, A2, A3, A4) -> stacked3_(A1, A2, A3, A4); +p_apply(p_o3_, A1, A2, A3, A4) -> p_o3_(A1, A2, A3, A4); +p_apply(wc_dumas, A1, A2, A3, A4) -> wc_dumas(A1, A2, A3, A4); +p_apply(helix3_, A1, A2, A3, A4) -> helix3_(A1, A2, A3, A4); +p_apply(stacked5_, A1, A2, A3, A4) -> stacked5_(A1, A2, A3, A4). + +loop(0, R) -> R; +loop(N, _R) -> loop(N-1,most_distant_atom(do_pseudoknot())). diff --git a/lib/compiler/test/inline_SUITE_data/smith.erl b/lib/compiler/test/inline_SUITE_data/smith.erl new file mode 100644 index 0000000000..6aec7ad295 --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/smith.erl @@ -0,0 +1,95 @@ +% file: "smith.erl" + +-ifdef(ETOS). +-define(IS_INTEGER(X),is_integer(X)). +-else. +-define(IS_INTEGER(X),integer(X)). +-endif. + +-module(smith). +-export([?MODULE/0]). + +?MODULE() -> + Tops = generate_sequences(100,32,1), + Side = generate_sequence(32,0), + statistics(runtime), + R = loop(2,Tops,Side,0), + {R,R =:= 16}. + +max(A,B) when ?IS_INTEGER(A), ?IS_INTEGER(B) -> + if + A > B -> A; + true -> B + end. + +alpha_beta_penalty(A,B) when ?IS_INTEGER(A), ?IS_INTEGER(B) -> max(A-4,B-1). + +generate_sequence(Length,R) when ?IS_INTEGER(Length) -> + if + Length == 0 -> []; + true -> [R rem 10 | generate_sequence(Length-1, + (R * 11 + 1237501) + rem 10067)] + end. + +generate_sequences(0,_,_) -> []; +generate_sequences(N,Length,R) when ?IS_INTEGER(N), ?IS_INTEGER(Length) -> + [generate_sequence(Length, R) | generate_sequences(N-1,Length,R+1)]. + +match_entry(Top,Side,UpperLeft,Upper,Left) when ?IS_INTEGER(Top), ?IS_INTEGER(Side) -> + MeLeft = alpha_beta_penalty(element(3, Left), element(1, Left)), + MeUpper = alpha_beta_penalty(element(3, Upper), element(2, Upper)), + MeUpperLeft = + if + Top == Side -> + max(MeLeft, + max(MeUpper, + max(element(3,UpperLeft)+1,0))); + true -> + max(MeLeft, + max(MeUpper, + max(element(3,UpperLeft),0))) + end, + {MeLeft, MeUpper, MeUpperLeft, + max(MeUpperLeft, + max(element(4,Left), + max(element(4,Upper),element(4,UpperLeft))))}. + +match_zero_entry(Top,Side,{Left,_,UpperLeft,Max}) when ?IS_INTEGER(Top), ?IS_INTEGER(Side) -> + ELeft = alpha_beta_penalty(UpperLeft, Left), + Weight = max(1-abs(Side-Top),0), + EUpperLeft = max(max(ELeft,max(1-abs(Side-Top),0)),0), + EMax = max(max(Max,EUpperLeft),0), + {ELeft, -1, EUpperLeft, EMax}. + +match(Tops,Side,Prev,UpperLeft,Left) -> + match0(Tops, Side, Prev, UpperLeft, Left, [], none). + +match0([],_,_,_,_,Acc,Last) -> {Acc,Last}; +match0([Top|Tops],Side,[Upper|Prev],UpperLeft,Left,Acc,Last) when + ?IS_INTEGER(Top), ?IS_INTEGER(Side) -> + E = match_entry(Top, Side, UpperLeft, Upper, Left), + match0(Tops, Side, Prev, Upper, E, [E|Acc], E); +match0([Top|Tops],Side,none,UpperLeft,Left,Acc,Last) when + ?IS_INTEGER(Top), ?IS_INTEGER(Side) -> + E = match_zero_entry(Top, Side, Left), + match0(Tops, Side, none, UpperLeft, E, [E|Acc], E). + +match_two_seq(Side,Top,Prev) -> + match_two_seq0(Side, Top, Prev, none). + +match_two_seq0([],_,_,Result) -> Result; +match_two_seq0([S|Side],Top,Prev,Acc) when ?IS_INTEGER(S) -> + {Row,Result} = match(Top,S,Prev,{0,0,0,0},{0,0,0,0}), + match_two_seq0(Side, Top, Row, Result). + +match_sequences(Tops,Side) -> + match_sequences0(Tops, Side, -9999999). + +match_sequences0([],_,MaxResult) -> MaxResult; +match_sequences0([Top|Tops],Side,CrntResult) -> + Result = element(4, match_two_seq(Top, Side, none)), + match_sequences0(Tops, Side, max(CrntResult, Result)). + +loop(0,Tops,Side,R) -> R; +loop(N,Tops,Side,R) -> loop(N-1,Tops,Side,match_sequences(Tops,Side)). diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl new file mode 100644 index 0000000000..e62b2cd77e --- /dev/null +++ b/lib/compiler/test/lc_SUITE.erl @@ -0,0 +1,162 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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(lc_SUITE). + +-author('[email protected]'). +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + basic/1,deeply_nested/1,no_generator/1, + empty_generator/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [basic,deeply_nested,no_generator,empty_generator]. + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +basic(Config) when is_list(Config) -> + ?line L0 = lists:seq(1, 10), + ?line L1 = my_map(fun(X) -> {x,X} end, L0), + ?line L1 = [{x,X} || X <- L0], + ?line L0 = my_map(fun({x,X}) -> X end, L1), + ?line [1,2,3,4,5] = [X || X <- L0, X < 6], + ?line [4,5,6] = [X || X <- L0, X > 3, X < 7], + ?line [] = [X || X <- L0, X > 32, X < 7], + ?line [1,3,5,7,9] = [X || X <- L0, odd(X)], + ?line [2,4,6,8,10] = [X || X <- L0, not odd(X)], + ?line [1,3,5,9] = [X || X <- L0, odd(X), X =/= 7], + ?line [2,4,8,10] = [X || X <- L0, not odd(X), X =/= 6], + + %% Append is specially handled. + ?line [1,3,5,9,2,4,8,10] = [X || X <- L0, odd(X), X =/= 7] ++ + [X || X <- L0, not odd(X), X =/= 6], + + %% Guards BIFs are evaluated in guard context. Weird, but true. + ?line [{a,b,true},{x,y,true,true}] = [X || X <- tuple_list(), element(3, X)], + + %% Filter expressions with andalso/orelse. + ?line "abc123" = alphanum("?abc123.;"), + + %% Error cases. + ?line [] = [{xx,X} || X <- L0, element(2, X) == no_no_no], + ?line {'EXIT',_} = (catch [X || X <- L1, list_to_atom(X) == dum]), + ?line [] = [X || X <- L1, X+1 < 2], + ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]), + ?line {'EXIT',{function_clause,[{?MODULE,_,[x]}|_]}} = + (catch [E || E <- id(x)]), + ok. + +tuple_list() -> + [{a,b,true},[a,b,c],glurf,{a,b,false,xx},{a,b},{x,y,true,true},{a,b,d,ddd}]. + +my_map(F, L) -> + [F(X) || X <- L]. + +odd(X) -> + X rem 2 == 1. + +alphanum(Str) -> + [C || C <- Str, ((C >= $0) andalso (C =< $9)) + orelse ((C >= $a) andalso (C =< $z)) + orelse ((C >= $A) andalso (C =< $Z))]. + +deeply_nested(Config) when is_list(Config) -> + [[99,98,97,96,42,17,1764,12,11,10,9,8,7,6,5,4,3,7,2,1]] = deeply_nested_1(), + ok. + +deeply_nested_1() -> + %% This used to compile really, really SLOW before R11B-1... + [[X1,X2,X3,X4,X5,X6,X7(),X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18(),X19,X20] || + X1 <- [99],X2 <- [98],X3 <- [97],X4 <- [96],X5 <- [42],X6 <- [17], + X7 <- [fun() -> X5*X5 end],X8 <- [12],X9 <- [11],X10 <- [10], + X11 <- [9],X12 <- [8],X13 <- [7],X14 <- [6],X15 <- [5], + X16 <- [4],X17 <- [3],X18 <- [fun() -> X16+X17 end],X19 <- [2],X20 <- [1]]. + +no_generator(Config) when is_list(Config) -> + ?line Seq = lists:seq(-10, 17), + ?line [no_gen_verify(no_gen(A, B), A, B) || A <- Seq, B <- Seq], + + %% Literal expression, for coverage. + ?line [a] = [a || true], + ?line [a,b,c] = [a || true] ++ [b,c], + ok. + +no_gen(A, B) -> + [{A,B} || A+B =:= 0] ++ + [{A,B} || A*B =:= 0] ++ + [{A,B} || A rem B =:= 3] ++ + [{A,B} || A =:= B] ++ + [{one_more,A,B} || no_gen_one_more(A, B)] ++ + [A || A =:= 1] ++ + [A || A =:= 2] ++ + [A || A =:= 3] ++ + [A || A =:= 4] ++ + [A || A =:= 5] ++ + [A || A =:= 6] ++ + [A || A =:= 7] ++ + [A || A =:= 8] ++ + [A || A =:= 9] ++ + [B || B =:= 1] ++ + [B || B =:= 2] ++ + [B || B =:= 3] ++ + [B || B =:= 4] ++ + [B || B =:= 5] ++ + [B || B =:= 6] ++ + [B || B =:= 7] ++ + [B || B =:= 8] ++ + [B || B =:= 9]. + +no_gen_verify(Res, A, B) -> + Pair = {A,B}, + ShouldBe = no_gen_eval(fun() -> A+B =:= 0 end, Pair) ++ + no_gen_eval(fun() -> A*B =:= 0 end, Pair) ++ + no_gen_eval(fun() -> B =/= 0 andalso A rem B =:= 3 end, Pair) ++ + no_gen_eval(fun() -> A =:= B end, Pair) ++ + no_gen_eval(fun() -> A + 1 =:= B end, {one_more,A,B}) ++ + no_gen_eval(fun() -> 1 =< A andalso A =< 9 end, A) ++ + no_gen_eval(fun() -> 1 =< B andalso B =< 9 end, B), + case Res of + ShouldBe -> ok; + _ -> + io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]), + ?t:fail() + end. + +no_gen_eval(Fun, Res) -> + case Fun() of + true -> [Res]; + false -> [] + end. + +no_gen_one_more(A, B) -> A + 1 =:= B. + +empty_generator(Config) when is_list(Config) -> + ?line [] = [X || {X} <- [], (false or (X/0 > 3))], + ok. + +id(I) -> I. + diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl new file mode 100644 index 0000000000..20969c0b26 --- /dev/null +++ b/lib/compiler/test/match_SUITE.erl @@ -0,0 +1,355 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(match_SUITE). + +-export([all/1, + pmatch/1,mixed/1,aliases/1,match_in_call/1, + untuplify/1,shortcut_boolean/1,letify_guard/1, + selectify/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [pmatch,mixed,aliases,match_in_call,untuplify,shortcut_boolean, + letify_guard,selectify]. + +pmatch(Config) when is_list(Config) -> + ?line ok = doit(1), + ?line ok = doit(2), + ?line {error,baz} = doit(3), + ?line {error,foobar} = doit(4), + ok. + +%% Thanks to Tobias Lindahl (HiPE). +-define(FOO(X), + case X of + 1 -> foo; + 2 -> bar; + 3 -> baz; + 4 -> foobar + end). + +doit(X) -> + case ?FOO(X) of + foo -> ok; + bar -> ok; + Other -> {error, Other} + end. + +mixed(Config) when is_list(Config) -> + ?line glufs = mixit(1), + ?line klafs = mixit(2), + ?line fnurra = mixit(3), + ?line usch = mixit(4), + ?line {error,blurf} = mixit(5), + ?line {error,87987987} = mixit(6), + ?line {error,{a,b,c}} = mixit(7), + ok. + +mixit(X) -> + case case X of + 1 -> a; + 2 -> b; + 3 -> 42; + 4 -> 77; + 5 -> blurf; + 6 -> 87987987; + 7 -> {a,b,c} + end of + a -> glufs; + b -> klafs; + 42 -> fnurra; + 77 -> usch; + Other -> {error,Other} + end. + +aliases(Config) when is_list(Config) -> + %% Lists/strings. + ?line ok = str_alias("abc"), + ?line ok = str_alias("def"), + ?line ok = str_alias("ghi"), + ?line ok = str_alias("klm"), + ?line ok = str_alias("qrs"), + ?line ok = str_alias("xy"), + ?line ok = str_alias(""), + ?line ok = str_alias([]), + ?line error = str_alias("blurf"), + + %% Characters/integers. + ?line ok = char_alias($v), + ?line ok = char_alias(118), + ?line ok = char_alias($w), + ?line ok = char_alias(119), + ?line ok = char_alias(42), + ?line ok = char_alias(3.0), + ?line error = char_alias($_), + ?line error = char_alias(0), + + ?line {42,42,42} = three(42), + + ?line {1,42,99,1,42,99} = tuple_alias({1,42,99}), + ?line {-10,20,-10,20,-10,20} = tuple_alias({-10,20}), + ?line 6 = tup_lit_alias({1,2,3}), + ?line 6 = tup_lit_alias_rev({1,2,3}), + + ?line {42,42,42,42} = multiple_aliases_1(42), + ?line {7,7,7} = multiple_aliases_2(7), + ?line {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}), + ok. + +str_alias(V) -> + Res = str_alias_1(V), + Res = str_alias_2(V). + +str_alias_1([$a,$b,$c]="abc"="a"++[$b,$c]=[97,98,99]) -> ok; +str_alias_1([$d|"ef"]="def") -> ok; +str_alias_1([$g|"hi"]="g"++"hi"="gh"++"i"="ghi"++"") -> ok; +str_alias_1("k"++"lm"=[$k|"lm"]) -> ok; +str_alias_1([113,114,115]="qrs"=[$q,$r,$s]="q"++"r"++"s") -> ok; +str_alias_1([$x,$y]="xy") -> ok; +str_alias_1(""=[]) -> ok; +str_alias_1(_) -> error. + +%% Make sure that different line numbers do not matter. + +str_alias_2([$a,$b,$c]= + "abc"= + "a"++[$b,$c + ]= + [97,98,99 + ]) -> ok; +str_alias_2([$d|"ef"]= + "def") -> ok; +str_alias_2([$g|"hi"]= + "g"++"hi"= + "gh"++"i"= + "ghi"++"") -> ok; +str_alias_2("k"++"lm"= + [$k|"lm" + ]) -> ok; +str_alias_2([113,114,115]= + "qrs"=[$q,$r,$s + ]= + "q"++"r"++"s") -> ok; +str_alias_2([$x,$y]= + "xy") -> ok; +str_alias_2(""= + []) -> ok; +str_alias_2(_) -> error. + +char_alias(V) -> + Res = char_alias_1(V), + Res = char_alias_2(V). + +char_alias_1(118=$v) -> ok; +char_alias_1($w=119) -> ok; +char_alias_1(42=42) -> ok; +char_alias_1(3.0=3.0) -> ok; +char_alias_1(_) -> error. + +char_alias_2(118= + $v) -> ok; +char_alias_2($w= + 119) -> ok; +char_alias_2(42= + 42) -> ok; +char_alias_2(3.0= + 3.0) -> ok; +char_alias_2(_) -> error. + +three(V) -> + Res = three_1(V), + Res = three_2(V). + +three_1(A=B=C) -> + {A,B,C}. + +three_2(A= + B= + C) -> + {A,B,C}. + +tuple_alias({A,B,C}={X,Y,Z}) -> + {A,B,C,X,Y,Z}; +tuple_alias({A,B}={C,D}={E,F}) -> + {A,B,C,D,E,F}. + +tup_lit_alias({A,B,C}={1,2,3}) -> + A+B+C. + +tup_lit_alias_rev({1,2,3}={A,B,C}) -> + A+B+C. + +multiple_aliases_1((A=B)=(C=D)) -> + {A,B,C,D}. + +multiple_aliases_2((A=B)=(A=C)) -> + {A,B,C}. + +multiple_aliases_3((A={_,_}=B)={_,_}=C) -> + {A,B,C}. + +%% OTP-7018. + +match_in_call(Config) when is_list(Config) -> + ?line mac_a(0), + ?line mac_b(1), + ?line mac_c(42), + ?line mac_d(42), + ?line mac_e({gurka,42}), + + ?line [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]), + ?line {'EXIT',_} = (catch mac_lc([{1,1}])), + + ok. + +mac_a(X) -> + id(_Gurka = {gurka,X}), + ok. + +mac_b(X) -> + id(Gurka = {gurka,X}), + gurka(Gurka, X), + ok. + +mac_c(X) -> + id(Gurka = Yxa = {gurka,X}), + id({Gurka,Yxa}), + ok. + +mac_d(X) -> + id({gurka,42} = {gurka,X}), + ok. + +mac_e(X) -> + id({gurka,42} = X), + ok. + +mac_lc(E) -> + Res = mac_lc1(E), + Res = mac_lc2(E). + +mac_lc1(E) -> + [{X,Y} || + {X,_} <- E, + (Y = X) =:= (Y = 1 + 1)]. + +mac_lc2(E) -> + [{X,Y} || + {X,_} <- E, + (Y = X) =:= (Y = 2)]. + +gurka({gurka,X}, X) -> ok. + + +untuplify(Config) when is_list(Config) -> + %% We do this to cover sys_core_fold:unalias_pat/1. + ?line {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias), + ?line error = untuplify_1([1,2], {3,4}, 42), + ok. + +untuplify_1(A, B, C) -> + case {A,B,C} of + {[X,Y],{Z,W},alias=Alias}=Top -> + {X,Y,Z,W,Alias,Top}; + [_,_]=CantMatch -> + CantMatch; + _ -> + error + end. + +%% Coverage of beam_dead:shortcut_boolean_label/4. +shortcut_boolean(Config) when is_list(Config) -> + ?line false = shortcut_boolean_1([0]), + ?line true = shortcut_boolean_1({42}), + ?line maybe = shortcut_boolean_1(self()), + ?line {'EXIT',_} = (catch shortcut_boolean_1([a,b])), + ?line {'EXIT',_} = (catch shortcut_boolean_1({a,b})), + ok. + +shortcut_boolean_1(X) -> + Outer = case not is_pid(X) of + true -> + V = case X of + [_] -> true; + {_} -> false + end, + not V; + false -> + maybe + end, + id(Outer). + + +%% Test sys_core_fold:letify_guard/3. +letify_guard(Config) when is_list(Config) -> + ?line {-15,a} = letify_guard(-15, a), + ?line 5 = letify_guard(2, 3), + ok. + +letify_guard(A, B) -> + case {A,B} of + %% The tuple will be built in the guard... + Z when tuple_size(Z) =:= 2, element(1, Z) < 0 -> + %% ... and again here. + Z; + {X,Y} -> X+Y + end. + +%% Test combining of is_eq_exact instructions to select_val +%% instructions in beam_dead and beam_peep. + +selectify(Config) when is_list(Config) -> + ?line integer = sel_different_types({r,42}), + ?line atom = sel_different_types({r,forty_two}), + ?line none = sel_different_types({r,18}), + ?line {'EXIT',_} = (catch sel_different_types([a,b,c])), + + ?line integer = sel_same_value({r,42}), + ?line error = sel_same_value({r,100}), + ?line error = sel_same_value(a), + + ?line integer42 = sel_same_value2(42), + ?line integer43 = sel_same_value2(43), + ?line error = sel_same_value2(44), + ok. + +sel_different_types({r,_}=T) when element(2, T) =:= forty_two -> + atom; +sel_different_types({r,_}=T) when element(2, T) =:= 42 -> + integer; +sel_different_types({r,_}) -> + none. + +sel_same_value({r,V}) when V =:= 42 -> + integer; +sel_same_value({r,V}) when V =:= 42 -> + integer42; +sel_same_value(_) -> + error. + +sel_same_value2(V) when V =:= 42 -> + integer42; +sel_same_value2(V) when V =:= 42; V =:= 43 -> + integer43; +sel_same_value2(_) -> + error. + +id(I) -> I. diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl new file mode 100644 index 0000000000..e096571d50 --- /dev/null +++ b/lib/compiler/test/misc_SUITE.erl @@ -0,0 +1,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. + diff --git a/lib/compiler/test/nested_call_in_case.core b/lib/compiler/test/nested_call_in_case.core new file mode 100644 index 0000000000..5c6b6909bd --- /dev/null +++ b/lib/compiler/test/nested_call_in_case.core @@ -0,0 +1,21 @@ +module 'nested_call_in_case' ['a'/2] + attributes [] + +'a'/2 = + fun (_x,_y) -> + case call 'erlang':'>' + (call 'erlang':'length' + (_x), _y) of + <'true'> when 'true' -> + 'yes' + <'false'> when 'true' -> + 'no' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end +end + + + diff --git a/lib/compiler/test/num_bif_SUITE.erl b/lib/compiler/test/num_bif_SUITE.erl new file mode 100644 index 0000000000..c246f56611 --- /dev/null +++ b/lib/compiler/test/num_bif_SUITE.erl @@ -0,0 +1,265 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(num_bif_SUITE). + +-include("test_server.hrl"). + +%% Tests optimization of the BIFs: +%% abs/1 +%% float/1 +%% float_to_list/1 +%% integer_to_list/1 +%% list_to_float/1 +%% list_to_integer/1 +%% round/1 +%% trunc/1 + +-export([all/1, t_abs/1, t_float/1, + t_float_to_list/1, t_integer_to_list/1, + t_list_to_integer/1, + t_list_to_float/1, t_list_to_float_safe/1, t_list_to_float_risky/1, + t_round/1, t_trunc/1]). + +all(suite) -> + test_lib:recompile(?MODULE), + [t_abs, t_float, t_float_to_list, t_integer_to_list, + t_list_to_float, t_list_to_integer, + t_round, t_trunc]. + +t_abs(Config) when is_list(Config) -> + %% Floats. + ?line 5.5 = abs(5.5), + ?line 0.0 = abs(0.0), + ?line 100.0 = abs(-100.0), + + %% Integers. + ?line 5 = abs(5), + ?line 0 = abs(0), + ?line 100 = abs(-100), + + %% The largest smallnum. OTP-3190. + ?line X = (1 bsl 27) - 1, + ?line X = abs(X), + ?line X = abs(X-1)+1, + ?line X = abs(X+1)-1, + ?line X = abs(-X), + ?line X = abs(-X-1)-1, + ?line X = abs(-X+1)+1, + + %% Bignums. + BigNum = 13984792374983749, + ?line BigNum = abs(BigNum), + ?line BigNum = abs(-BigNum), + ok. + +t_float(Config) when is_list(Config) -> + ?line 0.0 = float(0), + ?line 2.5 = float(2.5), + ?line 0.0 = float(0.0), + ?line -100.55 = float(-100.55), + ?line 42.0 = float(42), + ?line -100.0 = float(-100), + + %% Bignums. + ?line 4294967305.0 = float(4294967305), + ?line -4294967305.0 = float(-4294967305), + + %% Extremly big bignums. + ?line Big = list_to_integer(lists:duplicate(2000, $1)), + ?line {'EXIT', {badarg, _}} = (catch float(Big)), + + %% Invalid types and lists. + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(atom)), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(123)), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer([$1, [$2]])), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer("1.2")), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer("a")), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer("")), + ok. + + +%% Tests float_to_list/1. + +t_float_to_list(Config) when is_list(Config) -> + ?line test_ftl("0.0e+0", 0.0), + ?line test_ftl("2.5e+1", 25.0), + ?line test_ftl("2.5e+0", 2.5), + ?line test_ftl("2.5e-1", 0.25), + ?line test_ftl("-3.5e+17", -350.0e15), + ok. + +test_ftl(Expect, Float) -> + %% No ?line on the next line -- we want the line number from t_float_to_list. + Expect = remove_zeros(lists:reverse(float_to_list(Float)), []). + +%% Removes any non-significant zeros in a floating point number. +%% Example: 2.500000e+01 -> 2.5e+1 + +remove_zeros([$+, $e|Rest], [$0, X|Result]) -> + remove_zeros([$+, $e|Rest], [X|Result]); +remove_zeros([$-, $e|Rest], [$0, X|Result]) -> + remove_zeros([$-, $e|Rest], [X|Result]); +remove_zeros([$0, $.|Rest], [$e|Result]) -> + remove_zeros(Rest, [$., $0, $e|Result]); +remove_zeros([$0|Rest], [$e|Result]) -> + remove_zeros(Rest, [$e|Result]); +remove_zeros([Char|Rest], Result) -> + remove_zeros(Rest, [Char|Result]); +remove_zeros([], Result) -> + Result. + +%% Tests integer_to_list/1. + +t_integer_to_list(Config) when is_list(Config) -> + ?line "0" = integer_to_list(0), + ?line "42" = integer_to_list(42), + ?line "-42" = integer_to_list(-42), + ?line "-42" = integer_to_list(-42), + ?line "32768" = integer_to_list(32768), + ?line "268435455" = integer_to_list(268435455), + ?line "-268435455" = integer_to_list(-268435455), + ?line "123456932798748738738" = integer_to_list(123456932798748738738), + ?line Big_List = lists:duplicate(2000, $1), + ?line Big = list_to_integer(Big_List), + ?line Big_List = integer_to_list(Big), + ok. + +%% Tests list_to_float/1. + +t_list_to_float(suite) -> [t_list_to_float_safe, t_list_to_float_risky]. + +t_list_to_float_safe(Config) when is_list(Config) -> + ?line 0.0 = list_to_float("0.0"), + ?line 0.0 = list_to_float("-0.0"), + ?line 0.5 = list_to_float("0.5"), + ?line -0.5 = list_to_float("-0.5"), + ?line 100.0 = list_to_float("1.0e2"), + ?line 127.5 = list_to_float("127.5"), + ?line -199.5 = list_to_float("-199.5"), + + ?line {'EXIT', {badarg, _}} = (catch list_to_float("0")), + ?line {'EXIT', {badarg, _}} = (catch list_to_float("0..0")), + ?line {'EXIT', {badarg, _}} = (catch list_to_float("0e12")), + ?line {'EXIT', {badarg, _}} = (catch list_to_float("--0.0")), +%% ?line {'EXIT', {badarg, _}} = (catch list_to_float("0.0e+99999999")), + + ok. + +%% This might crash the emulator... +%% (Known to crash the Unix version of Erlang 4.4.1) + +t_list_to_float_risky(Config) when is_list(Config) -> + ?line Many_Ones = lists:duplicate(25000, $1), + ?line list_to_float("2."++Many_Ones), + ?line {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)), + ok. + +%% Tests list_to_integer/1. + +t_list_to_integer(Config) when is_list(Config) -> + ?line 0 = list_to_integer("0"), + ?line 0 = list_to_integer("00"), + ?line 0 = list_to_integer("-0"), + ?line 1 = list_to_integer("1"), + ?line -1 = list_to_integer("-1"), + ?line 42 = list_to_integer("42"), + ?line -12 = list_to_integer("-12"), + ?line 32768 = list_to_integer("32768"), + ?line 268435455 = list_to_integer("268435455"), + ?line -268435455 = list_to_integer("-268435455"), + + %% Bignums. + ?line 123456932798748738738 = list_to_integer("123456932798748738738"), + ?line list_to_integer(lists:duplicate(2000, $1)), + ok. + +%% Tests round/1. + +t_round(Config) when is_list(Config) -> + ?line 0 = round(0.0), + ?line 0 = round(0.4), + ?line 1 = round(0.5), + ?line 0 = round(-0.4), + ?line -1 = round(-0.5), + ?line 255 = round(255.3), + ?line 256 = round(255.6), + ?line -1033 = round(-1033.3), + ?line -1034 = round(-1033.6), + + % OTP-3722: + ?line X = (1 bsl 27) - 1, + ?line MX = -X, + ?line MXm1 = -X-1, + ?line MXp1 = -X+1, + ?line F = X + 0.0, + ?line X = round(F), + ?line X = round(F+1)-1, + ?line X = round(F-1)+1, + ?line MX = round(-F), + ?line MXm1 = round(-F-1), + ?line MXp1 = round(-F+1), + + ?line X = round(F+0.1), + ?line X = round(F+1+0.1)-1, + ?line X = round(F-1+0.1)+1, + ?line MX = round(-F+0.1), + ?line MXm1 = round(-F-1+0.1), + ?line MXp1 = round(-F+1+0.1), + + ?line X = round(F-0.1), + ?line X = round(F+1-0.1)-1, + ?line X = round(F-1-0.1)+1, + ?line MX = round(-F-0.1), + ?line MXm1 = round(-F-1-0.1), + ?line MXp1 = round(-F+1-0.1), + + ?line 0.5 = abs(round(F+0.5)-(F+0.5)), + ?line 0.5 = abs(round(F-0.5)-(F-0.5)), + ?line 0.5 = abs(round(-F-0.5)-(-F-0.5)), + ?line 0.5 = abs(round(-F+0.5)-(-F+0.5)), + + %% Bignums. + ?line 4294967296 = round(4294967296.1), + ?line 4294967297 = round(4294967296.9), + ?line -4294967296 = -round(4294967296.1), + ?line -4294967297 = -round(4294967296.9), + ok. + +t_trunc(Config) when is_list(Config) -> + ?line 0 = trunc(0.0), + ?line 5 = trunc(5.3333), + ?line -10 = trunc(-10.978987), + % The largest smallnum, converted to float (OTP-3722): + ?line X = (1 bsl 27) - 1, + ?line F = X + 0.0, + io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n", + [X, X, binary_to_list(term_to_binary(X)), + F, F, binary_to_list(term_to_binary(F)), + trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]), + ?line X = trunc(F), + ?line X = trunc(F+1)-1, + ?line X = trunc(F-1)+1, + ?line X = -trunc(-F), + ?line X = -trunc(-F-1)-1, + ?line X = -trunc(-F+1)+1, + + %% Bignums. + ?line 4294967305 = trunc(4294967305.7), + ?line -4294967305 = trunc(-4294967305.7), + ok. diff --git a/lib/compiler/test/parteval_SUITE.erl b/lib/compiler/test/parteval_SUITE.erl new file mode 100644 index 0000000000..3ef84571b9 --- /dev/null +++ b/lib/compiler/test/parteval_SUITE.erl @@ -0,0 +1,46 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(parteval_SUITE). + +-include("test_server.hrl"). + +-export([all/1, pe2/1]). + +all(suite) -> [pe2]. + +%% (This is more general than needed, since we once compiled the same +%% source code with and without a certain option.) +compile_and_load(Srcname, Outdir, Module, Options) -> + ?line Objname = filename:join(Outdir, "t1") ++ code:objfile_extension(), + ?line {ok, Module} = + compile:file(Srcname, + [{d, 'M', Module}, {outdir, Outdir}] ++ Options), + ?line {ok, B} = file:read_file(Objname), + ?line {module, Module} = code:load_binary(Module, Objname, B), + B. + +pe2(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Srcname = filename:join(DataDir, "t1.erl"), + ?line compile_and_load(Srcname, PrivDir, t1, []), + + ?line {Correct, Actual} = t1:run(), + ?line Correct = Actual, + ok. diff --git a/lib/compiler/test/parteval_SUITE_data/t1.erl b/lib/compiler/test/parteval_SUITE_data/t1.erl new file mode 100644 index 0000000000..5e4a40f103 --- /dev/null +++ b/lib/compiler/test/parteval_SUITE_data/t1.erl @@ -0,0 +1,140 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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(?M). + +-compile(export_all). + +%%% The arity-0 functions are all called from the test suite. + +f2() -> + size({1,2}). + +i() -> + case [] of + [] -> + ok; + X -> + hopp + end. + +e() -> + case 4+5 of +% X when X>10 -> kvock; % not removed by BEAM opt. + {X,X} when list(X) -> + kvack; + 9 -> + ok; + _ -> + ko + end. + +f() -> + element(2,{a,b,c,d}), + erlang:element(2,{a,b,c,d}), + "hej" ++ "hopp". + +g(X) -> + if + float(3.4) -> + hej; + X == 5, 4==4 -> + japp; + 4 == 4, size({1,2}) == 1 -> + ok + end. + +g() -> + {g(3),g(5)}. + +bliff() -> + if + 3==4 -> + himm + end. + +fi() -> + case 4 of + X when 4==3 -> + {X}; + 4 -> + 4; + _ -> + ok + end. + +iff() when 3==2 -> + if + 3 == 4 -> + baff; + 3 == 3 -> + nipp + end. + +sleep(I) -> receive after I -> ok end. + +sleep() -> + sleep(45). + +s() -> + case 4 of + 3 -> + ok + end. + +error_reason(R) when atom(R) -> + R; +error_reason(R) when tuple(R) -> + error_reason(element(1, R)). + +plusplus() -> + ?MODULE ++ " -> mindre snygg felhantering". + +call_it(F) -> + case (catch apply(?MODULE, F, [])) of + {'EXIT', R0} -> + {'EXIT', error_reason(R0)}; + V -> + V + end. + +run() -> + L = [{f2, 2}, + {i, ok}, + {e, ok}, + {f, "hejhopp"}, + {g, {hej, hej}}, + {bliff, {'EXIT', if_clause}}, + {fi, 4}, + {iff, {'EXIT', function_clause}}, + {sleep, ok}, + {s, {'EXIT', case_clause}, + {plusplus, {'EXIT', badarg}}}], + Actual = [call_it(F) || {F, _} <- L], + Correct = [C || {_, C} <- L], + {Correct, Actual}. + + +%%% Don't call, only compile. +t(A) -> + receive + A when 1==2 -> + ok; + B -> + B + end. diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl new file mode 100644 index 0000000000..c8919e5539 --- /dev/null +++ b/lib/compiler/test/pmod_SUITE.erl @@ -0,0 +1,90 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(pmod_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + basic/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [basic]. + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +basic(Config) when is_list(Config) -> + ?line basic_1(Config, []), + ?line basic_1(Config, [inline]), + ?line basic_1(Config, [{inline,500}]), + ok. + +basic_1(Config, Opts) -> + io:format("Options: ~p\n", [Opts]), + ?line ok = compile_load(pmod_basic, Config, Opts), + + ?line Prop1 = pmod_basic:new([{a,xb},{b,true},{c,false}]), + ?line Prop2 = pmod_basic:new([{y,zz}]), + ?line io:format("Prop1 = ~p\n", [Prop1]), + ?line io:format("Prop2 = ~p\n", [Prop2]), + + ?line {a,xb} = Prop1:lookup(a), + ?line none = Prop1:lookup(glurf), + ?line false = Prop1:or_props([]), + ?line true = Prop1:or_props([b,c]), + ?line true = Prop1:or_props([b,d]), + ?line false = Prop1:or_props([d]), + + ?line none = Prop2:lookup(kalle), + ?line {y,zz} = Prop2:lookup(y), + ?line {a,xb} = Prop1:lookup(a), + + ?line Prop3 = Prop1:prepend({blurf,true}), + ?line io:format("Prop3 = ~p\n", [Prop3]), + ?line {blurf,true} = Prop3:lookup(blurf), + + Prop4 = Prop3:append(42), + ?line io:format("Prop4 = ~p\n", [Prop4]), + ?line {42,5} = Prop4:stupid_sum(), + + %% Some record guards. + ?line ok = Prop4:bar({s,0}), + ?line ok = Prop4:bar_bar({s,blurf}), + ?line error = Prop4:bar_bar({s,a,b}), + ?line error = Prop4:bar_bar([]), + + ok. + +compile_load(Module, Conf, Opts) -> + ?line Dir = ?config(data_dir,Conf), + ?line Src = filename:join(Dir, atom_to_list(Module)), + ?line Out = ?config(priv_dir,Conf), + ?line CompRc = compile:file(Src, [report,{outdir,Out}|Opts]), + ?line {ok,Module} = CompRc, + ?line code:purge(Module), + ?line {module,Module} = + code:load_abs(filename:join(Out, atom_to_list(Module))), + ok. diff --git a/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl b/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl new file mode 100644 index 0000000000..e6f4c63421 --- /dev/null +++ b/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(pmod_basic, [Props]). + +-export([lookup/1,or_props/1,prepend/1,append/1,stupid_sum/0]). +-export([bar/1,bar_bar/1]). + +lookup(Key) -> + proplists:lookup(Key, Props). + +or_props(Keys) -> + Res = or_props_1(Keys, false), + true = is_bool(Res), %is_bool/1 does not use Props. + Res. + +prepend(Term) -> + new([Term|Props]). + +append(Term) -> + pmod_basic:new(Props++[Term]). + +or_props_1([K|Ks], Acc) -> + or_props_1(Ks, proplists:get_bool(K, Props) or Acc); +or_props_1([], Acc) -> Acc. + +is_bool(true) -> true; +is_bool(false) -> true; +is_bool(_) -> false. + +stupid_sum() -> + put(counter, 0), + Res = stupid_sum_1(Props, 0), + {Res,get(counter)}. + +stupid_sum_1([H|T], Sum0) -> + try add(Sum0, H) of + Sum -> stupid_sum_1(T, Sum) + catch + error:_ -> stupid_sum_1(T, Sum0) + after + bump() + end; +stupid_sum_1([], Sum) -> Sum. + +bump() -> + put(counter, get(counter)+1). + +add(A, B) -> + A+B. + +-record(s, {a}). + +bar(S) when S#s.a == 0 -> ok. + +bar_bar(S) when is_record(S, s) -> ok; +bar_bar(_) -> error. diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl new file mode 100644 index 0000000000..cb8833759a --- /dev/null +++ b/lib/compiler/test/receive_SUITE.erl @@ -0,0 +1,161 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% +%%% Purpose : Compiles various modules with tough code + +-module(receive_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + recv/1,coverage/1,otp_7980/1]). + +-include("test_server.hrl"). + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(2)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> + test_lib:recompile(?MODULE), + [recv,coverage,otp_7980]. + +-record(state, {ena = true}). + +recv(Config) when is_list(Config) -> + ?line Pid = spawn_link(fun() -> loop(#state{}) end), + Self = self(), + ?line Pid ! {Self,test}, + receive + {ok,test} -> ok; + {error,Other} -> + io:format("Got unpexected ~p", [Other]), + ?line ?t:fail() + after 10000 -> + ?line ?t:fail(no_answer) + end, + receive + X -> + io:format("Unexpected extra message: ~p", [X]), + ?line ?t:fail() + after 10 -> + ok + end, + ok. + +loop(S) -> + receive + _ when S#state.ena == false -> + loop(S); + {P,test} -> + P ! {ok,test}, + loop(S); + _X -> + loop(S) + end. + +coverage(Config) when is_list(Config) -> + do_link(self()), + do_unlink(self()), + do_monitor_node(node(), true), + do_monitor_node(node(), false), + do_group_leader(group_leader(), self()), + id(node(self())), + + erlang:'!'(self(), {a,10}), + self() ! {b,20}, + [{a,10},{b,20}] = receive_all(), + self() ! {c,42}, + receive + {c,42} -> + ok + after infinity -> + exit(cant_happen) + end, + + self() ! 17, + self() ! 19, + ?line 59 = tuple_to_values(infinity, x), + ?line 61 = tuple_to_values(999999, x), + ?line 0 = tuple_to_values(1, x), + ok. + +receive_all() -> + receive + Any -> + [Any|receive_all()] + after 0 -> + [] + end. + +do_monitor_node(Node, Bool) -> + monitor_node(Node, Bool). + +do_link(Pid) -> + link(Pid). + +do_unlink(Pid) -> + unlink(Pid). + +do_group_leader(Leader, Pid) -> + group_leader(Leader, Pid). + + +%% cover sys_core_fold:tuple_to_values/2 +tuple_to_values(infinity, X) -> + {A,B} = case X of + x -> + receive + Any -> + {42,Any} + end + end, + A+B; +tuple_to_values(Timeout, X) -> + {A,B} = case X of + x -> + receive + Any -> + {42,Any} + after Timeout -> + {0,0} + end + end, + A+B. + +%% OTP-7980. Thanks to Vincent de Phily. The following code would +%% be inccorrectly optimized by beam_jump. + +otp_7980(Config) when is_list(Config) -> + 7 = otp_7980_add_clients(10), + ok. + +otp_7980_add_clients(Count) -> + Timeout = 42, + lists:foldl(fun(_, N) -> + case N of + 1 -> ok; + _ -> receive after Timeout -> ok end + end, + N - 1 + end, Count, [1,2,3]). + +id(I) -> I. diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl new file mode 100644 index 0000000000..bd2ffd7f65 --- /dev/null +++ b/lib/compiler/test/record_SUITE.erl @@ -0,0 +1,525 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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% +%% +%%% Purpose : Test records. + +-module(record_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + errors/1,record_test_2/1,record_test_3/1,record_access_in_guards/1, + guard_opt/1,eval_once/1,foobar/1,missing_test_heap/1]). + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(2)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> + test_lib:recompile(?MODULE), + [errors,record_test_2,record_test_3,record_access_in_guards, + guard_opt,eval_once,foobar,missing_test_heap]. + +-record(foo, {a,b,c,d}). +-record(bar, {a,b,c,d}). +-record(barf, {a,b,c,d,e}). + +errors(Config) when is_list(Config) -> + Foo = #foo{a=1,b=2,c=3,d=4}, + ?line #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42), + + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)), + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)), + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)), + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)), + + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, + 35, 17, 42, -2)), + + ok. + +update_foo(#foo{}=R, A, B) -> + R#foo{a=A,b=B}. + +update_foo_bar(#foo{}=R, A) -> + R#bar{a=A}. + +update_foo_bar(#foo{}=R, A, _B) -> + R#bar{a=A,b=A}. + +update_foo_bar(#foo{}=R, A, _B, C) -> + R#bar{a=A,b=A,c=C}. + +update_foo_bar(#foo{}=R, A, _B, C, D) -> + R#bar{a=A,b=A,c=C,d=D}. + +update_foo_barf(#foo{}=R, A) -> + R#barf{a=A}. + +update_foo_barf(#foo{}=R, A, _B) -> + R#barf{a=A,b=A}. + +update_foo_barf(#foo{}=R, A, _B, C) -> + R#barf{a=A,b=A,c=C}. + +update_foo_barf(#foo{}=R, A, _B, C, D) -> + R#barf{a=A,b=A,c=C,d=D}. + +update_foo_barf(#foo{}=R, A, _B, C, D, E) -> + R#barf{a=A,b=A,c=C,d=D,e=E}. + + +-define(TrueGuard(Expr), if Expr -> ok; true -> ?t:fail() end). +-define(FalseGuard(Expr), if Expr -> ?t:fail(); true -> ok end). + +record_test_2(Config) when is_list(Config) -> + ?line true = is_record(#foo{}, foo), + ?line false = is_record(#foo{}, barf), + ?line false = is_record({foo}, foo), + + ?line true = erlang:is_record(#foo{}, foo), + ?line false = erlang:is_record(#foo{}, barf), + ?line false = erlang:is_record({foo}, foo), + + ?line false = is_record([], foo), + ?line false = is_record(Config, foo), + + ?line ?TrueGuard(is_record(#foo{}, foo)), + ?line ?FalseGuard(is_record(#foo{}, barf)), + ?line ?FalseGuard(is_record({foo}, foo)), + + ?line ?TrueGuard(erlang:is_record(#foo{}, foo)), + ?line ?FalseGuard(erlang:is_record(#foo{}, barf)), + ?line ?FalseGuard(erlang:is_record({foo}, foo)), + + ?line ?FalseGuard(is_record([], foo)), + ?line ?FalseGuard(is_record(Config, foo)), + + %% 'not is_record/2' to test guard optimization. + + ?line ?FalseGuard(not is_record(#foo{}, foo)), + ?line ?TrueGuard(not is_record(#foo{}, barf)), + ?line ?TrueGuard(not is_record({foo}, foo)), + + ?line ?FalseGuard(not erlang:is_record(#foo{}, foo)), + ?line ?TrueGuard(not erlang:is_record(#foo{}, barf)), + ?line ?TrueGuard(not erlang:is_record({foo}, foo)), + + Foo = id(#foo{}), + ?line ?FalseGuard(not erlang:is_record(Foo, foo)), + ?line ?TrueGuard(not erlang:is_record(Foo, barf)), + + ?line ?TrueGuard(not is_record(Config, foo)), + + ?line ?TrueGuard(not is_record(a, foo)), + ?line ?TrueGuard(not is_record([], foo)), + + %% Pass non-literal first argument. + + ?line true = is_record(id(#foo{}), foo), + ?line false = is_record(id(#foo{}), barf), + ?line false = is_record(id({foo}), foo), + + ?line true = erlang:is_record(id(#foo{}), foo), + ?line false = erlang:is_record(id(#foo{}), barf), + ?line false = erlang:is_record(id({foo}), foo), + + NoRec1 = id(blurf), + NoRec2 = id([]), + + ?line ?TrueGuard(not is_record(NoRec1, foo)), + ?line ?TrueGuard(not is_record(NoRec2, foo)), + + %% The optimizer attempts to move expressions to guards, + %% but it must not move an is_record/2 call that is not + %% allowed in a guard in the first place. + + ?line ok = case is_record(id({a}), id(a)) of + true -> ok; + false -> error + end, + + %% Force the use of guard bifs by using the 'xor' operation. + + False = id(false), + ?line ?TrueGuard(is_record(#foo{}, foo) xor False), + ?line ?FalseGuard(is_record(#foo{}, barf) xor False), + ?line ?FalseGuard(is_record({foo}, foo) xor False ), + + ?line ?TrueGuard(is_record(Foo, foo) xor False), + ?line ?FalseGuard(is_record(Foo, barf) xor False), + + + %% Implicit guards by using a list comprehension. + + List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]), + + ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)], + ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar)], + ?line [1,#foo{a=2},3,5,#foo{a=6},7] = + [X || X <- List, not is_record(X, bar)], + ?line [1,3,5,7] = + [X || X <- List, ((not is_record(X, bar)) and (not is_record(X, foo)))], + ?line [#foo{a=2},#bar{d=4},#foo{a=6}] = + [X || X <- List, ((is_record(X, bar)) or (is_record(X, foo)))], + ?line [1,3,#bar{d=4}] = + [X || X <- List, ((is_record(X, bar)) or (X < 5))], + + ?line MyList = [#foo{a=3},x,[],{a,b}], + ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)], + ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)], + ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end], + ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or + not is_binary(X)], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + not is_binary(X)], + ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], + ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + is_reference(X)], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin is_record(X, foo) or + not is_binary(X) end], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo) or + not is_binary(X) end], + ?line [#foo{a=3}] = [X || X <- MyList, + begin is_record(X, foo) or is_reference(X) end], + ?line [x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo) or + is_reference(X) end], + + %% Call is_record/2 with illegal arguments. + ?line [] = [X || X <- [], is_record(t, id(X))], + ?line {'EXIT',{badarg,_}} = (catch [X || X <- [1], is_record(t, id(X))]), + + %% Update several fields with a string literal. + ?line #barf{} = Barf0 = id(#barf{}), + ?line Barf = update_barf(Barf0), + ?line #barf{a="abc",b=1} = id(Barf), + + ok. + +record_test_3(Config) when is_list(Config) -> + ?line true = is_record(#foo{}, foo, 5), + ?line false = is_record(#foo{}, barf, 5), + ?line false = is_record(#foo{}, barf, 6), + ?line false = is_record({foo}, foo, 5), + + ?line true = erlang:is_record(#foo{}, foo, 5), + ?line false = erlang:is_record(#foo{}, barf, 5), + ?line false = erlang:is_record({foo}, foo, 5), + + ?line false = is_record([], foo), + ?line false = is_record(Config, foo), + + ?line ?TrueGuard(is_record(#foo{}, foo, 5)), + ?line ?FalseGuard(is_record(#foo{}, barf, 5)), + ?line ?FalseGuard(is_record(#foo{}, barf, 6)), + ?line ?FalseGuard(is_record({foo}, foo, 5)), + + ?line ?TrueGuard(erlang:is_record(#foo{}, foo, 5)), + ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 5)), + ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 6)), + ?line ?FalseGuard(erlang:is_record({foo}, foo, 5)), + + ?line ?FalseGuard(is_record([], foo, 5)), + ?line ?FalseGuard(is_record(Config, foo, 5)), + + %% 'not is_record/2' to test guard optimization. + + ?line ?FalseGuard(not is_record(#foo{}, foo, 5)), + ?line ?TrueGuard(not is_record(#foo{}, barf, 6)), + ?line ?TrueGuard(not is_record({foo}, foo, 5)), + + ?line ?FalseGuard(not erlang:is_record(#foo{}, foo, 5)), + ?line ?TrueGuard(not erlang:is_record(#foo{}, barf, 5)), + ?line ?TrueGuard(not erlang:is_record({foo}, foo, 5)), + + Foo = id(#foo{}), + ?line ?FalseGuard(not erlang:is_record(Foo, foo, 5)), + ?line ?TrueGuard(not erlang:is_record(Foo, barf, 6)), + + ?line ?TrueGuard(not is_record(Config, foo, 5)), + + ?line ?TrueGuard(not is_record(a, foo, 5)), + ?line ?TrueGuard(not is_record([], foo, 5)), + + %% Pass non-literal first argument. + + ?line true = is_record(id(#foo{}), foo, 5), + ?line false = is_record(id(#foo{}), barf, 6), + ?line false = is_record(id({foo}), foo, 5), + + ?line true = erlang:is_record(id(#foo{}), foo, 5), + ?line false = erlang:is_record(id(#foo{}), barf, 6), + ?line false = erlang:is_record(id({foo}), foo, 5), + + NoRec1 = id(blurf), + NoRec2 = id([]), + + ?line ?TrueGuard(not is_record(NoRec1, foo, 5)), + ?line ?TrueGuard(not is_record(NoRec2, foo, 5)), + + %% Force the use of guard bifs by using the 'xor' operation. + + False = id(false), + ?line ?TrueGuard(is_record(#foo{}, foo, 5) xor False), + ?line ?FalseGuard(is_record(#foo{}, barf, 6) xor False), + ?line ?FalseGuard(is_record({foo}, foo, 5) xor False ), + + ?line ?TrueGuard(is_record(Foo, foo, 5) xor False), + ?line ?FalseGuard(is_record(Foo, barf, 6) xor False), + + + %% Implicit guards by using a list comprehension. + + List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]), + + ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo, 5)], + ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar, 5)], + ?line [1,#foo{a=2},3,5,#foo{a=6},7] = + [X || X <- List, not is_record(X, bar, 5)], + ?line [1,3,5,7] = + [X || X <- List, ((not is_record(X, bar, 5)) and (not is_record(X, foo, 5)))], + ?line [#foo{a=2},#bar{d=4},#foo{a=6}] = + [X || X <- List, ((is_record(X, bar, 5)) or (is_record(X, foo, 5)))], + ?line [1,3,#bar{d=4}] = + [X || X <- List, ((is_record(X, bar, 5)) or (X < 5))], + + ?line MyList = [#foo{a=3},x,[],{a,b}], + ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo, 5)], + ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5)], + ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo, 5) end], + ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo, 5) end], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo, 5) or + not is_binary(X)], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5) or + not is_binary(X)], + ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], + ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + is_reference(X)], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin is_record(X, foo, 5) or + not is_binary(X) end], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo, 5) or + not is_binary(X) end], + ?line [#foo{a=3}] = [X || X <- MyList, + begin is_record(X, foo, 5) or is_reference(X) end], + ?line [x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo, 5) or + is_reference(X) end], + + %% Update several fields with a string literal. + ?line #barf{} = Barf0 = id(#barf{}), + ?line Barf = update_barf(Barf0), + ?line #barf{a="abc",b=1} = id(Barf), + + %% Non-literal arguments. + ?line true = is_record(id(#barf{}), id(barf), id(6)), + ?line false = is_record(id(#barf{}), id(barf), id(42)), + ?line false = is_record(id(#barf{}), id(foo), id(6)), + + ok. + +record_access_in_guards(Config) when is_list(Config) -> + ?line Priv = ?config(priv_dir, Config), + ?line file:set_cwd(test_lib:get_data_dir(Config)), + ?line Opts0 = [{outdir,Priv},report_errors|test_lib:opt_opts(?MODULE)], + M = record_access_in_guards, + + Opts = [strict_record_tests|Opts0], + ?line io:format("Options: ~p\n", [Opts]), + ?line {ok,M} = c:c(M, Opts), + ?line ok = M:t(), + ok. + + +%% Test optimization of record access and is_record/2 in guards. + +-record(r, {a = 4,b}). +-record(r1, {a,b}). +-record(r2, {a = #r1{},b,c=length([1,2,3])}). +-record(r3, {a = fun(_) -> #r1{} end(1), b}). + +guard_opt(Config) when is_list(Config) -> + ok = fun() -> + F = fun(F, [H,H|T]) when is_record(H, r) -> + [H|F(F, T)]; + (F, [H|T]) when is_record(H, r) -> + [H|F(F, T)]; + (_, []) -> [] + end, + [#r{a=4,b=7},#r{a=1,b=42}] = + F(F, [#r{a=4,b=7},#r{a=4,b=7},#r{a=1,b=42}]), + {'EXIT',_} = (catch F(F, [#r1{}])), + ok + end(), + + true = fun() -> + R = #r{}, + if is_record(R, r) -> true; true -> false end + end(), + + ok = fun() -> + F = fun(true, B) when B#r1.a -> ok; + (false, _) -> error + end, + ok = F(true, #r1{a=true}), + error = F(false, anything_goes), + {'EXIT',_} = (catch F(true, #r1{})), + {'EXIT',_} = (catch F(true, #r{})), + ok + end(), + + ok = fun() -> + F = fun([{a,R}=T]) when R#r.a =:= 42 -> + {ok,tuple_size(T)}; + ([{a,R}=T]) when R#r1.a =:= 7 -> + {ok,tuple_size(T)}; + (_) -> error + end, + {ok,2} = F([{a,#r{a=42}}]), + {ok,2} = F([{a,#r1{a=7}}]), + error = F([{a,#r1{}}]), + error = F({a,b,c}), + error = F([]), + ok + end(), + + ok = fun() -> + F = fun(X, Y, Z) when is_record(X, r1) andalso + (is_record(Y, r2) orelse + is_record(Z, r3)) -> true; + (_, _, _) -> false + end, + true = F(#r1{}, #r2{}, #r3{}), + true = F(#r1{}, #r2{}, blurf), + true = F(#r1{}, blurf, #r3{}), + false = F(#r1{}, blurf, blurf), + false = F(blurf, #r2{}, #r3{}), + false = F(blurf, #r2{}, blurf), + false = F(blurf, blurf, #r3{}), + false = F(blurf, blurf, blurf), + ok + end(), + + ok = fun() -> + F = fun(R=#r{a=42}) when R#r.b =:= 7 -> + {ok,R}; + (_) -> error + end, + {ok,#r{a=42,b=7}} = F(#r{a=42,b=7}), + error = F(#r{}), + error = F([a,b,c]), + ok + end(), + + ok. + +update_barf(R) -> + R#barf{a="abc",b=1}. + +eval_once(Config) when is_list(Config) -> + ?line once(fun(GetRec) -> + true = erlang:is_record(GetRec(), foo) + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1} + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1,b=2} + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1,b=2,c=3} + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1,b=2,c=3,d=4} + end, #foo{}), + ok. + +once(Test, Record) -> + put(?MODULE, 0), + GetRec = fun() -> + put(?MODULE, 1+get(?MODULE)), + Record + end, + Result = Test(GetRec), + case get(?MODULE) of + 1 -> ok; + N -> + io:format("Evaluated ~w times\n", [N]), + ?t:fail() + end, + Result. + +%% Thanks to Martin Bjorklund. + +-record(foobar, {status}). + +foobar(Config) when is_list(Config) -> + {ok,_,_} = x({foo, 1}), + ok. + +get_bar() -> + #foobar{status = 1}. + +x(Trans) -> + {foo, Barno} = Trans, + case get_bar() of + Bar when Bar#foobar.status == 1 -> + noop(Bar), + Bar33 = Bar#foobar{status = 1}, + {ok, Bar33, Barno}; + _ -> + Trans + end. + +noop(_) -> + ok. + +-record(foo_rec, + {foo_1, + foo_2 = 0, + foo_3 = 0}). + +missing_test_heap(Config) when is_list(Config) -> + #foo_rec{foo_2=2,foo_3=5} = missing_test_heap_1(#foo_rec{foo_2=1,foo_3=4}), + ok. + + +%% Two test_heap instructions would be incorrectly merged (not allowed +%% because of gc_bif instructions for addition). +missing_test_heap_1(A = #foo_rec {foo_1 = _B, + foo_3 = C, + foo_2 = D}) -> + A#foo_rec {foo_1 = {C, D}, + foo_3 = C + 1, + foo_2 = D + 1}. + +id(I) -> I. diff --git a/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl new file mode 100644 index 0000000000..c2b3ec2f34 --- /dev/null +++ b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl @@ -0,0 +1,177 @@ +%% +%% %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(record_access_in_guards). + +-export([t/0]). + +-record(r, {a = 4,b}). +-record(r1, {a,b}). +-record(r2, {a = #r1{},b,c=length([1,2,3])}). +-record(r3, {a = fun(_) -> #r1{} end(1), b}). + +t() -> + foo = fun(A) when A#r1.a > A#r1.b -> foo end(#r1{b = 2}), + 0 = fun(A) when A#r2.a -> 0 end(#r2{a = true}), + 1 = fun(A) when (#r1{a = A})#r1.a > 2 -> 1 end(3), + 2 = fun(N) when ((#r2{a = #r{a = 4}, b = length([a,b,c])})#r2.a)#r.a > N -> + 2 end(2), + 3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}), + ok = fun() -> + F = fun(A) when record(A#r.a, r1) -> 4; + (A) when record(A#r1.a, r1) -> 5 + end, + 5 = F(#r1{a = #r1{}}), + 4 = F(#r{a = #r1{}}), + ok + end(), + 3 = fun(A) when record(A#r1.a, r), + (A#r1.a)#r.a > 3 -> 3 + end(#r1{a = #r{a = 4}}), + 7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}), + [#r1{a = 2,b = 1}] = + fun() -> + [A || A <- [#r1{a = 1, b = 3}, + #r2{a = 2,b = 1}, + #r1{a = 2, b = 1}], + A#r1.a > + A#r1.b] + end(), + {[_],b} = + fun(L) -> + %% A is checked only once: + R1 = [{A,B} || A <- L, A#r1.a, B <- L, A#r1.b], + A = #r2{a = true}, + %% A is checked again: + B = if A#r1.a -> a; true -> b end, + {R1,B} + end([#r1{a = true, b = true}]), + + p = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o; + (_) -> p + end(#r1{a = 2}), + + o = fun(A) when (A#r1.a =:= 2) orelse (A#r2.a =:= 1) -> o; + (_) -> p + end(#r1{a = 2}), + + 3 = fun(A) when A#r1.a > 3, + record(A, r1) -> 3 + end(#r1{a = 5}), + + ok = fun() -> + F = fun(A) when (A#r2.a =:= 1) orelse (A#r2.a) -> 2; + (A) when (A#r1.a =:= 1) orelse (A#r1.a) -> 1; + (A) when (A#r2.a =:= 2) andalso (A#r2.b) -> 3 + end, + 1 = F(#r1{a = 1}), + 2 = F(#r2{a = true}), + 3 = F(#r2{a = 2, b = true}), + ok + end(), + + b = fun(A) when false or not (A#r.a =:= 1) -> a; + (_) -> b + end(#r1{a = 1}), + b = fun(A) when not (A#r.a =:= 1) or false -> a; + (_) -> b + end(#r1{a = 1}), + + ok = fun() -> + F = fun(A) when not (A#r.a =:= 1) -> yes; + (_) -> no + end, + no = F(#r1{a = 2}), + yes = F(#r{a = 2}), + no = F(#r{a = 1}), + ok + end(), + + a = fun(A) when record(A, r), + A#r.a =:= 1, + A#r.b =:= 2 ->a + end(#r{a = 1, b = 2}), + a = fun(A) when erlang:is_record(A, r), + A#r.a =:= 1, + A#r.b =:= 2 -> a + end(#r{a = 1, b = 2}), + a = fun(A) when is_record(A, r), + A#r.a =:= 1, + A#r.b =:= 2 -> a + end(#r{a = 1, b = 2}), + + nop = fun(A) when (is_record(A, r1) and (A#r1.a > 3)) or (A#r2.a < 1) -> + japp; + (_) -> + nop + end(#r2{a = 0}), + nop = fun(A) when (A#r1.a > 3) or (A#r2.a < 1) -> japp; + (_) -> + nop + end(#r2{a = 0}), + + ok = fun() -> + F = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o; + (_) -> p + end, + p = F(#r2{a = 1}), + p = F(#r1{a = 2}), + ok + end(), + + ok = fun() -> + F = fun(A) when fail, A#r1.a; A#r1.a -> ab; + (_) -> bu + end, + ab = F(#r1{a = true}), + bu = F(#r2{a = true}), + ok + end(), + + both = fun(A) when A#r.a, A#r.b -> both + end(#r{a = true, b = true}), + + ok = fun() -> + F = fun(A, B) when ((A#r1.a) orelse (B#r2.a)) + or (B#r2.b) or (A#r1.b) -> true; + (_, _) -> false + end, + true = F(#r1{a = false, b = false}, #r2{a = false, b = true}), + false = F(#r1{a = true, b = true}, #r1{a = false, b = true}), + ok + end(), + + ok = fun(R) -> + F = fun(Head, Version, Tab) -> + VersionOK = (Head#r.a =:= Version), + if + Tab =:= Head#r.b, VersionOK -> + ok; + true -> + error + end + end, + ok = F(R, 42, tab), + error = F(R, 42, a), + error = F(R, 0, tab), + {'EXIT',{{badrecord,r},_}} = (catch F({x,y,z}, 4, 5)), + ok + end(#r{a=42,b=tab}), + + ok. + diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl new file mode 100644 index 0000000000..3099538071 --- /dev/null +++ b/lib/compiler/test/test_lib.erl @@ -0,0 +1,75 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(test_lib). + +-include("test_server.hrl"). + +-export([recompile/1,opt_opts/1,get_data_dir/1,smoke_disasm/1]). + +recompile(Mod) when is_atom(Mod) -> + case whereis(cover_server) of + undefined -> ok; + _ -> + %% Re-compile the test suite if the cover server is running. + Beam = code:which(Mod), + Src = filename:rootname(Beam, ".beam") ++ ".erl", + Opts = [bin_opt_info|opt_opts(Mod)], + io:format("Recompiling ~p (~p)\n", [Mod,Opts]), + c:c(Src, [{outdir,filename:dirname(Src)}|Opts]) + end, + + %% Smoke-test of beam disassembler. + smoke_disasm(Mod). + +smoke_disasm(Mod) when is_atom(Mod) -> + smoke_disasm(code:which(Mod)); +smoke_disasm(File) when is_list(File) -> + Res = beam_disasm:file(File), + {beam_file,Mod} = {element(1, Res),element(2, Res)}. + +%% Retrieve the "interesting" compiler options (options for optimization +%% and compatibility) for the given module. + +opt_opts(Mod) -> + Comp = Mod:module_info(compile), + {value,{options,Opts}} = lists:keysearch(options, 1, Comp), + lists:filter(fun(no_copt) -> true; + (no_postopt) -> true; + (no_float_opt) -> true; + (no_new_funs) -> true; + (no_new_binaries) -> true; + (no_new_apply) -> true; + (no_gc_bifs) -> true; + (no_constant_pool) -> true; + (no_stack_trimming) -> true; + (no_binaries) -> true; + (debug_info) -> true; + (_) -> false + end, Opts). + +%% Some test suites gets cloned (e.g. to "record_SUITE" to "record_no_opt_SUITE"), +%% but the data directory is not cloned. This function retrieves the path to +%% the original data directory. + +get_data_dir(Config) -> + Data0 = ?config(data_dir, Config), + {ok,Data1,_} = regexp:sub(Data0, "_no_opt_SUITE", "_SUITE"), + {ok,Data2,_} = regexp:sub(Data1, "_post_opt_SUITE", "_SUITE"), + {ok,Data,_} = regexp:sub(Data2, "_r11_SUITE", "_SUITE"), + Data. diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl new file mode 100644 index 0000000000..c2f6dc24be --- /dev/null +++ b/lib/compiler/test/trycatch_SUITE.erl @@ -0,0 +1,911 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(trycatch_SUITE). + +-export([all/1,basic/1,lean_throw/1,try_of/1,try_after/1,%after_bind/1, + catch_oops/1,after_oops/1,eclectic/1,rethrow/1, + nested_of/1,nested_catch/1,nested_after/1, + nested_horrid/1,last_call_optimization/1,bool/1, + plain_catch_coverage/1,andalso_orelse/1]). + +-include("test_server.hrl"). + +all(suite) -> + test_lib:recompile(?MODULE), + [basic,lean_throw,try_of,try_after,%after_bind, + catch_oops,after_oops,eclectic,rethrow, + nested_of,nested_catch,nested_after, + nested_horrid,last_call_optimization, + bool,plain_catch_coverage,andalso_orelse]. + + +basic(Conf) when is_list(Conf) -> + ?line 2 = + try my_div(4, 2) + catch + Class:Reason -> {Class,Reason} + end, + ?line error = + try my_div(1, 0) + catch + error:badarith -> error + end, + ?line error = + try 1.0 / zero() + catch + error:badarith -> error + end, + ?line ok = + try my_add(53, atom) + catch + error:badarith -> ok + end, + ?line exit_nisse = + try exit(nisse) + catch + exit:nisse -> exit_nisse + end, + ?line ok = + try throw(kalle) + catch + kalle -> ok + end, + + %% Try some stuff where the compiler will optimize away the try. + + V = id({a,variable}), + ?line V = try V catch nisse -> error end, + ?line 42 = try 42 catch nisse -> error end, + ?line [V] = try [V] catch nisse -> error end, + ?line {ok,V} = try {ok,V} catch nisse -> error end, + + %% Same idea, but use an after too. + + ?line V = try V catch nisse -> error after after_call() end, + ?line after_clean(), + ?line 42 = try 42 after after_call() end, + ?line after_clean(), + ?line [V] = try [V] catch nisse -> error after after_call() end, + ?line after_clean(), + ?line {ok,V} = try {ok,V} after after_call() end, + + %% Try/of + ?line ok = try V of + {a,variable} -> ok + catch nisse -> erro + end, + + ok. + +after_call() -> + put(basic, after_was_called). + +after_clean() -> + after_was_called = erase(basic). + + +lean_throw(Conf) when is_list(Conf) -> + ?line {throw,kalle} = + try throw(kalle) + catch + Kalle -> {throw,Kalle} + end, + ?line {exit,kalle} = + try exit(kalle) + catch + Throw1 -> {throw,Throw1}; + exit:Reason1 -> {exit,Reason1} + end, + ?line {exit,kalle} = + try exit(kalle) + catch + exit:Reason2 -> {exit,Reason2}; + Throw2 -> {throw,Throw2} + end, + ?line {exit,kalle} = + try try exit(kalle) + catch + Throw3 -> {throw,Throw3} + end + catch + exit:Reason3 -> {exit,Reason3} + end, + ok. + + + +try_of(Conf) when is_list(Conf) -> + ?line {ok,{some,content}} = + try_of_1({value,{good,{some,content}}}), + ?line {error,[other,content]} = + try_of_1({value,{bad,[other,content]}}), + ?line {caught,{exit,{ex,it,[reason]}}} = + try_of_1({exit,{ex,it,[reason]}}), + ?line {caught,{throw,[term,{in,a,{tuple}}]}} = + try_of_1({throw,[term,{in,a,{tuple}}]}), + ?line {caught,{error,[bad,arg]}} = + try_of_1({error,[bad,arg]}), + ?line {caught,{error,badarith}} = + try_of_1({'div',{1,0}}), + ?line {caught,{error,badarith}} = + try_of_1({'add',{a,0}}), + ?line {caught,{error,badarg}} = + try_of_1({'abs',x}), + ?line {caught,{error,function_clause}} = + try_of_1(illegal), + ?line {error,{try_clause,{some,other_garbage}}} = + try try_of_1({value,{some,other_garbage}}) + catch error:Reason -> {error,Reason} + end, + ok. + +try_of_1(X) -> + try foo(X) of + {good,Y} -> {ok,Y}; + {bad,Y} -> {error,Y} + catch + Class:Reason -> + {caught,{Class,Reason}} + end. + + + +try_after(Conf) when is_list(Conf) -> + ?line {{ok,[some,value],undefined},finalized} = + try_after_1({value,{ok,[some,value]}},finalized), + ?line {{error,badarith,undefined},finalized} = + try_after_1({'div',{1,0}},finalized), + ?line {{error,badarith,undefined},finalized} = + try_after_1({'add',{1,a}},finalized), + ?line {{error,badarg,undefined},finalized} = + try_after_1({'abs',a},finalized), + ?line {{error,[the,{reason}],undefined},finalized} = + try_after_1({error,[the,{reason}]},finalized), + ?line {{throw,{thrown,[reason]},undefined},finalized} = + try_after_1({throw,{thrown,[reason]}},finalized), + ?line {{exit,{exited,{reason}},undefined},finalized} = + try_after_1({exit,{exited,{reason}}},finalized), + ?line {{error,function_clause,undefined},finalized} = + try_after_1(function_clause,finalized), + ?line ok = + try try_after_1({'add',{1,1}}, finalized) + catch + error:{try_clause,2} -> ok + end, + ?line finalized = erase(try_after), + ?line ok = + try try foo({exit,[reaso,{n}]}) + after put(try_after, finalized) + end + catch + exit:[reaso,{n}] -> ok + end, + ok. + +try_after_1(X, Y) -> + erase(try_after), + Try = + try foo(X) of + {ok,Value} -> {ok,Value,get(try_after)} + catch + Reason -> {throw,Reason,get(try_after)}; + error:Reason -> {error,Reason,get(try_after)}; + exit:Reason -> {exit,Reason,get(try_after)} + after + put(try_after, Y) + end, + {Try,erase(try_after)}. + + + +-ifdef(begone). + +after_bind(Conf) when is_list(Conf) -> + V = [make_ref(),self()|value], + ?line {value,{value,V}} = + after_bind_1({value,V}, V, {value,V}), + ok. + +after_bind_1(X, V, Y) -> + try + Try = + try foo(X) of + V -> value + catch + C1:V -> {caught,C1} + after + After = foo(Y) + end, + {Try,After} + of + V -> {value,V} + catch + C:D -> {caught,{C,D}} + end. + +-endif. + + + +catch_oops(Conf) when is_list(Conf) -> + V = {v,[a,l|u],{e},self()}, + ?line {value,V} = catch_oops_1({value,V}), + ?line {value,1} = catch_oops_1({'div',{1,1}}), + ?line {error,badarith} = catch_oops_1({'div',{1,0}}), + ?line {error,function_clause} = catch_oops_1(function_clause), + ?line {throw,V} = catch_oops_1({throw,V}), + ?line {exit,V} = catch_oops_1({exit,V}), + ok. + +catch_oops_1(X) -> + Ref = make_ref(), + try try foo({error,Ref}) + catch + error:Ref -> + foo(X) + end of + Value -> {value,Value} + catch + Class:Data -> {Class,Data} + end. + + + +after_oops(Conf) when is_list(Conf) -> + V = {self(),make_ref()}, + ?line {{value,V},V} = after_oops_1({value,V}, {value,V}), + ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}), + ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}), + ?line {{error,function_clause},undefined} = + after_oops_1({exit,V}, function_clause), + ok. + +after_oops_1(X, Y) -> + erase(after_oops), + Try = + try try foo(X) + after + put(after_oops, foo(Y)) + end of + V -> {value,V} + catch + C:D -> {C,D} + end, + {Try,erase(after_oops)}. + + + +eclectic(Conf) when is_list(Conf) -> + V = {make_ref(),3.1415926535,[[]|{}]}, + ?line {{value,{value,V},V},V} = + eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}), + ?line {{'EXIT',{V,[{?MODULE,foo,1}|_]}},V} = + eclectic_1({catch_foo,{error,V}}, undefined, {value,V}), + ?line {{error,{exit,V},{'EXIT',V}},V} = + eclectic_1({foo,{error,{exit,V}}}, error, {value,V}), + ?line {{value,{value,V},V}, + {'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}} = + eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}), + ?line {{'EXIT',V},V} = + eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}), + ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2}|_]}}}, + {'EXIT',V}} = + eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}), + ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1}|_]}}}, + {'EXIT',V}} = + eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}), + %% + ?line {{value,{value,{value,V},V}},V} = + eclectic_2({value,{value,V}}, undefined, {value,V}), + ?line {{value,{throw,{value,V},V}},V} = + eclectic_2({throw,{value,V}}, throw, {value,V}), + ?line {{caught,{'EXIT',V}},undefined} = + eclectic_2({value,{value,V}}, undefined, {exit,V}), + ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} = + eclectic_2({error,{value,V}}, throw, {error,V}), + ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} = + eclectic_2({value,{'abs',V}}, undefined, {value,V}), + ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}},V} = + eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}), + ?line {{caught,{'EXIT',V}},undefined} = + eclectic_2({value,{error,V}}, undefined, {exit,V}), + ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} = + eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}), + ok. + +eclectic_1(X, C, Y) -> + erase(eclectic), + Done = make_ref(), + Try = + try case X of + {catch_foo,V} -> catch {Done,foo(V)}; + {foo,V} -> {Done,foo(V)} + end of + {Done,D} -> {value,D,catch foo(D)}; + {'EXIT',_}=Exit -> Exit; + D -> {D,catch foo(D)} + catch + C:D -> {C,D,catch foo(D)} + after + put(eclectic, catch foo(Y)) + end, + {Try,erase(eclectic)}. + +eclectic_2(X, C, Y) -> + Done = make_ref(), + erase(eclectic), + Catch = + case + catch + {Done, + try foo(X) of + V -> {value,V,foo(V)} + catch + C:D -> {C,D,foo(D)} + after + put(eclectic, foo(Y)) + end} of + {Done,Z} -> {value,Z}; + Z -> {caught,Z} + end, + {Catch,erase(eclectic)}. + + + +rethrow(Conf) when is_list(Conf) -> + V = {a,[b,{c,self()},make_ref]}, + ?line {value2,value1} = + rethrow_1({value,V}, V), + ?line {caught2,{error,V}} = + rethrow_2({error,V}, undefined), + ?line {caught2,{exit,V}} = + rethrow_1({exit,V}, error), + ?line {caught2,{throw,V}} = + rethrow_1({throw,V}, undefined), + ?line {caught2,{throw,V}} = + rethrow_2({throw,V}, undefined), + ?line {caught2,{error,badarith}} = + rethrow_1({'add',{0,a}}, throw), + ?line {caught2,{error,function_clause}} = + rethrow_2(function_clause, undefined), + ?line {caught2,{error,{try_clause,V}}} = + rethrow_1({value,V}, exit), + ?line {value2,{caught1,V}} = + rethrow_1({error,V}, error), + ?line {value2,{caught1,V}} = + rethrow_1({exit,V}, exit), + ?line {value2,caught1} = + rethrow_2({throw,V}, V), + ok. + +rethrow_1(X, C1) -> + try try foo(X) of + C1 -> value1 + catch + C1:D1 -> {caught1,D1} + end of + V2 -> {value2,V2} + catch + C2:D2 -> {caught2,{C2,D2}} + end. + +rethrow_2(X, C1) -> + try try foo(X) of + C1 -> value1 + catch + C1 -> caught1 % Implicit class throw: + end of + V2 -> {value2,V2} + catch + C2:D2 -> {caught2,{C2,D2}} + end. + + + +nested_of(Conf) when is_list(Conf) -> + V = {[self()|make_ref()],1.4142136}, + ?line {{value,{value1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), + %% + ?line {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,try_clause}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{exit,{V,x3}}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x4}}}, + undefined, + undefined, + finalized} = + nested_of_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {throw,{V,x4}}), + %% + ?line {{value,{caught1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), + %% + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{'add',{2,c}},rethrow,void}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, {value,{V,x4}}), + ?line {{caught,{error,function_clause}}, + undefined, + undefined, + finalized} = + nested_of_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, function_clause), + ok. + +nested_of_1({X1,C1,V1}, + X2, X3, X4) -> + erase(nested3), + erase(nested4), + erase(nested), + Self = self(), + Try = + try + try self() + of + Self -> + try + foo(X1) + of + V1 -> {value1,foo(X2)} + catch + C1:V1 -> {caught1,foo(X2)} + after + put(nested3, foo(X3)) + end + after + put(nested4, foo(X4)) + end + of + V -> {value,V} + catch + C:D -> {caught,{C,D}} + after + put(nested, finalized) + end, + {Try,erase(nested3),erase(nested4),erase(nested)}. + + + +nested_catch(Conf) when is_list(Conf) -> + V = {[make_ref(),1.4142136,self()]}, + ?line {{value,{value1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), + %% + ?line {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,try_clause}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{exit,{V,x3}}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x4}}}, + undefined, + undefined, + finalized} = + nested_catch_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {throw,{V,x4}}), + %% + ?line {{value,{caught1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), + %% + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{'add',{2,c}},rethrow,void}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, {value,{V,x4}}), + ?line {{caught,{error,function_clause}}, + undefined, + undefined, + finalized} = + nested_catch_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, function_clause), + ok. + +nested_catch_1({X1,C1,V1}, + X2, X3, X4) -> + erase(nested3), + erase(nested4), + erase(nested), + Throw = make_ref(), + Try = + try + try throw(Throw) + catch + Throw -> + try + foo(X1) + of + V1 -> {value1,foo(X2)} + catch + C1:V1 -> {caught1,foo(X2)} + after + put(nested3, foo(X3)) + end + after + put(nested4, foo(X4)) + end + of + V -> {value,V} + catch + C:D -> {caught,{C,D}} + after + put(nested, finalized) + end, + {Try,erase(nested3),erase(nested4),erase(nested)}. + + + +nested_after(Conf) when is_list(Conf) -> + V = [{make_ref(),1.4142136,self()}], + ?line {value, + {V,x3}, + {value1,{V,x2}}, + finalized} = + nested_after_1({{value,{V,x1}},void,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}), + ?line {{caught,{error,{V,x2}}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,{V,x1}}, + {error,{V,x2}}, {value,{V,x3}}), + ?line {{caught,{exit,{V,x3}}}, + undefined, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,{V,x1}}, + {error,{V,x2}}, {exit,{V,x3}}), + %% + ?line {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,try_clause}, + void, {value,{V,x3}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,try_clause}, + void, {'div',{17,0}}), + %% + ?line {value, + {V,x3}, + {caught1,{V,x2}}, + finalized} = + nested_after_1({{throw,{V,x1}},throw,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}), + ?line {{caught,{error,badarith}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},throw,{V,x1}}, + {'add',{a,b}}, {value,{V,x3}}), + ?line {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},throw,{V,x1}}, + {'add',{a,b}}, {'abs',V}), + %% + ?line {{caught,{throw,{V,x1}}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},rethrow,void}, + void, {value,{V,x3}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},rethrow,void}, + void, {'div',{1,0}}), + ok. + +nested_after_1({X1,C1,V1}, + X2, X3) -> + erase(nested3), + erase(nested4), + erase(nested), + Self = self(), + Try = + try + try self() + after + After = + try + foo(X1) + of + V1 -> {value1,foo(X2)} + catch + C1:V1 -> {caught1,foo(X2)} + after + put(nested3, foo(X3)) + end, + put(nested4, After) + end + of + Self -> value + catch + C:D -> {caught,{C,D}} + after + put(nested, finalized) + end, + {Try,erase(nested3),erase(nested4),erase(nested)}. + + + +nested_horrid(Config) when is_list(Config) -> + _V = {make_ref(),nested_horrid,4.711}, + {[true,true],{[true,1.0],1.0}} = + nested_horrid_1({true,void,void}, 1.0), + ok. + +nested_horrid_1({X1,C1,V1}, X2) -> + try A1 = [X1,X1], + B1 = if X1 -> + A2 = [X1,X2], + B2 = foo(X2), + {A2,B2}; + true -> + A3 = [X2,X1], + B3 = foo(X2), + {A3,B3} + end, + {A1,B1} + catch + C1:V1 -> caught1 + end. + + + +foo({value,Value}) -> Value; +foo({'div',{A,B}}) -> + my_div(A, B); +foo({'add',{A,B}}) -> + my_add(A, B); +foo({'abs',X}) -> + my_abs(X); +foo({error,Error}) -> + erlang:error(Error); +foo({throw,Throw}) -> + erlang:throw(Throw); +foo({exit,Exit}) -> + erlang:exit(Exit); +foo({raise,{Class,Reason}}) -> + erlang:raise(Class, Reason); +foo(Term) when not is_atom(Term) -> Term. +%%foo(Atom) when is_atom(Atom) -> % must not be defined! + +my_div(A, B) -> + A div B. + +my_add(A, B) -> + A + B. + +my_abs(X) -> abs(X). + + +last_call_optimization(Config) when is_list(Config) -> + ?line error = in_tail(dum), + ?line StkSize0 = in_tail(0), + ?line StkSize = in_tail(50000), + io:format("StkSize0 = ~p", [StkSize0]), + io:format("StkSize = ~p", [StkSize]), + ?line StkSize = StkSize0, + ok. + +in_tail(E) -> + try erlang:abs(E) of + T -> + A = id([]), + B = id([]), + C = id([]), + id([A,B,C]), + do_tail(T) + catch error:badarg -> error + end. + +do_tail(0) -> + process_info(self(), stack_size); +do_tail(N) -> + in_tail(N-1). + +bool(Config) when is_list(Config) -> + ok = do_bool(false, false), + error = do_bool(false, true), + error = do_bool(true, false), + error = do_bool(true, true), + error = do_bool(true, blurf), + {'EXIT',_} = (catch do_bool(blurf, false)), + ok. + +%% The following function used to cause a crash in beam_bool. +do_bool(A0, B) -> + A = not A0, + try + id(42), + if + A, not B -> ok + end + catch + _:_ -> + error + end. + +plain_catch_coverage(Config) when is_list(Config) -> + %% Cover some code in beam_block:alloc_may_pass/1. + ?line {a,[42]} = do_plain_catch_list(42). + +do_plain_catch_list(X) -> + B = [X], + catch id({a,B}). + +andalso_orelse(Config) when is_list(Config) -> + ?line {2,{a,42}} = andalso_orelse_1(true, {a,42}), + ?line {b,{b}} = andalso_orelse_1(false, {b}), + ?line {catched,no_tuple} = andalso_orelse_1(false, no_tuple), + + ?line ok = andalso_orelse_2({type,[a]}), + ?line also_ok = andalso_orelse_2({type,[]}), + ?line also_ok = andalso_orelse_2({type,{a}}), + ok. + +andalso_orelse_1(A, B) -> + {try + if + A andalso element(1, B) =:= a -> + tuple_size(B); + true -> + element(1, B) + end + catch error:_ -> + catched + end,B}. + +id(I) -> I. + +andalso_orelse_2({Type,Keyval}) -> + try + if is_atom(Type) andalso length(Keyval) > 0 -> ok; + true -> also_ok + end + catch + _:_ -> fail + end. + +zero() -> + 0.0. diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl new file mode 100644 index 0000000000..6e60ab88cb --- /dev/null +++ b/lib/compiler/test/warnings_SUITE.erl @@ -0,0 +1,554 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(warnings_SUITE). + +%%-define(STANDALONE, true). + +-ifdef(STANDALONE). +-define(line, put(line, ?LINE), ). +-define(config(X,Y), foo). +-define(privdir, "warnings_SUITE_priv"). +-define(t, test_server). +-else. +-include("test_server.hrl"). +-define(datadir, ?config(data_dir, Conf)). +-define(privdir, ?config(priv_dir, Conf)). +-endif. + +-export([all/1,init_per_testcase/2,fin_per_testcase/2]). + +-export([pattern/1,pattern2/1,pattern3/1,pattern4/1, + guard/1,bad_arith/1,bool_cases/1,bad_apply/1, + files/1,effect/1,bin_opt_info/1,bin_construction/1]). + +% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(2)). + +init_per_testcase(_Case, Config) -> + ?line Dog = ?t:timetrap(?default_timeout), + [{watchdog, Dog} | Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> + test_lib:recompile(?MODULE), + [pattern,pattern2,pattern3,pattern4, + guard,bad_arith,bool_cases,bad_apply,files,effect, + bin_opt_info,bin_construction]. + +pattern(Config) when is_list(Config) -> + %% Test warnings generated by v3_core. + Ts = [{pattern, + <<"%% Just a comment here. + f(a={glurf,2}=A) -> A. + + g(A) -> + case A of + a=[_|_] -> error; + Other -> true + end. + + foo(X) -> + a = {nisse,b} = X. + ">>, + [warn_unused_vars], + {warnings, + [{2,v3_core,nomatch}, + {6,v3_core,nomatch}, + {11,v3_core,nomatch} ] }}], + ?line [] = run(Config, Ts), + ok. + +pattern2(Config) when is_list(Config) -> + %% Test warnings generated by sys_core_fold. + %% If we disable Core Erlang optimizations, we expect that + %% v3_kernel should generate some of the warnings. + Source = <<"f(A) -> ok; + f(B) -> error. + t(A, B, C) -> + case {A,B,C} of + {a,B} -> ok; + {_,B} -> ok + end. + ">>, + + %% Test warnings from sys_core_fold. + Ts = [{pattern2, + Source, + [nowarn_unused_vars], + {warnings,[{2,sys_core_fold,{nomatch_shadow,1}}, + {5,sys_core_fold,nomatch_clause_type}, + {6,sys_core_fold,nomatch_clause_type}]}}], + ?line [] = run(Config, Ts), + + %% Disable Core Erlang optimizations. v3_kernel should produce + %% a warning for the clause that didn't match. + Ts2 = [{pattern2, + Source, + [nowarn_unused_vars,no_copt], + {warnings, + [{2,v3_kernel,{nomatch_shadow,1}}]}}], + ?line [] = run(Config, Ts2), + ok. + +pattern3(Config) when is_list(Config) -> + %% Test warnings generated by the pattern matching compiler + %% in v3_kernel. + + Ts = [{pattern3, + <<" + f({A,_}) -> {ok,A}; + f([_|_]=B) -> {ok,B}; + f({urk,nisse}) -> urka_glurka. + ">>, + [nowarn_unused_vars], + {warnings, + [{4,v3_kernel,{nomatch_shadow,2}}]}}], + ?line [] = run(Config, Ts), + + ok. + +pattern4(Config) when is_list(Config) -> + %% Test warnings for clauses that cannot possibly match. + + Ts = [{pattern4, + <<" + t() -> + case true of + false -> a; + true -> b + end. + + fi() -> + case true of + false -> a; + false -> b + end, + case true of + true -> a; + true -> b; + X -> X + end, + case boolean of + true -> a; + false -> b + end. + int() -> + case 42 of + [a|b] -> no; + <<1>> -> no; + <<X>> -> no; + 17 -> no; + [] -> no; + a -> no; + {a,b,c} -> no + end. + tuple() -> + case {x,y,z} of + \"xyz\" -> no; + [a|b] -> no; + <<1>> -> no; + <<X>> -> no; + 17 -> no; + [] -> no; + a -> no; + {a,b,c} -> no; + {x,y} -> no + end. + ">>, + [nowarn_unused_vars], + {warnings, + [{9,sys_core_fold,no_clause_match}, + {18,sys_core_fold,no_clause_match}, + {23,sys_core_fold,no_clause_match}, + {33,sys_core_fold,no_clause_match} + ]}}], + ?line [] = run(Config, Ts), + + ok. + +guard(Config) when is_list(Config) -> + %% Test warnings for false guards. + + Ts = [{guard, + <<" + t(A, B) when element(x, dum) -> ok. + + tt(A, B) when 1 == 2 -> ok. + + ttt() when element(x, dum) -> ok. + + t4(T, F) when element({F}, T) -> ok. + t5(T, F) when element([F], T) -> ok. + t6(Pos, F) when element(Pos, [F]) -> ok. + t7(Pos) when element(Pos, []) -> ok. + ">>, + [nowarn_unused_vars], + {warnings, + [{2,sys_core_fold,no_clause_match}, + {2,sys_core_fold,nomatch_guard}, + {2,sys_core_fold,{eval_failure,badarg}}, + {4,sys_core_fold,no_clause_match}, + {4,sys_core_fold,nomatch_guard}, + {6,sys_core_fold,no_clause_match}, + {6,sys_core_fold,nomatch_guard}, + {6,sys_core_fold,{eval_failure,badarg}}, + {8,sys_core_fold,no_clause_match}, + {8,sys_core_fold,nomatch_guard}, + {8,sys_core_fold,{eval_failure,badarg}}, + {9,sys_core_fold,no_clause_match}, + {9,sys_core_fold,nomatch_guard}, + {9,sys_core_fold,{eval_failure,badarg}}, + {10,sys_core_fold,no_clause_match}, + {10,sys_core_fold,nomatch_guard}, + {10,sys_core_fold,{eval_failure,badarg}}, + {11,sys_core_fold,no_clause_match}, + {11,sys_core_fold,nomatch_guard}, + {11,sys_core_fold,{eval_failure,badarg}} + ]}}], + ?line [] = run(Config, Ts), + + ok. + +bad_arith(Config) when is_list(Config) -> + Ts = [{bad_arith, + <<"f() -> + if + a + 3 > 3 -> ok; + true -> error + end. + + g(A) -> + if + is_integer(A), a + 3 > 3 -> ok; + a + 3 > 42, is_integer(A) -> ok; + true -> error + end. + + h(A) -> + a + 3 + A. + ">>, + [], + {warnings, + [{3,sys_core_fold,nomatch_guard}, + {3,sys_core_fold,{eval_failure,badarith}}, + {9,sys_core_fold,nomatch_guard}, + {9,sys_core_fold,{eval_failure,badarith}}, + {10,sys_core_fold,nomatch_guard}, + {10,sys_core_fold,{eval_failure,badarith}}, + {15,sys_core_fold,{eval_failure,badarith}} + ] }}], + ?line [] = run(Config, Ts), + ok. + +bool_cases(Config) when is_list(Config) -> + Ts = [{bool_cases, + <<" + f(A, B) -> + case A > B of + true -> true; + false -> false; + Other -> {error,not_bool} + end. + + g(A, B) -> + case A =/= B of + false -> false; + true -> true; + Other -> {error,not_bool} + end. + + h(Bool) -> + case not Bool of + maybe -> strange; + false -> ok; + true -> error + end. + ">>, + [nowarn_unused_vars], + {warnings, + [{6,sys_core_fold,nomatch_shadow}, + {13,sys_core_fold,nomatch_shadow}, + {18,sys_core_fold,nomatch_clause_type} ]} }], + ?line [] = run(Config, Ts), + ok. + +bad_apply(Config) when is_list(Config) -> + Ts = [{bad_apply, + <<" + t(1) -> 42:42(); + t(2) -> erlang:42(); + t(3) -> 42:start(); + t(4) -> []:start(); + t(5) -> erlang:[](). + ">>, + [], + {warnings, + [{2,v3_kernel,bad_call}, + {3,v3_kernel,bad_call}, + {4,v3_kernel,bad_call}, + {5,v3_kernel,bad_call}, + {6,v3_kernel,bad_call}]}}], + ?line [] = run(Config, Ts), + + %% Also verify that the generated code generates the correct error. + ?line try erlang:42() of + _ -> ?line ?t:fail() + catch + error:badarg -> ok + end, + ok. + +files(Config) when is_list(Config) -> + Ts = [{files_1, + <<" + -file(\"file1\", 14). + + t1() -> + 1/0. + + -file(\"file2\", 7). + + t2() -> + 1/0. + ">>, + [], + {warnings, + [{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]}, + {"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}], + + ?line [] = run(Config, Ts), + ok. + +%% Test warnings for term construction and BIF calls in effect context. +effect(Config) when is_list(Config) -> + Ts = [{lc, + <<" + t(X) -> + case X of + warn_lc -> + [is_integer(Z) || Z <- [1,2,3]]; + warn_lc_2 -> + [{error,Z} || Z <- [1,2,3]]; + warn_lc_3 -> + [{error,abs(Z)} || Z <- [1,2,3]]; + no_warn_lc -> + [put(last_integer, Z) || Z <- [1,2,3]]; %no warning + unused_tuple_literal -> + {a,b,c}; + unused_list_literal -> + [1,2,3,4]; + unused_integer -> + 42; + unused_arith -> + X*X; + nested -> + [{ok,node(),?MODULE:foo(),self(),[time(),date()],time()}, + is_integer(X)]; + unused_bit_syntax -> + <<X:8>>; + unused_fun -> + fun() -> {ok,X} end; + unused_atom -> + ignore; %no warning + unused_nil -> + []; %no warning + comp_op -> + X =:= 2; + cookie -> + erlang:get_cookie() + end, + ok. + + %% No warnings should be generated in the following functions. + m1(X, Sz) -> + if + Sz =:= 0 -> X = 0; + true -> ok + end, + ok. + + m2(X, Sz) -> + if + Sz =:= 0 -> X = {a,Sz}; + true -> ok + end, + ok. + + m3(X, Sz) -> + if + Sz =:= 0 -> X = [a,Sz]; + true -> ok + end, + ok. + + m4(X, Sz, Var) -> + if + Sz =:= 0 -> X = Var; + true -> ok + end, + ok. + + m5(X, Sz) -> + if + Sz =:= 0 -> X = {a,b,c}; + true -> ok + end, + ok. + + m6(X, Sz) -> + if + Sz =:= 0 -> X = {a,Sz,[1,2,3]}; + true -> ok + end, + ok. + + m7(X, Sz) -> + if + Sz =:= 0 -> X = {a,Sz,[1,2,3],abs(Sz)}; + true -> ok + end, + ok. + ">>, + [], + {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}}, + {7,sys_core_fold,useless_building}, + {9,sys_core_fold,result_ignored}, + {9,sys_core_fold,useless_building}, + {13,sys_core_fold,useless_building}, + {15,sys_core_fold,useless_building}, + {17,sys_core_fold,useless_building}, + {19,sys_core_fold,result_ignored}, + {21,sys_core_fold,useless_building}, + {21,sys_core_fold,{no_effect,{erlang,date,0}}}, + {21,sys_core_fold,{no_effect,{erlang,node,0}}}, + {21,sys_core_fold,{no_effect,{erlang,self,0}}}, + {21,sys_core_fold,{no_effect,{erlang,time,0}}}, + {22,sys_core_fold,useless_building}, + {22,sys_core_fold,{no_effect,{erlang,is_integer,1}}}, + {24,sys_core_fold,useless_building}, + {26,sys_core_fold,useless_building}, + {32,sys_core_fold,{no_effect,{erlang,'=:=',2}}}, + {34,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}], + ?line [] = run(Config, Ts), + ok. + +bin_opt_info(Config) when is_list(Config) -> + Code = <<" + t1(Bin) -> + case Bin of + _ when byte_size(Bin) > 20 -> erlang:error(too_long); + <<_,T/binary>> -> t1(T); + <<>> -> ok + end. + + t2(<<_,T/bytes>>) -> + split_binary(T, 4). + ">>, + Ts1 = [{bsm1, + Code, + [bin_opt_info], + {warnings, + [{4,sys_core_fold,orig_bin_var_used_in_guard}, + {5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}}, + {9,beam_bsm,{no_bin_opt, + {binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}], + ?line [] = run(Config, Ts1), + + %% For coverage: don't give the bin_opt_info option. + Ts2 = [{bsm2, + Code, + [], + []}], + ?line [] = run(Config, Ts2), + ok. + +bin_construction(Config) when is_list(Config) -> + Ts = [{bin_construction, + <<" + t() -> + Bin = <<1,2,3>>, + <<Bin:4/binary>>. + + x() -> + Bin = <<1,2,3,7:4>>, + <<Bin/binary>>. + ">>, + [], + {warnings,[{4,sys_core_fold,embedded_binary_size}, + {8,sys_core_fold,{embedded_unit,8,28}}]}}], + ?line [] = run(Config, Ts), + + ok. + +%%% +%%% End of test cases. +%%% + +run(Config, Tests) -> + F = fun({N,P,Ws,E}, BadL) -> + case catch run_test(Config, P, Ws) of + E -> + BadL; + Bad -> + ?t:format("~nTest ~p failed. Expected~n ~p~n" + "but got~n ~p~n", [N, E, Bad]), + fail() + end + end, + lists:foldl(F, [], Tests). + + +%% Compiles a test module and returns the list of errors and warnings. + +run_test(Conf, Test0, Warnings) -> + Filename = 'warnings_test.erl', + ?line DataDir = ?privdir, + ?line Test = ["-module(warnings_test). ", Test0], + ?line File = filename:join(DataDir, Filename), + ?line Opts = [binary,export_all,return|Warnings], + ?line ok = file:write_file(File, Test), + + %% Compile once just to print all warnings. + ?line compile:file(File, [binary,export_all,report|Warnings]), + + %% Test result of compilation. + ?line Res = case compile:file(File, Opts) of + {ok, _M, Bin, []} when is_binary(Bin) -> + []; + {ok, _M, Bin, Ws0} when is_binary(Bin) -> + %% We are not interested in warnings from + %% erl_lint here. + WsL = [{F,[W || {_,Mod,_}=W <- Ws, + Mod =/= erl_lint]} || + {F,Ws} <- Ws0], + case WsL of + [{_File,Ws}] -> {warnings, Ws}; + _ -> list_to_tuple([warnings, WsL]) + end + end, + file:delete(File), + Res. + +fail() -> + io:format("failed~n"), + ?t:fail(). |