1%%% -*- erlang-indent-level: 2 -*-
2%%%-------------------------------------------------------------------
3%%% Author: Kostis Sagonas
4%%%
5%%% Tests for correct handling of funs.
6%%%-------------------------------------------------------------------
7-module(basic_fun).
8
9-export([test/0]).
10
11-export([dummy_foo/4, add1/1, test_fun03/0]).
12
13test() ->
14  ok = test_calls(),
15  ok = test_is_function(),
16  ok = test_is_function2(),
17  ok.
18
19%%--------------------------------------------------------------------
20%% Tests function and fun calls.
21
22test_calls() ->
23  ok = test_apply_call(?MODULE, dummy_foo),
24  ok = test_fun_call(fun dummy_foo/4),
25  ok = test_fun_call(fun ?MODULE:dummy_foo/4),
26  ok.
27
28test_apply_call(M, F) ->
29  M:F(bar, 42, foo, 17).
30
31test_fun_call(Fun) ->
32  Fun(bar, 42, foo, 17).
33
34dummy_foo(_, _, foo, _) -> ok.
35
36%%--------------------------------------------------------------------
37%% Tests handling of funs out of exported functions and 2-tuple funs.
38
39test_fun03() ->
40  MFPair = add1_as_2tuple(),
41  4712 = do_call(add1_as_export(), 4711),
42  {badfun, MFPair} = try do_call(MFPair, 88) catch error:Err -> Err end,
43  true = do_guard(add1_as_export()),
44  false = do_guard(MFPair), % 2-tuples do not satisfy is_function/1
45  ok.
46
47do_call(F, X) -> F(X).
48
49do_guard(F) when is_function(F) -> true;
50do_guard(_) -> false.
51
52add1_as_export() -> fun ?MODULE:add1/1.
53
54add1_as_2tuple() -> {?MODULE, add1}.
55
56add1(X) -> X+1.
57
58%%--------------------------------------------------------------------
59%% Tests the is_function guard and BIF.
60
61test_is_function() ->
62  Fun = fun (X, foo) -> dummy_foo(X, mnesia_lib, foo, [X]) end,
63  ok = test_when_guard(Fun),
64  ok = test_if_guard(Fun),
65  ok.
66
67test_when_guard(X) when is_function(X) -> ok.
68
69test_if_guard(X) ->
70  if is_function(X) -> ok;
71     true -> weird
72  end.
73
74%%--------------------------------------------------------------------
75%% Tests the is_function2 guard and BIF.
76
77test_is_function2() ->
78  ok = test_guard(),
79  ok = test_guard2(),
80  ok = test_call(),
81  ok.
82
83test_guard() ->
84  zero_fun = test_f2(fun () -> ok end),
85  unary_fun = test_f2(fun(X) -> X end),
86  binary_fun = test_f2(fun (X, Y) -> {X, Y} end),
87  no_fun = test_f2(gazonk),
88  ok.
89
90test_f2(Fun) when is_function(Fun, 0) ->
91  zero_fun;
92test_f2(Fun) when is_function(Fun, 1) ->
93  unary_fun;
94test_f2(Fun) when is_function(Fun, 2) ->
95  binary_fun;
96test_f2(_) ->
97  no_fun.
98
99test_guard2() ->
100  zero_fun = test_f2_n(fun () -> ok end, 0),
101  unary_fun = test_f2_n(fun (X) -> X end, 1),
102  binary_fun = test_f2_n(fun (X, Y) -> {X, Y} end, 2),
103  no_fun = test_f2_n(gazonk, 0),
104  ok.
105
106test_f2_n(F, N) when is_function(F, N) ->
107  case N of
108    0 -> zero_fun;
109    1 -> unary_fun;
110    2 -> binary_fun
111  end;
112test_f2_n(_, _) ->
113  no_fun.
114
115test_call() ->
116  true  = test_fn2(fun (X, Y) -> {X,Y} end, 2),
117  false = test_fn2(fun (X, Y) -> {X,Y} end, 3),
118  false = test_fn2(gazonk, 2),
119  {'EXIT', {badarg, _TR1}} = (catch test_fn2(gazonk, gazonk)),
120  {'EXIT', {badarg, _TR2}} = (catch test_fn2(fun (X, Y) -> {X, Y} end, gazonk)),
121  ok.
122
123test_fn2(F, N) ->
124  is_function(F, N).
125