1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(apply_SUITE). 21 22-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 23 init_per_group/2,end_per_group/2,mfa/1,fun_apply/1]). 24 25-export([foo/0,bar/1,baz/2]). 26 27-include_lib("common_test/include/ct.hrl"). 28 29suite() -> [{ct_hooks,[ts_install_cth]}]. 30 31all() -> 32 [mfa, fun_apply]. 33 34groups() -> 35 []. 36 37init_per_suite(Config) -> 38 test_lib:recompile(?MODULE), 39 Config. 40 41end_per_suite(_Config) -> 42 ok. 43 44init_per_group(_GroupName, Config) -> 45 Config. 46 47end_per_group(_GroupName, Config) -> 48 Config. 49 50 51-define(APPLY0(M, F), (fun(Res) -> Res = M:F() end)(apply(M, F, []))). 52-define(APPLY1(M, F, A1), (fun(Res) -> Res = M:F(A1) end)(apply(M, F, [A1]))). 53-define(APPLY2(M, F, A1, A2), (fun(Res) -> Res = M:F(A1, A2) end)(apply(M, F, [A1,A2]))). 54 55mfa(Config) when is_list(Config) -> 56 ok = ?APPLY0(?MODULE, foo), 57 {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]), 58 {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}), 59 60 Mod = id(?MODULE), 61 ok = ?APPLY0(Mod, foo), 62 {[a,b]} = ?APPLY1(Mod, bar, [a,b]), 63 {39,{a}} = ?APPLY2(Mod, baz, 39, {a}), 64 65 ok = ?APPLY0(?MODULE, (id(foo))), 66 {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]), 67 {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}), 68 69 ok = ?APPLY0(Mod, (id(foo))), 70 {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]), 71 {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}), 72 73 {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)), 74 {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)), 75 {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)), 76 {'EXIT',_} = (catch bad_literal_call(1)), 77 78 ok = apply(Mod, foo, id([])), 79 {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])), 80 {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])), 81 82 Erlang = id(erlang), 83 Self = self(), 84 Self = ?APPLY0(Erlang, self), 85 42.0 = ?APPLY1(Erlang, abs, -42.0), 86 b = ?APPLY2(Erlang, element, 2, {a,b,c}), 87 true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1), 88 true = ?APPLY1(Erlang, is_function, fun() -> ok end), 89 false = ?APPLY1(Erlang, is_function, blurf), 90 true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1), 91 true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0), 92 false = ?APPLY2(Erlang, is_function, blurf, 0), 93 94 apply(Mod, foo, []). 95 96%% The single call to this function with a literal argument caused type 97%% optimization to swap out the 'mod' field of a #b_remote{}, which was 98%% mishandled during code generation as it assumed that the module would always 99%% be an atom. 100bad_literal_call(I) -> 101 I:foo(). 102 103foo() -> 104 ok. 105 106bar(A) -> 107 {A}. 108 109baz(A, B) -> 110 {A,B}. 111 112-define(FUNAPPLY0(F), (fun(Res) -> Res = F() end)(apply(F, []))). 113-define(FUNAPPLY1(F, A1), (fun(Res) -> Res = F(A1) end)(apply(F, [A1]))). 114-define(FUNAPPLY2(F, A1, A2), (fun(Res) -> Res = F(A1, A2) end)(apply(F, [A1,A2]))). 115 116fun_apply(Config) when is_list(Config) -> 117 Self = self(), 118 119 Self = ?FUNAPPLY0(fun() -> self() end), 120 Self = ?FUNAPPLY0((id(fun() -> self() end))), 121 ok = ?FUNAPPLY0(fun ?MODULE:foo/0), 122 ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))), 123 124 -42 = ?FUNAPPLY1(fun(A) -> -A end, 42), 125 [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]), 126 {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]), 127 {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]), 128 129 {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b), 130 {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]), 131 {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}), 132 133 ok. 134 135id(I) -> I. 136