From d101155c5dc115a51725b52e500c9a981845f2da Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Fri, 28 Oct 2011 16:54:29 +0200 Subject: Behaviour callback discrepancy detection for Dialyzer --- .../test/behaviour_SUITE_data/dialyzer_options | 1 + .../results/gen_event_incorrect_return | 2 ++ .../results/gen_server_incorrect_args | 8 +++++ .../results/gen_server_missing_callbacks | 3 ++ .../behaviour_SUITE_data/results/sample_behaviour | 9 +++++ .../results/sample_behaviour_old | 4 +++ .../results/supervisor_incorrect_return | 2 ++ .../results/undefined_callbacks | 2 ++ .../src/gen_event_incorrect_return.erl | 33 +++++++++++++++++++ .../src/gen_server_incorrect_args.erl | 11 +++++++ .../src/gen_server_missing_callbacks.erl | 23 +++++++++++++ .../src/sample_behaviour/sample_behaviour.erl | 13 ++++++++ .../sample_behaviour/sample_callback_correct.erl | 32 ++++++++++++++++++ .../sample_behaviour/sample_callback_correct_2.erl | 38 ++++++++++++++++++++++ .../src/sample_behaviour/sample_callback_wrong.erl | 25 ++++++++++++++ .../src/sample_behaviour_old/correct_behaviour.erl | 6 ++++ .../src/sample_behaviour_old/correct_callback.erl | 15 +++++++++ .../incorrect_args_callback.erl | 13 ++++++++ .../incorrect_return_callback.erl | 15 +++++++++ .../src/sample_behaviour_old/missing_callback.erl | 10 ++++++ .../src/supervisor_incorrect_return.erl | 17 ++++++++++ .../undefined_callbacks/undefined_beh_callback.erl | 13 ++++++++ .../undefined_callbacks/undefined_behaviour.erl | 10 ++++++ 23 files changed, 305 insertions(+) create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl create mode 100644 lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl (limited to 'lib/dialyzer/test/behaviour_SUITE_data') diff --git a/lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options b/lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options new file mode 100644 index 0000000000..6df50943d8 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options @@ -0,0 +1 @@ +{dialyzer_options, [{warnings, [behaviours]}]}. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return new file mode 100644 index 0000000000..41c6dae55f --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return @@ -0,0 +1,2 @@ + +gen_event_incorrect_return.erl:16: The inferred return type for init/1 is 'error' which is not valid return for the callback of the gen_event behaviour diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args new file mode 100644 index 0000000000..333216bc5c --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args @@ -0,0 +1,8 @@ + +gen_server_incorrect_args.erl:3: Undefined callback function code_change/3 (behaviour 'gen_server') +gen_server_incorrect_args.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server') +gen_server_incorrect_args.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server') +gen_server_incorrect_args.erl:3: Undefined callback function init/1 (behaviour 'gen_server') +gen_server_incorrect_args.erl:3: Undefined callback function terminate/2 (behaviour 'gen_server') +gen_server_incorrect_args.erl:7: The inferred return type for handle_call/3 is {'no'} | {'ok'} which is not valid return for the callback of the gen_server behaviour +gen_server_incorrect_args.erl:7: The inferred type for the 2nd argument of handle_call/3 is 'boo' | 'foo' which is not valid for the callback of the gen_server behaviour diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks new file mode 100644 index 0000000000..5e0ed5fd27 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks @@ -0,0 +1,3 @@ + +gen_server_missing_callbacks.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server') +gen_server_missing_callbacks.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server') diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour new file mode 100644 index 0000000000..7420da2476 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour @@ -0,0 +1,9 @@ + +sample_callback_wrong.erl:15: The inferred return type for sample_callback_2/0 is 42 which is not valid return for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:16: The inferred return type for sample_callback_3/0 is 'fair' which is not valid return for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:17: The inferred return type for sample_callback_4/1 is 'fail' which is not valid return for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:19: The inferred return type for sample_callback_5/1 is string() which is not valid return for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:19: The inferred type for the 1st argument of sample_callback_5/1 is atom() which is not valid for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:21: The inferred return type for sample_callback_6/3 is {'okk',number()} which is not valid return for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:21: The inferred type for the 3rd argument of sample_callback_6/3 is atom() which is not valid for the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:3: Undefined callback function sample_callback_1/0 (behaviour 'sample_behaviour') diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old new file mode 100644 index 0000000000..948ea49ab1 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old @@ -0,0 +1,4 @@ + +incorrect_args_callback.erl:12: The inferred type for the 2nd argument of bar/2 is 'yes' which is not valid for the callback of the correct_behaviour behaviour +incorrect_return_callback.erl:9: The inferred return type for foo/0 is 'error' which is not valid return for the callback of the correct_behaviour behaviour +missing_callback.erl:5: Undefined callback function foo/0 (behaviour 'correct_behaviour') diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return b/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return new file mode 100644 index 0000000000..c96eb733a2 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return @@ -0,0 +1,2 @@ + +supervisor_incorrect_return.erl:14: The inferred return type for init/1 is {'ok',{{'one_against_one',0,1},[{_,_,_,_,_,_},...]}} which is not valid return for the callback of the supervisor behaviour diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks b/lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks new file mode 100644 index 0000000000..7147ffc750 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks @@ -0,0 +1,2 @@ + +undefined_beh_callback.erl:5: Callback info about the undefined_behaviour behaviour is not available diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl new file mode 100644 index 0000000000..f5ccf7f8c4 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl @@ -0,0 +1,33 @@ +-module(gen_event_incorrect_return). + +-behaviour(gen_event). + +-export([start_link/0, add_handler/0]). + +-export([init/1, handle_event/2, handle_call/2, + handle_info/2, terminate/2, code_change/3]). + +start_link() -> + gen_event:start_link({local, myserver}). + +add_handler() -> + gen_event:add_handler(myserver, ?MODULE, []). + +init([]) -> + error. + +handle_event(_Event, State) -> + {ok, State}. + +handle_call(_Request, State) -> + Reply = ok, + {ok, Reply, State}. + +handle_info(_Info, State) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl new file mode 100644 index 0000000000..df04dff80d --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl @@ -0,0 +1,11 @@ +-module(gen_server_incorrect_args). + +-behaviour(gen_server). + +-export([handle_call/3]). + +handle_call(_Request, From, _State) -> + case From of + 'boo' -> {'ok'}; + 'foo' -> {'no'} + end. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl new file mode 100644 index 0000000000..760466fdac --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl @@ -0,0 +1,23 @@ +-module(gen_server_missing_callbacks). + +-behaviour(gen_server). + +-export([start_link/0]). + +-export([init/1, handle_call/3, terminate/2, code_change/3]). + +start_link() -> + gen_server:start_link({local, myserver}, ?MODULE, [], []). + +init([]) -> + ignore. + +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl new file mode 100644 index 0000000000..116980986b --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl @@ -0,0 +1,13 @@ +-module(sample_behaviour). + +-type custom() :: 1..42. + +-callback sample_callback_1() -> term(). +-callback sample_callback_2() -> atom(). +-callback sample_callback_3() -> {'ok', custom()} | 'fail'. + +-callback sample_callback_4(term()) -> 'ok'. +-callback sample_callback_5(custom()) -> 'ok' | 'fail'. + +-callback sample_callback_6(custom(), custom(), string()) -> + {'ok', custom()} | 'fail'. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl new file mode 100644 index 0000000000..ab0378e6f0 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl @@ -0,0 +1,32 @@ +-module(sample_callback_correct). + +-behaviour(sample_behaviour). + +-export([ + sample_callback_1/0, + sample_callback_2/0, + sample_callback_3/0, + sample_callback_4/1, + sample_callback_5/1, + sample_callback_6/3 + ]). + +sample_callback_1() -> 42. % This is a valid return. +sample_callback_2() -> foo. % This is a valid return. +sample_callback_3() -> {ok, 17}. % This is a valid return. +sample_callback_4(Input) -> + put(mine, Input+1), % This is valid handling of the input + ok. % This is a valid return. +sample_callback_5(Input) -> + case Input - 1 < 22 of % This is valid handling of the input + true -> ok; % This is a valid return. + false -> fail % This is a valid return. + end. +sample_callback_6(OldNr, NewNr, Reason) -> + Diff = NewNr - OldNr, % This is valid handling of the input + Msg = string:join(["Reason: ", Reason], ","), % This is valid handling of the input + case Diff > 0 of + true -> put(mine, {NewNr, Msg}), + {ok, NewNr}; % This is a valid return. + false -> fail % This is a valid return. + end. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl new file mode 100644 index 0000000000..148cea6843 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl @@ -0,0 +1,38 @@ +-module(sample_callback_correct_2). + +-behaviour(sample_behaviour). + +-export([ + sample_callback_1/0, + sample_callback_2/0, + sample_callback_3/0, + sample_callback_4/1, + sample_callback_5/1, + sample_callback_6/3, + common_infrastructure/1 + ]). + +sample_callback_1() -> 42. % This is a valid return. +sample_callback_2() -> foo. % This is a valid return. +sample_callback_3() -> {ok, 17}. % This is a valid return. +sample_callback_4(Input) -> + case Input of + 1 -> common_infrastructure(Input); % This is 'correct' input for + _ -> ok % common_infrastructure. + end. +sample_callback_5(Input) -> + case get(Input) of % This is valid handling of a more generic input + true -> ok; % This is a valid return. + false -> fail % This is a valid return. + end. +sample_callback_6(OldNr, NewNr, Reason) -> + Diff = NewNr - OldNr, % This is valid handling of the input + Msg = string:join(["Reason: ", Reason], ","), % This is valid handling of the input + case Diff > 0 of + true -> put(mine, {NewNr, Msg}), + {ok, NewNr}; % This is a valid return. + false -> fail % This is a valid return. + end. + +common_infrastructure( 1) -> 'ok'; +common_infrastructure(42) -> 'fail'. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl new file mode 100644 index 0000000000..02a063fab7 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl @@ -0,0 +1,25 @@ +-module(sample_callback_wrong). + +-behaviour(sample_behaviour). + +-export([ +% sample_callback_1/0, + sample_callback_2/0, + sample_callback_3/0, + sample_callback_4/1, + sample_callback_5/1, + sample_callback_6/3 + ]). + +% sample_callback_1() -> 41. % We can't really break this contract so: missing! +sample_callback_2() -> 42. % This is not an atom(). +sample_callback_3() -> fair. % This is probably a typo. +sample_callback_4(_) -> % We cannot break the input. + fail. % We can definitely return a wrong value however. :) +sample_callback_5(Input) -> % Input is treated as an atom, result is a list. + atom_to_list(Input). % Both violate the contract. +sample_callback_6(OldNr, NewNr, Reason) -> + Diff = NewNr - OldNr, % This is valid handling of the input + %% Reason should have been treated as a string. + Msg = string:join(["Reason: ", atom_to_list(Reason)], ","), + {okk, NewNr}. %% This, too, is a typo. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl new file mode 100644 index 0000000000..90ce590997 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl @@ -0,0 +1,6 @@ +%%% This is a behaviour with info about its calllbacks. + +-module(correct_behaviour). + +-callback foo() -> yes | no. +-callback bar({atom(),_},[_]) -> term(). diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl new file mode 100644 index 0000000000..8f254520ab --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl @@ -0,0 +1,15 @@ +%%% This is a correct callback module for the correct_behaviour. + +-module(correct_callback). + +-behaviour(correct_behaviour). + +-export([foo/0, bar/2]). + +foo() -> + yes. + +bar({'query', 'boo'}, _Any) -> + no; +bar({'reply', [_R]}, [1,2,3]) -> + yes. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl new file mode 100644 index 0000000000..68fc60d418 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl @@ -0,0 +1,13 @@ +%%% This is a correct callback module for the correct_behaviour. + +-module(incorrect_args_callback). + +-behaviour(correct_behaviour). + +-export([foo/0, bar/2]). + +foo() -> + yes. + +bar({'reply', _Any}, yes) -> %% Should be a tuple and a list. + yes. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl new file mode 100644 index 0000000000..9ff920cdd0 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl @@ -0,0 +1,15 @@ +%%% This is a correct callback module for the correct_behaviour. + +-module(incorrect_return_callback). + +-behaviour(correct_behaviour). + +-export([foo/0, bar/2]). + +foo() -> + error. %% Should be 'yes' or 'no'. + +bar({'query', 'boo'}, _Any) -> + no; +bar({'reply', [_R]}, [1,2,3]) -> + yes. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl new file mode 100644 index 0000000000..e6c5306839 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl @@ -0,0 +1,10 @@ +%%% This is a correct callback module for the correct_behaviour. + +-module(missing_callback). + +-behaviour(correct_behaviour). + +-export([bar/2]). + +bar({'reply', _Any}, []) -> + yes. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl new file mode 100644 index 0000000000..616a9073ae --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl @@ -0,0 +1,17 @@ +-module(supervisor_incorrect_return). + +-behaviour(supervisor). + +-export([start_link/0]). + +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +init([]) -> + AChild = {'AName',{'AModule',start_link,[]}, + permanent,2000,worker,['AModule']}, + {ok,{{one_against_one,0,1}, [AChild]}}. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl new file mode 100644 index 0000000000..8223225b4b --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl @@ -0,0 +1,13 @@ +%%% This is a correct callback module for the correct_behaviour. + +-module(undefined_beh_callback). + +-behaviour(undefined_behaviour). + +-export([foo/0, bar/2]). + +foo() -> + yes. + +bar({'reply', _Any}, yes) -> + yes. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl new file mode 100644 index 0000000000..fb3d4c5e03 --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl @@ -0,0 +1,10 @@ +%%% This is a behaviour with undefined info about its calllbacks. + +-module(undefined_behaviour). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + [{foo, 0}, {bar, 2}]; +behaviour_info(_Other) -> + undefined. -- cgit v1.2.3