137
153
%% ------------------ start ------------------------
155
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139
157
start_normal(suite) ->
141
start_normal(Config) when list(Config) ->
142
?ACQUIRE_NODES(1, Config),
159
start_normal(Config) when is_list(Config) ->
160
put(sname, "start_normal"),
161
p("BEGIN TEST-CASE"),
143
162
Options = [{port, 20000}, {receive_handle, apa}],
144
163
{ok, Pid} = start_case(Options, ok),
164
megaco_tcp:stop_transport(Pid),
169
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148
171
start_invalid_opt(suite) ->
150
start_invalid_opt(Config) when list(Config) ->
151
?ACQUIRE_NODES(1, Config),
173
start_invalid_opt(Config) when is_list(Config) ->
174
put(sname, "start_invalid_opt"),
175
p("BEGIN TEST-CASE"),
152
176
Options = [{port, 20000}, {receivehandle, apa}],
153
ok = start_case(Options, error).
177
ok = start_case(Options, error),
182
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184
start_and_stop(suite) ->
186
start_and_stop(doc) ->
187
["This test case sets up a connection and then cloises it. "
188
"No data is sent. "];
189
start_and_stop(Config) when is_list(Config) ->
190
put(sname, "start_and_stop"),
191
p("BEGIN TEST-CASE"),
193
process_flag(trap_exit, true),
196
ServerNode = make_node_name(server),
197
ClientNode = make_node_name(client),
198
Nodes = [ServerNode, ClientNode],
199
ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE),
201
%% Create command sequences
202
p("create command sequences"),
204
ServerCmds = start_and_stop_server_commands(ServerPort),
205
{ok, ServerHost} = inet:gethostname(),
206
ClientCmds = start_and_stop_client_commands(ServerPort, ServerHost),
208
%% Start the test procs used in the test-case, one for each node
209
p("start command handlers"),
210
Server = server_start_command_handler(ServerNode, ServerCmds),
211
p("server command handler started: ~p", [Server]),
212
Client = client_start_command_handler(ClientNode, ClientCmds),
213
p("client command handler started: ~p", [Client]),
217
{listening, Server} ->
218
p("received listening message from server [~p] => "
219
"send continue to client [~p]~n", [Server, Client]),
220
Client ! {continue, self()},
223
{error, server_timeout}
226
await_command_handler_completion([Server, Client], timer:seconds(20)),
231
start_and_stop_server_commands(Port) ->
232
Opts = [{port, Port}],
236
desc = "Command sequence init",
238
{ok, State#server{parent = Self}}
242
desc = "Start transport",
244
server_start_transport(State)
250
server_listen(State, Opts)
254
desc = "Notify listening",
256
server_notify_listening(State)
260
desc = "Await nothing",
262
server_await_nothing(State, 6000)
268
server_stop_transport(State)
274
start_and_stop_client_commands(ServerPort, ServerHost) ->
275
Opts = [{port, ServerPort}, {host, ServerHost}],
279
desc = "Command sequence init",
281
{ok, State#client{parent = Self}}
285
desc = "Start transport",
287
client_start_transport(State)
291
desc = "Await continue",
293
client_await_continue_signal(State, 5000)
299
client_connect(State, Opts)
303
desc = "Await nothing",
305
client_await_nothing(State, 5000)
311
client_disconnect(State)
315
desc = "Stop transport",
317
client_stop_transport(State)
156
322
%% ------------------ sending ------------------------
324
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158
326
sendreceive(suite) ->
160
sendreceive(Config) when list(Config) ->
161
?ACQUIRE_NODES(1, Config),
328
sendreceive(Config) when is_list(Config) ->
329
put(sname, "sendreceive"),
330
p("BEGIN TEST-CASE"),
332
process_flag(trap_exit, true),
335
ServerNode = make_node_name(server),
336
ClientNode = make_node_name(client),
337
Nodes = [ServerNode, ClientNode],
338
ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE),
340
%% Create command sequences
341
p("create command sequences"),
343
ServerCmds = sendreceive_server_commands(ServerPort),
344
{ok, ServerHost} = inet:gethostname(),
345
ClientCmds = sendreceive_client_commands(ServerPort, ServerHost),
347
%% Start the test procs used in the test-case, one for each node
348
p("start command handlers"),
349
Server = server_start_command_handler(ServerNode, ServerCmds),
350
p("server command handler started: ~p", [Server]),
351
Client = client_start_command_handler(ClientNode, ClientCmds),
352
p("client command handler started: ~p", [Client]),
356
{listening, Server} ->
357
p("received listening message from server [~p] => "
358
"send continue to client [~p]~n", [Server, Client]),
359
Client ! {continue, self()},
362
{error, server_timeout}
365
await_command_handler_completion([Server, Client], timer:seconds(20)),
370
sendreceive_server_commands(Port) ->
371
Opts = [{port, Port}],
375
desc = "Command sequence init",
377
{ok, State#server{parent = Self}}
381
desc = "Start transport",
383
server_start_transport(State)
389
server_listen(State, Opts)
393
desc = "Notify listening",
395
server_notify_listening(State)
399
desc = "Await initial message (ping)",
401
server_await_initial_message(State, "ping", 5000)
405
desc = "Send reply (pong) to initial message",
407
server_send_message(State, "pong")
411
desc = "Await nothing before sending a message (hejsan)",
413
server_await_nothing(State, 1000)
417
desc = "Send message (hejsan)",
419
server_send_message(State, "hejsan")
423
desc = "Await reply (hoppsan) to message",
425
server_await_message(State, "hoppsan", 1000)
429
desc = "Await nothing before disconnecting",
431
server_await_nothing(State, 1000)
437
server_disconnect(State)
441
desc = "Await nothing before stopping transport",
443
server_await_nothing(State, 1000)
449
server_stop_transport(State)
454
sendreceive_client_commands(ServerPort, ServerHost) ->
455
Opts = [{port, ServerPort}, {host, ServerHost}],
459
desc = "Command sequence init",
461
{ok, State#client{parent = Self}}
465
desc = "Start transport",
467
client_start_transport(State)
471
desc = "Await continue",
473
client_await_continue_signal(State, 5000)
479
client_connect(State, Opts)
483
desc = "Send initial message (ping)",
485
client_send_message(State, "ping")
489
desc = "Await reply (pong) to initial message",
491
client_await_message(State, "pong", 1000)
495
desc = "Await message (hejsan)",
497
client_await_message(State, "hejsan", 5000)
501
desc = "Send reply (hoppsan) to message",
503
client_send_message(State, "hoppsan")
507
desc = "Await nothing before disconnecting",
509
client_await_nothing(State, 1000)
515
client_disconnect(State)
519
desc = "Await nothing before stopping transport",
521
client_await_nothing(State, 1000)
525
desc = "Stop transport",
527
client_stop_transport(State)
533
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535
block_unblock(suite) ->
537
block_unblock(Config) when is_list(Config) ->
538
put(sname, "block_unblock"),
539
p("BEGIN TEST-CASE"),
541
process_flag(trap_exit, true),
544
ServerNode = make_node_name(server),
545
ClientNode = make_node_name(client),
546
Nodes = [ServerNode, ClientNode],
547
ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE),
549
%% Create command sequences
550
p("create command sequences"),
552
ServerCmds = block_unblock_server_commands(ServerPort),
553
{ok, ServerHost} = inet:gethostname(),
554
ClientCmds = block_unblock_client_commands(ServerPort, ServerHost),
556
%% Start the test procs used in the test-case, one for each node
557
p("start command handlers"),
558
Server = server_start_command_handler(ServerNode, ServerCmds),
559
p("server command handler started: ~p", [Server]),
560
Client = client_start_command_handler(ClientNode, ClientCmds),
561
p("client command handler started: ~p", [Client]),
565
{listening, Server} ->
566
p("received listening message from server [~p] => "
567
"send continue to client [~p]~n", [Server, Client]),
568
Client ! {continue, self()},
571
{error, server_timeout}
577
p("received blocked message from client [~p] => "
578
"send continue to server [~p]~n", [Client, Server]),
579
Server ! {continue, self()},
585
await_command_handler_completion([Server, Client], timer:seconds(30)),
590
block_unblock_server_commands(Port) ->
591
Opts = [{port, Port}],
595
desc = "Command sequence init",
597
{ok, State#server{parent = Self}}
601
desc = "Start transport",
603
server_start_transport(State)
609
server_listen(State, Opts)
613
desc = "Notify listening",
615
server_notify_listening(State)
619
desc = "Await initial message (ping)",
621
server_await_initial_message(State, "ping", 5000)
625
desc = "Send reply (pong) to initial message",
627
server_send_message(State, "pong")
631
desc = "Await continue",
633
server_await_continue_signal(State, 5000)
637
desc = "Await nothing before sending a message (hejsan)",
639
server_await_nothing(State, 1000)
643
desc = "Send message (hejsan)",
645
server_send_message(State, "hejsan")
649
desc = "Await reply (hoppsan) to message",
651
server_await_message(State, "hoppsan", 10000)
655
desc = "Await nothing before disconnecting",
657
server_await_nothing(State, 1000)
663
server_disconnect(State)
667
desc = "Await nothing before stopping transport",
669
server_await_nothing(State, 1000)
675
server_stop_transport(State)
680
block_unblock_client_commands(ServerPort, ServerHost) ->
681
Opts = [{port, ServerPort}, {host, ServerHost}],
685
desc = "Command sequence init",
687
{ok, State#client{parent = Self}}
691
desc = "Start transport",
693
client_start_transport(State)
697
desc = "Await continue",
699
client_await_continue_signal(State, 5000)
705
client_connect(State, Opts)
709
desc = "Send initial message (ping)",
711
client_send_message(State, "ping")
715
desc = "Await reply (pong) to initial message",
717
client_await_message(State, "pong", 1000)
721
desc = "Await nothing before blocking",
723
client_await_nothing(State, 1000)
733
desc = "Notify blocked",
735
client_notify_blocked(State)
739
desc = "Await nothing before unblocking",
741
client_await_nothing(State, 5000)
747
client_unblock(State)
751
desc = "Await message (hejsan)",
753
client_await_message(State, "hejsan", 100)
757
desc = "Send reply (hoppsan) to message",
759
client_send_message(State, "hoppsan")
763
desc = "Await nothing before disconnecting",
765
client_await_nothing(State, 1000)
771
client_disconnect(State)
775
desc = "Await nothing before stopping transport",
777
client_await_nothing(State, 1000)
781
desc = "Stop transport",
783
client_stop_transport(State)
165
789
%% ------------------ errors ------------------------
791
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793
socket_failure(suite) ->
169
socket(Config) when list(Config) ->
170
?ACQUIRE_NODES(1, Config),
795
socket_failure(Config) when is_list(Config) ->
796
put(sname, "socket_failure"),
797
p("BEGIN TEST-CASE"),
799
%% process_flag(trap_exit, true),
804
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173
806
accept_process(suite) ->
175
accept_process(Config) when list(Config) ->
176
?ACQUIRE_NODES(1, Config),
808
accept_process(Config) when is_list(Config) ->
809
put(sname, "accept_process"),
810
p("BEGIN TEST-CASE"),
812
%% process_flag(trap_exit, true),
177
814
failing_accept_process().
817
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179
819
accept_supervisor(suite) ->
181
accept_supervisor(Config) when list(Config) ->
182
?ACQUIRE_NODES(1, Config),
821
accept_supervisor(Config) when is_list(Config) ->
822
put(sname, "accept_supervisor"),
823
p("BEGIN TEST-CASE"),
825
%% process_flag(trap_exit, true),
183
827
failing_accept_supervisor().
830
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185
832
connection_supervisor(suite) ->
187
connection_supervisor(Config) when list(Config) ->
188
?ACQUIRE_NODES(1, Config),
834
connection_supervisor(Config) when is_list(Config) ->
835
put(sname, "connection_supervisor"),
836
p("BEGIN TEST-CASE"),
838
%% process_flag(trap_exit, true),
189
840
failing_connection_supervisor().
843
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191
845
tcp_server(suite) ->
193
tcp_server(Config) when list(Config) ->
194
?ACQUIRE_NODES(1, Config),
847
tcp_server(Config) when is_list(Config) ->
848
put(sname, "tcp_server"),
849
p("BEGIN TEST-CASE"),
851
%% process_flag(trap_exit, true),
195
853
failing_tcp_server().
240
903
?SKIP(not_yet_implemented).
906
%%----------------------------------------------------------------------
907
%% Message Callback functions
908
%%----------------------------------------------------------------------
910
receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg)
911
when is_pid(ReceiveHandle) andalso is_binary(BinMsg) ->
912
Msg = binary_to_list(BinMsg),
913
ReceiveHandle ! {receive_message, {ControlPid, SendHandle, Msg}},
916
process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg)
917
when is_pid(ReceiveHandle) andalso is_binary(BinMsg) ->
918
Msg = binary_to_list(BinMsg),
919
ReceiveHandle ! {process_received_message, {ControlPid, SendHandle, Msg}},
243
923
%%======================================================================
244
924
%% Internal functions
245
925
%%======================================================================
246
% compute_res(All) ->
247
% compute_res(All, [], 0).
249
% compute_res([H | T], Bad, Sum) when integer(H) ->
250
% compute_res(T, Bad, Sum + H);
251
% compute_res([H | T], Bad, Sum) ->
252
% compute_res(T, [H | Bad], Sum);
253
% compute_res([], Bad, Sum) ->
254
% ok = io:format("#bytes: ~w; errors: ~p~n", [Sum, Bad]).
927
%% ------- Server command handler and utility functions ----------
929
server_start_command_handler(Node, Commands) ->
930
start_command_handler(Node, Commands, #server{}, "server").
932
server_start_transport(State) when is_record(State, server) ->
933
case (catch megaco_tcp:start_transport()) of
935
{ok, State#server{transport_ref = Ref}};
940
server_listen(#server{transport_ref = Ref} = State, Options)
941
when is_record(State, server) andalso is_list(Options) ->
942
Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
943
case (catch megaco_tcp:listen(Ref, Opts)) of
950
server_notify_listening(#server{parent = Parent} = State)
951
when is_record(State, server) ->
952
Parent ! {listening, self()},
955
server_await_continue_signal(#server{parent = Parent} = State, Timeout) ->
957
{continue, Parent} ->
963
server_await_initial_message(State, InitialMessage, Timeout)
964
when is_record(State, server) ->
966
{receive_message, {ControlPid, Handle, InitialMessage}} ->
967
NewState = State#server{control_pid = ControlPid,
972
p("received unexpected event: ~p", [Any]),
973
{error, {unexpected_event, Any}}
979
server_send_message(#server{handle = Handle} = State, Message) ->
980
megaco_tcp:send_message(Handle, Message),
983
server_await_nothing(State, Timeout)
984
when is_record(State, server) ->
987
p("received unexpected event: ~p", [Any]),
988
{error, {unexpected_event, Any}}
995
server_await_message(State, ExpectMessage, Timeout)
996
when is_record(State, server) ->
998
{receive_message, {_, _, ExpectMessage}} ->
1002
p("received unexpected event: ~p", [Any]),
1003
{error, {unexpected_event, Any}}
1009
server_disconnect(#server{handle = Handle} = State)
1010
when (Handle =/= undefined) ->
1011
megaco_tcp:close(Handle),
1012
{ok, State#server{handle = undefined}}.
1014
server_block(#server{handle = Handle} = State)
1015
when (Handle =/= undefined) ->
1016
megaco_tcp:block(Handle),
1019
server_unblock(#server{handle = Handle} = State)
1020
when (Handle =/= undefined) ->
1021
megaco_tcp:unblock(Handle),
1024
server_stop_transport(#server{transport_ref = Ref} = State)
1025
when (Ref =/= undefined) ->
1026
megaco_tcp:stop_transport(Ref),
1030
%% ------- Client command handler and utility functions ----------
1032
client_start_command_handler(Node, Commands) ->
1033
start_command_handler(Node, Commands, #client{}, "client").
1035
client_start_transport(State) when is_record(State, client) ->
1036
case (catch megaco_tcp:start_transport()) of
1038
{ok, State#client{transport_ref = Ref}};
1043
client_connect(#client{transport_ref = Ref} = State, Options)
1044
when is_record(State, client) andalso is_list(Options) ->
1045
Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
1046
case (catch megaco_tcp:connect(Ref, Opts)) of
1047
{ok, Handle, ControlPid} ->
1048
{ok, State#client{control_pid = ControlPid,
1054
client_await_continue_signal(#client{parent = Parent} = State, Timeout) ->
1056
{continue, Parent} ->
1062
client_notify_blocked(#client{parent = Parent} = State) ->
1063
Parent ! {blocked, self()},
1066
client_await_nothing(State, Timeout)
1067
when is_record(State, client) ->
1070
p("received unexpected event: ~p", [Any]),
1071
{error, {unexpected_event, Any}}
1076
client_send_message(#client{handle = Handle} = State, Message) ->
1077
megaco_tcp:send_message(Handle, Message),
1080
client_await_message(State, ExpectMessage, Timeout)
1081
when is_record(State, client) ->
1083
{receive_message, {_, _, ExpectMessage}} ->
1087
p("received unexpected event: ~p", [Any]),
1088
{error, {unexpected_event, Any}}
1094
client_block(#client{handle = Handle} = State)
1095
when (Handle =/= undefined) ->
1096
megaco_tcp:block(Handle),
1099
client_unblock(#client{handle = Handle} = State)
1100
when (Handle =/= undefined) ->
1101
megaco_tcp:unblock(Handle),
1104
client_disconnect(#client{handle = Handle} = State)
1105
when (Handle =/= undefined) ->
1106
megaco_tcp:close(Handle),
1107
{ok, State#client{handle = undefined, control_pid = undefined}}.
1109
client_stop_transport(#client{transport_ref = Ref} = State)
1110
when (Ref =/= undefined) ->
1111
megaco_tcp:stop_transport(Ref),
1115
%% -------- Command handler ---------
1117
start_command_handler(Node, Commands, State, ShortName) ->
1119
put(sname, ShortName),
1120
process_flag(trap_exit, true),
1121
Result = (catch command_handler(Commands, State)),
1122
p("command handler terminated with: "
1123
"~n Result: ~p", [Result]),
1126
erlang:spawn_link(Node, Fun).
1128
command_handler([], State) ->
1129
p("command_handler -> entry when done with"
1130
"~n State: ~p", [State]),
1132
command_handler([#command{id = Id,
1134
cmd = Cmd}|Commands], State) ->
1135
p("command_handler -> entry with"
1137
"~n Desc: ~p", [Id, Desc]),
1138
case (catch Cmd(State)) of
1140
p("command_handler -> cmd ~w ok", [Id]),
1141
command_handler(Commands, NewState);
1143
p("command_handler -> cmd ~w error: "
1144
"~n Reason: ~p", [Id, Reason]),
1145
{error, {cmd_error, Reason}};
1147
p("command_handler -> cmv ~w exit: "
1148
"~n Reason: ~p", [Id, Reason]),
1149
{error, {cmd_exit, Reason}};
1151
p("command_handler -> cmd ~w failure: "
1152
"~n Error: ~p", [Id, Error]),
1153
{error, {cmd_failure, Error}}
1157
await_command_handler_completion(Pids, Timeout) ->
1158
await_command_handler_completion(Pids, [], [], Timeout).
1160
await_command_handler_completion([], [], _Good, _Timeout) ->
1161
p("await_command_handler_completion -> entry when done"),
1163
await_command_handler_completion([], Bad, Good, _Timeout) ->
1164
p("await_command_handler_completion -> entry when done with bad result: "
1166
"~n Good: ~p", [Bad, Good]),
1168
await_command_handler_completion(Pids, Bad, Good, Timeout) ->
1169
p("await_command_handler_completion -> entry when waiting for"
1173
"~n Timeout: ~p", [Pids, Bad, Good, Timeout]),
1176
{'EXIT', Pid, {ok, FinalState}} ->
1177
p("await_command_handler_completion -> "
1178
"received ok EXIT signal from ~p", [Pid]),
1179
case lists:delete(Pid, Pids) of
1181
await_command_handler_completion(Pids, Bad, Good,
1182
Timeout - (ms() - Begin));
1184
p("await_command_handler_completion -> ~p done", [Pid]),
1185
await_command_handler_completion(Pids2,
1187
[{Pid, FinalState}|Good],
1188
Timeout - (ms() - Begin))
1191
{'EXIT', Pid, {error, Reason}} ->
1192
p("await_command_handler_completion -> "
1193
"received error EXIT signal from ~p", [Pid]),
1194
case lists:delete(Pid, Pids) of
1196
await_command_handler_completion(Pids, Bad, Good,
1197
Timeout - (ms() - Begin));
1199
p("await_command_handler_completion -> ~p done", [Pid]),
1200
await_command_handler_completion(Pids2,
1201
[{Pid, Reason}|Bad],
1203
Timeout - (ms() - Begin))
1207
p("await_command_handler_completion -> timeout"),
1208
exit({timeout, Pids})
1213
%% ------- Misc functions --------
1215
make_node_name(Name) ->
1216
case string:tokens(atom_to_list(node()), [$@]) of
1218
list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host]));
1220
exit("Test node must be started with '-sname'")
1228
p(get(sname), F, A).
1230
p(S, F, A) when is_list(S) ->
1231
io:format("*** [~s] ~p ~s ***"
1233
[format_timestamp(now()), self(), S | A]);
1235
io:format("*** [~s] ~p ~s *** "
1237
[format_timestamp(now()), self(), "undefined" | A]).
1241
{A,B,C} = erlang:now(),
1242
A*1000000000+B*1000+(C div 1000).
1245
format_timestamp({_N1, _N2, N3} = Now) ->
1246
{Date, Time} = calendar:now_to_datetime(Now),
1247
{YYYY,MM,DD} = Date,
1248
{Hour,Min,Sec} = Time,
1250
io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
1251
[YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
1252
lists:flatten(FormatDate).