diff options
Diffstat (limited to 'lib/ic/test/erl_client_c_server_SUITE.erl')
-rw-r--r-- | lib/ic/test/erl_client_c_server_SUITE.erl | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/lib/ic/test/erl_client_c_server_SUITE.erl b/lib/ic/test/erl_client_c_server_SUITE.erl new file mode 100644 index 0000000000..c5f5b6a218 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE.erl @@ -0,0 +1,350 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. 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% +%% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Test suite for erl-client/c-server +%%---------------------------------------------------------------------- + + +-module(erl_client_c_server_SUITE). +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2, all/1, void_test/1, + long_test/1, longlong_test/1, ushort_test/1, ulong_test/1, + ulonglong_test/1, double_test/1, char_test/1, wchar_test/1, + octet_test/1, bool_test/1, struct_test/1, struct2_test/1, + seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1, + seq5_test/1, array1_test/1, array2_test/1, enum_test/1, + string1_test/1, string2_test/1, string3_test/1, + string4_test/1, pid_test/1, port_test/1, ref_test/1, + term_test/1, typedef_test/1, inline_sequence_test/1, + term_sequence_test/1, term_struct_test/1, wstring1_test/1]). + +-define(DEFAULT_TIMEOUT, 20000). +-define(PORT_TIMEOUT, 15000). +-define(CALL_TIMEOUT, 5000). + +-define(C_SERVER_NODE_NAME, idl_c_server_test). + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i, we have + %% to make sure we are using the right m_i module. + code:purge(m_i), + code:load_file(m_i), + + WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + +all(doc) -> + "Test of IC with an Erlang client and a C server. " + "The communication is via Erlang distribution."; +all(suite) -> + [void_test, long_test, longlong_test, ushort_test, + ulong_test, ulonglong_test, double_test, + char_test, wchar_test, octet_test, bool_test, struct_test, + struct2_test, seq1_test, seq2_test, seq3_test, seq4_test, + seq5_test, array1_test, array2_test, enum_test, string1_test, + string2_test, string3_test, string4_test, pid_test, port_test, + ref_test, term_test, typedef_test, inline_sequence_test, + term_sequence_test, term_struct_test, wstring1_test]. + + +array1_test(doc) -> ""; +array1_test(suite) -> []; +array1_test(Config) -> + do_test(array1_test, Config). + +array2_test(doc) -> ""; +array2_test(suite) -> []; +array2_test(Config) -> + do_test(array2_test, Config). + +bool_test(doc) -> ""; +bool_test(suite) -> []; +bool_test(Config) -> + do_test(bool_test, Config). + +char_test(doc) -> ""; +char_test(suite) -> []; +char_test(Config) -> + do_test(char_test, Config). + +double_test(doc) -> ""; +double_test(suite) -> []; +double_test(Config) -> + do_test(double_test, Config). + +enum_test(doc) -> ""; +enum_test(suite) -> []; +enum_test(Config) -> + do_test(enum_test, Config). + +inline_sequence_test(doc) -> ""; +inline_sequence_test(suite) -> []; +inline_sequence_test(Config) -> + do_test(inline_sequence_test, Config). + +longlong_test(doc) -> ""; +longlong_test(suite) -> []; +longlong_test(Config) -> + do_test(longlong_test, Config). + +long_test(doc) -> ""; +long_test(suite) -> []; +long_test(Config) -> + do_test(long_test, Config). + +octet_test(doc) -> ""; +octet_test(suite) -> []; +octet_test(Config) -> + do_test(octet_test, Config). + +pid_test(doc) -> ""; +pid_test(suite) -> []; +pid_test(Config) -> + do_test(pid_test, Config). + +port_test(doc) -> ""; +port_test(suite) -> []; +port_test(Config) -> + do_test(port_test, Config). + +ref_test(doc) -> ""; +ref_test(suite) -> []; +ref_test(Config) -> + do_test(ref_test, Config). + +seq1_test(doc) -> ""; +seq1_test(suite) -> []; +seq1_test(Config) -> + do_test(seq1_test, Config). + +seq2_test(doc) -> ""; +seq2_test(suite) -> []; +seq2_test(Config) -> + do_test(seq2_test, Config). + +seq3_test(doc) -> ""; +seq3_test(suite) -> []; +seq3_test(Config) -> + do_test(seq3_test, Config). + +seq4_test(doc) -> ""; +seq4_test(suite) -> []; +seq4_test(Config) -> + do_test(seq4_test, Config). + +seq5_test(doc) -> ""; +seq5_test(suite) -> []; +seq5_test(Config) -> + do_test(seq5_test, Config). + +string1_test(doc) -> ""; +string1_test(suite) -> []; +string1_test(Config) -> + do_test(string1_test, Config). + +string2_test(doc) -> ""; +string2_test(suite) -> []; +string2_test(Config) -> + do_test(string2_test, Config). + +string3_test(doc) -> ""; +string3_test(suite) -> []; +string3_test(Config) -> + do_test(string3_test, Config). + +string4_test(doc) -> ""; +string4_test(suite) -> []; +string4_test(Config) -> + do_test(string4_test, Config). + +struct2_test(doc) -> ""; +struct2_test(suite) -> []; +struct2_test(Config) -> + do_test(struct2_test, Config). + +struct_test(doc) -> ""; +struct_test(suite) -> []; +struct_test(Config) -> + do_test(struct_test, Config). + +term_sequence_test(doc) -> ""; +term_sequence_test(suite) -> []; +term_sequence_test(Config) -> + do_test(term_sequence_test, Config). + +term_struct_test(doc) -> ""; +term_struct_test(suite) -> []; +term_struct_test(Config) -> + do_test(term_struct_test, Config). + +term_test(doc) -> ""; +term_test(suite) -> []; +term_test(Config) -> + do_test(term_test, Config). + +typedef_test(doc) -> ""; +typedef_test(suite) -> []; +typedef_test(Config) -> + do_test(typedef_test, Config). + +ulonglong_test(doc) -> ""; +ulonglong_test(suite) -> []; +ulonglong_test(Config) -> + do_test(ulonglong_test, Config). + +ulong_test(doc) -> ""; +ulong_test(suite) -> []; +ulong_test(Config) -> + do_test(ulong_test, Config). + +ushort_test(doc) -> ""; +ushort_test(suite) -> []; +ushort_test(Config) -> + do_test(ushort_test, Config). + +void_test(doc) -> ""; +void_test(suite) -> []; +void_test(Config) -> + do_test(void_test, Config). + +wchar_test(doc) -> ""; +wchar_test(suite) -> []; +wchar_test(Config) -> + do_test(wchar_test, Config). + +wstring1_test(doc) -> ""; +wstring1_test(suite) -> []; +wstring1_test(Config) -> + do_test(wstring1_test, Config). + + +do_test(Case, Config) -> + %% Trap exits + process_flag(trap_exit, true), + Node = atom_to_list(node()), + [_NodeName, HostName] = string:tokens(Node, "@"), + DataDir = ?config(data_dir, Config), + %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]), + Cookie = atom_to_list(erlang:get_cookie()), + ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME), + %% Start C-server node as a port program. We wait for the node + %% to connect to us. + Cmd = filename:join([DataDir, "c_server"]) ++ + " -this-node-name " ++ ServerNodeName ++ + " -peer-node " ++ Node ++ + " -cookie " ++ Cookie, + Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]), + ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName), + Res = case wait_for_hidden_node(ServerNode) of + ok -> + %% Need a port for port_test and typedef_test + put(port_test_port, Port), + R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)), + case wait_for_completion(Port) of + {error, timeout} -> + kill_off_node(ServerNode); + _ -> + ok + end, + R; + {error, timeout} -> + case wait_for_completion(Port) of + {error, timeout} -> + kill_off_node(ServerNode); + _ -> + ok + end, + {error, timeout} + end, + process_flag(trap_exit, false), + true = Res. + + +%% Wait for eof *and* exit status, but return if exit status indicates +%% an error, or we have been waiting more than PORT_TIMEOUT seconds. +%% +wait_for_completion(Port) -> + wait_for_completion(Port, 0). + +wait_for_completion(Port, N) when N < 2 -> + receive + {Port, {data, Bytes}} -> + %% Relay output + io:format("~s", [Bytes]), + wait_for_completion(Port, N); + {Port, {exit_status, 0}} -> + wait_for_completion(Port, N + 1); + {Port, {exit_status, Status}} -> + {error, Status}; + {Port, eof} -> + wait_for_completion(Port, N + 1); + {'EXIT', Port, Reason} -> + io:format("Port exited with reason: ~w~n", [Reason]), + wait_for_completion(Port, N); + {'EXIT', From, Reason} -> + io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]), + wait_for_completion(Port, N) + after ?PORT_TIMEOUT -> + {error, timeout} + end; +wait_for_completion(_, _) -> + ok. + +wait_for_hidden_node(Node) -> + Times = ?DEFAULT_TIMEOUT div 100, + wait_for_hidden_node(Node, Times, 100). + +wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 -> + io:format("Waiting for hidden node: ~p~n", [Node]), + case lists:member(Node, erlang:nodes(hidden)) of + true -> + ok; + false -> + delay(WaitTime), + wait_for_hidden_node(Node, Times - 1, WaitTime) + end; +wait_for_hidden_node(_Node, _, _WaitTime) -> + {error, timeout}. + +kill_off_node(Node) -> + catch rpc:cast(Node, erlang, halt, [1]). + +delay(Time) -> + receive + after Time -> + ok + end. + + + + |