diff options
author | Lukas Larsson <[email protected]> | 2014-01-08 18:54:15 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-02-24 15:16:03 +0100 |
commit | cd69c2a54201b4e0c4ba86d4248937120e1957e7 (patch) | |
tree | d9bdfe069adfb87d850f609753a342e4c9b4e899 /lib/ose/test | |
parent | b309ad9b4a3e4ff2d6d3a6e6270d37355a798bb1 (diff) | |
download | otp-cd69c2a54201b4e0c4ba86d4248937120e1957e7.tar.gz otp-cd69c2a54201b4e0c4ba86d4248937120e1957e7.tar.bz2 otp-cd69c2a54201b4e0c4ba86d4248937120e1957e7.zip |
ose: Create OSE application
Create an specific OSE application that mainly contains documentation
around the OSE specific part of Erlang/OTP.
Diffstat (limited to 'lib/ose/test')
-rw-r--r-- | lib/ose/test/Makefile | 67 | ||||
-rw-r--r-- | lib/ose/test/ose.cover | 2 | ||||
-rw-r--r-- | lib/ose/test/ose.spec | 1 | ||||
-rw-r--r-- | lib/ose/test/ose_SUITE.erl | 765 |
4 files changed, 835 insertions, 0 deletions
diff --git a/lib/ose/test/Makefile b/lib/ose/test/Makefile new file mode 100644 index 0000000000..7e2080ba38 --- /dev/null +++ b/lib/ose/test/Makefile @@ -0,0 +1,67 @@ +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + ose_SUITE + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +INSTALL_PROGS= $(TARGET_FILES) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/ose_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ + -I$(ERL_TOP)/lib/kernel/include + +EBIN = . + +EMAKEFILE=Emakefile +COVERFILE=ose.cover + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ + > $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + +release_tests_spec: make_emakefile + $(INSTALL_DIR) "$(RELSYSDIR)" + $(INSTALL_DATA) ose.spec $(EMAKEFILE) \ + $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)" + chmod -R u+w "$(RELSYSDIR)" + @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) + +release_docs_spec: diff --git a/lib/ose/test/ose.cover b/lib/ose/test/ose.cover new file mode 100644 index 0000000000..7b846cfaf6 --- /dev/null +++ b/lib/ose/test/ose.cover @@ -0,0 +1,2 @@ +%% -*- erlang -*- +{incl_app,ose,details}. diff --git a/lib/ose/test/ose.spec b/lib/ose/test/ose.spec new file mode 100644 index 0000000000..c897e8cd16 --- /dev/null +++ b/lib/ose/test/ose.spec @@ -0,0 +1 @@ +{suites,"../ose_test",all}. diff --git a/lib/ose/test/ose_SUITE.erl b/lib/ose/test/ose_SUITE.erl new file mode 100644 index 0000000000..7e81b19894 --- /dev/null +++ b/lib/ose/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. |