diff options
author | Lukas Larsson <[email protected]> | 2013-09-30 15:07:49 +0200 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-02-24 15:15:58 +0100 |
commit | fa3dd14716b2a7ad0c223ebacd2ffc6ecf6437e6 (patch) | |
tree | 9e01ad087ca43085f2b7efb80bf5f203d27124eb /lib/kernel/test | |
parent | 8ed59e4a9dddf083d2046e1bd58f397221928c0e (diff) | |
download | otp-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')
-rw-r--r-- | lib/kernel/test/Makefile | 4 | ||||
-rw-r--r-- | lib/kernel/test/ose_SUITE.erl | 765 |
2 files changed, 769 insertions, 0 deletions
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index f1b8a105ed..ac28d1aae9 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -79,6 +79,10 @@ MODULES= \ loose_node \ sendfile_SUITE +ifeq ($(findstring ose,$(TARGET)),ose) +MODULES+=ose_SUITE +endif + APP_FILES = \ appinc.app \ appinc1.app \ 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. |