aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/test/ose_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/test/ose_SUITE.erl')
-rw-r--r--lib/kernel/test/ose_SUITE.erl765
1 files changed, 765 insertions, 0 deletions
diff --git a/lib/kernel/test/ose_SUITE.erl b/lib/kernel/test/ose_SUITE.erl
new file mode 100644
index 0000000000..7e81b19894
--- /dev/null
+++ b/lib/kernel/test/ose_SUITE.erl
@@ -0,0 +1,765 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2013. 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(ose_SUITE).
+
+%-compile(export_all).
+
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,init_per_testcase/2,
+ end_per_testcase/2]).
+-export([
+ basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1,
+ hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1,
+ attach/1,multi_attach/1,detach/1,multi_detach/1,
+ open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1,
+ hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1,
+ send_errors/1,send_w_s_errors/1,listen_errors/1
+ ]).
+
+-define(INTERFACE,ose).
+
+
+init_per_testcase(_Func, Config) ->
+ Config.
+end_per_testcase(_Func, _Config) ->
+ ok.
+
+suite() -> [{timeout,{30,seconds}}].
+
+all() ->
+ [
+ basic,stress,multi_msg_numbers,multi_mailboxes,
+ hunt,multi_hunt,dehunt,multi_dehunt,
+ attach,multi_attach,detach,multi_detach,
+
+ open_errors,close_errors,get_id_errors,get_name_errors,
+ hunt_errors,dehunt_errors,attach_errors,detach_errors,
+ send_errors,send_w_s_errors,listen_errors
+ ].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ case os:type() of
+ {ose,_} ->
+ Config;
+ _Else ->
+ {skip,"Only run on OSE"}
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+basic(_Config) ->
+
+ [P1,P2] = multi_open(2,[42]),
+ P1Id = ?INTERFACE:get_id(P1),
+ P2Id = ?INTERFACE:get_id(P2),
+
+ ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>),
+ receive
+ {message,P1,V1} ->
+ {P2Id,P1Id,42,<<"ping">>} = V1,
+ ?INTERFACE:send(P1,P2Id,42,<<"pong">>);
+ Else1 ->
+ ct:fail({got_wrong_message,Else1})
+ end,
+
+ receive
+ {message,P2,V2} ->
+ {P1Id,P2Id,42,<<"pong">>} = V2;
+ Else2 ->
+ ct:fail({got_wrong_message,Else2})
+ end,
+
+ ?INTERFACE:close(P1),
+ ?INTERFACE:close(P2).
+
+%% Send 1000 messages and see if we can cope and that msg order is preserved
+stress(_Config) ->
+
+ Iterations = 1000,
+
+ [P1,P2] = multi_open(2,[42]),
+ P1Id = ?INTERFACE:get_id(P1),
+ P2Id = ?INTERFACE:get_id(P2),
+
+ spawn(fun() ->
+ n(fun(N) ->
+ Msg = [<<"ping">>|integer_to_list(N)],
+ ?INTERFACE:send(P2,P1Id,42,Msg)
+ end,Iterations)
+ end),
+ timer:sleep(100),
+ n(fun(N) ->
+ receive
+ {message,P1,Value} ->
+ Int = integer_to_binary(N),
+ {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value,
+ ok;
+ Else ->
+ ct:fail({got_wrong_message,Else})
+ end
+ end,Iterations),
+
+ ?INTERFACE:close(P1),
+ ?INTERFACE:close(P2).
+
+%% Listen to 1000 different message numbers and send some random messages
+multi_msg_numbers(_Config) ->
+
+ Iterations = 100,
+
+ [P1,P2] = multi_open(2,lists:seq(2000,3000)),
+ P1Id = ?INTERFACE:get_id(P1),
+
+ n(fun(_) ->
+ Num = random:uniform(1000)+2000,
+ ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>)
+ end,Iterations),
+
+ n(fun(_) ->
+ receive
+ {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000;
+ Id =< 3000 ->
+ Id = binary_to_integer(Num),
+ ok;
+ Else ->
+ ct:fail({got_wrong_message,Else})
+ end
+ end,Iterations),
+
+ ?INTERFACE:close(P1),
+ ?INTERFACE:close(P2).
+
+
+%% Create 100 mailboxes and send messages to them
+multi_mailboxes(_Config) ->
+
+ Mailboxes = 100,
+
+ [P1|MBs] = multi_open(Mailboxes,[42]),
+
+ [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs],
+
+ [receive
+ {message,P,Value} ->
+ Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)),
+ {_,_,42,<<"ping",Name/binary>>} = Value,
+ ok
+ end || P <- MBs],
+
+ [?INTERFACE:close(P) || P <- [P1|MBs]],
+ ok.
+
+hunt(_Config) ->
+ [P1,P2] = multi_open(2,[]),
+
+ Ref = ?INTERFACE:hunt(P1,"p2"),
+ receive
+ {mailbox_up,P1,Ref,Pid} ->
+ Pid = ?INTERFACE:get_id(P2),
+ ?INTERFACE:close(P1),
+ ?INTERFACE:close(P2);
+ Else ->
+ ct:fail({got_wrong_message,Else,Ref})
+ end.
+
+multi_hunt(_Config) ->
+
+ Iterations = 100,
+
+ P = ?INTERFACE:open("p"),
+
+ Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)],
+
+ Pids = [begin
+ Prt = ?INTERFACE:open("p"++integer_to_list(N)),
+ Pid = ?INTERFACE:get_id(Prt),
+ ?INTERFACE:close(Prt),
+ Pid
+ end || N <- lists:seq(1,Iterations)],
+
+ [receive
+ {mailbox_up,P,Ref,Pid} ->
+ ok
+ after 10 ->
+ ct:fail({did_not_get,Pid,Ref})
+ end || {Pid,Ref} <- lists:zip(Pids,Refs)],
+ ?INTERFACE:close(P).
+
+
+dehunt(_Config) ->
+ [P1] = multi_open(1,[]),
+ Ref = ?INTERFACE:hunt(P1,"p2"),
+ receive
+ _Else -> ct:fail({got,_Else})
+ after 1000 ->
+ ok
+ end,
+ P2 = ?INTERFACE:open("p2"),
+
+ % Make sure any messages are sent
+ receive after 10 -> ok end,
+
+ ok = ?INTERFACE:dehunt(P1,Ref),
+
+ % Make sure no messages are received
+ receive
+ _Else2 -> ct:fail({got,_Else2})
+ after 1000 ->
+ ?INTERFACE:close(P1),
+ ?INTERFACE:close(P2)
+ end.
+
+%%%
+%%% This testcase basically:
+%%% spawn 10 processes that in parallel
+%%% adds some hunts for different OSE processes
+%%% maybe create hunted OSE process
+%%% dehunt half of the hunts
+%%% create more hunts
+%%% if not created create hunted OSE process
+%%% veryify that all expected hunt messages are received
+%%% verify that all processes exited correctly
+%%%
+%%% This complex test is done to make sure that the internal handling
+%%% of dehunt works as expected.
+%%%
+multi_dehunt(_Config) ->
+ [P1] = multi_open(1,[]),
+
+ Scenario =
+ fun(Iterations) ->
+
+ Hunted = "p"++integer_to_list(Iterations),
+ %% Start a couple of hunts
+ Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)],
+
+ %% We alternate if the process is opened before or after the dehunt
+ P2O = if Iterations rem 2 == 0 ->
+ ?INTERFACE:open(Hunted);
+ true ->
+ undefined
+ end,
+
+ %% Remove half of them
+ {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 ->
+ ok = ?INTERFACE:dehunt(P1,Ref),
+ {[],Acc+1};
+ (Ref,Acc) ->
+ {Ref,Acc+1}
+ end,0,Refs),
+
+ %% Add some new ones
+ NewRefs = [?INTERFACE:hunt(P1,Hunted)
+ || _ <- lists:seq(1,Iterations div 4)]
+ ++ lists:flatten(RemRefs),
+
+ P2 = if P2O == undefined ->
+ ?INTERFACE:open(Hunted);
+ true ->
+ P2O
+ end,
+ P2Id = ?INTERFACE:get_id(P2),
+
+ %% Receive all the expected ones
+ lists:foreach(fun(Ref) ->
+ receive
+ {mailbox_up,P1,Ref,P2Id} ->
+ ok
+ after 1000 ->
+ io:format("Flush: ~p~n",[flush()]),
+ io:format("~p~n",[{Iterations,{did_not_get, Ref}}]),
+ ok = Ref
+ end
+ end,NewRefs),
+
+ %% Check that no other have arrived
+ receive
+ _Else ->
+ io:format("Flush: ~p~n",[flush()]),
+ io:format("~p~n",[{Iterations,{got, _Else}}]),
+ ok = _Else
+ after 100 ->
+ ok
+ end,
+ ?INTERFACE:close(P2)
+ end,
+
+ Self = self(),
+
+ n(fun(N) ->
+ spawn(fun() -> Self !
+ Scenario(N*25)
+ end),
+ ok
+ end,10),
+
+ n(fun(_N) ->
+ receive ok -> ok
+ after 60000 -> ct:fail(failed)
+ end
+ end,10),
+ ?INTERFACE:close(P1).
+
+attach(_Config) ->
+ [P1,P2] = multi_open(2,[]),
+
+ P2Id = ?INTERFACE:get_id(P2),
+ Ref = ?INTERFACE:attach(P1,P2Id),
+ ?INTERFACE:close(P2),
+ receive
+ {mailbox_down,P1,Ref,P2Id} ->
+ ?INTERFACE:close(P1);
+ _Else ->
+ ct:fail({got,_Else, {P1,Ref,P2Id}})
+ after 1000 ->
+ ct:fail({did_not_get,P1,Ref,P2Id})
+ end.
+
+multi_attach(_Config) ->
+
+ Iterations = 100,
+
+ [P1|Pids] = multi_open(Iterations,[]),
+
+ Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids],
+
+ [?INTERFACE:close(Pid) || Pid <- Pids],
+
+ [receive
+ {mailbox_down,P1,Ref,Pid} ->
+ ok
+ after 10000 ->
+ ct:fail({did_not_get,Pid,Ref})
+ end || {Pid,Ref} <- Refs],
+ ?INTERFACE:close(P1).
+
+detach(_Config) ->
+ [P1,P2] = multi_open(2,[]),
+ P2Id = ?INTERFACE:get_id(P2),
+ Ref = ?INTERFACE:attach(P1,P2Id),
+ receive
+ _Else -> ct:fail({got,_Else})
+ after 100 ->
+ ok
+ end,
+
+ ?INTERFACE:close(P2),
+
+ % Make sure any messages are sent
+ receive after 10 -> ok end,
+
+ ?INTERFACE:detach(P1,Ref),
+
+ % Make sure no messages are received
+ receive
+ _Else2 -> ct:fail({got,_Else2})
+ after 1000 ->
+ ?INTERFACE:close(P1)
+ end.
+
+%%%
+%%% This testcase basically:
+%%% spawn 10 processes that in parallel
+%%% adds some attach for different OSE processes
+%%% maybe close OSE process
+%%% dehunt half of the hunts
+%%% create more hunts
+%%% if not closed close attached OSE process
+%%% veryify that all expected attach messages are received
+%%% verify that all processes exited correctly
+%%%
+%%% This complex test is done to make sure that the internal handling
+%%% of dehunt works as expected.
+%%%
+multi_detach(_Config) ->
+ [P1] = multi_open(1,[]),
+
+ Scenario =
+ fun(Iterations) ->
+
+ Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)),
+ AttachedId = ?INTERFACE:get_id(Attached),
+ %% Start a couple of attachs
+ Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)],
+
+ %% We alternate if the process is closed before or after the detach
+ P2O = if Iterations rem 2 == 0 ->
+ ?INTERFACE:close(Attached);
+ true ->
+ undefined
+ end,
+
+ %% Remove half of them
+ {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 ->
+ ok = ?INTERFACE:detach(P1,Ref),
+ {[],Acc+1};
+ (Ref,Acc) ->
+ {Ref,Acc+1}
+ end,0,Refs),
+
+ %% Add some new ones
+ NewRefs = [?INTERFACE:attach(P1,AttachedId)
+ || _ <- lists:seq(1,Iterations div 4)]
+ ++ lists:flatten(RemRefs),
+
+ if P2O == undefined ->
+ ?INTERFACE:close(Attached);
+ true ->
+ P2O
+ end,
+
+ %% Receive all the expected ones
+ lists:foreach(fun(Ref) ->
+ receive
+ {mailbox_down,P1,Ref,AttachedId} ->
+ ok
+ after 1000 ->
+ io:format("Flush: ~p~n",[flush()]),
+ io:format("~p~n",[{Iterations,{did_not_get, Ref}}]),
+ ok = Ref
+ end
+ end,NewRefs),
+
+ %% Check that no other have arrived
+ receive
+ _Else ->
+ io:format("Flush: ~p~n",[flush()]),
+ io:format("~p~n",[{Iterations,{got, _Else}}]),
+ ok = _Else
+ after 100 ->
+ ok
+ end
+ end,
+
+ Self = self(),
+
+ n(fun(N) ->
+ spawn(fun() -> Self !
+ Scenario(N*5)
+ end),
+ ok
+ end,10),
+
+ n(fun(_N) ->
+ receive ok -> ok
+ after 60000 -> ct:fail(failed)
+ end
+ end,10),
+ ?INTERFACE:close(P1).
+
+
+open_errors(_Config) ->
+ {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} =
+ (catch ?INTERFACE:open(inval)),
+ {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} =
+ (catch ?INTERFACE:open(["p"|1])),
+ {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} =
+ (catch ?INTERFACE:open(["p",1234])),
+
+ ok.
+
+close_errors(_Config) ->
+ {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} =
+ (catch ?INTERFACE:close(inval)),
+
+ P1 = ?INTERFACE:open("p1"),
+ ok = ?INTERFACE:close(P1),
+ ok = ?INTERFACE:close(P1).
+
+
+get_id_errors(_Config) ->
+ {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} =
+ (catch ?INTERFACE:get_id(inval)),
+
+ P1 = ?INTERFACE:open("p1"),
+ ok = ?INTERFACE:close(P1),
+ {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} =
+ (catch ?INTERFACE:get_id(P1)),
+
+ ok.
+
+get_name_errors(_Config) ->
+ P1 = ?INTERFACE:open("p1"),
+ {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} =
+ (catch ?INTERFACE:get_name(P1,inval)),
+
+ undefined = ?INTERFACE:get_name(P1,1234),
+
+ P2 = ?INTERFACE:open("p2"),
+ P2Id = ?INTERFACE:get_id(P2),
+ ok = ?INTERFACE:close(P1),
+ {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} =
+ (catch ?INTERFACE:get_name(P1,P2Id)),
+ ?INTERFACE:close(P2),
+
+ P3 = ?INTERFACE:open([255]),
+ <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)),
+ ?INTERFACE:close(P3),
+
+ ok.
+
+hunt_errors(_Config) ->
+
+ {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} =
+ (catch ?INTERFACE:hunt(inval,"hello")),
+
+ P1 = ?INTERFACE:open("p1"),
+ {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} =
+ (catch ?INTERFACE:hunt(P1,["hello",12345])),
+
+ P2 = ?INTERFACE:open(<<255>>),
+ P2Pid = ?INTERFACE:get_id(P2),
+ Ref = ?INTERFACE:hunt(P1,[255]),
+ receive
+ {mailbox_up,P1,Ref,P2Pid} ->
+ ok;
+ Else ->
+ ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}})
+ after 150 ->
+ ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}})
+ end,
+
+ ok = ?INTERFACE:close(P1),
+ ok = ?INTERFACE:close(P2),
+ {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} =
+ (catch ?INTERFACE:hunt(P1,["hello"])),
+
+ ok.
+
+dehunt_errors(_Config) ->
+ P1 = ?INTERFACE:open("p1"),
+ Ref = ?INTERFACE:hunt(P1,"p2"),
+
+ {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} =
+ (catch ?INTERFACE:dehunt(inval,Ref)),
+
+ {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} =
+ (catch ?INTERFACE:dehunt(P1,inval)),
+
+ ok = ?INTERFACE:dehunt(P1,Ref),
+ ok = ?INTERFACE:dehunt(P1,Ref),
+
+ ok = ?INTERFACE:close(P1),
+
+ {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} =
+ (catch ?INTERFACE:dehunt(P1,Ref)),
+
+ case ?INTERFACE of
+ ose -> ok;
+ _ ->
+ P2 = ?INTERFACE:open("p2"),
+ ok = ?INTERFACE:close(P2)
+ end,
+
+ receive
+ Else -> ct:fail({got,Else})
+ after 100 ->
+ ok
+ end.
+
+attach_errors(_Config) ->
+ P1 = ?INTERFACE:open("p1"),
+ P2 = ?INTERFACE:open("p2"),
+ P2Id = ?INTERFACE:get_id(P2),
+
+ {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} =
+ (catch ?INTERFACE:attach(inval,P2Id)),
+
+ {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} =
+ (catch ?INTERFACE:attach(P1,[12345])),
+
+ ok = ?INTERFACE:close(P1),
+ ok = ?INTERFACE:close(P2),
+ {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} =
+ (catch ?INTERFACE:attach(P1,P2Id)),
+
+ ok.
+
+detach_errors(_Config) ->
+ P1 = ?INTERFACE:open("p1"),
+ P2 = ?INTERFACE:open("p2"),
+ P2Id = ?INTERFACE:get_id(P2),
+
+ Ref = ?INTERFACE:attach(P1,P2Id),
+
+ {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} =
+ (catch ?INTERFACE:detach(inval,Ref)),
+
+ {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} =
+ (catch ?INTERFACE:detach(P1,inval)),
+
+ ok = ?INTERFACE:detach(P1,Ref),
+ ok = ?INTERFACE:detach(P1,Ref),
+
+ case ?INTERFACE of
+ ose -> ok;
+ _ ->
+ ok = ?INTERFACE:close(P1)
+ end,
+
+ ok = ?INTERFACE:close(P2),
+ ok = ?INTERFACE:close(P1),
+
+ {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} =
+ (catch ?INTERFACE:detach(P1,Ref)),
+
+ receive
+ Else -> ct:fail({got,Else})
+ after 100 ->
+ ok
+ end.
+
+send_errors(_Config) ->
+ P1 = ?INTERFACE:open("p1"),
+ P2 = ?INTERFACE:open("p2"),
+ P2Id = ?INTERFACE:get_id(P2),
+
+ {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(inval,P2Id,42,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P1,inval,42,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P1,P2Id,inval,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} =
+ (catch ?INTERFACE:send(P1,P2Id,42,inval)),
+
+ ok = ?INTERFACE:close(P2),
+ ok = ?INTERFACE:send(P1,P2Id,42,"hello"),
+ ok = ?INTERFACE:close(P1),
+
+ {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P1,P2Id,42,"hello")),
+
+ receive
+ Else -> ct:fail({got,Else})
+ after 100 ->
+ ok
+ end.
+
+send_w_s_errors(_Config) ->
+ P1 = ?INTERFACE:open("p1"),
+ P1Id = ?INTERFACE:get_id(P1),
+ P2 = ?INTERFACE:open("p2"),
+ P2Id = ?INTERFACE:get_id(P2),
+ P3 = ?INTERFACE:open("p3"),
+ P3Id = ?INTERFACE:get_id(P3),
+
+ {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")),
+ {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} =
+ (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)),
+
+ ok = ?INTERFACE:close(P3),
+ ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"),
+
+ ok = ?INTERFACE:close(P1),
+ ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"),
+ ok = ?INTERFACE:close(P2),
+
+ {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} =
+ (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")),
+
+ receive
+ Else -> ct:fail({got,Else})
+ after 100 ->
+ ok
+ end.
+
+listen_errors(_Config) ->
+
+ P1 = ?INTERFACE:open("p1"),
+ P1Id = ?INTERFACE:get_id(P1),
+
+ {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} =
+ (catch ?INTERFACE:listen(inval,[42])),
+ {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} =
+ (catch ?INTERFACE:listen(P1,inval)),
+ {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} =
+ (catch ?INTERFACE:listen(P1,[1 bsl 33])),
+
+ ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]),
+
+ case ?INTERFACE of
+ ose -> ok;
+ _ ->
+ ?INTERFACE:send(P1,P1Id,42,"hello"),
+ timer:sleep(50),
+ ?INTERFACE:listen(P1,[]),
+ ?INTERFACE:send(P1,P1Id,42,"hello2"),
+
+ receive
+ {message,P1,42,"hello"} -> ok
+ end,
+
+ receive
+ Else -> ct:fail({got,Else})
+ after 100 ->
+ ok
+ end
+ end,
+
+ ok = ?INTERFACE:close(P1),
+ {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} =
+ (catch ?INTERFACE:listen(P1,[42])),
+
+ ok.
+
+%%
+%% Internal functions
+%%
+multi_open(N,ListenNums) ->
+ multi_open(N,ListenNums,[]).
+
+multi_open(0,_,Acc) ->
+ Acc;
+multi_open(N,ListenNums,Acc) ->
+ P = ?INTERFACE:open("p"++integer_to_list(N)),
+ ok = ?INTERFACE:listen(P,ListenNums),
+ multi_open(N-1,ListenNums,[P|Acc]).
+
+n(_F,0) ->
+ ok;
+n(F,N) ->
+ ok = F(N),
+ n(F,N-1).
+
+
+flush() ->
+ receive
+ Msg ->
+ [Msg|flush()]
+ after 0 ->
+ []
+ end.