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, 24 mfa/1,fun_apply/1,involved/1]). 25 26-export([foo/0,bar/1,baz/2]). 27 28-include_lib("common_test/include/ct.hrl"). 29 30suite() -> [{ct_hooks,[ts_install_cth]}]. 31 32all() -> 33 [{group,p}]. 34 35groups() -> 36 [{p,test_lib:parallel(), 37 [mfa, 38 fun_apply, 39 involved 40 ]}]. 41 42init_per_suite(Config) -> 43 test_lib:recompile(?MODULE), 44 Config. 45 46end_per_suite(_Config) -> 47 ok. 48 49init_per_group(_GroupName, Config) -> 50 Config. 51 52end_per_group(_GroupName, Config) -> 53 Config. 54 55 56-define(APPLY0(M, F), (fun(Res) -> Res = M:F() end)(apply(M, F, []))). 57-define(APPLY1(M, F, A1), (fun(Res) -> Res = M:F(A1) end)(apply(M, F, [A1]))). 58-define(APPLY2(M, F, A1, A2), (fun(Res) -> Res = M:F(A1, A2) end)(apply(M, F, [A1,A2]))). 59 60mfa(Config) when is_list(Config) -> 61 ok = ?APPLY0(?MODULE, foo), 62 {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]), 63 {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}), 64 65 Mod = id(?MODULE), 66 ok = ?APPLY0(Mod, foo), 67 {[a,b]} = ?APPLY1(Mod, bar, [a,b]), 68 {39,{a}} = ?APPLY2(Mod, baz, 39, {a}), 69 70 ok = ?APPLY0(?MODULE, (id(foo))), 71 {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]), 72 {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}), 73 74 ok = ?APPLY0(Mod, (id(foo))), 75 {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]), 76 {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}), 77 78 {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)), 79 {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)), 80 {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)), 81 {'EXIT',_} = (catch bad_literal_call(1)), 82 83 ok = apply(Mod, foo, id([])), 84 {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])), 85 {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])), 86 87 Erlang = id(erlang), 88 Self = self(), 89 Self = ?APPLY0(Erlang, self), 90 42.0 = ?APPLY1(Erlang, abs, -42.0), 91 b = ?APPLY2(Erlang, element, 2, {a,b,c}), 92 true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1), 93 true = ?APPLY1(Erlang, is_function, fun() -> ok end), 94 false = ?APPLY1(Erlang, is_function, blurf), 95 true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1), 96 true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0), 97 false = ?APPLY2(Erlang, is_function, blurf, 0), 98 99 apply(Mod, foo, []). 100 101%% The single call to this function with a literal argument caused type 102%% optimization to swap out the 'mod' field of a #b_remote{}, which was 103%% mishandled during code generation as it assumed that the module would always 104%% be an atom. 105bad_literal_call(I) -> 106 I:foo(). 107 108foo() -> 109 ok. 110 111bar(A) -> 112 {A}. 113 114baz(A, B) -> 115 {A,B}. 116 117-define(FUNAPPLY0(F), (fun(Res) -> Res = F() end)(apply(F, []))). 118-define(FUNAPPLY1(F, A1), (fun(Res) -> Res = F(A1) end)(apply(F, [A1]))). 119-define(FUNAPPLY2(F, A1, A2), (fun(Res) -> Res = F(A1, A2) end)(apply(F, [A1,A2]))). 120 121fun_apply(Config) when is_list(Config) -> 122 Self = self(), 123 124 Self = ?FUNAPPLY0(fun() -> self() end), 125 Self = ?FUNAPPLY0((id(fun() -> self() end))), 126 ok = ?FUNAPPLY0(fun ?MODULE:foo/0), 127 ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))), 128 129 -42 = ?FUNAPPLY1(fun(A) -> -A end, 42), 130 [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]), 131 {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]), 132 {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]), 133 134 {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b), 135 {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]), 136 {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}), 137 138 ok. 139 140involved(_Config) -> 141 self() ! message, 142 ok = involved_1(), 143 144 self() ! message, 145 error = involved_2(), 146 ok. 147 148involved_1() -> 149 try 150 receive 151 _ -> 152 fun erlang:atom_to_list/1('') 153 end 154 of 155 [] -> 156 ok 157 catch 158 _:_ -> 159 error 160 end. 161 162involved_2() -> 163 try 164 receive 165 _ -> 166 fun erlang:atom_to_list/1() 167 end 168 of 169 [] -> 170 ok 171 catch 172 _:_ -> 173 error 174 end. 175 176id(I) -> I. 177