aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/test/ose_SUITE.erl
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2013-09-30 15:07:49 +0200
committerLukas Larsson <[email protected]>2014-02-24 15:15:58 +0100
commitfa3dd14716b2a7ad0c223ebacd2ffc6ecf6437e6 (patch)
tree9e01ad087ca43085f2b7efb80bf5f203d27124eb /lib/kernel/test/ose_SUITE.erl
parent8ed59e4a9dddf083d2046e1bd58f397221928c0e (diff)
downloadotp-fa3dd14716b2a7ad0c223ebacd2ffc6ecf6437e6.tar.gz
otp-fa3dd14716b2a7ad0c223ebacd2ffc6ecf6437e6.tar.bz2
otp-fa3dd14716b2a7ad0c223ebacd2ffc6ecf6437e6.zip
ose: Add module that allows interaction with any OSE process
The interface of this module is made to be as generic as possible in order for other IPC mechanisms to mimic it and allow porting of code between different os:es.
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.