diff options
157 files changed, 7724 insertions, 4411 deletions
diff --git a/.travis.yml b/.travis.yml index 51453639b0..5a87bd3fd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -100,8 +100,8 @@ matrix: api_key: secure: vW5PN6zng5H5+TCvwfwpGZsABrdCWYcFwDm3KXq+plsecBmTayu/0jgNso5Z97FbzDGVTLHWchvywEYQWnmrEByyOrqH73v1LN6JEfN99VpSrdFr15IzhblcyU1R9ugYc3WEoYjX0Q1uGelDSWRuuQOPbzy8mZf3D4rSGonyraP7jPTdHhs5P3ZWk6OMFz+tCdF4XohXqbhXIBOeH/EKg0svX2u5IcV01/YOL8LHWz6G7+gqBryEXx1+ngjQXQmMQwd7Yg3WOKE4XV9gX8ixZsbpUPZXAQKF+VOYdEgeiIr1hI0tBQUYX7FYEzYH5MCxqng5RdaPTOAm1oQroyGkIcWSXzDwN4AhJ7xqa/0NRdEaBPdQzPBCc+pVUDkxBR1ytXjBQqdQMnI6184TDiU5XBnj3kmieLkkKPKQNoPve/Y8Q8zutw4GNc7gixGcQCjtAFUbrT73QVRrezQH0qIdt23rivvf2R7CCOWSmgzowrswmtHdgeEVbodUIBPTNp7qzlUk9gDp6vW0XrOC4qEFI+VaY5PsEOXrrxZmI3gGGJgsbfzRvzvvupQcLNERniJ67r/uumbForpL0x1c65scKuMWwcn1wqt2OLbDoIIuM31Ph2HX/09TTqECU7CTvqLT5MnbZHXGjY9c3ch+sY3tSfaEX6aazl/Dqx28c7boCEw= file: - - ${TRAVIS_TAG}-bundle.txt - - ${TRAVIS_TAG}-bundle.tar.gz + - ${TRAVIS_TAG}.0-bundle.txt + - ${TRAVIS_TAG}.0-bundle.tar.gz on: # We only deploy on pushes to tags that match the regexp tags: true diff --git a/OTP_VERSION b/OTP_VERSION index a5a5c04503..3abee4573a 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.2.7 +22.2.8 diff --git a/erts/doc/src/alt_disco.xml b/erts/doc/src/alt_disco.xml index 067eb4992d..d95e62bc8a 100644 --- a/erts/doc/src/alt_disco.xml +++ b/erts/doc/src/alt_disco.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2018</year><year>2018</year> + <year>2018</year><year>2019</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -22,7 +22,7 @@ </legalnotice> - <title>How to Implement an Alternative Service Discovery for Erlang Distribution + <title>How to Implement an Alternative Node Discovery for Erlang Distribution </title> <prepared>Timmo Verlaan</prepared> <responsible></responsible> @@ -34,20 +34,20 @@ <file>alt_disco.xml</file> </header> <p> - This section describes how to implement an alternative discovery mechanism - for Erlang distribution. Discovery is normally done using DNS and the - Erlang Port Mapper Daemon (EPMD) for port discovery. + This section describes how to implement an alternative node discovery + mechanism for Erlang distribution. Node discovery is normally done using DNS + and the Erlang Port Mapper Daemon (EPMD) for port registration and lookup. </p> <note><p> - Support for alternative service discovery mechanisms was added in Erlang/OTP + Support for alternative node discovery mechanisms was added in Erlang/OTP 21. </p></note> <section> <title>Introduction</title> - <p>To implement your own service discovery module you have to write your own + <p>To implement your own node discovery module you have to write your own EPMD module. The <seealso marker="kernel:erl_epmd">EPMD module</seealso> is responsible for providing the location of another node. The distribution modules (<c>inet_tcp_dist</c>/<c>inet_tls_dist</c>) call the EPMD module to diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml index 311483022d..75353cbc07 100644 --- a/erts/doc/src/epmd.xml +++ b/erts/doc/src/epmd.xml @@ -72,6 +72,12 @@ therefore required for an Erlang network to function correctly.</p> + <note><p>On Windows the maximum number of nodes allowed in one + epmd instance is 60. This is because of limitations in the current + implementation. If you need more nodes, you should look into using + and erlang based epmd implementation such as + <url href="https://github.com/erlang/epmd">Erlang EPMD</url>.</p></note> + <taglist> <tag>Starting the port mapper daemon</tag> <item> diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index ed1b0880b4..a37707f7f9 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -575,7 +575,11 @@ <tag><marker id="async_thread_pool_size"/><c><![CDATA[+A size]]></c></tag> <item> <p>Sets the number of threads in async thread pool. Valid range - is 0-1024. Defaults to 1.</p> + is 0-1024. The async thread pool is used by linked-in drivers to + handle work that may take a very long time. Since OTP-21 there are + very few linked-in drivers in the default Erlang/OTP distribution + that uses the async thread pool. Most of them have been migrated to + dirty IO schedulers. Defaults to 1.</p> </item> <tag><c><![CDATA[+B [c | d | i]]]></c></tag> <item> @@ -1015,6 +1019,12 @@ executing on ordinary schedulers. If the amount of dirty CPU schedulers was allowed to be unlimited, dirty CPU bound jobs would potentially starve normal jobs.</p> + <p>Typical users of the dirty CPU schedulers are large garbage collections, + json protocol encode/decoders written as nifs and matrix manipulation + libraries.</p> + <p>You can use <seealso marker="runtime_tools:msacc">msacc(3)</seealso> + in order to see the current load of the dirty CPU schedulers threads + and adjust the number used accordingly.</p> </item> <tag><marker id="+SDPcpu"/><c><![CDATA[+SDPcpu DirtyCPUSchedulersPercentage:DirtyCPUSchedulersOnlinePercentage]]></c></tag> @@ -1043,16 +1053,18 @@ <tag><marker id="+SDio"/><c><![CDATA[+SDio DirtyIOSchedulers]]></c></tag> <item> <p>Sets the number of dirty I/O scheduler threads to create. - Valid range is 0-1024. By - default, the number of dirty I/O scheduler threads created is 10, - same as the default number of threads in the <seealso - marker="#async_thread_pool_size">async thread pool</seealso>.</p> + Valid range is 1-1024. By + default, the number of dirty I/O scheduler threads created is 10.</p> <p>The amount of dirty IO schedulers is not limited by the amount of normal schedulers <seealso marker="#+SDcpu">like the amount of dirty CPU schedulers</seealso>. This since only I/O bound work is expected to execute on dirty I/O schedulers. If the user should schedule CPU bound jobs on dirty I/O schedulers, these jobs might starve ordinary jobs executing on ordinary schedulers.</p> + <p>Typical users of the dirty IO schedulers are reading and writing to files.</p> + <p>You can use <seealso marker="runtime_tools:msacc">msacc(3)</seealso> + in order to see the current load of the dirty IO schedulers threads + and adjust the number used accordingly.</p> </item> <tag><c><![CDATA[+sFlag Value]]></c></tag> <item> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 7fa61d0195..48208574d1 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2018</year> + <year>2004</year><year>2019</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1546,6 +1546,45 @@ </section> +<section><title>Erts 10.3.5.10</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug in <c>ets:update_counter/4</c>, when called + with an invalid <c>UpdateOp</c> and a <c>Key</c> that + does not exist, causing <c>ets:info(T,size)</c> to return + incorrect values. Bug exists since OTP-19.0.2.</p> + <p> + Own Id: OTP-16404 Aux Id: ERL-1127 </p> + </item> + <item> + <p> + A process could get into an inconsistent state where it + was runnable, but never scheduled for execution. This + could occur when a mix of <c>normal</c> and <c>low</c> + priority processes where scheduled on the same type of + dirty scheduler simultaneously.</p> + <p> + Own Id: OTP-16446 Aux Id: ERL-1157 </p> + </item> + <item> + <p> + Corrected the valid range of the <c>erl</c> command line + argument <seealso marker="erts:erl#+SDio"><c>+SDio + <NumberOfDirtyIoSchedulers></c></seealso> from + <c>0..1024</c> to <c>1..1024</c>. <c>+SDio 0</c> was + erroneously allowed which just caused the VM to crash on + the first dirty I/O job scheduled.</p> + <p> + Own Id: OTP-16481</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 10.3.5.9</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -3865,7 +3904,7 @@ marker="kernel:erl_epmd"><c>erl_epmd</c></seealso> reference manual and ERTS User's Guide <seealso marker="erts:alt_disco">How to Implement an Alternative - Service Discovery for Erlang Distribution</seealso>.</p> + Node Discovery for Erlang Distribution</seealso>.</p> <p> Own Id: OTP-15086 Aux Id: PR-1694 </p> </item> @@ -3874,6 +3913,69 @@ </section> +<section><title>Erts 9.3.3.15</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A process could end up in a state where it got endlessly + rescheduled without making any progress. This occurred + when a system task, such as check of process code (part + of a code purge), was scheduled on a high priority + process trying to execute on a dirty scheduler.</p> + <p> + Own Id: OTP-16436 Aux Id: ERL-1152 </p> + </item> + <item> + <p> + Fixed bug in <c>erlang:list_to_ref/1</c> when called with + a reference created by a remote note. Function + <c>list_to_ref/1</c> is intended for debugging and not to + be used in application programs. Bug exist since OTP + 20.0.</p> + <p> + Own Id: OTP-16438</p> + </item> + <item> + <p> + A process could get into an inconsistent state where it + was runnable, but never scheduled for execution. This + could occur when a mix of <c>normal</c> and <c>low</c> + priority processes where scheduled on the same type of + dirty scheduler simultaneously.</p> + <p> + Own Id: OTP-16446 Aux Id: ERL-1157 </p> + </item> + <item> + <p> + Fixed erroneous mapping of exit reason from <c>kill</c> + to <c>killed</c> on reception of some exit signals due to + a broken link. This bug has existed since ERTS version + 5.5.2 (OTP R11).</p> + <p> + This bug was also unknowingly fixed in ERTS version 10.0 + (OTP 21.0) due to a new ERTS internal implementation of + signaling between processes.</p> + <p> + Own Id: OTP-16465 Aux Id: ERL-1165, OTP-6160, OTP-14589 </p> + </item> + <item> + <p> + Corrected the valid range of the <c>erl</c> command line + argument <seealso marker="erts:erl#+SDio"><c>+SDio + <NumberOfDirtyIoSchedulers></c></seealso> from + <c>0..1024</c> to <c>1..1024</c>. <c>+SDio 0</c> was + erroneously allowed which just caused the VM to crash on + the first dirty I/O job scheduled.</p> + <p> + Own Id: OTP-16481</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 9.3.3.14</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index 6379e4e04d..c1af14cc89 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -578,8 +578,8 @@ do_break(void) ASSERT(erts_thr_progress_is_blocking()); erts_printf("\n" - "BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded\n" - " (v)ersion (k)ill (D)b-tables (d)istribution\n"); + "BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo\n" + " (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution\n"); while (1) { if ((i = sys_get_key(0)) <= 0) diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 547e4064a2..5f0352f5c0 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -694,7 +694,7 @@ void erts_usage(void) erts_fprintf(stderr, "-SDPcpu p1:p2 specify dirty CPU schedulers (p1) and dirty CPU schedulers\n"); erts_fprintf(stderr, " online (p2) as percentages of logical processors configured\n"); erts_fprintf(stderr, " and logical processors available, respectively\n"); - erts_fprintf(stderr, "-SDio n set number of dirty I/O schedulers, valid range is [0-%d]\n", + erts_fprintf(stderr, "-SDio n set number of dirty I/O schedulers, valid range is [1-%d]\n", ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS); erts_fprintf(stderr, "-t size set the maximum number of atoms the emulator can handle\n"); erts_fprintf(stderr, " valid range is [%d-%d]\n", @@ -1054,7 +1054,7 @@ early_init(int *argc, char **argv) /* } else if (sys_strncmp(type, "io", 2) == 0) { arg = get_arg(argv[i]+5, argv[i+1], &i); dirty_io_scheds = atoi(arg); - if (dirty_io_scheds < 0 || + if (dirty_io_scheds < 1 || dirty_io_scheds > ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS) { erts_fprintf(stderr, "bad number of dirty I/O schedulers %s\n", diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index ab95748458..fbda73d518 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -6770,7 +6770,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, if ((argc != 4) || !GET_BIN(env, argv[2], &sndData) || !GET_UINT(env, argv[3], &eflags)) { - SSDBG( descP, ("SOCKET", "nif_send -> argv decode failed\r\n") ); + SGDBG( ("SOCKET", "nif_send -> argv decode failed\r\n") ); return enif_make_badarg(env); } sockRef = argv[0]; // We need this in case we send in case we send abort @@ -6909,7 +6909,7 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, if ((argc != 5) || !GET_BIN(env, argv[2], &sndData) || !GET_UINT(env, argv[4], &eflags)) { - SSDBG( descP, ("SOCKET", "nif_sendto -> argv decode failed\r\n") ); + SGDBG( ("SOCKET", "nif_sendto -> argv decode failed\r\n") ); return enif_make_badarg(env); } sockRef = argv[0]; // We need this in case we send abort (to the caller) @@ -7047,7 +7047,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, if ((argc != 4) || !IS_MAP(env, argv[2]) || !GET_UINT(env, argv[3], &eflags)) { - SSDBG( descP, ("SOCKET", "nif_sendmsg -> argv decode failed\r\n") ); + SGDBG( ("SOCKET", "nif_sendmsg -> argv decode failed\r\n") ); return enif_make_badarg(env); } sockRef = argv[0]; // We need this in case we send abort (to the caller) diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index bce4ae1a5f..a263ac87bc 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -2234,6 +2234,25 @@ analyze_and_print_freebsd_host_info(Version) -> +init_per_group(GroupName, Config) + when (GroupName =:= sc_remote_close) orelse + (GroupName =:= sc_remote_shutdown) orelse + (GroupName =:= traffic) -> + io:format("init_per_group(~w) -> entry with" + "~n Config: ~p" + "~n", [GroupName, Config]), + %% Maybe we should skip the entire suite for this platform, + %% but for now we just skip these groups, which seem to + %% have problems (slave node start). + %% As stated elsewhere, its not really Fedora 16, but + %% the *really* slow VM that is the issue. + try is_old_fedora16() of + ok -> + Config + catch + throw:{skip, _} = SKIP -> + SKIP + end; init_per_group(ttest = _GroupName, Config) -> io:format("init_per_group(~w) -> entry with" "~n Config: ~p" @@ -24427,7 +24446,9 @@ sc_lc_recvfrom_response_udpL(_Config) when is_list(_Config) -> tc_try(sc_lc_recvfrom_response_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> - Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, + Recv = fun(Sock, To) -> + socket:recvfrom(Sock, [], To) + end, InitState = #{domain => local, protocol => default, recv => Recv}, @@ -24461,8 +24482,20 @@ sc_lc_receive_response_udp(InitState) -> #{desc => "open socket", cmd => fun(#{domain := Domain, protocol := Proto} = State) -> Sock = sock_open(Domain, dgram, Proto), - SA = sock_sockname(Sock), - {ok, State#{sock => Sock, sa => SA}} + %% SA = sock_sockname(Sock), + case socket:sockname(Sock) of + {ok, SA} -> + {ok, State#{sock => Sock, sa => SA}}; + {error, eafnosupport = Reason} -> + ?SEV_IPRINT("Failed get socket name: " + "~n ~p", [Reason]), + (catch socket:close(Sock)), + {skip, Reason}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed get socket name: " + "~n ~p", [Reason]), + ERROR + end end}, #{desc => "bind socket", cmd => fun(#{sock := Sock, local_sa := LSA}) -> diff --git a/erts/emulator/test/socket_test_lib.erl b/erts/emulator/test/socket_test_lib.erl index 39cbf0c79f..f05796cbcf 100644 --- a/erts/emulator/test/socket_test_lib.erl +++ b/erts/emulator/test/socket_test_lib.erl @@ -194,49 +194,34 @@ which_local_host_info(Domain) -> which_local_host_info(_Domain, []) -> {error, no_address}; -which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) -> - which_local_host_info(Domain, IFL); which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) -> which_local_host_info(Domain, IFL); which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) -> which_local_host_info(Domain, IFL); which_local_host_info(Domain, [{Name, IFO}|IFL]) -> - try which_local_host_info2(Domain, IFO) of - Info -> - {ok, Info#{name => Name}} - catch - throw:_:_ -> + case if_is_running_and_not_loopback(IFO) of + true -> + try which_local_host_info2(Domain, IFO) of + Info -> + {ok, Info#{name => Name}} + catch + throw:_:_ -> + which_local_host_info(Domain, IFL) + end; + false -> which_local_host_info(Domain, IFL) end; which_local_host_info(Domain, [_|IFL]) -> which_local_host_info(Domain, IFL). -%% which_local_host_info2(Domain, IFO) -> -%% case lists:keysearch(flags, 1, IFO) of -%% {value, {flags, Flags}} -> -%% which_local_host_info2(Domain, IFO, Flags); -%% false -> -%% {error, no_flags} -%% end. - - -%% which_local_host_info2(_Domain, [], _Flags) -> -%% {error, no_address}; -%% which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) -%% when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> -%% {ok, {Flags, Addr}}; -%% which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) -%% when (size(Addr) =:= 8) andalso -%% (element(1, Addr) =/= 0) andalso -%% (element(1, Addr) =/= 16#fe80) -> -%% {ok, {Flags, Addr}}; -%% which_local_host_info2(Domain, [_|IFO], Flags) -> -%% which_local_host_info2(Domain, IFO, Flags). - -%% foo(Info, inet = Domain, IFO) -> -%% foo(Info, Domain, IFO, [flags, addr, netmask, broadaddr, hwaddr]); -%% foo(Info, inet6 = Domain, IFO) -> -%% foo(Info, Domain, IFO, [flags, addr, netmask, hwaddr]). +if_is_running_and_not_loopback(If) -> + lists:keymember(flags, 1, If) andalso + begin + {value, {flags, Flags}} = lists:keysearch(flags, 1, If), + (not lists:member(loopback, Flags)) andalso + lists:member(running, Flags) + end. + which_local_host_info2(inet = _Domain, IFO) -> Addr = which_local_host_info3(addr, IFO, diff --git a/erts/preloaded/ebin/atomics.beam b/erts/preloaded/ebin/atomics.beam Binary files differindex 610264de8f..aa246f8808 100644 --- a/erts/preloaded/ebin/atomics.beam +++ b/erts/preloaded/ebin/atomics.beam diff --git a/erts/preloaded/ebin/counters.beam b/erts/preloaded/ebin/counters.beam Binary files differindex df4a3dce2d..1fb85276f9 100644 --- a/erts/preloaded/ebin/counters.beam +++ b/erts/preloaded/ebin/counters.beam diff --git a/erts/preloaded/ebin/erl_init.beam b/erts/preloaded/ebin/erl_init.beam Binary files differindex 511f38624d..04559ff767 100644 --- a/erts/preloaded/ebin/erl_init.beam +++ b/erts/preloaded/ebin/erl_init.beam diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex 7723e420fe..b8adf71297 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erl_tracer.beam b/erts/preloaded/ebin/erl_tracer.beam Binary files differindex 18a06a7446..4430489710 100644 --- a/erts/preloaded/ebin/erl_tracer.beam +++ b/erts/preloaded/ebin/erl_tracer.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 1f8d94d547..b744d97a41 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_code_purger.beam b/erts/preloaded/ebin/erts_code_purger.beam Binary files differindex 16b1930635..a94b37854e 100644 --- a/erts/preloaded/ebin/erts_code_purger.beam +++ b/erts/preloaded/ebin/erts_code_purger.beam diff --git a/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam b/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam Binary files differindex b67b682a6d..dd92fb9582 100644 --- a/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam +++ b/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex bf5193729b..d52ae9a2dc 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/erts_literal_area_collector.beam b/erts/preloaded/ebin/erts_literal_area_collector.beam Binary files differindex 72d347f401..44103e5d56 100644 --- a/erts/preloaded/ebin/erts_literal_area_collector.beam +++ b/erts/preloaded/ebin/erts_literal_area_collector.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex be3036d4f2..06074d1717 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/persistent_term.beam b/erts/preloaded/ebin/persistent_term.beam Binary files differindex bb889f181e..dc4a1aceb5 100644 --- a/erts/preloaded/ebin/persistent_term.beam +++ b/erts/preloaded/ebin/persistent_term.beam diff --git a/erts/preloaded/ebin/prim_buffer.beam b/erts/preloaded/ebin/prim_buffer.beam Binary files differindex e7c8adf589..a54a956fac 100644 --- a/erts/preloaded/ebin/prim_buffer.beam +++ b/erts/preloaded/ebin/prim_buffer.beam diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam Binary files differindex 6b3e0220cc..7b39f3e5ba 100644 --- a/erts/preloaded/ebin/prim_eval.beam +++ b/erts/preloaded/ebin/prim_eval.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex d4cb52e5a8..d0ef080a30 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex 2293728375..197ff59503 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_net.beam b/erts/preloaded/ebin/prim_net.beam Binary files differindex 02dea609fa..76d4f0fc69 100644 --- a/erts/preloaded/ebin/prim_net.beam +++ b/erts/preloaded/ebin/prim_net.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex bcdd836d5b..75413bb065 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex 1cffd45f05..1a5f34f3ee 100644 --- a/erts/preloaded/ebin/socket.beam +++ b/erts/preloaded/ebin/socket.beam diff --git a/erts/preloaded/ebin/socket_registry.beam b/erts/preloaded/ebin/socket_registry.beam Binary files differindex 9e055cbe48..a5eb2c190f 100644 --- a/erts/preloaded/ebin/socket_registry.beam +++ b/erts/preloaded/ebin/socket_registry.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex 16bc893d41..14558a7424 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl index 1605c20f2c..658a138694 100644 --- a/erts/preloaded/src/erl_prim_loader.erl +++ b/erts/preloaded/src/erl_prim_loader.erl @@ -300,12 +300,18 @@ check_file_result(Func, Target, {error,Reason}) -> %% This is equal to calling logger:error/2 which %% we don't want to do from code_server during system boot. %% We don't want to call logger:timestamp() either. - logger ! {log,error,#{label=>{?MODULE,file_error},report=>Report}, - #{pid=>self(), - gl=>group_leader(), - time=>os:system_time(microsecond), - error_logger=>#{tag=>error_report, - type=>std_error}}}, + _ = try + logger ! {log,error,#{label=>{?MODULE,file_error},report=>Report}, + #{pid=>self(), + gl=>group_leader(), + time=>os:system_time(microsecond), + error_logger=>#{tag=>error_report, + type=>std_error}}} + catch _:_ -> + %% If logger has not been started yet we just display it + erlang:display({?MODULE,file_error}), + erlang:display(Report) + end, error end; check_file_result(_, _, Other) -> diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl index 1aa5d85c64..f241be8569 100644 --- a/erts/preloaded/src/prim_file.erl +++ b/erts/preloaded/src/prim_file.erl @@ -575,11 +575,11 @@ list_dir_convert([RawName | Rest], SkipInvalid, Result) -> %% This is equal to calling logger:warning/3 which %% we don't want to do from code_server during system boot. %% We don't want to call logger:timestamp() either. - logger ! {log,warning,"Non-unicode filename ~p ignored\n", [RawName], - #{pid=>self(), - gl=>group_leader(), - time=>os:system_time(microsecond), - error_logger=>#{tag=>warning_msg}}}, + catch logger ! {log,warning,"Non-unicode filename ~p ignored\n", [RawName], + #{pid=>self(), + gl=>group_leader(), + time=>os:system_time(microsecond), + error_logger=>#{tag=>warning_msg}}}, list_dir_convert(Rest, SkipInvalid, Result); {error, _} -> {error, {no_translation, RawName}} diff --git a/lib/compiler/src/beam_ssa_bsm.erl b/lib/compiler/src/beam_ssa_bsm.erl index cb36f1c242..d950ef58ec 100644 --- a/lib/compiler/src/beam_ssa_bsm.erl +++ b/lib/compiler/src/beam_ssa_bsm.erl @@ -520,20 +520,29 @@ cm_register_prior(Src, DstCtx, Lbl, State) -> State#cm{ prior_matches = PriorMatches }. cm_combine_tail(Src, DstCtx, Bool, Acc, State0) -> - SrcCtx = match_context_of(Src, State0#cm.definitions), + SrcCtx0 = match_context_of(Src, State0#cm.definitions), + + {SrcCtx, Renames} = cm_combine_tail_1(Bool, DstCtx, SrcCtx0, + State0#cm.renames), %% We replace the source with a context alias as it normally won't be used %% on the happy path after being matched, and the added cost of conversion %% is negligible if it is. Aliases = maps:put(Src, {0, SrcCtx}, State0#cm.match_aliases), - - Renames0 = State0#cm.renames, - Renames = Renames0#{ Bool => #b_literal{val=true}, DstCtx => SrcCtx }, - State = State0#cm{ match_aliases = Aliases, renames = Renames }, {Acc, State}. +cm_combine_tail_1(Bool, DstCtx, SrcCtx, Renames0) -> + case Renames0 of + #{ SrcCtx := New } -> + cm_combine_tail_1(Bool, DstCtx, New, Renames0); + #{} -> + Renames = Renames0#{ Bool => #b_literal{val=true}, + DstCtx => SrcCtx }, + {SrcCtx, Renames} + end. + %% Lets functions accept match contexts as arguments. The parameter must be %% unused before the bs_start_match instruction, and it must be matched in the %% first block. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index a789b82910..2e91f7b53e 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -45,7 +45,8 @@ expression_before_match/1,erl_689/1,restore_on_call/1, restore_after_catch/1,matches_on_parameter/1,big_positions/1, matching_meets_apply/1,bs_start_match2_defs/1, - exceptions_after_match_failure/1, bad_phi_paths/1]). + exceptions_after_match_failure/1, bad_phi_paths/1, + combine_empty_segments/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -82,7 +83,8 @@ groups() -> expression_before_match,erl_689,restore_on_call, matches_on_parameter,big_positions, matching_meets_apply,bs_start_match2_defs, - exceptions_after_match_failure,bad_phi_paths]}]. + exceptions_after_match_failure,bad_phi_paths, + combine_empty_segments]}]. init_per_suite(Config) -> @@ -2033,4 +2035,14 @@ bad_phi_paths_1(Arg) -> end, id(B). +combine_empty_segments(_Config) -> + <<0,1,2,3>> = combine_empty_segments_1(<<0,1,2,3>>), + ok. + +combine_empty_segments_1(A) -> + <<B/bits>> = A, + <<C/bits>> = B, + <<D/bits>> = C, + D. + id(I) -> I. diff --git a/lib/crypto/test/crypto_bench_SUITE.erl b/lib/crypto/test/crypto_bench_SUITE.erl index c66a27f0c8..d738902ac8 100644 --- a/lib/crypto/test/crypto_bench_SUITE.erl +++ b/lib/crypto/test/crypto_bench_SUITE.erl @@ -67,7 +67,7 @@ init_per_suite(Config0) -> calibrate([{sec_goal,10} | Config1]) catch _:_ -> - {fail, "Crypto did not start"} + {skip, "Crypto did not start"} end. end_per_suite(_Config) -> diff --git a/lib/crypto/test/crypto_property_test_SUITE.erl b/lib/crypto/test/crypto_property_test_SUITE.erl index 18977f733a..bcfd5d3de1 100644 --- a/lib/crypto/test/crypto_property_test_SUITE.erl +++ b/lib/crypto/test/crypto_property_test_SUITE.erl @@ -31,7 +31,21 @@ all() -> [encrypt_decrypt_one_time, %%% First prepare Config and compile the property tests for the found tool: init_per_suite(Config) -> - ct_property_test:init_per_suite(Config). + case + try crypto:start() of + ok -> true; + {error, already_started} -> true; + _ -> false + catch + _:_ -> false + end + of + true -> + ct_property_test:init_per_suite(Config); + false -> + {skip, "Crypto did not start"} + end. + end_per_suite(Config) -> Config. diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl index 41cd132734..572f86e3c9 100644 --- a/lib/crypto/test/engine_SUITE.erl +++ b/lib/crypto/test/engine_SUITE.erl @@ -80,7 +80,7 @@ groups() -> init_per_suite(Config) -> - case {os:type(), crypto:info_lib()} of + try {os:type(), crypto:info_lib()} of {_, [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}]} -> {skip, "Problem with engine on OpenSSL 1.0.1s-freebsd"}; @@ -100,6 +100,8 @@ init_per_suite(Config) -> catch _:_ -> {skip, "Crypto did not start"} end + catch _:_ -> + {skip, "Crypto not loaded"} end. end_per_suite(_Config) -> diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index 85522c99b2..aa4eb6ad45 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -23,7 +23,7 @@ <copyright> <year>2011</year> -<year>2019</year> +<year>2020</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1046,8 +1046,9 @@ each node from which requests are sent.</p> <tag><c>&transport_opt;</c></tag> <item> <p> -Any transport option except <c>applications</c> or -<c>capabilities</c>. +Any transport option except <c>applications</c>, +<c>capabilities</c>, <c>transport_config</c>, and +<c>transport_module</c>. Used as defaults for transport configuration, values passed to &add_transport; overriding values configured on the service.</p> </item> @@ -1398,10 +1399,11 @@ Options <c>monitor</c> and <c>link</c> are ignored in the list-valued case. An MFA is applied with an additional term prepended to its argument list, and should return either the pid of the handler process that -invokes <c>diameter_traffic:request/1</c> on the term in order to +invokes <c>diameter_traffic:request/1</c> on the argument in order to process the request, or the atom <c>discard</c>. -The handler process need not be local, but diameter must be started on -the remote node.</p> +The handler process need not be local, and diameter need not be +started on the remote node, but diameter and relevant application +callbacks must be on the code path.</p> <p> Defaults to the empty list.</p> diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 8dcba93273..780b0b894a 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -43,6 +43,57 @@ first.</p> <!-- ===================================================================== --> +<section><title>diameter 2.2.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The possibility of choosing a handler process for an + incoming Diameter request with a configured MFA was + documented in OTP 20.0, but counters (with + {traffic_counters, true}) were not incremented when this + process was on a remote node. Counters are now + incremented on the node that configures the transport in + question.</p> + <p> + Introduced in OTP 21.3.</p> + <p> + Own Id: OTP-16457</p> + </item> + <item> + <p> + Transport options differing from those passed to + diameter:add_transport/2 were used in several situations: + when starting a transport process after connect_timer + expiry after an initial connection attempt has failed, + when starting a transport process after a connection has + been accepted, when sending events, when returning + options in diameter:service_info/2, and possibly more. In + particular, the following configuration options to + diameter:add_transport/2 were dropped: avp_dictionaries, + incoming_maxlen, spawn_opt, strict_mbit.</p> + <p> + Moreover, any service options mistakenly passed to + diameter:add_transport/2 were interpreted as such, + instead of being ignored as the documentation states, + with the consequence that outgoing and incoming requests + saw different values of some options, some were always + taken from transport options, and others from service + options.</p> + <p> + diameter:add_transport/2 must be called in new code for + the fix to have effect.</p> + <p> + Introduced in OTP 20.1.</p> + <p> + Own Id: OTP-16459</p> + </item> + </list> + </section> + +</section> + <section><title>diameter 2.2.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/diameter/examples/code/GNUmakefile b/lib/diameter/examples/code/GNUmakefile index f5c2e5f869..9efb966e65 100644 --- a/lib/diameter/examples/code/GNUmakefile +++ b/lib/diameter/examples/code/GNUmakefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2015. All Rights Reserved. +# Copyright Ericsson AB 2010-2020. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,10 +18,10 @@ # %CopyrightEnd% # -EXAMPLES = client server relay # redirect proxy +EXAMPLES = client server relay redirect # proxy CALLBACKS = $(EXAMPLES:%=%_cb) -MODULES = node $(EXAMPLES) $(EXAMPLES:%=%_cb) +MODULES = $(EXAMPLES) $(EXAMPLES:%=%_cb) BEAM = $(MODULES:%=%.beam) diff --git a/lib/diameter/examples/code/README b/lib/diameter/examples/code/README new file mode 100644 index 0000000000..b639849390 --- /dev/null +++ b/lib/diameter/examples/code/README @@ -0,0 +1,105 @@ + +This directory contains small examples of simple Diameter nodes. They +don't do everything a real node should do obviously, but they're a +starting point. + +Each example consists of an interface module with functions to start +and stop a service and add transport, and a corresponding callback +module for the Diameter application the service configures. A real +node might support multiple Diameter applications, either with the +same callback or sharing a common callback, maybe using extra +arguments to distinguish between callbacks for the different +applications. + +The interface functions are named start, stop, connect, and listen; +the client example also has a call function that sends an example +message. Service names should be atoms in these modules (since the +default setting of Origin-Host assumes this), but doesn't need to be +in general. Options are passed directly to diameter:start_service/2 +and diameter:add_transport/2, with some additional convenience options +for the latter; in particular, the atoms tcp and sctp to connect to or +listen on default endpoints (127.0.01:3868), or tuples with protocol +and another endpoint {eg. {tcp, {192,168,1,5}, 3869}. This convenience +makes the simplest usage like this in an Erlang shell: + + diameter:start(). + server:start(). + server:listen(tcp). + client:start(). + client:connect(tcp). + client:call(). + +Or put a relay between the client and server: + + diameter:start(). + server:start(). + server:listen(sctp). + relay:start(). + relay:connect(sctp). + relay:listen(tcp). + client:start(). + client:connect(tcp). + client:call(). + +Most services should probably set the following options, which have +been added to solve various problems over the years, while the +defaults have not been changed for backwards compatibility. + + {decode_format, map} + + Provide decoded messages in #diameter_packet.msg of a + handle_request or handle_answer callback in the form [Name | Avps], + where Name is the atom() name of the message in the (Diameter) + application dictionary in question (eg. 'ACR') and Avps is a map + of AVP values. This avoids compile-time dependencies on the + generated records and their (generally) long-winded names. The + hrl files generated from dictionaries are best avoided. + + {restrict_connections, false} + + Accept multiple connections with the same peer. By default, + diameter will only accept a single connection with a given peer, + which the Diameter RFC can be interpreted as requiring. In + practice, wanting multiple connections to the same peer is + common. + + {string_decode, false} + + Disable the decoding of string-ish Diameter types to Erlang + strings, leaving them as binary(). Strings can be costly if + decoded Diameter messages are passed between processes. + + {strict_mbit, false} + + Relax the interpretation of the M-bit so that an AVP setting + this bit is not regarded as a 5001 error when the message + grammar in question doesn't explicitly list the AVP. Without + this, a Redirect-Host AVP received in a 3006 + (DIAMETER_REDIRECT_INDICATION) answer-message from a redirect + agent will be treated as error, and there have been other + situations in which the default value has caused problems (or at + least surprise). + + {call_mutates_state, false} (on each configured application) + + Avoid pick_peer and subsequent callbacks going through a single + process, which can be a bottleneck. Better to use the tid() of + an ets table as (immutable) state, for example. + +Other options that are particularly useful/necessary in some +situations are: + + pool_size - Create a pool of accepting processes for a listening + transport, to avoid refused connections when many peers + connect simultaneously. Can also be used on a connecting + transport to establish multiple connections with a + single call to diameter:add_transport/2. + + sequence - Ensure unique End-to-End and Hop-by-Hop identifiers over + a cluster of Erlang nodes. + + share_peers - Share peer connections across a cluster of + use_shared_peers Erlang nodes. + + spawn_opt - Replace diameter's spawning of a new handler process for + each request by something else: diameter_dist is an example. diff --git a/lib/diameter/examples/code/client.erl b/lib/diameter/examples/code/client.erl index 0864919cdd..04c91e37fa 100644 --- a/lib/diameter/examples/code/client.erl +++ b/lib/diameter/examples/code/client.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2017. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -18,120 +18,173 @@ %% %CopyrightEnd% %% +-module(client). + %% -%% An example Diameter client that can sends base protocol RAR +%% An example Diameter client that can sends base protocol ACR %% requests to a connected peer. %% -%% The simplest usage is as follows this to connect to a server -%% listening on the default port on the local host, assuming diameter -%% is already started (eg. diameter:start()). +%% Simplest usage to connect to a server listening on TCP at +%% 127.0.0.1:3868: %% %% client:start(). %% client:connect(tcp). %% client:call(). %% -%% The first call starts the a service with the default name of -%% ?MODULE, the second defines a connecting transport that results in -%% a connection to the peer (if it's listening), the third sends it a -%% RAR and returns the answer. -%% - --module(client). - --include_lib("diameter/include/diameter.hrl"). -export([start/1, %% start a service start/2, %% connect/2, %% add a connecting transport - call/1, %% send using the record encoding - cast/1, %% send using the list encoding and detached + call/2, %% send a request stop/1]). %% stop a service -%% A real application would typically choose an encoding and whether -%% they want the call to return the answer or not. Sending with -%% both the record and list encoding here, one detached and one not, -%% is just for demonstration purposes. %% Convenience functions using the default service name. -export([start/0, connect/1, stop/0, call/0, - cast/0]). + call/1]). -define(DEF_SVC_NAME, ?MODULE). -define(L, atom_to_list). +-define(LOOPBACK, {127,0,0,1}). -%% The service configuration. As in the server example, a client -%% supporting multiple Diameter applications may or may not want to -%% configure a common callback module on all applications. +%% Service configuration. -define(SERVICE(Name), [{'Origin-Host', ?L(Name) ++ ".example.com"}, {'Origin-Realm', "example.com"}, {'Vendor-Id', 0}, {'Product-Name', "Client"}, {'Auth-Application-Id', [0]}, - {string_decode, false}, {decode_format, map}, + {restrict_connections, false}, + {strict_mbit, false}, + {string_decode, false}, {application, [{alias, common}, {dictionary, diameter_gen_base_rfc6733}, - {module, client_cb}]}]). + {module, client_cb}, + {answer_errors, callback}, + {call_mutates_state, false}]}]). -%% start/1 +%% start/2 -start(Name) - when is_atom(Name) -> - start(Name, []); +start(Name, Opts) -> + Defaults = [T || {K,_} = T <- ?SERVICE(Name), + not lists:keymember(K, 1, Opts)], + diameter:start_service(Name, Opts ++ Defaults). -start(Opts) - when is_list(Opts) -> +%% start/1 + +start(Opts) -> start(?DEF_SVC_NAME, Opts). %% start/0 start() -> - start(?DEF_SVC_NAME). + start(?DEF_SVC_NAME, []). -%% start/2 +%% connect/1 -start(Name, Opts) -> - node:start(Name, Opts ++ [T || {K,_} = T <- ?SERVICE(Name), - false == lists:keymember(K, 1, Opts)]). +connect(Opts) -> + connect(?DEF_SVC_NAME, Opts). %% connect/2 +connect(Name, Opts) + when is_list(Opts) -> + diameter:add_transport(Name, {connect, lists:flatmap(fun opts/1, Opts)}); + +%% backwards compatibility with old config +connect(Name, {T, Opts}) -> + connect(Name, [T | Opts]); connect(Name, T) -> - node:connect(Name, T). + connect(Name, [T]). -connect(T) -> - connect(?DEF_SVC_NAME, T). +%% call/2 -%% call/1 +call(Name, #{'Session-Id' := _} = Avps) -> + Defaults = #{'Destination-Realm' => "example.com", + 'Accounting-Record-Type' => 1, %% EVENT_RECORD + 'Accounting-Record-Number' => 0}, + ACR = ['ACR' | maps:merge(Defaults, Avps)], + diameter:call(Name, common, ACR, []); -call(Name) -> - SId = diameter:session_id(?L(Name)), - RAR = ['RAR' | #{'Session-Id' => SId, - 'Auth-Application-Id' => 0, - 'Re-Auth-Request-Type' => 0}], - diameter:call(Name, common, RAR, []). +call(Name, #{} = Avps) -> + call(Name, Avps#{'Session-Id' => diameter:session_id(?L(Name))}); -call() -> - call(?DEF_SVC_NAME). +call(Name, Avps) -> + call(Name, maps:from_list(Avps)). -%% cast/1 +%% call/1 + +call(Avps) -> + call(?DEF_SVC_NAME, Avps). -cast(Name) -> - SId = diameter:session_id(?L(Name)), - RAR = ['RAR', {'Session-Id', SId}, - {'Auth-Application-Id', 0}, - {'Re-Auth-Request-Type', 1}], - diameter:call(Name, common, RAR, [detach]). +%% call/0 -cast() -> - cast(?DEF_SVC_NAME). +call() -> + call(?DEF_SVC_NAME, #{}). %% stop/1 stop(Name) -> - node:stop(Name). + diameter:stop_service(Name). stop() -> stop(?DEF_SVC_NAME). + +%% =========================================================================== + +%% opts/1 +%% +%% Map some terms to transport_module/transport_config pairs as a +%% convenience, pass everything else unmodified. + +opts(T) + when T == any; + T == tcp; + T == sctp -> + opts({T, loopback, 3868}); + +opts({T, RA, RP}) -> + opts({T, [], RA, RP}); + +opts({T, loopback, RA, RP}) -> + opts({T, ?LOOPBACK, RA, RP}); + +opts({T, LA, RA, RP}) + when is_tuple(LA) -> + opts({T, [{ip, LA}], RA, RP}); + +opts({any, Opts, RA, RP}) -> + All = Opts ++ opts(RA, RP), + [{transport_module, diameter_sctp}, + {transport_config, All, 2000}, + {transport_module, diameter_tcp}, + {transport_config, All}]; + +opts({tcp, Opts, RA, RP}) -> + opts({diameter_tcp, Opts, RA, RP}); + +opts({sctp, Opts, RA, RP}) -> + opts({diameter_sctp, Opts, RA, RP}); + +opts({Mod, Opts, loopback, RP}) -> + opts({Mod, Opts, ?LOOPBACK, RP}); + +opts({Mod, Opts, RA, default}) -> + opts({Mod, Opts, RA, 3868}); + +opts({Mod, Opts, RA, RP}) -> + [{transport_module, Mod}, + {transport_config, opts(RA, RP) ++ Opts}]; + +opts(T) -> + [T]. + +%% opts/2 + +opts(loopback, RP) -> + opts(?LOOPBACK, RP); + +opts(RA, RP) -> + [{raddr, RA}, {rport, RP}, {reuseaddr, true}]. diff --git a/lib/diameter/examples/code/client_cb.erl b/lib/diameter/examples/code/client_cb.erl index af2d4d6da7..7721c47a9a 100644 --- a/lib/diameter/examples/code/client_cb.erl +++ b/lib/diameter/examples/code/client_cb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2017. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ -module(client_cb). -include_lib("diameter/include/diameter.hrl"). --include_lib("diameter/include/diameter_gen_base_rfc3588.hrl"). %% diameter callbacks -export([peer_up/3, @@ -50,28 +49,16 @@ pick_peer([Peer | _], _, _SvcName, _State) -> %% prepare_request/3 -prepare_request(#diameter_packet{msg = ['RAR' = T | Avps]}, _, {_, Caps}) -> - #diameter_caps{origin_host = {OH, DH}, - origin_realm = {OR, DR}} +prepare_request(#diameter_packet{msg = [Name | Avps]}, _, {_, Caps}) -> + #diameter_caps{origin_host = {OH, _}, + origin_realm = {OR, _}} = Caps, - - {send, [T | if is_map(Avps) -> - Avps#{'Origin-Host' => OH, - 'Origin-Realm' => OR, - 'Destination-Host' => DH, - 'Destination-Realm' => DR}; - is_list(Avps) -> - [{'Origin-Host', OH}, - {'Origin-Realm', OR}, - {'Destination-Host', DH}, - {'Destination-Realm', DR} - | Avps] - end]}. + {send, [Name | Avps#{'Origin-Host' => OH, 'Origin-Realm' => OR}]}. %% prepare_retransmit/3 -prepare_retransmit(Packet, SvcName, Peer) -> - prepare_request(Packet, SvcName, Peer). +prepare_retransmit(Pkt, _SvcName, _Peer) -> + {send, Pkt}. %% handle_answer/4 @@ -86,4 +73,4 @@ handle_error(Reason, _Request, _SvcName, _Peer) -> %% handle_request/3 handle_request(_Packet, _SvcName, _Peer) -> - erlang:error({unexpected, ?MODULE, ?LINE}). + {answer_message, 3001}. %% DIAMETER_COMMAND_UNSUPPORTED diff --git a/lib/diameter/examples/code/node.erl b/lib/diameter/examples/code/node.erl deleted file mode 100644 index 77810bf893..0000000000 --- a/lib/diameter/examples/code/node.erl +++ /dev/null @@ -1,202 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% -%% A library module used by the example Diameter nodes. Does little -%% more than provide an alternate/simplified transport configuration. -%% - --module(node). - --export([start/2, - listen/2, - connect/2, - stop/1]). - --export([message/3]). - --type protocol() - :: tcp | sctp. - --type ip_address() - :: default - | inet:ip_address(). - --type server_transport() - :: protocol() - | {protocol(), ip_address(), non_neg_integer()}. - --type server_opts() - :: server_transport() - | {server_transport(), [diameter:transport_opt()]} - | [diameter:transport_opt()]. - --type client_transport() - :: protocol() | any - | {protocol() | any, ip_address(), non_neg_integer()} - | {protocol() | any, ip_address(), ip_address(), non_neg_integer()}. - --type client_opts() - :: client_transport() - | {client_transport(), [diameter:transport_opt()]} - | [diameter:transport_opt()]. - -%% The server_transport() and client_transport() config is just -%% convenience: arbitrary options can be specifed as a -%% [diameter:transport_opt()]. - --define(DEFAULT_PORT, 3868). - -%% --------------------------------------------------------------------------- -%% Interface functions -%% --------------------------------------------------------------------------- - -%% start/2 - --spec start(diameter:service_name(), [diameter:service_opt()]) - -> ok - | {error, term()}. - -start(Name, Opts) - when is_atom(Name), is_list(Opts) -> - diameter:start_service(Name, Opts). - -%% connect/2 - --spec connect(diameter:service_name(), client_opts()) - -> {ok, diameter:transport_ref()} - | {error, term()}. - -connect(Name, Opts) - when is_list(Opts) -> - diameter:add_transport(Name, {connect, Opts}); - -connect(Name, {T, Opts}) -> - connect(Name, Opts ++ client_opts(T)); - -connect(Name, T) -> - connect(Name, [{connect_timer, 5000} | client_opts(T)]). - -%% listen/2 - --spec listen(diameter:service_name(), server_opts()) - -> {ok, diameter:transport_ref()} - | {error, term()}. - -listen(Name, Opts) - when is_list(Opts) -> - diameter:add_transport(Name, {listen, Opts}); - -listen(Name, {T, Opts}) -> - listen(Name, Opts ++ server_opts(T)); - -listen(Name, T) -> - listen(Name, server_opts(T)). - -%% stop/1 - --spec stop(diameter:service_name()) - -> ok - | {error, term()}. - -stop(Name) -> - diameter:stop_service(Name). - -%% --------------------------------------------------------------------------- -%% Internal functions -%% --------------------------------------------------------------------------- - -%% server_opts/1 -%% -%% Return transport options for a listening transport. - -server_opts({T, Addr, Port}) -> - [{transport_module, tmod(T)}, - {transport_config, [{reuseaddr, true}, - {sender, true}, - {message_cb, [fun ?MODULE:message/3, 0]}, - {ip, addr(Addr)}, - {port, Port}]}]; - -server_opts(T) -> - server_opts({T, loopback, ?DEFAULT_PORT}). - -%% client_opts/1 -%% -%% Return transport options for a connecting transport. - -client_opts({T, LA, RA, RP}) - when T == all; %% backwards compatibility - T == any -> - [[S, {C,Os}], T] = [client_opts({P, LA, RA, RP}) || P <- [sctp,tcp]], - [S, {C,Os,2000} | T]; - -client_opts({T, LA, RA, RP}) -> - [{transport_module, tmod(T)}, - {transport_config, [{raddr, addr(RA)}, - {rport, RP}, - {reuseaddr, true} - | ip(LA)]}]; - -client_opts({T, RA, RP}) -> - client_opts({T, default, RA, RP}); - -client_opts(T) -> - client_opts({T, loopback, loopback, ?DEFAULT_PORT}). - -%% --------------------------------------------------------------------------- - -tmod(tcp) -> diameter_tcp; -tmod(sctp) -> diameter_sctp. - -ip(default) -> - []; -ip(loopback) -> - [{ip, {127,0,0,1}}]; -ip(Addr) -> - [{ip, Addr}]. - -addr(loopback) -> - {127,0,0,1}; -addr(A) -> - A. - -%% --------------------------------------------------------------------------- - -%% message/3 -%% -%% Simple message callback that limits the number of concurrent -%% requests on the peer connection in question. - -%% Incoming request. -message(recv, <<_:32, 1:1, _/bits>> = Bin, N) -> - [Bin, N < 32, fun ?MODULE:message/3, N+1]; - -%% Outgoing request. -message(ack, <<_:32, 1:1, _/bits>>, _) -> - []; - -%% Incoming answer or request discarded. -message(ack, _, N) -> - [N =< 32, fun ?MODULE:message/3, N-1]; - -%% Outgoing message or incoming answer. -message(_, Bin, _) -> - [Bin]. diff --git a/lib/diameter/examples/code/redirect.erl b/lib/diameter/examples/code/redirect.erl index 6934e54507..1f9749ba84 100644 --- a/lib/diameter/examples/code/redirect.erl +++ b/lib/diameter/examples/code/redirect.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,52 +20,80 @@ -module(redirect). --include_lib("diameter/include/diameter.hrl"). --include_lib("diameter/include/diameter_gen_base_rfc3588.hrl"). +%% +%% An example Diameter redirect agent. +%% +%% Simplest usage to listen on TCP at 127.0.0.1:3868. +%% +%% redirect:start(). +%% redirect:listen(tcp). +%% +%% Interface. -export([start/1, listen/2, stop/1]). +%% Convenience functions using the default service name. -export([start/0, listen/1, stop/0]). --define(APP_ALIAS, ?MODULE). --define(SVC_NAME, ?MODULE). --define(CALLBACK_MOD, redirect_mod). +-define(DEF_SVC_NAME, ?MODULE). %% The service configuration. -define(SERVICE(Name), [{'Origin-Host', atom_to_list(Name) ++ ".example.com"}, {'Origin-Realm', "example.com"}, {'Vendor-Id', 193}, {'Product-Name', "RedirectAgent"}, - {'Auth-Application-Id', [?DIAMETER_APP_ID_RELAY]}, - {application, [{alias, ?APP_ALIAS}, - {dictionary, ?DIAMETER_DICT_RELAY}, - {module, ?CALLBACK_MOD}]}]). + {'Auth-Application-Id', [16#FFFFFFFF]}, + {decode_format, map}, + {restrict_connections, false}, + {strict_mbit, false}, + {string_decode, false}, + {application, [{alias, redirect}, + {dictionary, diameter_gen_relay}, + {module, redirect_cb}, + {call_mutates_state, false}]}]). + +%% start/0 + +start() -> + start(?DEF_SVC_NAME). %% start/1 start(Name) when is_atom(Name) -> - peer:start(Name, ?SERVICE(Name)). + start(Name, []); -start() -> - start(?SVC_NAME). +start(Opts) + when is_list(Opts) -> + start(?DEF_SVC_NAME, Opts). + +%% start/2 + +start(Name, Opts) -> + Defaults = [T || {K,_} = T <- ?SERVICE(Name), + not lists:keymember(K, 1, Opts)], + diameter:start_service(Name, Opts ++ Defaults). %% listen/2 -listen(Name, T) -> - peer:listen(Name, T). +listen(Name, Opts) -> + server:listen(Name, Opts). + +%% listen/1 -listen(T) -> - listen(?SVC_NAME, T). +listen(Opts) -> + listen(?DEF_SVC_NAME, Opts). %% stop/1 stop(Name) -> - peer:stop(Name). + diameter:stop_service(Name). + +%% stop.0 stop() -> - stop(?SVC_NAME). + stop(?DEF_SVC_NAME). diff --git a/lib/diameter/examples/code/redirect_cb.erl b/lib/diameter/examples/code/redirect_cb.erl index 8325e86391..76ab091be3 100644 --- a/lib/diameter/examples/code/redirect_cb.erl +++ b/lib/diameter/examples/code/redirect_cb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ -module(redirect_cb). -include_lib("diameter/include/diameter.hrl"). --include_lib("diameter/include/diameter_gen_base_rfc3588.hrl"). %% diameter callbacks -export([peer_up/3, @@ -33,30 +32,71 @@ handle_error/4, handle_request/3]). --define(UNEXPECTED, erlang:error({unexpected, ?MODULE, ?LINE})). +%% Dictionary to encode answer-message AVPs with. +-define(Dict, diameter_gen_base_rfc6733). + +%% Raise an error on callbacks that aren't expected. +-define(ERROR, error({unexpected, ?MODULE, ?LINE})). + +%% peer_up/3 peer_up(_SvcName, _Peer, State) -> State. +%% peer_down/3 + peer_down(_SvcName, _Peer, State) -> State. +%% pick_peer/4 + pick_peer(_, _, _SvcName, _State) -> - ?UNEXPECTED. + false. + +%% prepare_request/3 prepare_request(_, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% prepare_retransmit/3 prepare_retransmit(_Packet, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% handle_answer/4 handle_answer(_Packet, _Request, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% handle_error/4 handle_error(_Reason, _Request, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% handle_request/3 -handle_request(#diameter_packet{msg = _, errors = []}, _SvcName, {_, Caps}) -> - #diameter_caps{} +handle_request(#diameter_packet{avps = Avps}, _, {_, Caps}) -> + #diameter_caps{origin_host = {OH, _}, + origin_realm = {OR, _}} = Caps, - discard. %% TODO + + Tail = [#diameter_avp{data = {?Dict, A, V}} + || {A,V} <- [{'Origin-Host', OH}, + {'Origin-Realm', OR}, + {'Result-Code', 3006}, %% DIAMETER_REDIRECT_INDICATION + {'Redirect-Host', <<"aaa://server.example.com:3868">>}]], + + {reply, ['answer-message' | lists:append([session(Avps), Tail])]}. + +%% =========================================================================== + +%% session/1 + +session(Avps) -> + try + [] = [A || #diameter_avp{code = 263, vendor_id = undefined} = A + <- Avps, + throw(A)] + catch + Avp -> [Avp] + end. diff --git a/lib/diameter/examples/code/relay.erl b/lib/diameter/examples/code/relay.erl index 806f79915b..ec53ac01f1 100644 --- a/lib/diameter/examples/code/relay.erl +++ b/lib/diameter/examples/code/relay.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -18,81 +18,94 @@ %% %CopyrightEnd% %% +-module(relay). + %% %% An example Diameter relay agent. %% -%% Usage to connect to a server listening on the default port over TCP -%% and to listen on the default port over SCTP is as follows, assuming -%% diameter is already started (eg. diameter:start()). +%% Simplets usage to connect to a server listening on TCP at +%% 127.0.0.1:3868 and listen for connections on TCP at the same +%% endpoint: %% -%% Eg. relay:start(). -%% relay:connect(tcp). -%% relay:listen(sctp). +%% relay:start(). +%% relay:connect(tcp). +%% relay:listen(sctp). %% --module(relay). - +%% Interface. -export([start/1, start/2, listen/2, connect/2, stop/1]). +%% Convenience functions using the default service name. -export([start/0, listen/1, connect/1, stop/0]). +%% Default service name. -define(DEF_SVC_NAME, ?MODULE). -%% The service configuration. +%% Service configuration. -define(SERVICE(Name), [{'Origin-Host', atom_to_list(Name) ++ ".example.com"}, {'Origin-Realm', "example.com"}, {'Vendor-Id', 193}, {'Product-Name', "RelayAgent"}, {'Auth-Application-Id', [16#FFFFFFFF]}, + {decode_format, map}, + {restrict_connections, false}, {string_decode, false}, + {strict_mbit, false}, {application, [{alias, relay}, {dictionary, diameter_gen_relay}, - {module, relay_cb}]}]). + {module, relay_cb}, + {call_mutates_state, false}]}]). -%% start/1 +%% start/2 -start(Name) - when is_atom(Name) -> - start(Name, []). +start(Name, Opts) -> + Defaults = [T || {K,_} = T <- ?SERVICE(Name), + not lists:keymember(K, 1, Opts)], + diameter:start_service(Name, Opts ++ Defaults). %% start/1 -start() -> - start(?DEF_SVC_NAME). +start(Opts) -> + start(?DEF_SVC_NAME, Opts). -%% start/2 +%% start/0 -start(Name, Opts) -> - node:start(Name, Opts ++ [T || {K,_} = T <- ?SERVICE(Name), - false == lists:keymember(K, 1, Opts)]). +start() -> + start(?DEF_SVC_NAME, []). %% listen/2 -listen(Name, T) -> - node:listen(Name, T). +listen(Name, Opts) -> + server:listen(Name, Opts). -listen(T) -> - listen(?DEF_SVC_NAME, T). +%% listen/1 + +listen(Opts) -> + listen(?DEF_SVC_NAME, Opts). %% connect/2 -connect(Name, T) -> - node:connect(Name, T). +connect(Name, Opts) -> + client:connect(Name, Opts). + +%% connect/1 -connect(T) -> - connect(?DEF_SVC_NAME, T). +connect(Opts) -> + connect(?DEF_SVC_NAME, Opts). %% stop/1 stop(Name) -> - node:stop(Name). + diameter:stop_service(Name). + +%% stop/0 stop() -> stop(?DEF_SVC_NAME). diff --git a/lib/diameter/examples/code/relay_cb.erl b/lib/diameter/examples/code/relay_cb.erl index 6df1738143..0d56a14401 100644 --- a/lib/diameter/examples/code/relay_cb.erl +++ b/lib/diameter/examples/code/relay_cb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,48 +21,59 @@ -module(relay_cb). -include_lib("diameter/include/diameter.hrl"). --include_lib("diameter/include/diameter_gen_base_rfc3588.hrl"). %% diameter callbacks -export([peer_up/3, peer_down/3, - pick_peer/5, - prepare_request/4, - prepare_retransmit/4, - handle_answer/5, - handle_error/5, + pick_peer/4, + prepare_request/3, + prepare_retransmit/3, + handle_answer/4, + handle_error/4, handle_request/3]). +%% peer_up/3 + peer_up(_SvcName, _Peer, State) -> State. +%% peer_down/3 + peer_down(_SvcName, _Peer, State) -> State. -%% Returning 'relay' from handle_request causes diameter to resend the -%% incoming request, which leads to pick_peer and prepare_request -%% callbacks as if sending explicitly. The 'extra' argument is -%% appended to the argument list for callbacks following from -%% resending of the request. +%% handle_request/3 + +%% Assume the destination is directly connected; filter +%% correspondingly; don't relay to the sender. +handle_request(_Pkt, _SvcName, {_, Caps}) -> + #diameter_caps{origin_host = {_, OH}} + = Caps, + {relay, [{timeout, 2000}, + {filter, {all, [host, realm, {neg, {host, OH}}]}}]}. -handle_request(_Pkt, _SvcName, _Peer) -> - {relay, [{timeout, 1000}, {extra, [relayed]}]}. +%% pick_peer/4 -%% diameter will filter the sender in the Peers list. -pick_peer([Peer | _], _, _SvcName, _State, relayed) -> +pick_peer([Peer | _], _, _SvcName, _State) -> {ok, Peer}. -prepare_request(Pkt, _SvcName, _Peer, relayed) -> +%% prepare_request/3 + +prepare_request(Pkt, _SvcName, _Peer) -> {send, Pkt}. -prepare_retransmit(Pkt, _SvcName, _Peer, relayed) -> +%% prepare_request/3 + +prepare_retransmit(Pkt, _SvcName, _Peer) -> {send, Pkt}. -%% diameter expects handle_answer to return the diameter_packet record -%% containing the answer when called for a relayed request. +%% handle_answer/4 -handle_answer(Pkt, _Request, _SvcName, _Peer, relayed) -> +%% Relay an answer by returning the first argument. +handle_answer(Pkt, _Request, _SvcName, _Peer) -> Pkt. -handle_error(Reason, _Request, _SvcName, _Peer, relayed) -> +%% handle_error/4 + +handle_error(Reason, _Request, _SvcName, _Peer) -> {error, Reason}. diff --git a/lib/diameter/examples/code/server.erl b/lib/diameter/examples/code/server.erl index a91be70664..6ee49fb678 100644 --- a/lib/diameter/examples/code/server.erl +++ b/lib/diameter/examples/code/server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2015. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -18,23 +18,20 @@ %% %CopyrightEnd% %% +-module(server). + %% -%% An example Diameter server that can respond to the base protocol -%% RAR sent by the client example. +%% An example Diameter server that answers the base protocol ACR sent +%% by the client example. %% -%% The simplest example to start a server listening on the loopback -%% address (which will serve the example usage given in client.erl) is -%% like this assuming diameter is already started (eg. diameter:start()): +%% Simplest usage to listen on TCP at 127.0.0.1:3868: %% %% server:start(). %% server:listen(tcp). %% -%% The first call starts a service, the second adds a transport listening -%% on the default port. -%% --module(server). +%% Interface. -export([start/1, %% start a service start/2, %% listen/2, %% add a listening transport @@ -45,6 +42,9 @@ listen/1, stop/0]). +%% Internal callback. +-export([message/3]). + -define(DEF_SVC_NAME, ?MODULE). %% The service configuration. In a server supporting multiple Diameter @@ -55,45 +55,110 @@ {'Vendor-Id', 193}, {'Product-Name', "Server"}, {'Auth-Application-Id', [0]}, + {decode_format, map}, {restrict_connections, false}, + {strict_mbit, false}, {string_decode, false}, {application, [{alias, common}, {dictionary, diameter_gen_base_rfc6733}, - {module, server_cb}]}]). + {module, server_cb}, + {call_mutates_state, false}]}]). -%% start/1 +%% start/2 -start(Name) - when is_atom(Name) -> - start(Name, []); +start(Name, Opts) -> + Defaults = [T || {K,_} = T <- ?SERVICE(Name), + not lists:keymember(K, 1, Opts)], + diameter:start_service(Name, Opts ++ Defaults). -start(Opts) - when is_list(Opts) -> +%% start/1 + +start(Opts) -> start(?DEF_SVC_NAME, Opts). %% start/0 start() -> - start(?DEF_SVC_NAME). - -%% start/2 - -start(Name, Opts) -> - node:start(Name, Opts ++ [T || {K,_} = T <- ?SERVICE(Name), - false == lists:keymember(K, 1, Opts)]). + start(?DEF_SVC_NAME, []). %% listen/2 +listen(Name, Opts) + when is_list(Opts) -> + diameter:add_transport(Name, {listen, lists:flatmap(fun opts/1, Opts)}); + +%% backwards compatibility with old config +listen(Name, {T, Opts}) -> + listen(Name, [T | Opts]); listen(Name, T) -> - node:listen(Name, T). + listen(Name, [T]). -listen(T) -> - listen(?DEF_SVC_NAME, T). +%% listen/1 + +listen(Opts) -> + listen(?DEF_SVC_NAME, Opts). %% stop/1 stop(Name) -> - node:stop(Name). + diameter:stop_service(Name). + +%% stop/0 stop() -> stop(?DEF_SVC_NAME). + +%% =========================================================================== + +%% opts/1 +%% +%% Map a 3-tuple a transport_module/transport_config pair as a +%% convenience, pass everything else unmodified. + +opts(T) + when T == tcp; + T == sctp -> + opts({T, loopback, default}); + +opts({tcp, Addr, Port}) -> + opts({diameter_tcp, Addr, Port}); + +opts({sctp, Addr, Port}) -> + opts({diameter_sctp, Addr, Port}); + +opts({Mod, loopback, Port}) -> + opts({Mod, {127,0,0,1}, Port}); + +opts({Mod, Addr, default}) -> + opts({Mod, Addr, 3868}); + +opts({Mod, Addr, Port}) -> + [{transport_module, Mod}, + {transport_config, [{reuseaddr, true}, + {sender, true}, + {message_cb, {?MODULE, message, [0]}}, + {ip, Addr}, + {port, Port}]}]; +opts(T) -> + [T]. + +%% message/3 +%% +%% Simple message callback that limits the number of concurrent +%% requests on the peer connection in question. + +%% Incoming request. +message(recv, <<_:32, 1:1, _/bits>> = Bin, N) -> + [Bin, N < 32, {?MODULE, message, [N+1]}]; + +%% Outgoing request. +message(ack, <<_:32, 1:1, _/bits>>, _) -> + []; + +%% Incoming answer or request discarded. +message(ack, _, N) -> + [N =< 32, {?MODULE, message, [N-1]}]; + +%% Outgoing message or incoming answer. +message(_, Bin, _) -> + [Bin]. diff --git a/lib/diameter/examples/code/server_cb.erl b/lib/diameter/examples/code/server_cb.erl index a2fb8fbda6..5662717c00 100644 --- a/lib/diameter/examples/code/server_cb.erl +++ b/lib/diameter/examples/code/server_cb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2015. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ -module(server_cb). -include_lib("diameter/include/diameter.hrl"). --include_lib("diameter/include/diameter_gen_base_rfc6733.hrl"). %% diameter callbacks -export([peer_up/3, @@ -37,67 +36,87 @@ handle_error/4, handle_request/3]). --define(UNEXPECTED, erlang:error({unexpected, ?MODULE, ?LINE})). +%% Raise an error on callbacks that aren't expected. +-define(ERROR, error({unexpected, ?MODULE, ?LINE})). + +%% peer_up/3 peer_up(_SvcName, _Peer, State) -> State. +%% peer_down/3 + peer_down(_SvcName, _Peer, State) -> State. -pick_peer(_, _, _SvcName, _State) -> - ?UNEXPECTED. +%% pick_peer/3 + +%% Don't let requests be sent, so other request callbacks shouldn't +%% happen. +pick_peer(_LocalCandidates, _RemoteCandidates, _SvcName, _State) -> + false. + +%% prepare_request/3 -prepare_request(_, _SvcName, _Peer) -> - ?UNEXPECTED. +prepare_request(_Packet, _SvcName, _Peer) -> + ?ERROR. + +%% prepare_retransmit/3 prepare_retransmit(_Packet, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% handle_answer/4 handle_answer(_Packet, _Request, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% handle_error/4 handle_error(_Reason, _Request, _SvcName, _Peer) -> - ?UNEXPECTED. + ?ERROR. + +%% handle_request/3 -%% A request whose decode was successful ... -handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) - when is_record(Req, diameter_base_RAR) -> +%% ACR without decode errors. +handle_request(#diameter_packet{msg = ['ACR' | #{} = Request], + errors = []}, + _SvcName, + {_, Caps}) -> #diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps, - #diameter_base_RAR{'Session-Id' = Id, - 'Re-Auth-Request-Type' = Type} - = Req, - - {reply, #diameter_base_RAA{'Result-Code' = rc(Type), - 'Origin-Host' = OH, - 'Origin-Realm' = OR, - 'Session-Id' = Id}}; - -%% ... or one that wasn't. 3xxx errors are answered by diameter itself -%% but these are 5xxx errors for which we must contruct a reply. -%% diameter will set Result-Code and Failed-AVP's. -handle_request(#diameter_packet{msg = Req}, _SvcName, {_, Caps}) - when is_record(Req, diameter_base_RAR) -> + + #{'Session-Id' := Sid, + 'Accounting-Record-Type' := T, + 'Accounting-Record-Number' := N} + = Request, + + Answer = #{'Result-Code' => 2001, %% DIAMETER_SUCCESS + 'Origin-Host' => OH, + 'Origin-Realm' => OR, + 'Session-Id' => Sid, + 'Accounting-Record-Type' => T, + 'Accounting-Record-Number' => N}, + + {reply, ['ACA' | Answer]}; + +%% ACR with decode errors. +handle_request(#diameter_packet{msg = ['ACR' | #{} = Request]}, + _SvcName, + {_, Caps}) -> #diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps, - #diameter_base_RAR{'Session-Id' = Id} - = Req, - {reply, #diameter_base_RAA{'Origin-Host' = OH, - 'Origin-Realm' = OR, - 'Session-Id' = Id}}; + Answer = maps:merge(maps:with(['Session-Id'], Request), + #{'Origin-Host' => OH, + 'Origin-Realm' => OR}), -%% Answer that any other message is unsupported. + %% Let diameter set Result-Code and Failed-AVP if there were + %% decode errors. + {reply, ['answer-message' | Answer]}; + +%% Answer anything else as unsupported. handle_request(#diameter_packet{}, _SvcName, _) -> {answer_message, 3001}. %% DIAMETER_COMMAND_UNSUPPORTED - -%% Map Re-Auth-Request-Type to Result-Code just for the purpose of -%% generating different answers. - -rc(0) -> - 2001; %% DIAMETER_SUCCESS -rc(_) -> - 5012. %% DIAMETER_UNABLE_TO_COMPLY diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile index 98636ed6e2..d6854cfd27 100644 --- a/lib/diameter/src/Makefile +++ b/lib/diameter/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2018. All Rights Reserved. +# Copyright Ericsson AB 2010-2020. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -210,12 +210,16 @@ realclean: clean PLT = ./otp.plt -plt: +plt: $(PLT) + +$(PLT): dialyzer --build_plt \ --apps erts stdlib kernel \ xmerl ssl public_key crypto \ compiler syntax_tools runtime_tools \ - --output_plt $(PLT) \ + --output_plt $@ \ + --get_warnings \ + --statistics \ --verbose dialyze: opt $(PLT) @@ -224,9 +228,12 @@ dialyze: opt $(PLT) -Wno_improper_lists \ $(EBIN)/diameter_gen_base_rfc3588.$(EMULATOR) \ $(patsubst %, $(EBIN)/%.$(EMULATOR), \ - $(notdir $(RT_MODULES) $(CT_MODULES) $(INFO_MODULES))) + $(notdir $(DICT_YRL) \ + $(RT_MODULES) \ + $(CT_MODULES) \ + $(INFO_MODULES))) # Omit all but the common dictionary module since these -# (diameter_gen_relay in particular) generate warning depending on how +# (diameter_gen_relay in particular) generate warnings depending on how # much of the included diameter_gen.hrl they use. # ---------------------------------------------------- diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl index 7f172e1fa1..2982486a10 100644 --- a/lib/diameter/src/base/diameter.erl +++ b/lib/diameter/src/base/diameter.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2019. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -146,8 +146,9 @@ services() -> %% service_info/2 %% --------------------------------------------------------------------------- --spec service_info(service_name(), atom() | [atom()]) - -> any(). +-spec service_info(service_name(), Item | [Item]) + -> any() + when Item :: atom() | peer_ref(). service_info(SvcName, Option) -> diameter_service:info(SvcName, Option). @@ -351,45 +352,45 @@ call(SvcName, App, Message) -> %% Options common to both start_service/2 and add_transport/2. -type common_opt() - :: {pool_size, pos_integer()} + :: {avp_dictionaries, [module()]} | {capabilities_cb, eval()} | {capx_timeout, 'Unsigned32'()} - | {strict_capx, boolean()} - | {strict_mbit, boolean()} - | {avp_dictionaries, [module()]} + | {connect_timer, 'Unsigned32'()} | {disconnect_cb, eval()} - | {dpr_timeout, 'Unsigned32'()} | {dpa_timeout, 'Unsigned32'()} + | {dpr_timeout, 'Unsigned32'()} | {incoming_maxlen, message_length()} | {length_errors, exit | handle | discard} - | {connect_timer, 'Unsigned32'()} - | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}} + | {pool_size, pos_integer()} + | {spawn_opt, list() | mfa()} + | {strict_capx, boolean()} + | {strict_mbit, boolean()} | {watchdog_config, [{okay|suspect, non_neg_integer()}]} - | {spawn_opt, list() | mfa()}. + | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}. %% Options passed to start_service/2 -type service_opt() :: capability() | {application, [application_opt()]} + | {decode_format, decode_format()} | {restrict_connections, restriction()} | {sequence, sequence() | eval()} | {share_peers, remotes()} - | {decode_format, decode_format()} - | {traffic_counters, boolean()} - | {string_decode, boolean()} | {strict_arities, true | strict_arities()} + | {string_decode, boolean()} + | {traffic_counters, boolean()} | {use_shared_peers, remotes()} | common_opt(). -type application_opt() :: {alias, app_alias()} + | {answer_errors, callback|report|discard} + | {call_mutates_state, boolean()} | {dictionary, module()} | {module, app_module()} - | {state, any()} - | {call_mutates_state, boolean()} - | {answer_errors, callback|report|discard} - | {request_errors, answer_3xxx|answer|callback}. + | {request_errors, answer_3xxx|answer|callback} + | {state, any()}. -type app_alias() :: any(). @@ -407,11 +408,11 @@ call(SvcName, App, Message) -> %% Options passed to add_transport/2 -type transport_opt() - :: {transport_module, atom()} + :: {applications, [app_alias()]} + | {capabilities, [capability()]} | {transport_config, any()} | {transport_config, any(), 'Unsigned32'() | infinity} - | {applications, [app_alias()]} - | {capabilities, [capability()]} + | {transport_module, atom()} | common_opt() | {private, any()}. @@ -430,8 +431,8 @@ call(SvcName, App, Message) -> %% Options passed to call/4 -type call_opt() - :: {extra, list()} + :: detach + | {extra, list()} | {filter, peer_filter()} - | {timeout, 'Unsigned32'()} | {peer, peer_ref()} - | detach. + | {timeout, 'Unsigned32'()}. diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index 493a6ab1e3..7f6baf666a 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -208,7 +208,7 @@ values(Avps) -> encode_avps(_, _, [#diameter_avp{} | _] = Avps, Opts) -> encode_avps(Avps, Opts); -%% ... or as a tuple list or record. +%% ... or as a tuple list, map, or record. encode_avps(Mod, MsgName, Values, Opts) -> Mod:encode_avps(MsgName, Values, Opts). diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl index 36ae4c2276..495e57e456 100644 --- a/lib/diameter/src/base/diameter_config.erl +++ b/lib/diameter/src/base/diameter_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -661,6 +661,9 @@ opt(transport, {transport_module, M}) -> opt(transport, {transport_config, _, Tmo}) -> ?IS_UINT32(Tmo) orelse Tmo == infinity; +opt(transport, {transport_config, _}) -> + true; + opt(transport, {applications, As}) -> is_list(As); @@ -720,15 +723,16 @@ opt(_, {K, _}) when K == disconnect_cb; K == capabilities_cb -> true; -opt(transport, {K, _}) - when K == transport_config; - K == private -> +opt(transport, {private, _}) -> true; -%% Anything else, which is ignored in transport config. This makes -%% options sensitive to spelling mistakes, but arbitrary options are -%% passed by some users as a way to identify transports so can't just -%% do away with it. +%% Anything else is ignored in transport config. This makes options +%% sensitive to spelling mistakes and unintentionally passing service +%% options, but arbitrary options are passed by some users as a way to +%% identify transports (they can be returned by diameter:service_info/2 +%% for example) so can't just do away with it, although silently +%% swallowing service options is at least debatable. The documentation +%% says anything, so accept anything. opt(K, _) -> K == transport. diff --git a/lib/diameter/src/base/diameter_dist.erl b/lib/diameter/src/base/diameter_dist.erl index ed23152b8b..1edca58eb9 100644 --- a/lib/diameter/src/base/diameter_dist.erl +++ b/lib/diameter/src/base/diameter_dist.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2019. All Rights Reserved. +%% Copyright Ericsson AB 2019-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,6 +27,21 @@ %% transport configuration, to be able to distribute incoming Diameter %% requests to handler processes (local or remote) in various ways. %% +%% The gen_server implemented here must be started on each node on +%% which {diameter_dist, route_session, _} is configured as a +%% spawn_opt MFA, as well as each node that wants to receive requests. +%% This happens as a consequence of diameter application start, but a +%% minimal solution could start only this server on nodes that should +%% handle requests but not configure transport. (Although the typical +%% case is probably that diameter should be started in any case; for +%% example, to be able to originate requests.) +%% +%% Moreover, attach/1 must be called to communicate the list of +%% services for which the local node is willing to handle requests. +%% The servers on different nodes communicate so that each server +%% knows which nodes are prepared to handle requests for which +%% services. +%% %% spawn_opt callbacks -export([spawn_local/2, diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index cf5e7f21d3..b86dcaf923 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 77d184cfc7..520a7233cc 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -735,29 +735,31 @@ init_peers() -> %% Alias, %% TPid} +%% Valid service options are all 2-tuples. service_opts(Opts) -> - remove([{strict_arities, true}, - {avp_dictionaries, []}], - maps:merge(maps:from_list([{monitor, false} | def_opts()]), - maps:from_list(Opts))). + remove([{strict_arities, true}, {avp_dictionaries, []}], + merge(lists:append([[{monitor, false}] | def_opts()]), Opts)). + +merge(List1, List2) -> + maps:merge(maps:from_list(List1), maps:from_list(List2)). remove(List, Map) -> maps:filter(fun(K,V) -> not lists:member({K,V}, List) end, Map). -def_opts() -> %% defaults on the service map - [{share_peers, false}, - {use_shared_peers, false}, - {sequence, {0,32}}, - {restrict_connections, nodes}, - {incoming_maxlen, 16#FFFFFF}, - {strict_arities, true}, - {strict_mbit, true}, - {decode_format, record}, - {avp_dictionaries, []}, - {traffic_counters, true}, - {string_decode, true}, - {spawn_opt, []}]. +def_opts() -> %% defaults on the options map + [[{decode_format, record}, %% service options + {restrict_connections, nodes}, + {sequence, {0,32}}, + {share_peers, false}, + {strict_arities, true}, + {string_decode, true}, + {traffic_counters, true}, + {use_shared_peers, false}], + [{avp_dictionaries, []}, %% common options + {incoming_maxlen, 16#FFFFFF}, + {spawn_opt, []}, + {strict_mbit, true}]]. mref(false = No) -> No; @@ -875,27 +877,46 @@ start(Ref, Type, Opts, N, #state{watchdogT = WatchdogT, = Svc1 = merge_service(Opts, Svc0), Svc = binary_caps(Svc1, SD), - {SOpts, TOpts} = merge_opts(SvcOpts, Opts), - RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, SOpts]), - T = {TOpts, SOpts, RecvData, Svc}, + {Map, Rest} = merge_opts(SvcOpts, Opts), + RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, Map]), + T = {Rest, Map, RecvData, Svc}, Rec = #watchdog{type = Type, ref = Ref, - options = TOpts}, - + options = Opts}, %% original options, returned + %% by service_info/2 diameter_lib:fold_n(fun(_,A) -> [wd(Type, Ref, T, WatchdogT, Rec) | A] end, [], N). -merge_opts(SvcOpts, Opts) -> - Keys = [K || {K,_} <- def_opts()], - SO = [T || {K,_} = T <- Opts, lists:member(K, Keys)], - TO = Opts -- SO, - {maps:merge(maps:with(Keys, SvcOpts), maps:from_list(SO)), - TO ++ [T || {K,_} = T <- maps:to_list(SvcOpts), - not lists:member(K, Keys), - not lists:keymember(K, 1, Opts)]}. +%% This is awkward. We have service options that have been passed to +%% diameter:start_service/2 (minus application and capabilities +%% options, removed in diameter_config) and transport options passed +%% to diameter:add_transport/2. The former can include defaults for +%% the latter, but the latter can also contain arbitrary options that +%% are just returned by diameter:service_info/2. There's nothing +%% stopping these arbitrary options from being valid service options, +%% but these aren't interpreted as such. +%% +%% The options are merged (transport defaults have already been merged +%% into the service options in service_opts/1) and split into a map +%% for the service options and a few transport options, and a list for +%% the rest. This is historical convolution. Some options are are +%% pulled out of the list on the way to starting the transport process +%% in diameter_peer_fsm, but more work could probably be done here to +%% simplify things. +%% +%% Transport options are not necessarily 2-tuples: the transport_config +%% 3-tuple means they can't just be turned into a map. +merge_opts(SOpts, TOpts) -> + [SD,TD] = Def = def_opts(), + Keys = [K || L <- Def, {K,_} <- L], + Opts = [T || {K,_} = T <- TOpts, lists:keymember(K, 1, TD)], + {maps:merge(maps:with(Keys, SOpts), maps:from_list(Opts)),%% merge TOpts + TOpts ++ [T || {K,_} = T <- maps:to_list(SOpts), %% append SOpts + not lists:keymember(K, 1, SD), + [] == [A || {A,_} <- TOpts, A == K]]}. binary_caps(Svc, true) -> Svc; diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index 8423e30269..4667bbc3f2 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2019. All Rights Reserved. +%% Copyright Ericsson AB 2013-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -86,6 +86,7 @@ string_decode := boolean(), strict_arities => diameter:strict_arities(), strict_mbit := boolean(), + ordered_encode => boolean(), incoming_maxlen := diameter:message_length()}}). %% Note that incoming_maxlen is currently handled in diameter_peer_fsm, %% so that any message exceeding the maximum is discarded. Retain the @@ -284,12 +285,18 @@ recv(false, false, TPid, Pkt, _, _) -> spawn_request(false, _, _, _, _, _, _) -> %% no transport discard; -%% An MFA should return the pid() of a process in which the argument -%% fun in applied, or the atom 'discard' if the fun is not applied. -%% The latter results in an acknowledgment back to the transport -%% process when appropriate, to ensure that send/recv callbacks can -%% count outstanding requests. Acknowledgement is implicit if the -%% handler process dies (in a handle_request callback for example). +%% An MFA should return the pid() of a process that invokes +%% diameter_traffic:request(ReqT), or the atom 'discard' if the +%% function is not called. The latter results in an acknowledgment +%% back to the transport process when appropriate, to ensure that +%% send/recv callbacks can count outstanding requests. Acknowledgement +%% is implicit if the handler process dies (in a handle_request +%% callback for example). +%% +%% There is no requirement that diameter be started on nodes on which +%% handler processes are spawned, just that diameter and application +%% callbacks are on the code path. (Although the MFA itself may have +%% requirements, as in the case of diameter_dist.) spawn_request(AppT, {M,F,A}, Ack, TPid, Pkt, Dict0, RecvData) -> %% Term to pass to request/1 in an appropriate process. Module %% diameter_dist implements callbacks. @@ -520,7 +527,7 @@ request_cb(noreply, _App, EvalPktFs, EvalFs) -> %% Relay a request to another peer. This is equivalent to doing an %% explicit call/4 with the message in question except that (1) a loop -%% will be detected by examining Route-Record AVP's, (3) a +%% will be detected by examining Route-Record AVP's, (2) a %% Route-Record AVP will be added to the outgoing request and (3) the %% End-to-End Identifier will default to that in the %% #diameter_header{} without the need for an end_to_end_identifier @@ -556,14 +563,7 @@ request_cb(T, App, _, _) -> send_A({reply, Ans}, TPid, App, Dict0, RecvData, Pkt, _Caps, Fs) -> AppDict = App#diameter_app.dictionary, MsgDict = msg_dict(AppDict, Dict0, Ans), - send_answer(Ans, - TPid, - MsgDict, - AppDict, - Dict0, - RecvData, - Pkt, - Fs); + send_answer(Ans, TPid, MsgDict, AppDict, Dict0, RecvData, Pkt, Fs); send_A({call, Opts}, TPid, App, Dict0, RecvData, Pkt, Caps, Fs) -> AppDict = App#diameter_app.dictionary, @@ -667,7 +667,7 @@ is_answer_message(#diameter_packet{msg = Msg}, Dict0) -> is_answer_message([#diameter_header{is_request = R, is_error = E} | _], _) -> E andalso not R; -%% Message sent as a map or tagged avp/value list. +%% Message sent as a map or avp list. is_answer_message([Name | _], _) -> Name == 'answer-message'; @@ -1239,7 +1239,12 @@ is_result(RC, true, _) -> %% incr/2 incr(TPid, Counter) -> - diameter_stats:incr(Counter, TPid, 1). + Node = node(TPid), + if Node == node() -> + diameter_stats:incr(Counter, TPid, 1); + true -> + spawn(Node, diameter_stats, incr, [Counter, TPid, 1]) + end. %% rcc/1 @@ -1866,23 +1871,26 @@ z(#diameter_packet{header = H, bin = Bin, transport_data = T}) -> transport_data = T}. %% send/1 +%% +%% Send from a remote node using a peer connection on this one. Pkt is +%% already stripped. send({TPid, Pkt, #request{handler = Pid} = Req0, SvcName, Timeout, TRef}) -> Req = Req0#request{handler = self()}, - recv(TPid, Pid, TRef, zend_requezt(TPid, Pkt, Req, SvcName, Timeout)). + Pid ! recv(TPid, TRef, send_request(TPid, Pkt, Req, SvcName, Timeout)). -%% recv/4 +%% recv/3 %% %% Relay an answer from a remote node. -recv(TPid, Pid, TRef, {LocalTRef, MRef}) -> +recv(TPid, TRef, {LocalTRef, MRef}) -> receive {answer, _, _, _, _} = A -> - Pid ! A; + A; {'DOWN', MRef, process, _, _} -> - Pid ! {failover, TRef}; + {failover, TRef}; {failover = T, LocalTRef} -> - Pid ! {T, TRef}; + {T, TRef}; T -> exit({timeout, LocalTRef, TPid} = T) end. diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index bb2a4a8e92..627213637b 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2019. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -62,7 +62,15 @@ {"2.1.4.1", [{restart_application, diameter}]}, %% 20.3.8.19 {"2.1.5", [{restart_application, diameter}]}, %% 21.0 {"2.1.6", [{restart_application, diameter}]}, %% 21.1 - {"2.2", [{update, diameter_dist, {advanced, "2.2"}}]} %% 21.3 + {"2.2", [{restart_application, diameter}]}, %% 21.3 + {"2.2.1", [{load_module, diameter}, %% 21.3.5 + {load_module, diameter_codec}, + {update, diameter_config}, + {update, diameter_dist}, + {update, diameter_peer_fsm}, + {update, diameter_service}, + {load_module, diameter_traffic}, + {update, diameter_tcp}]} ], [ {"0.9", [{restart_application, diameter}]}, @@ -106,6 +114,14 @@ {"2.1.4.1", [{restart_application, diameter}]}, {"2.1.5", [{restart_application, diameter}]}, {"2.1.6", [{restart_application, diameter}]}, - {"2.2", [{restart_application, diameter}]} + {"2.2", [{restart_application, diameter}]}, + {"2.2.1", [{load_module, diameter}, + {load_module, diameter_codec}, + {update, diameter_config}, + {update, diameter_dist}, + {update, diameter_peer_fsm}, + {update, diameter_service}, + {load_module, diameter_traffic}, + {update, diameter_tcp}]} ] }. diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk index d16292bb88..cf938785e3 100644 --- a/lib/diameter/src/modules.mk +++ b/lib/diameter/src/modules.mk @@ -1,7 +1,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2019. All Rights Reserved. +# Copyright Ericsson AB 2010-2020. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -98,13 +98,14 @@ BINS = \ # Released files relative to ../examples. EXAMPLES = \ code/GNUmakefile \ - code/node.erl \ code/client.erl \ code/client_cb.erl \ code/server.erl \ code/server_cb.erl \ code/relay.erl \ code/relay_cb.erl \ + code/redirect.erl \ + code/redirect_cb.erl \ dict/rfc4004_mip.dia \ dict/rfc4005_nas.dia \ dict/rfc4006_cc.dia \ diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index e5e766d2a0..a051aeb156 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -569,7 +569,11 @@ m({'DOWN', M, process, P, _} = T, #monitor{parent = MRef, %% l/2 %% -%% Transition listener state. +%% Transition listener state. Or not anymore since any message causes +%% the process to exit. + +-spec l(tuple(), #listener{}) + -> no_return(). %% Service process has died. l({'DOWN', _, process, Pid, _} = T, #listener{service = Pid, diff --git a/lib/diameter/test/diameter_dist_SUITE.erl b/lib/diameter/test/diameter_dist_SUITE.erl index b2e4c35b9a..2fda2830ae 100644 --- a/lib/diameter/test/diameter_dist_SUITE.erl +++ b/lib/diameter/test/diameter_dist_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2019. All Rights Reserved. +%% Copyright Ericsson AB 2019-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -160,15 +160,32 @@ ping(Config) -> %% %% Start diameter services. -start(SvcName) - when is_atom(SvcName) -> +%% There's no need to start diameter on a node that only services +%% diameter_dist as a handler of incoming requests, but the +%% diameter_dist server must be started since the servers communicate +%% to determine who services what. The typical case is probably that +%% handler nodes also want to be able to send Diameter requests, in +%% which case the application needs to be started and diameter_dist is +%% started as a part of this, but only start the server here to ensure +%% everything still works as expected. +start({_SvcName, [_, {S1, _}, {S2, _}, _]}) + when node() == S1; %% server1 + node() == S2 -> %% server2 + Mod = diameter_dist, + {ok, _} = gen_server:start({local, Mod}, Mod, _Args = [], _Opts = []), + ok; + +start({SvcName, [{S0, _}, _, _, {C, _}]}) + when node() == S0; %% server0 + node() == C -> %% client ok = diameter:start(), ok = diameter:start_service(SvcName, ?SERVICE((?L(SvcName)))); -start(Config) -> +start(Config) + when is_list(Config) -> Nodes = ?util:read_priv(Config, nodes), [] = [{N,RC} || {N,S} <- Nodes, - RC <- [rpc:call(N, ?MODULE, start, [S])], + RC <- [rpc:call(N, ?MODULE, start, [{S, Nodes}])], RC /= ok]. sequence() -> @@ -194,13 +211,12 @@ origin(Server) -> %% Establish one connection from the client, terminated on the first %% server node, the others handling requests. -connect({?SERVER, Config, [{Node, _} | _]}) -> - if Node == node() -> %% server0 - ?util:write_priv(Config, lref, {Node, ?util:listen(?SERVER, tcp)}); - true -> - diameter_dist:attach([?SERVER]) - end, - ok; +connect({?SERVER, Config, [{Node, _} | _]}) + when Node == node() -> %% server0 + ok = ?util:write_priv(Config, lref, {Node, ?util:listen(?SERVER, tcp)}); + +connect({?SERVER, _Config, _}) -> %% server[12]: register to receive requests + ok = diameter_dist:attach([?SERVER]); connect({?CLIENT, Config, _}) -> ?util:connect(?CLIENT, tcp, ?util:read_priv(Config, lref)), @@ -239,7 +255,18 @@ send(Config) -> send(Config, 0, Dict) -> [{Server0, _} | _] = ?util:read_priv(Config, nodes) , Node = atom_to_binary(Server0, utf8), - {false, _} = {dict:is_key(Node, Dict), dict:to_list(Dict)}; + {false, _} = {dict:is_key(Node, Dict), dict:to_list(Dict)}, + %% Check that counters have been incremented as expected on server0. + [Info] = rpc:call(Server0, diameter, service_info, [?SERVER, connections]), + {[Stats], _} = {[S || {statistics, S} <- Info], Info}, + {[{recv, 1, 100}, {send, 0, 100}], _} + = {[{D,R,N} || T <- [recv, send], + {{{0,275,R}, D}, N} <- Stats, + D == T], + Stats}, + {[{send, 0, 100, 2001}], _} + = {[{D,R,N,C} || {{{0,275,R}, D, {'Result-Code', C}}, N} <- Stats], + Stats}; send(Config, N, Dict) -> #diameter_base_STA{'Result-Code' = ?SUCCESS, diff --git a/lib/diameter/test/diameter_event_SUITE.erl b/lib/diameter/test/diameter_event_SUITE.erl index a291dde6be..6d1d1dfd8f 100644 --- a/lib/diameter/test/diameter_event_SUITE.erl +++ b/lib/diameter/test/diameter_event_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2017. All Rights Reserved. +%% Copyright Ericsson AB 2013-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -28,6 +28,8 @@ -export([suite/0, all/0, + init_per_suite/1, + end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). @@ -85,6 +87,13 @@ all() -> cea_timeout, stop]. +%% Not used, but a convenient place to enable trace. +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + init_per_testcase(Name, Config) -> [{name, Name} | Config]. @@ -109,17 +118,19 @@ start_server(Config) -> %% Connect with matching capabilities and expect the connection to %% come up. up(Config) -> - {Svc, Ref} = connect(Config, [{connect_timer, 5000}, - {watchdog_timer, 15000}]), + {Svc, Ref, T} = connect(Config, [{strict_mbit, false}, + {connect_timer, 5000}, + {watchdog_timer, 15000}]), start = event(Svc), - {up, Ref, {TPid, Caps}, Cfg, #diameter_packet{msg = M}} = event(Svc), + {{up, Ref, {TPid, Caps}, T, #diameter_packet{msg = M}}, _} + = {event(Svc), T}, ['CEA' | #{}] = M, %% assert {watchdog, Ref, _, {initial, okay}, _} = event(Svc), %% Kill the transport process and see that the connection is %% reestablished after a watchdog timeout, not after connect_timer %% expiry. exit(TPid, kill), - {down, Ref, {TPid, Caps}, Cfg} = event(Svc), + {{down, Ref, {TPid, Caps}, T}, _} = {event(Svc), T}, {watchdog, Ref, _, {okay, down}, _} = event(Svc), {reconnect, Ref, _} = event(Svc, 10000, 20000). @@ -127,24 +138,25 @@ up(Config) -> %% to indicate as much and then for the transport to be restarted %% (after connect_timer). down(Config) -> - {Svc, Ref} = connect(Config, [{capabilities, [{'Acct-Application-Id', - [?DICT_ACCT:id()]}]}, - {applications, [?DICT_ACCT]}, - {connect_timer, 5000}, - {watchdog_timer, 20000}]), + {Svc, Ref, T} = connect(Config, [{capabilities, [{'Acct-Application-Id', + [?DICT_ACCT:id()]}]}, + {applications, [?DICT_ACCT]}, + {connect_timer, 5000}, + {watchdog_timer, 20000}]), start = event(Svc), - {closed, Ref, {'CEA', ?NO_COMMON_APP, _, #diameter_packet{msg = M}}, _} - = event(Svc), + {{closed, Ref, {'CEA', ?NO_COMMON_APP, _, #diameter_packet{msg = M}}, T}, + _} + = {event(Svc), T}, ['CEA' | #{}] = M, %% assert {reconnect, Ref, _} = event(Svc, 4000, 10000). %% Connect with matching capabilities but have the server delay its %% CEA and cause the client to timeout. cea_timeout(Config) -> - {Svc, Ref} = connect(Config, [{capx_timeout, ?SERVER_CAPX_TMO div 2}, - {connect_timer, 2*?SERVER_CAPX_TMO}]), + {Svc, Ref, T} = connect(Config, [{capx_timeout, ?SERVER_CAPX_TMO div 2}, + {connect_timer, 2*?SERVER_CAPX_TMO}]), start = event(Svc), - {closed, Ref, {'CEA', timeout}, _} = event(Svc). + {{closed, Ref, {'CEA', timeout}, T}, _} = {event(Svc), T}. stop(_Config) -> ok = diameter:stop(). @@ -168,8 +180,9 @@ connect(Config, Opts) -> Name = Pre ++ uniq() ++ ?CLIENT, diameter:subscribe(Name), ok = start_service(Name, ?SERVICE(Name, [?DICT_COMMON, ?DICT_ACCT])), - {ok, Ref} = diameter:add_transport(Name, opts(Config, Opts)), - {Name, Ref}. + {connect, _} = T = opts(Config, Opts), + {ok, Ref} = diameter:add_transport(Name, T), + {Name, Ref, T}. uniq() -> "-" ++ diameter_util:unique_string(). diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl index ee44ed8dc9..7d47efd527 100644 --- a/lib/diameter/test/diameter_examples_SUITE.erl +++ b/lib/diameter/test/diameter_examples_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2017. All Rights Reserved. +%% Copyright Ericsson AB 2013-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,6 +27,8 @@ -export([suite/0, all/0, groups/0, + init_per_suite/1, + end_per_suite/1, init_per_group/2, end_per_group/2]). @@ -85,6 +87,13 @@ groups() -> [{all, [parallel], [{group, P} || P <- ?PROTS]} | [{P, [], Tc} || P <- ?PROTS]]. +%% Not used, but a convenient place to enable trace. +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + init_per_group(all, Config) -> Config; @@ -216,12 +225,14 @@ make_name(Dict) -> %% Compile example code under examples/code. code(Config) -> - Node = slave(compile, here()), - [] = rpc:call(Node, - ?MODULE, - install, - [proplists:get_value(priv_dir, Config)]), - {ok, Node} = ct_slave:stop(compile). + try + [] = rpc:call(slave(compile, here()), + ?MODULE, + install, + [proplists:get_value(priv_dir, Config)]) + after + {ok, _} = ct_slave:stop(compile) + end. %% Compile on another node since the code path may be modified. install(PrivDir) -> diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index 47b00c25a2..452bd28333 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2019. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -128,7 +128,7 @@ %% =========================================================================== %% Fraction of shuffle/parallel groups to randomly skip. --define(SKIP, 0.25). +-define(SKIP, 0.90). %% Positive number of testcases from which to select (randomly) from %% tc(), the list of testcases to run, or [] to run all. The random @@ -305,7 +305,8 @@ names() -> S <- ?STRING_DECODES, ST <- ?CALLBACKS, SS <- ?SENDERS, - CS <- ?SENDERS]. + CS <- ?SENDERS, + ?SKIP =< rand:uniform()]. names(Names, []) -> [N || N <- Names, @@ -336,14 +337,9 @@ init_per_group(_) -> init_per_group(Name, Config) when Name == shuffle; Name == parallel -> - case rand:uniform() < ?SKIP of - true -> - {skip, random}; - false -> - start_services(Config), - add_transports(Config), - replace({sleep, Name == parallel}, Config) - end; + start_services(Config), + add_transports(Config), + replace({sleep, Name == parallel}, Config); init_per_group(sctp = Name, Config) -> {_, Sctp} = lists:keyfind(Name, 1, Config), diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk index a8fbca5bc8..e72b6216a7 100644 --- a/lib/diameter/vsn.mk +++ b/lib/diameter/vsn.mk @@ -17,5 +17,5 @@ # %CopyrightEnd% APPLICATION = diameter -DIAMETER_VSN = 2.2.1 +DIAMETER_VSN = 2.2.2 APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN) diff --git a/lib/hipe/icode/hipe_icode_primops.erl b/lib/hipe/icode/hipe_icode_primops.erl index a1f1128124..63b34f23a4 100644 --- a/lib/hipe/icode/hipe_icode_primops.erl +++ b/lib/hipe/icode/hipe_icode_primops.erl @@ -133,6 +133,7 @@ is_safe({hipe_bs_primop, {bs_append, _, _, _, _}}) -> false; is_safe({hipe_bs_primop, {bs_private_append, _, _}}) -> false; is_safe({hipe_bs_primop, bs_init_writable}) -> true; is_safe(build_stacktrace) -> true; +is_safe(raw_raise) -> false; is_safe(#mkfun{}) -> true; is_safe(#unsafe_element{}) -> true; is_safe(#unsafe_update_element{}) -> true; diff --git a/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl b/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl index ba9c03d4ba..9f79231e5a 100644 --- a/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl +++ b/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl @@ -25,6 +25,7 @@ test() -> ok = test_guard_bif(), ok = test_eclectic(), ok = test_raise(), + ok = test_effect(), ok. %%-------------------------------------------------------------------- @@ -675,4 +676,18 @@ do_test_raise_3(Expr) -> erlang:raise(exit, {exception,C,E}, Stk) end. +test_effect() -> + ok = effect_try(2), + {'EXIT',{badarith,_}} = (catch effect_try(bad)), + ok. + +effect_try(X) -> + try + X + 1 + catch + C:E:Stk -> + erlang:raise(C, E, Stk) + end, + ok. + id(I) -> I. diff --git a/lib/kernel/doc/src/erl_epmd.xml b/lib/kernel/doc/src/erl_epmd.xml index 2adbf11a28..31f49a05cb 100644 --- a/lib/kernel/doc/src/erl_epmd.xml +++ b/lib/kernel/doc/src/erl_epmd.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2018</year><year>2018</year> + <year>2018</year><year>2019</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -36,7 +36,7 @@ <p>This module communicates with the EPMD daemon, see <seealso marker="erts:epmd">epmd</seealso>. To implement your own epmd module please see <seealso marker="erts:alt_disco">ERTS User's Guide: How to Implement an - Alternative Service Discovery for Erlang Distribution</seealso></p> + Alternative Node Discovery for Erlang Distribution</seealso></p> </description> <funcs> diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 39da9ef3d6..7cf7ab3b4d 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2018</year> + <year>2004</year><year>2019</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1048,7 +1048,7 @@ marker="kernel:erl_epmd"><c>erl_epmd</c></seealso> reference manual and ERTS User's Guide <seealso marker="erts:alt_disco">How to Implement an Alternative - Service Discovery for Erlang Distribution</seealso>.</p> + Node Discovery for Erlang Distribution</seealso>.</p> <p> Own Id: OTP-15086 Aux Id: PR-1694 </p> </item> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 68e1205301..5469d8694c 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1437,11 +1437,16 @@ error_msg(Format, Args) -> %% This is equal to calling logger:error/3 which we don't want to %% do from code_server. We don't want to call logger:timestamp() %% either. - logger ! {log,error,Format,Args, - #{pid=>self(), - gl=>group_leader(), - time=>os:system_time(microsecond), - error_logger=>#{tag=>error}}}, + _ = try + logger ! {log,error,Format,Args, + #{pid=>self(), + gl=>group_leader(), + time=>os:system_time(microsecond), + error_logger=>#{tag=>error}}} + catch _:_ -> + erlang:display({?MODULE,error}), + erlang:display({Format,Args}) + end, ok. -spec info_msg(io:format(), [term()]) -> 'ok'. @@ -1449,11 +1454,11 @@ info_msg(Format, Args) -> %% This is equal to calling logger:info/3 which we don't want to %% do from code_server. We don't want to call logger:timestamp() %% either. - logger ! {log,info,Format,Args, - #{pid=>self(), - gl=>group_leader(), - time=>os:system_time(microsecond), - error_logger=>#{tag=>info_msg}}}, + catch logger ! {log,info,Format,Args, + #{pid=>self(), + gl=>group_leader(), + time=>os:system_time(microsecond), + error_logger=>#{tag=>info_msg}}}, ok. objfile_extension() -> diff --git a/lib/kernel/src/logger_config.erl b/lib/kernel/src/logger_config.erl index 5024d20cfe..af8ebfd4e9 100644 --- a/lib/kernel/src/logger_config.erl +++ b/lib/kernel/src/logger_config.erl @@ -41,7 +41,7 @@ delete(Tid,Id) -> allow(Tid,Level,Module) -> LevelInt = level_to_int(Level), - case ets:lookup(Tid,Module) of + try ets:lookup(Tid,Module) of [{Module,{ModLevel,cached}}] when is_integer(ModLevel), LevelInt =< ModLevel -> true; @@ -53,11 +53,17 @@ allow(Tid,Level,Module) -> allow(Tid,Level); _ -> false + catch error:badarg -> + true end. allow(Tid,Level) -> - GlobalLevelInt = ets:lookup_element(Tid,?PRIMARY_KEY,2), - level_to_int(Level) =< GlobalLevelInt. + try ets:lookup_element(Tid,?PRIMARY_KEY,2) of + GlobalLevelInt -> + level_to_int(Level) =< GlobalLevelInt + catch error:badarg -> + true + end. exist(Tid,What) -> ets:member(Tid,table_key(What)). diff --git a/lib/kernel/src/logger_proxy.erl b/lib/kernel/src/logger_proxy.erl index 24b293805c..6ab8e3e4c5 100644 --- a/lib/kernel/src/logger_proxy.erl +++ b/lib/kernel/src/logger_proxy.erl @@ -42,11 +42,16 @@ StringOrReport :: unicode:chardata() | logger:report(), Meta :: logger:metadata(). log(RemoteLog) -> - Olp = persistent_term:get(?MODULE), - case logger_olp:get_pid(Olp) =:= self() of + Olp = persistent_term:get(?MODULE, undefined), + case (Olp =:= undefined) orelse (logger_olp:get_pid(Olp) =:= self()) of true -> %% This happens when the log event comes from the %% emulator, and the group leader is on a remote node. + %% + %% OR + %% + %% when we are to log a remote message before the logger_proxy + %% has started _ = handle_load(RemoteLog, no_state), ok; false -> @@ -112,9 +117,12 @@ init([]) -> %% Log event to send to the node where the group leader of it's client resides handle_load({remote,Node,Log},State) -> - %% If the connection is overloaded (send_nosuspend returns false), - %% we drop the message. - _ = erlang:send_nosuspend({?SERVER,Node},Log), + case erlang:send({?SERVER,Node},Log,[nosuspend]) of + _ok_or_nosuspend -> + %% If the connection is overloaded (send returns nosuspend), + %% we drop the message. + ok + end, State; %% Log event to log on this node handle_load({log,Level,Format,Args,Meta},State) -> diff --git a/lib/kernel/test/logger_proxy_SUITE.erl b/lib/kernel/test/logger_proxy_SUITE.erl index 777531e4ed..bae2bd8d17 100644 --- a/lib/kernel/test/logger_proxy_SUITE.erl +++ b/lib/kernel/test/logger_proxy_SUITE.erl @@ -72,6 +72,7 @@ all() -> [basic, emulator, remote, + remote_disconnect, remote_emulator, config, restart_after, @@ -118,6 +119,19 @@ remote(Config) -> remote(cleanup,_Config) -> ok = logger:remove_handler(?HNAME). +remote_disconnect(Config) -> + {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]), + ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}), + RemoteGL = rpc:call(Node, erlang, whereis, [user]), + net_kernel:disconnect(Node), + L1 = ?LOC#{ gl => RemoteGL }, logger:notice("Log from ~p; ~p",[?FUNCTION_NAME,?LINE],L1), + ok = ensure(L1), + L2 = ?LOC#{ gl => RemoteGL }, logger:notice([{test_case,?FUNCTION_NAME},{line,?LINE}],L2), + ok = ensure(L2), + ok. +remote_disconnect(cleanup,_Config) -> + ok = logger:remove_handler(?HNAME). + remote_emulator(Config) -> {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]), ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}), diff --git a/lib/kernel/test/net_SUITE.erl b/lib/kernel/test/net_SUITE.erl index 4f27628bed..1e657a6cdd 100644 --- a/lib/kernel/test/net_SUITE.erl +++ b/lib/kernel/test/net_SUITE.erl @@ -219,6 +219,8 @@ api_b_getifaddrs() -> i("IfAddrs: " "~n ~p", [IfAddrs]), ok; + {error, enotsup = Reason} -> + skip(Reason); {error, Reason} -> ?FAIL(Reason) end. diff --git a/lib/megaco/test/megaco_codec_flex_lib.erl b/lib/megaco/test/megaco_codec_flex_lib.erl index e322c21dad..566ab0fe47 100644 --- a/lib/megaco/test/megaco_codec_flex_lib.erl +++ b/lib/megaco/test/megaco_codec_flex_lib.erl @@ -60,6 +60,8 @@ init(Config) when is_list(Config) -> %% "~n", [?MODULE, Res]), process_flag(trap_exit, Flag), case Res of + {error, {failed_loading_flex_scanner_driver, Reason}} -> + skip(?F("Failed loading flex driver: ~p", [Reason])); {error, Reason} -> skip(Reason); {ok, FlexConfig} -> diff --git a/lib/megaco/test/megaco_mess_SUITE.erl b/lib/megaco/test/megaco_mess_SUITE.erl index 0e4d2b90cb..f3dfc053c6 100644 --- a/lib/megaco/test/megaco_mess_SUITE.erl +++ b/lib/megaco/test/megaco_mess_SUITE.erl @@ -9896,10 +9896,10 @@ otp_6442_resend_request1(Config) when is_list(Config) -> try_tc(otp6442rreq1, Pre, Case, Post). do_otp_6442_resend_request1([MgNode]) -> - d("[MG] start the simulator "), + d("[MG] start the simulator"), {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), - d("[MG] create the event sequence"), + d("[MG] create the event sequence (~p)", [Mg]), MgMid = {deviceName,"mg"}, MgEvSeq = otp_6442_resend_request1_mg_event_sequence(MgMid), @@ -10103,11 +10103,6 @@ otp_6442_resend_request1_mg_event_sequence(Mid) -> ?otp_6442_resend_request1_mg_verify_service_change_rep_fun(), NotifyReplyVerify = ?otp_6442_resend_request1_mg_verify_notify_rep_fun(), - %% ConnectVerify = - %% otp_6442_resend_request1_mg_verify_handle_connect_fun(), - %% ServiceChangeReplyVerify = - %% otp_6442_resend_request1_mg_verify_service_change_reply_fun(), - %% NotifyReplyVerify = otp_6442_resend_request1_mg_verify_notify_reply_fun(), EvSeq = [ {debug, false}, megaco_start, diff --git a/lib/megaco/test/megaco_mib_SUITE.erl b/lib/megaco/test/megaco_mib_SUITE.erl index 8763145bbc..e040705b05 100644 --- a/lib/megaco/test/megaco_mib_SUITE.erl +++ b/lib/megaco/test/megaco_mib_SUITE.erl @@ -53,8 +53,8 @@ -include("megaco_test_lib.hrl"). -define(TEST_VERBOSITY, info). % silence | info | debug --define(MGC_VERBOSITY, info). --define(MG_VERBOSITY, info). +-define(MGC_VERBOSITY, debug). +-define(MG_VERBOSITY, debug). -define(LOAD_COUNTER_START, 100). -define(A4444, ["11111111", "00000000", "00000000"]). @@ -292,28 +292,40 @@ connect(suite) -> connect(doc) -> []; connect(Config) when is_list(Config) -> - put(verbosity, ?TEST_VERBOSITY), - put(sname, "TEST"), - i("connect -> starting"), - progress("start nodes"), - MgcNode = make_node_name(mgc), - Mg1Node = make_node_name(mg1), - Mg2Node = make_node_name(mg2), - d("connect -> Nodes: " - "~n MgcNode: ~p" - "~n Mg1Node: ~p" - "~n Mg2Node: ~p", [MgcNode, Mg1Node, Mg2Node]), - ok = ?START_NODES([MgcNode, Mg1Node, Mg2Node]), - + Pre = fun() -> + progress("start nodes"), + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + d("connect -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p", [MgcNode, Mg1Node, Mg2Node]), + Nodes = [MgcNode, Mg1Node, Mg2Node], + ok = ?START_NODES(Nodes, true), + Nodes + end, + Case = fun do_connect/1, + Post = fun(Nodes) -> + progress("stop nodes"), + d("stop nodes"), + ?STOP_NODES(lists:reverse(Nodes)) + end, + try_tc(connect, Pre, Case, Post). + +do_connect([MgcNode, Mg1Node, Mg2Node]) -> %% Start the MGC and MGs - ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], - progress("start MGC"), + + ET = [{text, tcp}, {text, udp}, {binary, tcp}, {binary, udp}], + progress("start MGC (on ~p)", [MgcNode]), {ok, Mgc} = start_mgc(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), - progress("start MG1"), + + progress("start MG1 (on ~p) using tcp", [Mg1Node]), {ok, Mg1} = start_mg(Mg1Node, {deviceName, "mg1"}, text, tcp, ?MG_VERBOSITY), - progress("start MG2"), + + progress("start MG2 (on ~p) using udp", [Mg2Node]), {ok, Mg2} = start_mg(Mg2Node, {deviceName, "mg2"}, binary, udp, ?MG_VERBOSITY), @@ -385,7 +397,6 @@ connect(Config) when is_list(Config) -> stop(Mgc), i("connect -> done", []), - progress("done"), ok. @@ -397,27 +408,36 @@ traffic(suite) -> traffic(doc) -> []; traffic(Config) when is_list(Config) -> - put(verbosity, ?TEST_VERBOSITY), - put(sname, "TEST"), - i("traffic -> starting"), - progress("start nodes"), - MgcNode = make_node_name(mgc), - Mg1Node = make_node_name(mg1), - Mg2Node = make_node_name(mg2), - Mg3Node = make_node_name(mg3), - Mg4Node = make_node_name(mg4), - d("traffic -> Nodes: " - "~n MgcNode: ~p" - "~n Mg1Node: ~p" - "~n Mg2Node: ~p" - "~n Mg3Node: ~p" - "~n Mg4Node: ~p", - [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]), - ok = ?START_NODES([MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]), - + Pre = fun() -> + progress("start nodes"), + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + Mg3Node = make_node_name(mg3), + Mg4Node = make_node_name(mg4), + Nodes = [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node], + d("traffic -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p" + "~n Mg3Node: ~p" + "~n Mg4Node: ~p", + [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]), + ok = ?START_NODES(Nodes, true), + Nodes + end, + Case = fun do_traffic/1, + Post = fun(Nodes) -> + progress("stop nodes"), + d("stop nodes"), + ?STOP_NODES(lists:reverse(Nodes)) + end, + try_tc(traffic, Pre, Case, Post). + +do_traffic([MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]) -> %% Start the MGC and MGs - i("traffic -> start the MGC"), - progress("start MGC"), + i("start the MGC"), + progress("start MGC (on ~p)", [MgcNode]), ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], {ok, Mgc} = start_mgc(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), @@ -550,7 +570,6 @@ traffic(Config) when is_list(Config) -> stop(Mgc), i("traffic -> done", []), - progress("done"), ok. @@ -671,10 +690,12 @@ traffic_connect_mg([{Node, Name, Coding, Trans}|Mg], Acc) -> traffic_connect_mg(Mg, [{Name, Pid}|Acc]). traffic_connect_mg(Node, Name, Coding, Trans) -> + progress("start (and connect) ~s (on ~p) using ~p", [Name, Node, Trans]), Mid = {deviceName, Name}, {ok, Pid} = start_mg(Node, Mid, Coding, Trans, ?MG_VERBOSITY), %% Ask the MGs to do a service change + progress("perform ~s service change", [Name]), {ok, Res} = service_change(Pid), d("traffic_connect_mg -> (~s) service change result: ~p", [Name, Res]), Pid. @@ -831,8 +852,12 @@ mgc_init(Config) -> RH = megaco:user_info(Mid,receive_handle), d("mgc_init -> parse receive info"), ListenTo = mgc_parse_receive_info(RI, RH), - i("mgc_init -> start transport(s)"), + i("mgc_init -> start transport(s) with:" + "~n ListenTo: ~p", [ListenTo]), {Tcp, Udp} = mgc_start_transports(ListenTo), + i("mgc_init -> transport(s) started:" + "~n Tcp: ~p" + "~n Udp: ~p", [Tcp, Udp]), {Mid, Tcp, Udp}. @@ -1247,10 +1272,15 @@ mg_loop(#mg{state = State} = S) -> %% Do a service change {service_change, Parent} when S#mg.parent == Parent, State == initiated -> - i("mg_loop(~p) -> received request to perform service change", - [State]), + i("mg_loop(~p) -> received request to perform service change when:" + "~n Conn Handle: ~p" + "~n Conn Data: ~p", + [State, + S#mg.conn_handle, + megaco:conn_info(S#mg.conn_handle, conn_data)]), Res = mg_service_change(S#mg.conn_handle), - d("mg_loop(~p) -> result: ~p", [State, Res]), + d("mg_loop(~p) -> service change request send result: ~p", + [State, Res]), mg_loop(S#mg{state = connecting}); @@ -1358,9 +1388,12 @@ mg_start_tcp(MgcPort, RH) -> {port, MgcPort}, {receive_handle, RH}, {tcp_options, [{nodelay, true}]}], + i("tcp transport started: attempt (tcp) connect to MGC at:" + "~n ~p", [LocalHost]), case megaco_tcp:connect(Sup, Opts) of {ok, SendHandle, ControlPid} -> PrelMgcMid = preliminary_mid, + i("tcp transport (tcp) connected: attempt (megaco) connect:"), {ok, ConnHandle} = megaco:connect(RH, PrelMgcMid, SendHandle, ControlPid), @@ -1382,12 +1415,18 @@ mg_start_udp(MgcPort, RH) -> %% local host. Try instead to "figure out" tha actual address... LocalAddr = which_local_addr(), Opts = [{port, 0}, {receive_handle, RH}], + i("udp transport started: attempt (udp) open"), case megaco_udp:open(Sup, Opts) of {ok, Handle, ControlPid} -> MgcMid = preliminary_mid, + i("udp transport open: " + "now create send handle with MGC address: " + "~n ~p", [LocalAddr]), SendHandle = megaco_udp:create_send_handle(Handle, LocalAddr, MgcPort), + i("udp transport: attempt (megaco) connect to:" + "~n ~p", [SendHandle]), {ok, ConnHandle} = megaco:connect(RH, MgcMid, SendHandle, ControlPid), @@ -1712,6 +1751,7 @@ get_conf(Key, Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Tries to find a valid local address... which_local_addr() -> case inet:getifaddrs() of {ok, IFs} -> @@ -1722,10 +1762,10 @@ which_local_addr() -> ?SKIP({failed_get_local_addr, Reason}) end. +%% We explicitly skip some interfaces that we know is not "valid" +%% (docker stuff) which_local_addr([]) -> ?SKIP(failed_get_local_addr); -which_local_addr([{"lo" = _IfName, _IfOpts}|IFs]) -> - which_local_addr(IFs); which_local_addr([{"br-" ++ _ = _IfName, _IfOpts}|IFs]) -> which_local_addr(IFs); which_local_addr([{"docker" ++ _ = _IfName, _IfOpts}|IFs]) -> @@ -1738,14 +1778,38 @@ which_local_addr([{_IfName, IfOpts}|IFs]) -> which_local_addr(IFs) end. +which_local_addr2(IfOpts) -> + case if_is_running(IfOpts) of + true -> + which_local_addr3(IfOpts); + false -> + error + end. -which_local_addr2([]) -> +if_is_running(If) -> + lists:keymember(flags, 1, If) andalso + begin + {value, {flags, Flags}} = lists:keysearch(flags, 1, If), + (not lists:member(loopback, Flags)) andalso lists:member(running, Flags) + end. + +which_local_addr3([]) -> error; -which_local_addr2([{addr, Addr}|_]) +which_local_addr3([{addr, Addr}|_]) when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> {ok, Addr}; -which_local_addr2([_|T]) -> - which_local_addr2(T). +which_local_addr3([_|T]) -> + which_local_addr3(T). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +try_tc(TCName, Pre, Case, Post) -> + try_tc(TCName, "TEST", ?TEST_VERBOSITY, Pre, Case, Post). + +try_tc(TCName, Name, Verbosity, Pre, Case, Post) -> + ?TRY_TC(TCName, Name, Verbosity, Pre, Case, Post). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/megaco/test/megaco_segment_SUITE.erl b/lib/megaco/test/megaco_segment_SUITE.erl index 018625d9cb..08b86606de 100644 --- a/lib/megaco/test/megaco_segment_SUITE.erl +++ b/lib/megaco/test/megaco_segment_SUITE.erl @@ -47,6 +47,7 @@ ]). +-include_lib("common_test/include/ct.hrl"). -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). -include_lib("megaco/include/megaco_message_v3.hrl"). @@ -2103,6 +2104,8 @@ send_segmented_msg_plain4(doc) -> "Forth plain test that it is possible to send segmented messages. " "Send window = 3. "; send_segmented_msg_plain4(Config) when is_list(Config) -> + Factor = ?config(megaco_factor, Config), + ct:timetrap(Factor * ?SECS(60)), Pre = fun() -> MgcNode = make_node_name(mgc), MgNode = make_node_name(mg), @@ -2114,19 +2117,19 @@ send_segmented_msg_plain4(Config) when is_list(Config) -> ok = ?START_NODES(Nodes), Nodes end, - Case = fun do_send_segmented_msg_plain4/1, + Case = fun(X) -> do_send_segmented_msg_plain4(Factor, X) end, Post = fun(Nodes) -> d("stop nodes"), ?STOP_NODES(lists:reverse(Nodes)) end, try_tc(ssmp4, Pre, Case, Post). -do_send_segmented_msg_plain4([MgcNode, MgNode]) -> +do_send_segmented_msg_plain4(Factor, [MgcNode, MgNode]) -> d("[MGC] start the simulator "), {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), d("[MGC] create the event sequence"), - MgcEvSeq = ssmp4_mgc_event_sequence(text, tcp), + MgcEvSeq = ssmp4_mgc_event_sequence(Factor, text, tcp), i("wait some time before starting the MGC simulation"), sleep(1000), @@ -2141,7 +2144,7 @@ do_send_segmented_msg_plain4([MgcNode, MgNode]) -> {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), d("[MG] create the event sequence"), - MgEvSeq = ssmp4_mg_event_sequence(text, tcp), + MgEvSeq = ssmp4_mg_event_sequence(Factor, text, tcp), i("wait some time before starting the MG simulation"), sleep(1000), @@ -2169,7 +2172,7 @@ do_send_segmented_msg_plain4([MgcNode, MgNode]) -> %% MGC generator stuff %% -ssmp4_mgc_event_sequence(text, tcp) -> +ssmp4_mgc_event_sequence(Factor, text, tcp) -> DecodeFun = ssmp4_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), EncodeFun = ssmp4_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), Mid = {deviceName,"mgc"}, @@ -2238,33 +2241,38 @@ ssmp4_mgc_event_sequence(text, tcp) -> SegmentRep7 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 7, false), SegmentRep8 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 8, true), TransAck = ssmp4_mgc_trans_ack_msg(Mid, TransId), + TO = fun(T) -> Factor*T end, EvSeq = [{debug, true}, + {trigger, "verbosity", + fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, {decode, DecodeFun}, {encode, EncodeFun}, {listen, 2944}, {expect_accept, any}, - {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {expect_receive, "service-change-request", {ScrVerifyFun, TO(5000)}}, {send, "service-change-reply", ServiceChangeRep}, {expect_nothing, 1000}, {send, "notify request", NotifyReq}, - {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}}, - {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, - {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, TO(1000)}}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, TO(1000)}}, + {expect_receive, "notify reply: segment 3", {NrVerifyFun3, TO(1000)}}, {expect_nothing, 1000}, {send, "segment reply 1", SegmentRep1}, - {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}}, + {expect_receive, "notify reply: segment 4", {NrVerifyFun4, TO(1000)}}, {expect_nothing, 1000}, {send, "segment reply 2", SegmentRep2}, - {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}}, + {expect_receive, "notify reply: segment 5", {NrVerifyFun5, TO(1000)}}, {expect_nothing, 1000}, {send, "segment reply 3", SegmentRep3}, - {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}}, + {expect_receive, "notify reply: segment 6", {NrVerifyFun6, TO(1000)}}, {expect_nothing, 1000}, {send, "segment reply 4", SegmentRep4}, - {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}}, + {expect_receive, "notify reply: segment 7", {NrVerifyFun7, TO(1000)}}, {expect_nothing, 1000}, {send, "segment reply 5", SegmentRep5}, - {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}}, + {expect_receive, "notify reply: segment 8", {NrVerifyFun8, TO(1000)}}, {expect_nothing, 1000}, {send, "segment reply 6", SegmentRep6}, {expect_nothing, 1000}, @@ -2531,7 +2539,7 @@ ssmp4_mgc_trans_ack_msg(Mid, TransId) -> %% %% MG generator stuff %% -ssmp4_mg_event_sequence(text, tcp) -> +ssmp4_mg_event_sequence(Factor, text, tcp) -> Mid = {deviceName,"mg"}, RI = [ {port, 2944}, @@ -2552,7 +2560,8 @@ ssmp4_mg_event_sequence(text, tcp) -> Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]}, Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8], NotifyReqVerify = ssmp4_mg_verify_notify_request_fun(Tids), - AckVerify = ssmp4_mg_verify_ack_fun(), + AckVerify = ssmp4_mg_verify_ack_fun(), + TO = fun(T) -> Factor*T end, EvSeq = [ {debug, true}, {megaco_trace, disable}, @@ -2573,7 +2582,7 @@ ssmp4_mg_event_sequence(text, tcp) -> {megaco_update_conn_info, max_pdu_size, 128}, {sleep, 1000}, {megaco_callback, handle_trans_request, NotifyReqVerify}, - {megaco_callback, handle_trans_ack, AckVerify, 15000}, + {megaco_callback, handle_trans_ack, AckVerify, TO(15000)}, megaco_stop_user, megaco_stop, {sleep, 1000} @@ -2661,30 +2670,34 @@ ssmp4_mg_verify_notify_request_fun(Tids) -> ssmp4_mg_verify_notify_request( {handle_trans_request, _CH, ?VERSION, ARs}, Tids) - when length(ARs) == length(Tids) -> + when length(ARs) =:= length(Tids) -> (catch ssmp4_mg_do_verify_notify_request(Tids, ARs)); ssmp4_mg_verify_notify_request( {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) -> + e("MG Notify Request verification failed: invalid action requests" + "~n ARs: ~p", [ARs]), {error, {invalid_action_requests, ARs}, ok}; ssmp4_mg_verify_notify_request( {handle_trans_request, CH, V, ARs}, _Tids) -> + e("MG Notify Request verification failed: invalid trans request" + "~n CH: ~p" + "~n V: ~p" + "~n ARs: ~p", [CH, V, ARs]), {error, {invalid_trans_request, {CH, V, ARs}}, ok}; ssmp4_mg_verify_notify_request(Crap, _Tids) -> - io:format("ssmp4_mg_verify_notify_request -> unknown request" - "~n Crap: ~p" - "~n Tids: ~p" - "~n", [Crap, _Tids]), + e("MG Notify Request verification failed: unknown request" + "~n Crap: ~p" + "~n Tids: ~p", [Crap, _Tids]), {error, {unexpected_event, Crap}, ok}. ssmp4_mg_do_verify_notify_request(Tids, ARs) -> - io:format("ssmp4_mg_do_verify_notify_request -> ok" - "~n Tids: ~p" - "~n ARs: ~p" - "~n", [Tids, ARs]), + p("MG Notify Request verification - attempt verify action request(s):" + "~n Tids: ~p" + "~n ARs: ~p", [Tids, ARs]), ActionReplies = ssmp4_mg_do_verify_notify_request_ars(Tids, ARs), - io:format("ssmp4_mg_do_verify_notify_request -> ok" - "~n ActionReplies: ~p" - "~n", [ActionReplies]), + p("MG Notify Request verification - ok" + "~n ActionReplies: ~p" + "~n", [ActionReplies]), Reply = {{handle_ack, ssmp4}, ActionReplies}, {ok, ARs, Reply}. @@ -2698,10 +2711,9 @@ ssmp4_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) -> ssmp4_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]). ssmp4_mg_do_verify_notify_request_ar(Tid, AR) -> - io:format("ssmp4_mg_do_verify_notify_request_ar -> ok" - "~n Tid: ~p" - "~n AR: ~p" - "~n", [Tid, AR]), + p("ssmp4_mg_do_verify_notify_request_ar -> ok" + "~n Tid: ~p" + "~n AR: ~p", [Tid, AR]), {Cid, CR} = case AR of #'ActionRequest'{contextId = CtxId, @@ -3648,6 +3660,10 @@ ssmmsr1_mgc_event_sequence(text, tcp) -> TransAck = ssmmsr1_mgc_trans_ack_msg(Mid, TransId), ReadyForSegments = ssmmsr1_mgc_ready_for_segments_fun(), EvSeq = [{debug, true}, + {trigger, "verbosity", + fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, {decode, DecodeFun}, {encode, EncodeFun}, {listen, 2944}, @@ -3977,6 +3993,10 @@ ssmmsr1_mg_event_sequence(text, tcp) -> ReadyForSegments = ssmmsr1_mg_ready_for_segments_fun(), EvSeq = [ {debug, true}, + {trigger, + fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, {megaco_trace, disable}, %% {megaco_trace, max}, megaco_start, @@ -4393,6 +4413,10 @@ ssmmsr2_mgc_event_sequence(text, tcp) -> SegmentRep1 = ssmmsr2_mgc_segment_reply_msg(Mid, TransId, 1, false), ReadyForSegments = ssmmsr2_mgc_ready_for_segments_fun(), EvSeq = [{debug, true}, + {trigger, "verbosity", + fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, {decode, DecodeFun}, {encode, EncodeFun}, {listen, 2944}, @@ -4701,6 +4725,10 @@ ssmmsr2_mg_event_sequence(text, tcp) -> ReadyForSegments = ssmmsr2_mg_ready_for_segments_fun(), EvSeq = [ {debug, true}, + {trigger, + fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, {megaco_trace, disable}, %% {megaco_trace, max}, megaco_start, @@ -7912,34 +7940,49 @@ p(F, A) -> [?FTS(), self() | A]). +%% e(F) -> +%% e(F, []). + +e(F, A) -> + print(error, get(verbosity), "ERROR", get(tc), F, A). + + i(F) -> i(F, []). i(F, A) -> - print(info, get(verbosity), get(tc), "INF", F, A). + print(info, get(verbosity), "INFO", get(tc), F, A). d(F) -> d(F, []). d(F, A) -> - print(debug, get(verbosity), get(tc), "DBG", F, A). + print(debug, get(verbosity), "DBG", get(tc), F, A). printable(_, debug) -> true; printable(info, info) -> true; +printable(error, _) -> true; printable(_,_) -> false. -print(Severity, Verbosity, Tc, P, F, A) -> - print(printable(Severity, Verbosity), Tc, P, F, A). +print(Severity, Verbosity, P, TC, F, A) -> + print(printable(Severity, Verbosity), P, TC, F, A). -print(true, Tc, P, F, A) -> - io:format("*** [~s] ~s ~p ~s:~w ***" - "~n " ++ F ++ "~n", - [?FTS(), P, self(), get(sname), Tc | A]); +print(true, P, TC, F, A) when (TC =:= undefined) -> + print(P, "", F, A); +print(true, P, TC, F, A) when is_atom(TC) -> + print(P, ":" ++ atom_to_list(TC), F, A); +print(true, P, TC, F, A) when is_list(TC) -> + print(P, TC, F, A); print(_, _, _, _, _) -> ok. +print(P, TCStr, F, A) -> + io:format("*** [~s] ~s ~p ~s~s ***" + "~n " ++ F ++ "~n", + [?FTS(), P, self(), get(sname), TCStr | A]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/megaco/test/megaco_test_generator.erl b/lib/megaco/test/megaco_test_generator.erl index e179f87de8..a7920e7f9e 100644 --- a/lib/megaco/test/megaco_test_generator.erl +++ b/lib/megaco/test/megaco_test_generator.erl @@ -423,7 +423,7 @@ handler_main(Parent, Mod, State, []) -> handler_main(Parent, Mod, State, [Instruction|Instructions]) -> d("handler_main -> entry with" - "~n Instruction: ~p", [Instruction]), + "~n Instruction: ~p", [Instruction]), receive {stop, Parent} -> d("handler_main -> premature stop requested"), @@ -435,6 +435,8 @@ handler_main(Parent, Mod, State, [Instruction|Instructions]) -> Result = (catch Mod:terminate({parent_died, Reason}, State)), exit({parent_died, Reason, Result}) after 0 -> + d("handler_main -> exec: " + "~n Instruction: ~p", [Instruction]), case (catch handler_callback_exec(Mod, State, Instruction)) of {ok, NewState} -> handler_main(Parent, Mod, NewState, Instructions); diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl index a337224afb..1e4b7841ee 100644 --- a/lib/megaco/test/megaco_test_lib.erl +++ b/lib/megaco/test/megaco_test_lib.erl @@ -478,8 +478,29 @@ init_per_suite(Config) -> %% This version is *not* ok: Skip true end, - COND = [{unix, [{linux, LinuxVersionVerify}, - {darwin, DarwinVersionVerify}]}], + %% We are "looking" for a specific machine (a VM) + %% which are *old and crappy" and slow, because it + %% causes a bunch of test cases to fail randomly. + %% But we don not want to test for the host name... + WinVersionVerify = + fun(V) when (V =:= {6,2,9200}) -> + try erlang:system_info(schedulers) of + 2 -> + true; + _ -> + false + catch + _:_:_ -> + true + end; + (_) -> + false + end, + COND = [ + {unix, [{linux, LinuxVersionVerify}, + {darwin, DarwinVersionVerify}]}%% , + %% {win32, [{nt, WinVersionVerify}]} + ], case os_based_skip(COND) of true -> {skip, "Unstable host and/or os (or combo thererof)"}; @@ -569,14 +590,15 @@ analyze_and_print_host_info() -> {unix, freebsd} -> analyze_and_print_freebsd_host_info(Version); {unix, sunos} -> - io:format("Solaris: ~s" - "~n", [Version]), - 2; + analyze_and_print_solaris_host_info(Version); + {win32, nt} -> + analyze_and_print_win_host_info(Version); _ -> io:format("OS Family: ~p" - "~n OS Type: ~p" - "~n Version: ~p" - "~n", [OsFam, OsName, Version]), + "~n OS Type: ~p" + "~n Version: ~p" + "~n Num Schedulers: ~s" + "~n", [OsFam, OsName, Version, str_num_schedulers()]), try erlang:system_info(schedulers) of 1 -> 10; @@ -591,6 +613,14 @@ analyze_and_print_host_info() -> 10 end end. + +str_num_schedulers() -> + try erlang:system_info(schedulers) of + N -> f("~w", [N]) + catch + _:_:_ -> "-" + end. + analyze_and_print_linux_host_info(Version) -> case file:read_file_info("/etc/issue") of @@ -607,34 +637,44 @@ analyze_and_print_linux_host_info(Version) -> case (catch linux_which_cpuinfo()) of {ok, {CPU, BogoMIPS}} -> io:format("CPU: " - "~n Model: ~s" - "~n BogoMIPS: ~s" - "~n", [CPU, BogoMIPS]), + "~n Model: ~s" + "~n BogoMIPS: ~s" + "~n Num Schedulers: ~s" + "~n", [CPU, BogoMIPS, str_num_schedulers()]), %% We first assume its a float, and if not try integer try list_to_float(string:trim(BogoMIPS)) of - F when F > 1000 -> + F when F > 4000 -> 1; F when F > 1000 -> 2; + F when F > 500 -> + 3; _ -> - 3 + 5 catch _:_:_ -> - %% try list_to_integer(string:trim(BogoMIPS)) of - I when I > 1000 -> + I when I > 4000 -> 1; I when I > 1000 -> 2; + I when I > 500 -> + 3; _ -> - 3 + 5 catch _:_:_ -> - 1 + 5 % Be a "bit" conservative... end end; + {ok, CPU} -> + io:format("CPU: " + "~n Model: ~s" + "~n Num Schedulers: ~s" + "~n", [CPU, str_num_schedulers()]), + 2; % Be a "bit" conservative... _ -> - 1 + 5 % Be a "bit" (more) conservative... end, %% Check if we need to adjust the factor because of the memory try linux_which_meminfo() of @@ -704,9 +744,9 @@ linux_which_meminfo() -> (MemSz3 >= 4194304) -> 1; (MemSz3 >= 2097152) -> - 2; + 3; true -> - 3 + 5 end; _X -> 0 @@ -813,47 +853,43 @@ analyze_and_print_freebsd_host_info(Version) -> io:format("FreeBSD:" "~n Version: ~p" "~n", [Version]), - Extract = - fun(Key) -> - string:tokens(string:trim(os:cmd("sysctl " ++ Key)), [$:]) - end, + %% This test require that the program 'sysctl' is in the path. + %% First test with 'which sysctl', if that does not work + %% try with 'which /sbin/sysctl'. If that does not work either, + %% we skip the test... try begin - CPU = - case Extract("hw.model") of - ["hw.model", Model] -> - string:trim(Model); - _ -> - "-" - end, - CPUSpeed = - case Extract("hw.clockrate") of - ["hw.clockrate", Speed] -> - list_to_integer(string:trim(Speed)); - _ -> - -1 - end, - NCPU = - case Extract("hw.ncpu") of - ["hw.ncpu", N] -> - list_to_integer(string:trim(N)); - _ -> - -1 + SysCtl = + case string:trim(os:cmd("which sysctl")) of + [] -> + case string:trim(os:cmd("which /sbin/sysctl")) of + [] -> + throw(sysctl); + SC2 -> + SC2 + end; + SC1 -> + SC1 end, - Memory = - case Extract("hw.physmem") of - ["hw.physmem", PhysMem] -> - list_to_integer(string:trim(PhysMem)) div 1024; - _ -> - -1 + Extract = + fun(Key) -> + string:tokens(string:trim(os:cmd(SysCtl ++ " " ++ Key)), + [$:]) end, + CPU = analyze_freebsd_cpu(Extract), + CPUSpeed = analyze_freebsd_cpu_speed(Extract), + NCPU = analyze_freebsd_ncpu(Extract), + Memory = analyze_freebsd_memory(Extract), io:format("CPU:" - "~n Model: ~s" - "~n Speed: ~w" - "~n N: ~w" + "~n Model: ~s" + "~n Speed: ~w" + "~n N: ~w" + "~n Num Schedulers: ~w" "~nMemory:" "~n ~w KB" - "~n", [CPU, CPUSpeed, NCPU, Memory]), + "~n", + [CPU, CPUSpeed, NCPU, + erlang:system_info(schedulers), Memory]), CPUFactor = if (CPUSpeed =:= -1) -> @@ -869,6 +905,8 @@ analyze_and_print_freebsd_host_info(Version) -> end; true -> if + (NCPU =:= -1) -> + 1; (NCPU >= 4) -> 2; (NCPU >= 2) -> @@ -894,8 +932,300 @@ analyze_and_print_freebsd_host_info(Version) -> end catch _:_:_ -> + io:format("CPU:" + "~n Num Schedulers: ~w" + "~n", [erlang:system_info(schedulers)]), + case erlang:system_info(schedulers) of + 1 -> + 10; + 2 -> + 5; + _ -> + 2 + end + end. + +analyze_freebsd_cpu(Extract) -> + analyze_freebsd_item(Extract, "hw.model", fun(X) -> X end, "-"). + +analyze_freebsd_cpu_speed(Extract) -> + analyze_freebsd_item(Extract, + "hw.clockrate", + fun(X) -> list_to_integer(X) end, + -1). + +analyze_freebsd_ncpu(Extract) -> + analyze_freebsd_item(Extract, + "hw.ncpu", + fun(X) -> list_to_integer(X) end, + -1). + +analyze_freebsd_memory(Extract) -> + analyze_freebsd_item(Extract, + "hw.physmem", + fun(X) -> list_to_integer(X) div 1024 end, + -1). + +analyze_freebsd_item(Extract, Key, Process, Default) -> + try + begin + case Extract(Key) of + [Key, Model] -> + Process(string:trim(Model)); + _ -> + Default + end + end + catch + _:_:_ -> + Default + end. + + +analyze_and_print_solaris_host_info(Version) -> + Release = + case file:read_file_info("/etc/release") of + {ok, _} -> + case [string:trim(S) || S <- string:tokens(os:cmd("cat /etc/release"), [$\n])] of + [Rel | _] -> + Rel; + _ -> + "-" + end; + _ -> + "-" + end, + %% Display the firmware device tree root properties (prtconf -b) + Props = [list_to_tuple([string:trim(PS) || PS <- Prop]) || + Prop <- [string:tokens(S, [$:]) || + S <- string:tokens(os:cmd("prtconf -b"), [$\n])]], + BannerName = case lists:keysearch("banner-name", 1, Props) of + {value, {_, BN}} -> + string:trim(BN); + _ -> + "-" + end, + InstructionSet = + case string:trim(os:cmd("isainfo -k")) of + "Pseudo-terminal will not" ++ _ -> + "-"; + IS -> + IS + end, + PtrConf = [list_to_tuple([string:trim(S) || S <- Items]) || Items <- [string:tokens(S, [$:]) || S <- string:tokens(os:cmd("prtconf"), [$\n])], length(Items) > 1], + SysConf = + case lists:keysearch("System Configuration", 1, PtrConf) of + {value, {_, SC}} -> + SC; + _ -> + "-" + end, + NumPhysProc = + begin + NPPStr = string:trim(os:cmd("psrinfo -p")), + try list_to_integer(NPPStr) of + _ -> + NPPStr + catch + _:_:_ -> + "-" + end + end, + NumProc = try integer_to_list(length(string:tokens(os:cmd("psrinfo"), [$\n]))) of + NPStr -> + NPStr + catch + _:_:_ -> + "-" + end, + MemSz = + case lists:keysearch("Memory size", 1, PtrConf) of + {value, {_, MS}} -> + MS; + _ -> + "-" + end, + io:format("Solaris: ~s" + "~n Release: ~s" + "~n Banner Name: ~s" + "~n Instruction Set: ~s" + "~n CPUs: ~s (~s)" + "~n System Config: ~s" + "~n Memory Size: ~s" + "~n Num Schedulers: ~s" + "~n~n", [Version, Release, BannerName, InstructionSet, + NumPhysProc, NumProc, + SysConf, MemSz, + str_num_schedulers()]), + MemFactor = + try string:tokens(MemSz, [$ ]) of + [SzStr, "Mega" ++ _] -> + try list_to_integer(SzStr) of + Sz when Sz > 8192 -> + 0; + Sz when Sz > 4096 -> + 1; + Sz when Sz > 2048 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + [SzStr, "Giga" ++ _] -> + try list_to_integer(SzStr) of + Sz when Sz > 8 -> + 0; + Sz when Sz > 4 -> + 1; + Sz when Sz > 2 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + _ -> + 10 + catch + _:_:_ -> + 10 + end, + try erlang:system_info(schedulers) of + 1 -> + 10; + 2 -> + 5; + N when (N =< 6) -> + 2; + _ -> 1 + catch + _:_:_ -> + 10 + end + MemFactor. + + +analyze_and_print_win_host_info(Version) -> + SysInfo = which_win_system_info(), + OsName = win_sys_info_lookup(os_name, SysInfo), + OsVersion = win_sys_info_lookup(os_version, SysInfo), + SysMan = win_sys_info_lookup(system_manufacturer, SysInfo), + NumProcs = win_sys_info_lookup(num_processors, SysInfo), + TotPhysMem = win_sys_info_lookup(total_phys_memory, SysInfo), + io:format("Windows: ~s" + "~n OS Version: ~s (~p)" + "~n System Manufacturer: ~s" + "~n Number of Processor(s): ~s" + "~n Total Physical Memory: ~s" + "~n", [OsName, OsVersion, Version, SysMan, NumProcs, TotPhysMem]), + MemFactor = + try + begin + [MStr, MUnit|_] = + string:tokens(lists:delete($,, TotPhysMem), [$\ ]), + case string:to_lower(MUnit) of + "gb" -> + try list_to_integer(MStr) of + M when M > 8 -> + 0; + M when M > 4 -> + 1; + M when M > 2 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + "mb" -> + try list_to_integer(MStr) of + M when M > 8192 -> + 0; + M when M > 4096 -> + 1; + M when M > 2048 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + _ -> + 10 + end + end + catch + _:_:_ -> + 10 + end, + CPUFactor = + case erlang:system_info(schedulers) of + 1 -> + 10; + 2 -> + 5; + _ -> + 2 + end, + CPUFactor + MemFactor. + +win_sys_info_lookup(Key, SysInfo) -> + win_sys_info_lookup(Key, SysInfo, "-"). + +win_sys_info_lookup(Key, SysInfo, Def) -> + case lists:keysearch(Key, 1, SysInfo) of + {value, {Key, Value}} -> + Value; + false -> + Def + end. + +%% This function only extracts the prop we actually care about! +which_win_system_info() -> + SysInfo = os:cmd("systeminfo"), + try process_win_system_info(string:tokens(SysInfo, [$\r, $\n]), []) + catch + _:_:_ -> + io:format("Failed process System info: " + "~s~n", [SysInfo]), + [] + end. + +process_win_system_info([], Acc) -> + Acc; +process_win_system_info([H|T], Acc) -> + case string:tokens(H, [$:]) of + [Key, Value] -> + case string:to_lower(Key) of + "os name" -> + process_win_system_info(T, + [{os_name, string:trim(Value)}|Acc]); + "os version" -> + process_win_system_info(T, + [{os_version, string:trim(Value)}|Acc]); + "system manufacturer" -> + process_win_system_info(T, + [{system_manufacturer, string:trim(Value)}|Acc]); + "processor(s)" -> + [NumProcStr|_] = string:tokens(Value, [$\ ]), + T2 = lists:nthtail(list_to_integer(NumProcStr), T), + process_win_system_info(T2, + [{num_processors, NumProcStr}|Acc]); + "total physical memory" -> + process_win_system_info(T, + [{total_phys_memory, string:trim(Value)}|Acc]); + _ -> + process_win_system_info(T, Acc) + end; + _ -> + process_win_system_info(T, Acc) end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -942,33 +1272,33 @@ try_tc(TCName, Name, Verbosity, Pre, Case, Post) p("try_tc -> starting: try pre"), try Pre() of State -> - p("try_tc -> pre done: try case"), + p("try_tc -> pre done: try test case"), try Case(State) of Res -> - p("try_tc -> case done: try post"), + p("try_tc -> test case done: try post"), (catch Post(State)), p("try_tc -> done"), Res catch throw:{skip, _} = SKIP:_ -> - p("try_tc -> case (throw) skip: try post"), + p("try_tc -> test case (throw) skip: try post"), (catch Post(State)), - p("try_tc -> case (throw) skip: done"), + p("try_tc -> test case (throw) skip: done"), SKIP; exit:{skip, _} = SKIP:_ -> - p("try_tc -> case (exit) skip: try post"), + p("try_tc -> test case (exit) skip: try post"), (catch Post(State)), - p("try_tc -> case (exit) skip: done"), + p("try_tc -> test case (exit) skip: done"), SKIP; C:E:S -> - p("try_tc -> case failed: try post"), + p("try_tc -> test case failed: try post"), (catch Post(State)), case megaco_test_global_sys_monitor:events() of [] -> - p("try_tc -> case failed: done"), + p("try_tc -> test case failed: done"), exit({case_catched, C, E, S}); SysEvs -> - p("try_tc -> case failed with system event(s): " + p("try_tc -> test case failed with system event(s): " "~n ~p", [SysEvs]), {skip, "TC failure with system events"} end diff --git a/lib/megaco/test/megaco_test_megaco_generator.erl b/lib/megaco/test/megaco_test_megaco_generator.erl index 4c2b66e3cd..4eedd8d731 100644 --- a/lib/megaco/test/megaco_test_megaco_generator.erl +++ b/lib/megaco/test/megaco_test_megaco_generator.erl @@ -377,7 +377,8 @@ handle_exec({expect_nothing, To}, State) -> "~n ~p", [Any]), error({expect_nothing, Any}) after To -> - {ok, State} + p("go nothing (~p) as expected", [To]), + {ok, State} end; handle_exec({megaco_trace, disable}, State) -> @@ -683,6 +684,7 @@ handle_exec({megaco_callback, nocall, Timeout}, State) -> Err = {unexpected_callback, Type, Msg, Pid}, {error, State#state{result = [Err|Res]}} after Timeout -> + p("got no callback (~p) as expected", [Timeout]), {ok, State} end; @@ -1090,11 +1092,16 @@ handle_megaco_callback_call(P, Msg) -> d("handle_megaco_callback_call -> deliver reply after delay [~w]", [Delay]), Reply; + {'EXIT', Pid, Reason} when (Pid =:= P) -> + d("handle_megaco_callback_call -> " + "received unexpected EXIT signal (from ~p): " + "~n Reason: ~p", [Pid, Reason]), + exit({unexpected_EXIT_signal, Pid, Reason}); {'EXIT', SomePid, SomeReason} -> d("handle_megaco_callback_call -> " - "received unexpected EXIT signal: " - "~n SomePid: ~p" - "~n SomeReason: ~p", [SomePid, SomeReason]), + "received unexpected EXIT signal from unknown process: " + "~n Pid: ~p" + "~n Reason: ~p", [SomePid, SomeReason]), exit({unexpected_EXIT_signal, SomePid, SomeReason}) end. diff --git a/lib/megaco/test/megaco_test_tcp_generator.erl b/lib/megaco/test/megaco_test_tcp_generator.erl index 04ac32b381..0edeac6733 100644 --- a/lib/megaco/test/megaco_test_tcp_generator.erl +++ b/lib/megaco/test/megaco_test_tcp_generator.erl @@ -404,6 +404,7 @@ handle_exec({expect_receive, Desc, {Verify, To}}, e("received unknown message: ~p", [Else]), {error, {expect_receive, {unexpected_message, Else}}} after To -> + e("(expect) receive timeout: ~w", [To]), {error, {expect_receive, timeout}} end; @@ -419,7 +420,7 @@ handle_exec({expect_closed, To}, {ok, State#state{connection = undefined, result = [closed|Acc]}} after To -> - e("expect_closed timeout after ~w", [To]), + e("(expect) closed timeout after ~w", [To]), {error, {expect_closed, timeout}} end; @@ -434,7 +435,7 @@ handle_exec({expect_nothing, To}, e("expect_nothing - received: ~p", [Any]), {error, {expect_nothing, Any}} after To -> - p("expect_nothing timeout after ~w", [To]), + p("got nothing (~w) as expected", [To]), {ok, State#state{result = [{nothing, To}|Acc]}} end; diff --git a/lib/megaco/test/megaco_trans_SUITE.erl b/lib/megaco/test/megaco_trans_SUITE.erl index 1703e197c5..1e281987b8 100644 --- a/lib/megaco/test/megaco_trans_SUITE.erl +++ b/lib/megaco/test/megaco_trans_SUITE.erl @@ -4397,6 +4397,10 @@ mtrtaat_err_desc(T) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Transaction Sender +%% +%% + multi_trans_req_and_ack_ackmaxcount(suite) -> []; multi_trans_req_and_ack_ackmaxcount(doc) -> @@ -4514,6 +4518,9 @@ mtrtaaamc_mgc_event_sequence(text, tcp) -> DiscoVerify = ?mtrtaaamc_mgc_verify_handle_disconnect_fun(), EvSeq = [ {debug, true}, + {trigger, fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, {megaco_trace, disable}, megaco_start, {megaco_start_user, Mid, RI, []}, @@ -4545,12 +4552,12 @@ mtrtaaamc_mgc_event_sequence(text, tcp) -> mtrtaaamc_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> - io:format("mtrtaaamc_mgc_verify_handle_connect -> ok" - "~n CH: ~p~n", [CH]), + i("MGC Connect verification ok" + "~n ~p~n", [CH]), {ok, CH, ok}; mtrtaaamc_mgc_verify_handle_connect(Else) -> - io:format("mtrtaaamc_mgc_verify_handle_connect -> unknown" - "~n Else: ~p~n", [Else]), + e("MGC Connect verification failed: unknown" + "~n ~p~n", [Else]), {error, Else, ok}. mtrtaaamc_mgc_verify_service_change_req_fun(Mid) -> @@ -4560,8 +4567,9 @@ mtrtaaamc_mgc_verify_service_change_req_fun(Mid) -> mtrtaaamc_mgc_verify_service_change_req( {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> - io:format("mtrtaaamc_mgc_verify_service_change_req -> ok" - "~n AR: ~p~n", [AR]), + i("MGC Service Change Request verification: begin" + "~n AR: ~p" + "~n", [AR]), case AR of #'ActionRequest'{commandRequests = [CR]} -> case CR of @@ -4577,11 +4585,17 @@ mtrtaaamc_mgc_verify_service_change_req( #'ServiceChangeParm'{ serviceChangeMethod = restart, serviceChangeReason = [[$9,$0,$1|_]]} -> + i("MGC Service Change Request " + "verification ok"), Reply = {discard_ack, [mtrtaaamc_mgc_service_change_reply_ar(Mid, 1)]}, {ok, AR, Reply}; _ -> + e("MGC Service Change Request " + "verification failed: invalid SCP" + "~n ~p" + "~n", [Parms]), Err = {invalid_SCP, Parms}, ED = mtrtaaamc_err_desc(Parms), ErrReply = {discard_ack, @@ -4589,32 +4603,50 @@ mtrtaaamc_mgc_verify_service_change_req( {error, Err, ErrReply} end; _ -> + e("MGC Service Change Request " + "verification failed: " + "invalid termination id" + "~n ~p" + "~n", [Tid]), Err = {invalid_termination_id, Tid}, ED = mtrtaaamc_err_desc(Tid), ErrReply = {discard_ack, ED}, {error, Err, ErrReply} end; _ -> + e("MGC Service Change Request verification failed: " + "invalid command" + "~n ~p" + "~n", [Cmd]), Err = {invalid_command, Cmd}, ED = mtrtaaamc_err_desc(Cmd), ErrReply = {discard_ack, ED}, {error, Err, ErrReply} end; _ -> + e("MGC Service Change Request verification failed: " + "invalid command request" + "~n ~p" + "~n", [CR]), Err = {invalid_command_request, CR}, ED = mtrtaaamc_err_desc(CR), ErrReply = {discard_ack, ED}, {error, Err, ErrReply} end; _ -> + e("MGC Service Change Request verification failed: " + "invalid action request" + "~n ~p" + "~n", [AR]), Err = {invalid_action_request, AR}, ED = mtrtaaamc_err_desc(AR), ErrReply = {discard_ack, ED}, {error, Err, ErrReply} end; mtrtaaamc_mgc_verify_service_change_req(Else, _Mid) -> - io:format("mtrtaaamc_mgc_verify_service_change_req -> unknown" - "~n Else: ~p~n", [Else]), + e("MGC Service Change Request verification failed: unknown" + "~n ~p" + "~n", [Else]), ED = mtrtaaamc_err_desc(Else), ErrReply = {discard_ack, ED}, {error, Else, ErrReply}. @@ -4626,9 +4658,11 @@ mtrtaaamc_mgc_verify_notify_request_fun() -> mtrtaaamc_mgc_verify_notify_request( {handle_trans_request, _, ?VERSION, [AR]}) -> - io:format("mtrtaaamc_mgc_verify_notify_request:fun -> ok" - "~n AR: ~p~n", [AR]), + i("MGC Notify Request verification: begin" + "~n AR: ~p" + "~n", [AR]), case AR of + %% *** SLOPPY ACK *** #'ActionRequest'{contextId = 1 = Cid, commandRequests = [CR]} -> #'CommandRequest'{command = Cmd} = CR, @@ -4640,9 +4674,15 @@ mtrtaaamc_mgc_verify_notify_request( observedEventLst = [OE]} = OED, #'ObservedEvent'{eventName = "al/of"} = OE, HandleAck = {handle_sloppy_ack, {kalle, Rid}}, + i("MGC Notify Request verification ok: sloppy ack" + "~n Cid: ~p" + "~n Tid: ~p" + "~n Rid: ~p", [Cid, Tid, Rid]), Reply = {HandleAck, [mtrtaaamc_mgc_notify_reply_ar(Cid, Tid)]}, {ok, AR, Reply}; + + %% *** PROPER ACK *** #'ActionRequest'{contextId = 2 = Cid, commandRequests = [CR]} -> #'CommandRequest'{command = Cmd} = CR, @@ -4650,43 +4690,54 @@ mtrtaaamc_mgc_verify_notify_request( #'NotifyRequest'{terminationID = [Tid], observedEventsDescriptor = OED, errorDescriptor = asn1_NOVALUE} = NR, - #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEventsDescriptor'{requestId = _Rid, + observedEventLst = [OE]} = OED, #'ObservedEvent'{eventName = "al/of"} = OE, + i("MGC Notify Request verification ok: discard ack" + "~n Cid: ~p" + "~n Tid: ~p" + "~n Rid: ~p", [Cid, Tid, _Rid]), Reply = {discard_ack, [mtrtaaamc_mgc_notify_reply_ar(Cid, Tid)]}, {ok, AR, Reply}; + _ -> + e("MGC Notify Request verification failed: unexpected AR" + "~n ~p" + "~n", [AR]), ED = mtrtaaamc_err_desc(AR), ErrReply = {discard_ack, ED}, {error, AR, ErrReply} end; mtrtaaamc_mgc_verify_notify_request(Else) -> - io:format("mtrtaaamc_mgc_verify_notify_request:fun -> unknown" - "~n Else: ~p~n", [Else]), + e("MGC Notify Request verification failed: unexpected callback" + "~n ~p" + "~n", [Else]), ED = mtrtaaamc_err_desc(Else), ErrReply = {discard_ack, ED}, {error, Else, ErrReply}. mtrtaaamc_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, {kalle, Rid}}) -> - io:format("mtrtaaamc_mgc_verify_ack -> ok" - "~n CH: ~p" - "~n Rid: ~p" - "~n", [CH, Rid]), + i("MGC Ack verification: ok (kalle)" + "~n CH: ~p" + "~n Rid: ~p" + "~n", [CH, Rid]), {ok, CH, ok}; mtrtaaamc_mgc_verify_ack(Else) -> - io:format("mtrtaaamc_mgc_verify_ack -> unknown" - "~n Else: ~p~n", [Else]), + e("MGC Ack verification failed: unknown" + "~n ~p~n", [Else]), {error, Else, ok}. mtrtaaamc_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> - io:format("mtrtaaamc_mgc_verify_handle_disconnect -> ok" - "~n CH: ~p" - "~n R: ~p" - "~n", [CH, R]), + i("MGC Disconnect verification: ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), {ok, CH, ok}; mtrtaaamc_mgc_verify_handle_disconnect(Else) -> - io:format("mtrtaaamc_mgc_verify_handle_disconnect -> unknown" - "~n Else: ~p~n", [Else]), + e("MGC Disconnect verification failed: unknown" + "~n ~p" + "~n", [Else]), {error, Else, ok}. @@ -4698,26 +4749,11 @@ mtrtaaamc_mgc_service_change_reply_ar(Mid, Cid) -> CR = cre_cmdReply(SCR), cre_actionReply(Cid, [CR]). -%% mtrtaaamc_mgc_service_change_reply_msg(Mid, TransId, Cid) -> -%% AR = mtrtaaamc_mgc_service_change_reply_ar(Mid, Cid), -%% TRes = cre_transResult([AR]), -%% TR = cre_transReply(TransId, TRes), -%% Trans = cre_transaction(TR), -%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), -%% cre_megacoMessage(Mess). - mtrtaaamc_mgc_notify_reply_ar(Cid, TermId) -> NR = cre_notifyReply([TermId]), CR = cre_cmdReply(NR), cre_actionReply(Cid, [CR]). -%% mtrtaaamc_mgc_notify_reply(Mid, TransId, Cid, TermId) -> -%% AR = mtrtaaamc_mgc_notify_reply_ar(Cid, TermId), -%% TRes = cre_transResult([AR]), -%% TR = cre_transReply(TransId, TRes), -%% Trans = cre_transaction(TR), -%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), -%% cre_megacoMessage(Mess). %% @@ -4757,6 +4793,9 @@ mtrtaaamc_mg_event_sequence(text, tcp) -> NotifyReplyVerify = ?mtrtaaamc_mg_verify_notify_reply_fun(), EvSeq = [ {debug, true}, + {trigger, fun() -> + put(verbosity, ?TEST_VERBOSITY) + end}, megaco_start, {megaco_start_user, Mid, RI, []}, start_transport, @@ -4780,20 +4819,35 @@ mtrtaaamc_mg_event_sequence(text, tcp) -> {megaco_update_conn_info, trans_ack, true}, {megaco_update_conn_info, trans_req, true}, {megaco_conn_info, all}, + {megaco_conn_info, requests}, {megaco_cast, NR(1,1), []}, + {megaco_conn_info, requests}, {megaco_cast, NR(1,2), []}, + {megaco_conn_info, requests}, {megaco_cast, NR(1,3), []}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {megaco_cast, NR(2,1), []}, + {megaco_conn_info, requests}, {megaco_cast, NR(2,2), []}, + {megaco_conn_info, requests}, {megaco_cast, NR(2,3), []}, + {megaco_conn_info, requests}, {megaco_cast, NR(1,4), [{trans_req,false}]}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_conn_info, requests}, {sleep, 3000}, megaco_stop_user, megaco_stop, @@ -4802,18 +4856,21 @@ mtrtaaamc_mg_event_sequence(text, tcp) -> EvSeq. mtrtaaamc_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> - io:format("mtrtaaamc_mg_verify_handle_connect -> ok" - "~n CH: ~p~n", [CH]), + i("MG Connect verification: ok" + "~n CH: ~p" + "~n", [CH]), {ok, CH, ok}; mtrtaaamc_mg_verify_handle_connect(Else) -> - io:format("mtrtaaamc_mg_verify_handle_connect -> unknown" - "~n Else: ~p~n", [Else]), + e("MG Connect verification failed: unknown" + "~n ~p" + "~n", [Else]), {error, Else, ok}. mtrtaaamc_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> - io:format("mtrtaaamc_mg_verify_service_change_reply -> ok" - "~n AR: ~p~n", [AR]), + i("MG Service Change Reply verification: begin" + "~n AR: ~p" + "~n", [AR]), case AR of #'ActionReply'{commandReply = [SCR]} -> case SCR of @@ -4827,37 +4884,73 @@ mtrtaaamc_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, {serviceChangeResParms, #'ServiceChangeResParm'{ serviceChangeMgcId = _RemoteMid}} -> + i("MG Service Change Reply verification ok"), {ok, AR, ok}; {Tag, Val} -> + e("MG Service Change Reply " + "verification failed: " + "invalid service change result" + "~n Tag: ~p" + "~n Val: ~p" + "~n", [Tag, Val]), Err = {invalid_service_change_result, Tag, Val}, {error, Err, ok} end; _ -> + e("MG Service Change Reply verification failed: " + "invalid termination id" + "~n ~p" + "~n", [Tid]), Err = {invalid_termination_id, Tid}, {error, Err, ok} end; {Tag, Val} -> + e("MG Service Change Reply verification failed: " + "invalid command reply" + "~n Tag: ~p" + "~n Val: ~p" + "~n", [Tag, Val]), Err = {invalid_command_reply, Tag, Val}, {error, Err, ok} end; _ -> + e("MG Service Change Reply verification failed: invalid action reply" + "~n ~p" + "~n", [AR]), Err = {invalid_action_reply, AR}, {error, Err, ok} end; mtrtaaamc_mg_verify_service_change_reply(Else) -> - io:format("mtrtaaamc_mg_verify_service_change_reply -> unknown" - "~n Else: ~p~n", [Else]), + e("MG Service Change Reply verification failed -> unknown" + "~n ~p" + "~n", [Else]), {error, Else, ok}. mtrtaaamc_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> - io:format("mtrtaaamc_mg_verify_notify_reply -> ok" - "~n AR: ~p~n", [AR]), + i("MG Notify Reply verification ok:" + "~n ~p~n", [AR]), {ok, AR, ok}; +mtrtaaamc_mg_verify_notify_reply({handle_unexpected_trans, CH, PV, T} = Else) -> + e("MG Notify Reply verification failed: unexpected transaction" + "~n CH: ~p" + "~n PV: ~p" + "~n T: ~p" + "~n", [CH, PV, T]), + {error, Else, ok}; +mtrtaaamc_mg_verify_notify_reply({handle_unexpected_trans, CH, PV, E, T} = Else) -> + e("MG Notify Reply failed: unexpected transaction" + "~n CH: ~p" + "~n PV: ~p" + "~n E: ~p" + "~n T: ~p" + "~n", [CH, PV, E, T]), + {error, Else, ok}; mtrtaaamc_mg_verify_notify_reply(Else) -> - io:format("mtrtaaamc_mg_verify_notify_reply -> unknown" - "~n Else: ~p~n", [Else]), + e("MG Notify Reply failed -> unknown" + "~n ~p" + "~n", [Else]), {error, Else, ok}. mtrtaaamc_mg_service_change_request_ar(_Mid, Cid) -> @@ -4869,13 +4962,6 @@ mtrtaaamc_mg_service_change_request_ar(_Mid, Cid) -> CR = cre_cmdReq(CMD), cre_actionReq(Cid, [CR]). -%% mtrtaaamc_mg_service_change_request_msg(Mid, TransId, Cid) -> -%% AR = mtrtaaamc_mg_service_change_request_ar(Mid, Cid), -%% TR = cre_transReq(TransId, [AR]), -%% Trans = cre_transaction(TR), -%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), -%% cre_megacoMessage(Mess). - mtrtaaamc_mg_notify_request_ar(Rid, Tid, Cid) -> TT = cre_timeNotation("19990729", "22000000"), Ev = cre_obsEvent("al/of", TT), @@ -4885,13 +4971,6 @@ mtrtaaamc_mg_notify_request_ar(Rid, Tid, Cid) -> CR = cre_cmdReq(CMD), cre_actionReq(Cid, [CR]). -%% mtrtaaamc_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> -%% AR = mtrtaaamc_mg_notify_request_ar(Rid, TermId, Cid), -%% TR = cre_transReq(TransId, [AR]), -%% Trans = cre_transaction(TR), -%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), -%% cre_megacoMessage(Mess). - %% %% Common functions for the multi_trans_req_timeout test case @@ -5376,7 +5455,7 @@ mtrtaarac_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, "~n AR: ~p~n", [AR]), {ok, AR, ok}; mtrtaarac_mg_verify_notify_reply(Else) -> - e("mtrtaarac_mg_verify_notify_reply -> invalid notify reply" + e("MG Notify Reply verification failed: invalid notify reply" "~n Expected: handle_trans_reply with ok" "~n Received: ~p", [Else]), {error, Else, ok}. @@ -6946,38 +7025,6 @@ mtraaap_mg_verify_service_change_reply(Else) -> "~n Else: ~p~n", [Else]), {error, Else, ok}. -%% mtraaap_mg_verify_notify_request_fun() -> -%% fun(Ev) -> -%% mtraaap_mg_verify_notify_request(Ev) -%% end. - -%% mtraaap_mg_verify_notify_request( -%% {handle_trans_request, _, ?VERSION, [AR]}) -> -%% io:format("mtraaap_mg_verify_notify_request -> ok" -%% "~n AR: ~p~n", [AR]), -%% case AR of -%% #'ActionRequest'{contextId = 1 = Cid, -%% commandRequests = [CR]} -> -%% #'CommandRequest'{command = Cmd} = CR, -%% {notifyReq, NR} = Cmd, -%% #'NotifyRequest'{terminationID = [Tid], -%% observedEventsDescriptor = OED, -%% errorDescriptor = asn1_NOVALUE} = NR, -%% #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, -%% #'ObservedEvent'{eventName = "al/of"} = OE, -%% Reply = {discard_ack, [mtraaap_mg_notify_reply_ar(Cid, Tid)]}, -%% {ok, 3000, AR, Reply}; -%% _ -> -%% ED = mtraaap_err_desc(AR), -%% ErrReply = {discard_ack, ED}, -%% {error, AR, ErrReply} -%% end; -%% mtraaap_mg_verify_notify_request(Else) -> -%% io:format("mtraaap_mg_verify_notify_request:fun -> unknown" -%% "~n Else: ~p~n", [Else]), -%% ED = mtraaap_err_desc(Else), -%% ErrReply = {discard_ack, ED}, -%% {error, Else, ErrReply}. mtraaap_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> @@ -8325,7 +8372,7 @@ otp71922_mgc_event_sequence(text, tcp, MgMid) -> {encoding_config, []}, {transport_module, megaco_tcp} ], - Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + Tid = #megaco_term_id{id = ["00000000","00000100","01101101"]}, NR = fun(Cid, Rid) -> [otp71922_mgc_notify_request_ar(Rid, Tid, Cid)] end, @@ -8368,12 +8415,14 @@ otp71922_mgc_event_sequence(text, tcp, MgMid) -> otp71922_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> - io:format("otp71922_mgc_verify_handle_connect -> ok" - "~n CH: ~p~n", [CH]), + i("received expected handle_connect with" + "~n CH: ~p" + "~n => force a 2 second sleep before return", [CH]), {ok, timer:seconds(2), CH, ok}; otp71922_mgc_verify_handle_connect(Else) -> - io:format("otp71922_mgc_verify_handle_connect -> unknown" - "~n Else: ~p~n", [Else]), + e("otp71922_mgc_verify_handle_connect -> invalid handle-connect: " + "~n Extected: handle_connect" + "~n Received: ~p", [Else]), {error, Else, ok}. otp71922_mgc_verify_service_change_req_fun(Mid) -> @@ -8383,8 +8432,8 @@ otp71922_mgc_verify_service_change_req_fun(Mid) -> otp71922_mgc_verify_service_change_req( {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> - io:format("otp71922_mgc_verify_service_change_req -> ok" - "~n AR: ~p~n", [AR]), + i("otp71922_mgc_verify_service_change_req -> ok" + "~n AR: ~p", [AR]), case AR of #'ActionRequest'{commandRequests = [CR]} -> case CR of @@ -8595,8 +8644,11 @@ otp71922_mg_event_sequence(text, tcp, Mid) -> {transport_module, megaco_tcp} ], ServiceChangeReq = [otp71922_mg_service_change_request_ar(Mid, 1)], - Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, - NR = fun(Cid, Rid) -> + %% This is so that we can match notify request and reply + Tid1 = #megaco_term_id{id = ["00000000","00000001","01101101"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000010","01101101"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000011","01101101"]}, + NR = fun(Cid, Rid, Tid) -> [otp71922_mg_notify_request_ar(Rid, Tid, Cid)] end, ConnectVerify = ?otp71922_mg_verify_handle_connect_fun(), @@ -8629,20 +8681,20 @@ otp71922_mg_event_sequence(text, tcp, Mid) -> {megaco_update_conn_info, trans_ack, true}, {megaco_update_conn_info, trans_req, true}, {megaco_conn_info, all}, - {megaco_cast, NR(1,1), []}, - {megaco_cast, NR(1,2), []}, - {megaco_cast, NR(1,3), []}, + {megaco_cast, NR(1,1,Tid1), []}, + {megaco_cast, NR(1,2,Tid2), []}, + {megaco_cast, NR(1,3,Tid3), []}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, {megaco_callback, handle_trans_reply, NotifyReplyVerify}, {megaco_update_conn_info, trans_timer, 120000}, - {megaco_cast, NR(2,1), []}, - {megaco_cast, NR(2,2), []}, - {megaco_cast, NR(2,3), []}, + {megaco_cast, NR(2,1,Tid1), []}, + {megaco_cast, NR(2,2,Tid2), []}, + {megaco_cast, NR(2,3,Tid3), []}, {megaco_callback, handle_trans_request, NotifyReqVerify}, - {megaco_callback, handle_trans_reply, NotifyReplyVerify}, - {megaco_callback, handle_trans_reply, NotifyReplyVerify}, - {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, {sleep, 3000}, megaco_stop_user, megaco_stop, @@ -8651,18 +8703,17 @@ otp71922_mg_event_sequence(text, tcp, Mid) -> EvSeq. otp71922_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> - io:format("otp71922_mg_verify_handle_connect -> ok" - "~n CH: ~p~n", [CH]), + i("received expected handle_connect:" + "~n CH: ~p", [CH]), {ok, CH, ok}; otp71922_mg_verify_handle_connect(Else) -> - io:format("otp71922_mg_verify_handle_connect -> unknown" - "~n Else: ~p~n", [Else]), + e("otp71922_mg_verify_handle_connect -> received unexpected:" + "~n Expected: handle_connect" + "~n Received: ~p", [Else]), {error, Else, ok}. otp71922_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> - io:format("otp71922_mg_verify_service_change_reply -> ok" - "~n AR: ~p~n", [AR]), case AR of #'ActionReply'{commandReply = [SCR]} -> case SCR of @@ -8676,70 +8727,55 @@ otp71922_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, {serviceChangeResParms, #'ServiceChangeResParm'{ serviceChangeMgcId = _RemoteMid}} -> + i("received expected handle_trans_reply " + "(service change) with ok" + "~n AR: ~p", [AR]), {ok, AR, ok}; {Tag, Val} -> + e("received expected handle_trans_reply " + "(service change) with error" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), Err = {invalid_service_change_result, Tag, Val}, {error, Err, ok} end; _ -> + e("received expected handle_trans_reply " + "(service change) with error" + "~n Tid: ~p", [Tid]), Err = {invalid_termination_id, Tid}, {error, Err, ok} end; {Tag, Val} -> + e("received expected handle_trans_reply " + "(action reply) with error" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), Err = {invalid_command_reply, Tag, Val}, {error, Err, ok} end; _ -> + e("received expected handle_trans_reply with error" + "~n AR: ~p", [AR]), Err = {invalid_action_reply, AR}, {error, Err, ok} end; otp71922_mg_verify_service_change_reply(Else) -> - io:format("otp71922_mg_verify_service_change_reply -> unknown" - "~n Else: ~p~n", [Else]), + e("invalid service change reply:" + "~n Expected: handle_trans_reply" + "~n Received: ~p", [Else]), {error, Else, ok}. -%% otp71922_mg_verify_notify_request_fun() -> -%% fun(Ev) -> -%% otp71922_mg_verify_notify_request(Ev) -%% end. - -%% otp71922_mg_verify_notify_request( -%% {handle_trans_request, _, ?VERSION, [AR]}) -> -%% io:format("otp71922_mg_verify_notify_request -> ok" -%% "~n AR: ~p~n", [AR]), -%% case AR of -%% #'ActionRequest'{contextId = 1 = Cid, -%% commandRequests = [CR]} -> -%% #'CommandRequest'{command = Cmd} = CR, -%% {notifyReq, NR} = Cmd, -%% #'NotifyRequest'{terminationID = [Tid], -%% observedEventsDescriptor = OED, -%% errorDescriptor = asn1_NOVALUE} = NR, -%% #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, -%% #'ObservedEvent'{eventName = "al/of"} = OE, -%% Reply = {discard_ack, [otp71922_mg_notify_reply_ar(Cid, Tid)]}, -%% {ok, AR, Reply}; -%% _ -> -%% ED = otp71922_err_desc(AR), -%% ErrReply = {discard_ack, ED}, -%% {error, AR, ErrReply} -%% end; -%% otp71922_mg_verify_notify_request(Else) -> -%% io:format("otp71922_mg_verify_notify_request -> unknown" -%% "~n Else: ~p~n", [Else]), -%% ED = otp71922_err_desc(Else), -%% ErrReply = {discard_ack, ED}, -%% {error, Else, ErrReply}. - otp71922_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> - io:format("otp71922_mg_verify_notify_reply -> ok" - "~n AR: ~p~n", [AR]), + i("received expected handle_notify_reply -> ok" + "~n AR: ~p", [AR]), {ok, AR, ok}; otp71922_mg_verify_notify_reply(Else) -> - io:format("otp71922_mg_verify_notify_reply -> unknown" - "~n Else: ~p~n", [Else]), + e("otp71922_mg_verify_notify_reply -> invalid notify reply" + "~n Expected: handle_trans_reply with ok" + "~n Received: ~p", [Else]), {error, Else, ok}. otp71922_mg_service_change_request_ar(_Mid, Cid) -> @@ -8751,18 +8787,6 @@ otp71922_mg_service_change_request_ar(_Mid, Cid) -> CR = cre_cmdReq(CMD), cre_actionReq(Cid, [CR]). -%% otp71922_mg_service_change_request_msg(Mid, TransId, Cid) -> -%% AR = otp71922_mg_service_change_request_ar(Mid, Cid), -%% TR = cre_transReq(TransId, [AR]), -%% Trans = cre_transaction(TR), -%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), -%% cre_megacoMessage(Mess). - -%% otp71922_mg_notify_reply_ar(Cid, TermId) -> -%% NR = cre_notifyReply([TermId]), -%% CR = cre_cmdReply(NR), -%% cre_actionReply(Cid, [CR]). - otp71922_mg_notify_request_ar(Rid, Tid, Cid) -> TT = cre_timeNotation("19990729", "22000000"), Ev = cre_obsEvent("al/of", TT), @@ -8772,13 +8796,6 @@ otp71922_mg_notify_request_ar(Rid, Tid, Cid) -> CR = cre_cmdReq(CMD), cre_actionReq(Cid, [CR]). -%% otp71922_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> -%% AR = otp71922_mg_notify_request_ar(Rid, TermId, Cid), -%% TR = cre_transReq(TransId, [AR]), -%% Trans = cre_transaction(TR), -%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), -%% cre_megacoMessage(Mess). - %% %% Common functions for the multi_trans_req_timeout test case @@ -9632,11 +9649,13 @@ printable(info, info) -> true; printable(error, _) -> true; printable(_,_) -> false. - print2(true, P, F, A) -> - S = ?F("*** [~s] ~s ~p ~w ***" + S = ?F("*** [~s] ~s ~p~s ***" "~n " ++ F ++ "~n" - "~n", [?FTS(), P, self(), get(tc) | A]), + "~n", [?FTS(), P, self(), case get(tc) of + undefined -> ""; + TC -> " " ++ atom_to_list(TC) + end | A]), io:format("~s", [S]); print2(_, _, _, _) -> ok. diff --git a/lib/public_key/asn1/PKIX1Algorithms88.asn1 b/lib/public_key/asn1/PKIX1Algorithms88.asn1 index 6cc6745af6..207ab005a9 100644 --- a/lib/public_key/asn1/PKIX1Algorithms88.asn1 +++ b/lib/public_key/asn1/PKIX1Algorithms88.asn1 @@ -283,4 +283,12 @@ sect571k1 OBJECT IDENTIFIER ::= { ellipticCurve 38 } sect571r1 OBJECT IDENTIFIER ::= { ellipticCurve 39 } + + id-edwards-curve-algs OBJECT IDENTIFIER ::= { 1 3 101 } + + id-X25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 110 } + id-X448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 111 } + id-Ed25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 112 } + id-Ed448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 113 } + END diff --git a/lib/public_key/src/pubkey_cert_records.erl b/lib/public_key/src/pubkey_cert_records.erl index 6a80874df8..1c79f904f3 100644 --- a/lib/public_key/src/pubkey_cert_records.erl +++ b/lib/public_key/src/pubkey_cert_records.erl @@ -113,7 +113,8 @@ supportedPublicKeyAlgorithms(?'id-keyExchangeAlgorithm') -> 'KEA-PublicKey'; supportedPublicKeyAlgorithms(?'id-ecPublicKey') -> 'ECPoint'. supportedCurvesTypes(?'characteristic-two-field') -> characteristic_two_field; -supportedCurvesTypes(?'prime-field') -> prime_field. +supportedCurvesTypes(?'prime-field') -> prime_field; +supportedCurvesTypes(?'id-edwards-curve-algs') -> edwards_curve. namedCurves(?'sect571r1') -> sect571r1; namedCurves(?'sect571k1') -> sect571k1; @@ -148,6 +149,8 @@ namedCurves(?'sect163r1') -> sect163r1; namedCurves(?'sect163k1') -> sect163k1; namedCurves(?'secp256r1') -> secp256r1; namedCurves(?'secp192r1') -> secp192r1; +namedCurves(?'id-X25519') -> x25519; +namedCurves(?'id-X448') -> x448; namedCurves(?'brainpoolP160r1') -> brainpoolP160r1; namedCurves(?'brainpoolP160t1') -> brainpoolP160t1; namedCurves(?'brainpoolP192r1') -> brainpoolP192r1; @@ -162,7 +165,6 @@ namedCurves(?'brainpoolP384r1') -> brainpoolP384r1; namedCurves(?'brainpoolP384t1') -> brainpoolP384t1; namedCurves(?'brainpoolP512r1') -> brainpoolP512r1; namedCurves(?'brainpoolP512t1') -> brainpoolP512t1; - namedCurves(sect571r1) -> ?'sect571r1'; namedCurves(sect571k1) -> ?'sect571k1'; namedCurves(sect409r1) -> ?'sect409r1'; @@ -196,6 +198,8 @@ namedCurves(sect163r1) -> ?'sect163r1'; namedCurves(sect163k1) -> ?'sect163k1'; namedCurves(secp256r1) -> ?'secp256r1'; namedCurves(secp192r1) -> ?'secp192r1'; +namedCurves(x25519) -> ?'id-X25519'; +namedCurves(x448) -> ?'id-X448'; namedCurves(brainpoolP160r1) -> ?'brainpoolP160r1'; namedCurves(brainpoolP160t1) -> ?'brainpoolP160t1'; namedCurves(brainpoolP192r1) -> ?'brainpoolP192r1'; diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 47266c514c..ce5151750d 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -1536,6 +1536,10 @@ ec_curve_spec({ecParameters, ECParams}) -> ec_curve_spec(ECParams); ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) -> ec_curve_spec({namedCurve, pubkey_cert_records:namedCurves(OID)}); +ec_curve_spec({namedCurve, x25519 = Name}) -> + Name; +ec_curve_spec({namedCurve, x448 = Name}) -> + Name; ec_curve_spec({namedCurve, Name}) when is_atom(Name) -> crypto:ec_curve(Name). diff --git a/lib/snmp/doc/src/snmp_agent_netif.xml b/lib/snmp/doc/src/snmp_agent_netif.xml index a8dea5ab7b..66a1bd900f 100644 --- a/lib/snmp/doc/src/snmp_agent_netif.xml +++ b/lib/snmp/doc/src/snmp_agent_netif.xml @@ -36,7 +36,7 @@ <image file="snmp_agent_netif_1.gif"> <icaption>The Purpose of Agent Net if</icaption> </image> - <p>The Network Interface (Net if) process delivers SNMP PDUs to a + <p>The Network Interface (Net If) process delivers SNMP PDUs to a master agent, and receives SNMP PDUs from the master agent. The most common behaviour of a Net if process is that is receives bytes from a network, decodes them into an SNMP PDU, which it sends to a master @@ -70,7 +70,7 @@ <marker id="messages"></marker> <title>Messages</title> <p>The section <em>Messages</em> describes mandatory messages, which - Net if must send and be able to receive. + Net If must send and be able to receive. </p> <p>In this section an <c>Address</c> field is a <c>{Domain, Addr}</c> tuple where <c>Domain</c> is diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml index 54a7eafe76..978aff59b1 100644 --- a/lib/snmp/doc/src/snmp_app.xml +++ b/lib/snmp/doc/src/snmp_app.xml @@ -4,7 +4,7 @@ <appref> <header> <copyright> - <year>1997</year><year>2019</year> + <year>1997</year><year>2020</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -594,7 +594,7 @@ in the snmp_config file! <tag><marker id="manager_server"></marker> <c><![CDATA[server() = [server_opt()] <optional>]]></c></tag> <item> - <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()} | {cbproxy, server_cbproxy()}</c></p> + <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()} | {cbproxy, server_cbproxy()} | {netif_sup, server_nis()}</c></p> <p>Specifies the options for the manager server process.</p> <p>Default is <c>silence</c>.</p> </item> @@ -641,6 +641,36 @@ in the snmp_config file! <p>Default is <c>temporary</c>.</p> </item> + <tag><marker id="manager_server_nis"></marker> + <c><![CDATA[server_nis() = none (default) | {PingTO, PongTO} <optional>]]></c></tag> + <item> + <p>This option specifies if the server should actively supervise the + net-if process. + Note that this will only work if the used net-if process actually supports + the protocol. See + <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour for more info. </p> + <taglist> + <tag><marker id="manager_server_nis_none"></marker> + <c><![CDATA[none (default)]]></c></tag> + <item> + <p>No active supervision of the net-if process. </p> + </item> + + <tag><marker id="manager_server_nis_active"></marker> + <c><![CDATA[{PingTO :: pos_integer(), PongTO :: pos_integer()}]]></c></tag> + <item> + <p>The <c>PingTO</c> time specifies the between a successful ping + (or start) and the time when a ping message is to be sent to the net-if + process (basically the time between ping). </p> + <p>The <c>PongTO</c> time specifies how long time the net-if process + has to respond to a ping message, with a <em>pong</em> message. + Its starts counting when the ping message has been sent.</p> + <p>Both times are in milli seconds.</p> + </item> + </taglist> + <p>Default is <c>none</c>.</p> + </item> + <tag><marker id="manager_config"></marker> <c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag> <item> diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index d615edcec0..79c6703c94 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2016</year> + <year>1997</year><year>2020</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -612,7 +612,7 @@ in so far as it will be converted to the new format if found. <tag><marker id="manager_server"></marker> <c><![CDATA[server() = [server_opt()] <optional>]]></c></tag> <item> - <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()} | {cbproxy, server_cbproxy()}</c></p> + <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()} | {cbproxy, server_cbproxy()} | {netif_sup, server_nis()}</c></p> <p>Specifies the options for the manager server process.</p> <p>Default is <c>silence</c>.</p> </item> @@ -659,6 +659,40 @@ in so far as it will be converted to the new format if found. <p>Default is <c>temporary</c>.</p> </item> + <tag><marker id="manager_server_nis"></marker> + <c><![CDATA[server_nis() = none (default) | {PingTO, PongTO} <optional>]]></c></tag> + <item> + <p>This option specifies if the server should actively supervise the + net-if process. + Note that this will only work if the used net-if process actually supports + the protocol. See + <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour for more info. </p> + <taglist> + <tag><marker id="manager_server_nis_none"></marker> + <c><![CDATA[none (default)]]></c></tag> + <item> + <p>No active supervision of the net-if process. </p> + </item> + + <tag><marker id="manager_server_nis_active"></marker> + <c><![CDATA[{PingTO :: pos_integer(), PongTO :: pos_integer()}]]></c></tag> + <item> + <p>The <c>PingTO</c> time specifies the between a successful ping + (or start) and the time when a + <seealso marker="snmp_manager_netif#im_ping">ping</seealso> + message is to be sent to the net-if + process (basically the time between ping:s). </p> + <p>The <c>PongTO</c> time specifies how long time the net-if process + has to respond to a ping message, with a + <seealso marker="snmp_manager_netif#om_pong">pong</seealso> + message. + It starts counting when the ping message has been sent.</p> + <p>Both times are in milli seconds.</p> + </item> + </taglist> + <p>Default is <c>none</c>.</p> + </item> + <tag><marker id="manager_config"></marker> <c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag> <item> diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml index 0dfcdbda0d..9825f3f3bd 100644 --- a/lib/snmp/doc/src/snmp_manager_netif.xml +++ b/lib/snmp/doc/src/snmp_manager_netif.xml @@ -37,7 +37,7 @@ <icaption>The Purpose of Manager Net if</icaption> </image> - <p>The Network Interface (Net if) process delivers SNMP PDUs to the + <p>The Network Interface (Net If) process delivers SNMP PDUs to the manager server, and receives SNMP PDUs from the manager server. The most common behaviour of a Net if process is that is receives request PDU from the manager server, encodes the PDU into bytes @@ -54,131 +54,186 @@ both uses UDP as the transport protocol i.e the transport domains <c>transportDomainUdpIpv4</c> and/or <c>transportDomainUdpIpv6</c>. The difference between the two modules is that the latter is - "multi-threaded", i.e. for each message/request a new process + "multi-threaded", i.e. for each message/request a new process is created that processes the message/request and then exits. </p> + <p>There is a <c>server</c> config option, + <seealso marker="snmp_config#manager_server_nis">netif_sup</seealso> + that enables "active" Net If supervision. This is very simple mechanism. + The (supervising) process simply sends a + <seealso marker="#im_ping">ping</seealso> message and expects a + <seealso marker="#om_pong">pong</seealso> message response + (withing a specific time). + The interval between each <c>ping/pong</c> exhange is user configurable. + As is the time that is allowed for the + <seealso marker="#om_pong">pong</seealso> + message to arrive. + Both the NetIf module(s) provided with the app supports active supervision. + If a NetIf module/process is used which do not implement this, then + the server cannot be configured with active supervision. </p> + <p>It is also possible to write your own Net if process and this section describes how to do that.</p> <section> <marker id="mandatory_functions"></marker> <title>Mandatory Functions</title> - <p>A Net if process must implement the SNMP manager + <p>A Net If process must implement the SNMP manager <seealso marker="snmpm_network_interface">network interface behaviour</seealso>. </p> </section> <section> <title>Messages</title> - <p>The section <em>Messages</em> describes mandatory messages, which - Net if must send to the manager server process. - </p> + <p>The section <em>Messages</em> describes mandatory (with exception + for the ping/pong messages) messages, + which Net If must send to the manager server process. </p> <p>In this section a <c>Domain</c> field is the transport domain i.e one of <c>transportDomainUdpIpv4</c> or <c>transportDomainUdpIpv6</c>, and an <c>Addr</c> field is an <c>{</c><seealso marker="kernel:inet#type-ip_address"><c>IpAddr</c></seealso><c>,IpPort}</c> tuple.</p> - <p>Net if must send the following message when it receives an - SNMP PDU from the network that is aimed for the MasterAgent: - </p> - <pre> + <section> + <marker id="outgoing_messages"></marker> + <title>Outgoing Messages</title> + + <p>Net if must send the following message when it receives an + SNMP PDU from the network that is aimed for the MasterAgent: </p> + <pre> Server ! {snmp_pdu, Pdu, Domain, Addr} - </pre> - <list type="bulleted"> - <item> - <p><c>Pdu</c> is an SNMP PDU record, as defined in - <c>snmp_types.hrl</c>, with the SNMP request.</p> - </item> - <item> - <p><c>Domain</c> is the source transport domain. </p> - </item> - <item> - <p><c>Addr</c> is the source address. </p> - </item> - </list> - <pre> + </pre> + <list type="bulleted"> + <item> + <p><c>Pdu</c> is an SNMP PDU record, as defined in + <c>snmp_types.hrl</c>, with the SNMP request.</p> + </item> + <item> + <p><c>Domain</c> is the source transport domain. </p> + </item> + <item> + <p><c>Addr</c> is the source address. </p> + </item> + </list> + + <pre> Server ! {snmp_trap, Trap, Domain, Addr} - </pre> - <list type="bulleted"> - <item> - <p><c>Trap</c> is either an SNMP pdu record or an trappdu record, - as defined in <c>snmp_types.hrl</c>, with the SNMP request.</p> - </item> - <item> - <p><c>Domain</c> is the source transport domain. </p> - </item> - <item> - <p><c>Addr</c> is the source address. </p> - </item> - </list> - <pre> + </pre> + <list type="bulleted"> + <item> + <p><c>Trap</c> is either an SNMP pdu record or an trappdu record, + as defined in <c>snmp_types.hrl</c>, with the SNMP request.</p> + </item> + <item> + <p><c>Domain</c> is the source transport domain. </p> + </item> + <item> + <p><c>Addr</c> is the source address. </p> + </item> + </list> + + <pre> Server ! {snmp_inform, Ref, Pdu, PduMS, Domain, Addr} - </pre> - <list type="bulleted"> - <item> - <p><c>Ref</c> is either the atom <c>ignore</c> or something - that can be used to identify the inform-request (e.g. request-id). - <c>ignore</c> is used if the response (acknowledgment) to the - inform-request has already been sent (this means that the server - will not make the call to the - <seealso marker="snmpm_network_interface#inform_response">inform_response</seealso> - function). See the - <seealso marker="snmp_config#manager_irb">inform request behaviour</seealso> - configuration option for more info.</p> - </item> - <item> - <p><c>Pdu</c> is an SNMP PDU record, as defined in - <c>snmp_types.hrl</c>, with the SNMP request.</p> - </item> - <item> - <p><c>Domain</c> is the source transport domain. </p> - </item> - <item> - <p><c>Addr</c> is the source address. </p> - </item> - </list> - <pre> + </pre> + <list type="bulleted"> + <item> + <p><c>Ref</c> is either the atom <c>ignore</c> or something + that can be used to identify the inform-request (e.g. request-id). + <c>ignore</c> is used if the response (acknowledgment) to the + inform-request has already been sent (this means that the server + will not make the call to the + <seealso marker="snmpm_network_interface#inform_response">inform_response</seealso> + function). See the + <seealso marker="snmp_config#manager_irb">inform request behaviour</seealso> + configuration option for more info.</p> + </item> + <item> + <p><c>Pdu</c> is an SNMP PDU record, as defined in + <c>snmp_types.hrl</c>, with the SNMP request.</p> + </item> + <item> + <p><c>Domain</c> is the source transport domain. </p> + </item> + <item> + <p><c>Addr</c> is the source address. </p> + </item> + </list> + + <pre> Server ! {snmp_report, Data, Domain, Addr} - </pre> - <list type="bulleted"> - <item> - <p><c>Data</c> is either <c>{ok, Pdu}</c> or - <c>{error, ReqId, ReasonInfo, Pdu}</c>. Which one is used depends - on the return value from the MPD - <seealso marker="snmpm_mpd#process_msg">process_msg</seealso> function. If the MsgData is <c>ok</c>, - the first is used, and if it is <c>{error, ReqId, Reason}</c> - the latter is used.</p> - </item> - <item> - <p><c>Pdu</c> is an SNMP PDU record, as defined in - <c>snmp_types.hrl</c>, with the SNMP request.</p> - </item> - <item> - <p><c>ReqId</c> is an integer.</p> - </item> - <item> - <p><c>ReasonInfo</c> is a term().</p> - </item> - <item> - <p><c>Domain</c> is the source transport domain. </p> - </item> - <item> - <p><c>Addr</c> is the source address. </p> - </item> - </list> + </pre> + <list type="bulleted"> + <item> + <p><c>Data</c> is either <c>{ok, Pdu}</c> or + <c>{error, ReqId, ReasonInfo, Pdu}</c>. Which one is used depends + on the return value from the MPD + <seealso marker="snmpm_mpd#process_msg">process_msg</seealso> function. If the MsgData is <c>ok</c>, + the first is used, and if it is <c>{error, ReqId, Reason}</c> + the latter is used.</p> + </item> + <item> + <p><c>Pdu</c> is an SNMP PDU record, as defined in + <c>snmp_types.hrl</c>, with the SNMP request.</p> + </item> + <item> + <p><c>ReqId</c> is an integer.</p> + </item> + <item> + <p><c>ReasonInfo</c> is a term().</p> + </item> + <item> + <p><c>Domain</c> is the source transport domain. </p> + </item> + <item> + <p><c>Addr</c> is the source address. </p> + </item> + </list> + + <marker id="om_pong"></marker> + <pre> +Supervisor ! {pong, self()} + </pre> + <list type="bulleted"> + <item> + <p><c>Supervisor</c> is the process that sent the + <seealso marker="#im_ping">ping</seealso> message (see below). </p> + </item> + </list> + </section> <section> - <title>Notes</title> - <p>Since the Net if process is responsible for encoding and - decoding of SNMP messages, it must also update the relevant - counters in the SNMP group in MIB-II. It can use the functions - in the module <c>snmpm_mpd</c> for this purpose (refer to the - Reference Manual, section <c>snmp</c>, module <c>snmpm_mpd</c> - for more details). - </p> - <p>There are also some useful functions for encoding and - decoding of SNMP messages in the module <c>snmp_pdus</c>. - </p> + <marker id="incoming_messages"></marker> + <title>Incoming Messages</title> + <p>This section describes the incoming messages which a Net If + process may choose to respond to. </p> + + <list type="bulleted"> + <item> + <marker id="im_ping"></marker> + <p><c>{ping, Supervisor}</c></p> + <p>This message is sent to the Net If process by a process that + has been configured to perfor "active supervision" of the Net If + process. The Net If process should respond immediately with + a <seealso marker="#om_pong">pong</seealso> message. </p> + <list type="bulleted"> + <item> + <p><c>Supervisor</c> is a <c>pid()</c>. </p> + </item> + </list> + </item> + </list> </section> </section> + + <section> + <title>Notes</title> + <p>Since the Net if process is responsible for encoding and + decoding of SNMP messages, it must also update the relevant + counters in the SNMP group in MIB-II. It can use the functions + in the module <c>snmpm_mpd</c> for this purpose (refer to the + Reference Manual, section <c>snmp</c>, module <c>snmpm_mpd</c> + for more details). </p> + + <p>There are also some useful functions for encoding and + decoding of SNMP messages in the module <c>snmp_pdus</c>. </p> + </section> </chapter> diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index c45df98ee0..71308dcf80 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2004</year><year>2018</year> + <year>2004</year><year>2020</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1487,6 +1487,21 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1 verbosity <c>silence</c>, nothing is printed. The higher the verbosity, the more is printed.</p> + <marker id="restart"></marker> + </desc> + </func> + + <func> + <name since="">restart(Ref) -> void()</name> + <fsummary>Restart the indicated process</fsummary> + <type> + <v>Ref = net_if</v> + </type> + <desc> + <p>Restart the indicated process (<c>Ref</c>). Note that its not + without risk to restart a process, and should therefor be used + with care. </p> + <marker id="format_reason"></marker> </desc> </func> diff --git a/lib/snmp/doc/src/snmpm_user.xml b/lib/snmp/doc/src/snmpm_user.xml index c961300490..fe0ac0b0d2 100644 --- a/lib/snmp/doc/src/snmpm_user.xml +++ b/lib/snmp/doc/src/snmpm_user.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2004</year><year>2016</year> + <year>2004</year><year>2020</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -96,7 +96,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(), <name since="">handle_error(ReqId, Reason, UserData) -> void()</name> <fsummary>Handle error</fsummary> <type> - <v>ReqId = integer()</v> + <v>ReqId = netif | integer()</v> <v>Reason = {unexpected_pdu, SnmpInfo} | {invalid_sec_info, SecInfo, SnmpInfo} | {empty_message, Addr, Port} | term()</v> <v>SnmpInfo = snmp_gen_info()</v> <v>SecInfo = term()</v> @@ -115,7 +115,11 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(), <p>If <c>ReqId</c> is less then 0, it means that this information was not available to the manager (that info was never retrieved before the message was discarded). </p> - <p>For <c>SnmpInfo</c> see handle_agent below.</p> + <p>For <c>SnmpInfo</c> see handle_agent below.</p> + <p>Note that there is a special case when the value of <c>ReqId</c> + has the value of the atom <c>netif</c>. This means that the NetIF + process has suffered a "fatal" error and been restarted. + With possible loss of traffic! </p> <marker id="handle_agent"></marker> </desc> diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl index 8e60cecaf9..c0859f6fd8 100644 --- a/lib/snmp/src/manager/snmpm.erl +++ b/lib/snmp/src/manager/snmpm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2019. All Rights Reserved. +%% Copyright Ericsson AB 2004-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -89,8 +89,9 @@ system_start_time/0, sys_up_time/0, - info/0, - verbosity/2 + info/0, info/1, + verbosity/2, + restart/1 ]). -export([format_reason/1, format_reason/2]). @@ -297,6 +298,9 @@ oid_to_type(Oid) -> info() -> snmpm_server:info(). +info(Key) -> + proplists:get_value(Key, info(), {error, not_found}). + %% -- Verbosity -- @@ -316,6 +320,16 @@ verbosity(all, V) -> snmpm_server:verbosity(note_store, V). +%% -- Restart -- + +%% Restart various component processes in the manager +%% Note that the effects of this is diffiult to +%% predict, so it should be use with *caution*! + +restart(net_if = What) -> + snmpm_server:restart(What). + + %% -- Users -- %% Register the 'user'. diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index fc6ddc5738..decda09022 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -151,6 +151,7 @@ -define(SERVER_OPT_GCT_DEFAULT, 30000). -define(SERVER_OPT_MT_DEFAULT, true). -define(SERVER_OPT_CBP_DEFAULT, temporary). % permanent +-define(SERVER_OPT_NIS_DEFAULT, none). %% -define(DEF_ADDR_TAG, default_addr_tag). -define(DEFAULT_TARGETNAME, default_agent). @@ -1115,15 +1116,17 @@ do_init(Opts) -> end, %% -- Server (optional) -- - ServerOpts = get_opt(server, Opts, []), + ServerOpts = get_opt(server, Opts, []), ServerVerb = get_opt(verbosity, ServerOpts, ?SERVER_OPT_VERB_DEFAULT), ServerGct = get_opt(timeout, ServerOpts, ?SERVER_OPT_GCT_DEFAULT), ServerMt = get_opt(multi_threaded, ServerOpts, ?SERVER_OPT_MT_DEFAULT), ServerCBP = get_opt(cbproxy, ServerOpts, ?SERVER_OPT_CBP_DEFAULT), + ServerNIS = get_opt(netif_sup, ServerOpts, ?SERVER_OPT_NIS_DEFAULT), ets:insert(snmpm_config_table, {server_verbosity, ServerVerb}), ets:insert(snmpm_config_table, {server_timeout, ServerGct}), ets:insert(snmpm_config_table, {server_multi_threaded, ServerMt}), ets:insert(snmpm_config_table, {server_cbproxy, ServerCBP}), + ets:insert(snmpm_config_table, {server_nis, ServerNIS}), %% -- Mibs (optional) -- ?vdebug("initiate mini mib", []), @@ -1132,7 +1135,7 @@ do_init(Opts) -> init_mini_mib(Mibs), %% -- Net-if (optional) -- - ?vdebug("net_if options", []), + ?vdebug("net-if options", []), NetIfIrb = case get_opt(inform_request_behaviour, Opts, ?IRB_DEFAULT) of user -> @@ -1421,6 +1424,9 @@ verify_server_opts([{multi_threaded, MT}|Opts]) when is_boolean(MT) -> verify_server_opts([{cbproxy, CBP}|Opts]) -> verify_server_cbproxy(CBP), verify_server_opts(Opts); +verify_server_opts([{netif_sup, NIS}|Opts]) -> + verify_server_nis(NIS), + verify_server_opts(Opts); verify_server_opts([Opt|_]) -> error({invalid_server_option, Opt}). @@ -1436,6 +1442,17 @@ verify_server_cbproxy(permanent) -> verify_server_cbproxy(CBP) -> error({invalid_server_cbproxy, CBP}). +verify_server_nis(none) -> + ok; +verify_server_nis({PingTo, PongTo} = V) when is_integer(PingTo) andalso + (PingTo > 0) andalso + is_integer(PongTo) andalso + (PongTo > 0) -> + ok; +verify_server_nis(NIS) -> + error({invalid_server_netif_sup, NIS}). + + verify_net_if_opts([]) -> ok; verify_net_if_opts([{module, Mod}|Opts]) -> diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index c2e5c6d2f0..0d57bc944a 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -58,6 +58,14 @@ %% -define(VMODULE,"NET_IF"). -include("snmp_verbosity.hrl"). +%% This is for debugging!! +-ifdef(snmp_debug). +-define(allow_exec, true). +-else. +-define(allow_exec, false). +-endif. + + -record(state, { server, @@ -67,7 +75,8 @@ log, irb = auto, % auto | {user, integer()} irgc, - filter + filter, + allow_exec = ?allow_exec }). -record(transport, @@ -92,6 +101,7 @@ -define(ATL_SEQNO_MAX, 2147483647). + %%%------------------------------------------------------------------- %%% API %%%------------------------------------------------------------------- @@ -520,6 +530,13 @@ handle_call(info, _From, State) -> Reply = get_info(State), {reply, Reply, State}; +%% This is for debugging!! +handle_call({exec, F}, _From, #state{allow_exec = true} = State) + when is_function(F, 0) -> + ?vlog("[call] exec", []), + {reply, F(), State}; + + handle_call(Req, From, State) -> warning_msg("received unknown request (from ~p): ~n~p", [Req, From]), {reply, {error, {invalid_request, Req}}, State}. @@ -556,6 +573,13 @@ handle_cast(filter_reset, State) -> reset_counters(), {noreply, State}; +%% This is for debugging!! +handle_cast({exec, F}, #state{allow_exec = true} = State) when is_function(F, 0) -> + ?vlog("[cast] exec", []), + F(), + {noreply, State}; + + handle_cast(Msg, State) -> warning_msg("received unknown message: ~n~p", [Msg]), {noreply, State}. @@ -597,6 +621,20 @@ handle_info({disk_log, _Node, Log, Info}, State) -> handle_info({'DOWN', _, _, _, _} = Info, State) -> handle_info_down(Info, State); + +handle_info({ping, Pid}, State) -> + ?vdebug("received ping message from ~p", [Pid]), + Pid ! {pong, self()}, + {noreply, State}; + + +%% This is for debugging!! +handle_info({exec, F}, #state{allow_exec = true} = State) when is_function(F, 0) -> + ?vlog("[info] exec", []), + F(), + {noreply, State}; + + handle_info(Info, State) -> handle_info_unknown(Info, State). diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl index fe2c22d9ba..1a8d09ab9b 100644 --- a/lib/snmp/src/manager/snmpm_server.erl +++ b/lib/snmp/src/manager/snmpm_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2019. All Rights Reserved. +%% Copyright Ericsson AB 2004-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -45,13 +45,13 @@ %% discovery/2, discovery/3, discovery/4, discovery/5, discovery/6, - %% system_info_updated/2, get_log_type/0, set_log_type/1, reconfigure/0, info/0, - verbosity/1, verbosity/2 + verbosity/1, verbosity/2, + restart/1 ]). @@ -77,6 +77,9 @@ %% GCT exports -export([gct_init/1, gct/2]). +%% NIS exports +-export([nis_init/2, nis_loop/1]). + %% CallBack Proxy exports -export([cbproxy_loop/1, do_handle_error/4, @@ -157,6 +160,24 @@ net_if, net_if_mod, net_if_ref, + + %% NetIF supervision + %% This (config) option defines if/how the "server" + %% shall supervise the net-if process. + %% And by "supervise" we don't meant in the way a + %% *supervisor" supervisor. This is "active" supervision + %% (basically, send ping and expect pong back). + %% There are two alternatives: + %% none - No supervision (default) + %% {PingInterval, PongTimeout} + %% PingInterval :: pos_integer() + %% Time between a successful test and the next. + %% PongInterval :: pos_integer() + %% Time the NetIF process has to answer a ping + %% + nis :: none | {pos_integer(), pos_integer()}, + nis_pid :: undefined | pid(), % Pid of the process doing the actual sup + req, %% ???? Last request id in outgoing message oid, %% ???? Last oid in request outgoing message mini_mib, @@ -492,6 +513,9 @@ cancel_async_request(UserId, ReqId) -> call({cancel_async_request, UserId, ReqId}). +info() -> + call(info). + verbosity(Verbosity) -> case ?vvalidate(Verbosity) of Verbosity -> @@ -500,9 +524,6 @@ verbosity(Verbosity) -> {error, {invalid_verbosity, Verbosity}} end. -info() -> - call(info). - verbosity(net_if = Ref, Verbosity) -> verbosity2(Ref, Verbosity); verbosity(note_store = Ref, Verbosity) -> @@ -516,9 +537,10 @@ verbosity2(Ref, Verbosity) -> {error, {invalid_verbosity, Verbosity}} end. -%% Target -> all | server | net_if -%% system_info_updated(Target, What) -> -%% call({system_info_updated, Target, What}). + +restart(net_if = What) -> + cast({restart, What}). + get_log_type() -> call(get_log_type). @@ -590,6 +612,15 @@ do_init() -> {NoteStore, NoteStoreRef} = do_init_note_store(Prio), {NetIf, NetIfModule, NetIfRef} = do_init_net_if(NoteStore), + %% -- (maybe) Start the NetIF "supervisor" -- + {NIS, NISPid} = + case snmpm_config:system_info(server_nis) of + {ok, none = V} -> + {V, undefined}; + {ok, {PingTO, PongTO} = V} -> + {V, nis_start(NetIf, PingTO, PongTO)} + end, + MiniMIB = snmpm_config:make_mini_mib(), State = #state{mini_mib = MiniMIB, gct = GCT, @@ -598,6 +629,8 @@ do_init() -> net_if = NetIf, net_if_mod = NetIfModule, net_if_ref = NetIfRef, + nis = NIS, + nis_pid = NISPid, cbproxy = CBProxy, cbproxy_pid = CBPPid}, ?vlog("started", []), @@ -624,7 +657,7 @@ do_init_note_store(Prio) -> end. do_init_net_if(NoteStore) -> - ?vdebug("try start net if", []), + ?vdebug("try start net-if", []), {ok, NetIfModule} = snmpm_config:system_info(net_if_module), case snmpm_misc_sup:start_net_if(NetIfModule, NoteStore) of {ok, Pid} -> @@ -638,6 +671,7 @@ do_init_net_if(NoteStore) -> throw({error, {failed_starting_net_if, Reason}}) end. + %% --------------------------------------------------------------------- %% --------------------------------------------------------------------- @@ -1017,6 +1051,13 @@ handle_call(Req, _From, State) -> {reply, {error, unknown_request}, State}. +handle_cast({restart, net_if}, + #state{net_if = Pid} = State) -> + ?vlog("received net_if (~p) restart message", [Pid]), + %% We will get an exit signel/message, which will trigger a (re-)start + exit(Pid, kill), + {noreply, State}; + handle_cast(Msg, State) -> warning_msg("received unknown message: ~n~p", [Msg]), {noreply, State}. @@ -1077,19 +1118,18 @@ handle_info(gc_timeout, #state{gct = GCT} = State) -> {noreply, State}; -handle_info({'DOWN', _MonRef, process, Pid, _Reason}, - #state{note_store = NoteStore, - net_if = Pid} = State) -> - ?vlog("received 'DOWN' message regarding net_if", []), - {NetIf, _, Ref} = do_init_net_if(NoteStore), - {noreply, State#state{net_if = NetIf, net_if_ref = Ref}}; +handle_info({'DOWN', _MonRef, process, Pid, Reason}, + #state{net_if = Pid} = State) -> + ?vlog("received 'DOWN' message regarding net_if (~p)", [Pid]), + NewState = handle_netif_down(State, Reason), + {noreply, NewState}; handle_info({'DOWN', _MonRef, process, Pid, _Reason}, #state{note_store = Pid, net_if = NetIf, net_if_mod = Mod} = State) -> - ?vlog("received 'DOWN' message regarding note_store", []), + ?vlog("received 'DOWN' message regarding note_store (~p)", [Pid]), {ok, Prio} = snmpm_config:system_info(prio), {NoteStore, Ref} = do_init_note_store(Prio), Mod:note_store(NetIf, NoteStore), @@ -1118,8 +1158,17 @@ handle_info({'EXIT', Pid, Reason}, #state{cbproxy_pid = Pid} = State) -> {noreply, State#state{cbproxy_pid = NewCBP}}; +handle_info({'EXIT', Pid, Reason}, #state{net_if = NetIF, + nis = {PingTO, PongTO}, + nis_pid = Pid} = State) -> + warning_msg("NetIF (active) supervisor (~w) process crashed: " + "~n ~p", [Pid, Reason]), + NewNIS = nis_start(NetIF, PingTO, PongTO), + {noreply, State#state{nis_pid = NewNIS}}; + + handle_info(Info, State) -> - warning_msg("received unknown info: ~n~p", [Info]), + warning_msg("received unknown info: ~n ~p", [Info]), {noreply, State}. @@ -1146,8 +1195,9 @@ code_change(_Vsn, #state{gct = Pid} = State0, _Extra) -> %% Terminate %%---------------------------------------------------------- -terminate(Reason, #state{gct = GCT, cbproxy = CBP}) -> +terminate(Reason, #state{nis_pid = NIS, gct = GCT, cbproxy = CBP}) -> ?vdebug("terminate: ~p",[Reason]), + nis_stop(NIS), cbproxy_stop(CBP), gct_stop(GCT), snmpm_misc_sup:stop_note_store(), @@ -3119,7 +3169,17 @@ handle_invalid_result(Func, Args, InvalidResult) -> "~n Invalid result: ~p", [Func, Args, InvalidResult]). - + +handle_netif_down(#state{note_store = NoteStore, + nis_pid = NIS} = State, + Reason) -> + %% Srart a new NetIF + {NetIF, _, Ref} = do_init_net_if(NoteStore), + %% Inform the (active) supervisor + nis_netif(NIS, NetIF), + netif_down_inform_users(Reason), + State#state{net_if = NetIF, net_if_ref = Ref}. + handle_down(MonRef) -> (catch do_handle_down(MonRef)). @@ -3608,6 +3668,258 @@ new_timeout(T1, T2) -> %%---------------------------------------------------------------------- +%% NetIF Supervisor +%% +%% The NIS process "supervises" the NetIF process. That does *not* mean +%% that it takes on the role of a standard erlang 'supervisor' process. +%% The NIS is instead a process that "actively" supervises by means +%% of "ping" messages, which the supervised process must respond to +%% (with a pong message) *in time*. +%% If it does not, NIS assumes that it has hung, and kills it. +%% The server process then restarts the NetIF process and informs NIS. +%%---------------------------------------------------------------------- + +nis_start(NetIF, PingTO, PongTO) -> + ?vdebug("start nis process (~w, ~w)", [PingTO, PongTO]), + State = #{parent => self(), + netif_pid => NetIF, + ping_to => PingTO, + ping_tref => undefined, + ping_start => undefined, % Time when ping sent + ping_max => undefined, % Max roundtrip time + pong_to => PongTO, + pong_tref => undefined, + kill_cnt => 0}, + proc_lib:start_link(?MODULE, nis_init, [State, get(verbosity)]). + +nis_stop(NIS) when is_pid(NIS) -> + NIS ! {?MODULE, self(), stop}; +nis_stop(_) -> + ok. + + +nis_info(NIS) when is_pid(NIS) -> + NIS ! {?MODULE, self(), info}, + receive + {?MODULE, NIS, {info, Info}} -> + Info + after 1000 -> + [] + end; +nis_info(_) -> + []. + + +nis_netif(NIS, NetIF) when is_pid(NIS) andalso is_pid(NetIF) -> + NIS ! {?MODULE, self(), {netif, NetIF}}; +nis_netif(_, _) -> + ok. + + +nis_init(#{parent := Parent, + netif_pid := NetIF, + ping_to := PingTO} = State, + Verbosity) -> + put(verbosity, Verbosity), + put(sname, mnis), + ?vlog("starting"), + MRef = erlang:monitor(process, NetIF), + TRef = erlang:start_timer(PingTO, self(), ping_timeout), + erlang:register(snmpm_server_nis, self()), + proc_lib:init_ack(Parent, self()), + ?vlog("started"), + nis_loop(State#{netif_mref => MRef, + ping_tref => TRef}). + +%% The NetIF is dead. Its up to the server to restart it and inform us +nis_loop(#{parent := Parent, + netif_pid := undefined, + ping_tref := undefined, + pong_tref := undefined} = State) -> + receive + {?MODULE, Parent, stop} -> + ?vlog("[idle] stop received"), + nis_handle_stop(State), + exit(normal); + + {?MODULE, Pid, info} -> + ?vtrace("[idle] info received"), + Info = nis_handle_info(State), + Pid ! {?MODULE, self(), {info, Info}}, + ?MODULE:nis_loop(State); + + {?MODULE, Parent, {netif, NetIF}} -> + ?vlog("[idle] (new) netif started: ~p => start ping timer", [NetIF]), + MRef = erlang:monitor(process, NetIF), + PingTO = maps:get(ping_to, State), + TRef = erlang:start_timer(PingTO, self(), ping_timeout), + ?MODULE:nis_loop(State#{netif_pid => NetIF, + netif_mref => MRef, + ping_max => undefined, + ping_tref => TRef}); + + _Any -> + ?MODULE:nis_loop(State) + + after 5000 -> + %% This is for code upgrade + ?MODULE:nis_loop(State) + end; + +%% PING timer running (waiting for ping-timeout) +nis_loop(#{parent := Parent, + netif_pid := NetIF, + netif_mref := MRef, + ping_tref := PingTRef, + pong_tref := undefined} = State) when is_pid(NetIF) andalso + (PingTRef =/= undefined) -> + receive + {'DOWN', MRef, process, NetIF, _} -> + ?vlog("[ping] netif died => cancel ping timer"), + erlang:cancel_timer(PingTRef), + ?MODULE:nis_loop(State#{netif_pid => undefined, + netif_mref => undefined, + ping_tref => undefined}); + + {?MODULE, Parent, stop} -> + ?vlog("[ping] stop received"), + nis_handle_stop(State), + exit(normal); + + {?MODULE, Pid, info} -> + ?vtrace("[ping] info received"), + Info = nis_handle_info(State), + Pid ! {?MODULE, self(), {info, Info}}, + ?MODULE:nis_loop(State); + + %% Time to ping NetIF + {timeout, PingTRef, ping_timeout} -> + ?vlog("[ping] (ping-) timer timeout => send ping and start pong timer"), + NetIF ! {ping, self()}, + PongTO = maps:get(pong_to, State), + TRef = erlang:start_timer(PongTO, self(), pong_timeout), + ?MODULE:nis_loop(State#{ping_tref => undefined, + ping_start => us(), + pong_tref => TRef}); + + _Any -> + ?MODULE:nis_loop(State) + + after 5000 -> + %% This is for code upgrade + ?MODULE:nis_loop(State) + end; + +%% PONG timer running (waiting for pong message) +nis_loop(#{parent := Parent, + netif_pid := NetIF, + netif_mref := MRef, + ping_tref := undefined, + pong_tref := PongTRef} = State) when is_pid(NetIF) andalso + (PongTRef =/= undefined) -> + receive + {'DOWN', MRef, process, NetIF, _} -> + ?vlog("[pong] netif died => cancel pong timer"), + erlang:cancel_timer(PongTRef), + ?MODULE:nis_loop(State#{netif_pid => undefined, + netif_mref => undefined, + pong_tref => undefined}); + + {?MODULE, Parent, stop} -> + ?vlog("[pong] stop received"), + nis_handle_stop(State), + exit(normal); + + {?MODULE, Pid, info} -> + ?vlog("[pong] info received"), + Info = nis_handle_info(State), + Pid ! {?MODULE, self(), {info, Info}}, + ?MODULE:nis_loop(State); + + {pong, NetIF} -> + ?vlog("[pong] received pong => cancel pong timer, start ping timer"), + T = us(), + erlang:cancel_timer(PongTRef), + Start = maps:get(ping_start, State), + Max = maps:get(ping_max, State), + RT = T - Start, + NewMax = + if + (Max =:= undefined) -> + ?vtrace("[pong] Max: ~w", [RT]), + RT; + (RT > Max) -> + ?vtrace("[pong] New Max: ~w", [RT]), + RT; + true -> + Max + end, + PingTO = maps:get(ping_to, State), + PingTRef = erlang:start_timer(PingTO, self(), ping_timeout), + ?MODULE:nis_loop(State#{ping_tref => PingTRef, + ping_start => undefined, + ping_max => NewMax, + pong_tref => undefined}); + + %% Time to kill NetIF + {timeout, PongTRef, pong_timeout} -> + ?vinfo("[pong] (pong-) timer timeout => kill NetIF (~p)", [NetIF]), + nis_handle_pong_timeout(NetIF, MRef), + KCnt = maps:get(kill_cnt, State), + ?MODULE:nis_loop(State#{netif_pid => undefined, + netif_mref => undefined, + pong_tref => undefined, + kill_cnt => KCnt + 1}); + + _Any -> + ?MODULE:nis_loop(State) + + after 5000 -> + %% This is for code upgrade + ?MODULE:nis_loop(State) + end. + + +nis_handle_info(#{ping_max := undefined, kill_cnt := KCnt}) -> + [{kcnt, KCnt}]; +nis_handle_info(#{ping_max := Max, kill_cnt := KCnt}) -> + [{max, Max}, {kcnt, KCnt}]. + + +nis_handle_stop(#{pong_tref := PongTRef, + ping_tref := PingTRef}) -> + cancel_timer(PongTRef), + cancel_timer(PingTRef). + +%% Inform all users that the netif process has been killed +nis_handle_pong_timeout(NetIF, MRef) -> + erlang:demonitor(MRef, [flush]), + exit(NetIF, kill), + netif_down_inform_users({pong, killed}), + ok. + + +%%---------------------------------------------------------------------- + +%% Inform all users that "something" fatal happened to the NetIF process. +netif_down_inform_users(Reason) -> + InformUser = fun(UserId) -> + spawn(fun() -> + case snmpm_config:user_info(UserId) of + {ok, UserMod, UserData} -> + UserMod:handle_error(netif, + Reason, + UserData); + {error, _} -> + ok + end, + exit(normal) + end) + end, + lists:foreach(InformUser, snmpm_config:which_users()). + + +%%---------------------------------------------------------------------- maybe_delete(false, ReqId) -> ets:delete(snmpm_request_table, ReqId); @@ -3651,6 +3963,9 @@ is_started(#state{net_if = _Pid, net_if_mod = _Mod}) -> %%---------------------------------------------------------------------- +cast(Req) -> + gen_server:cast(?SERVER, Req). + call(Req) -> call(Req, infinity). @@ -3672,15 +3987,16 @@ get_info(#state{gct = GCT, net_if = NI, net_if_mod = NIMod, note_store = NS, + nis_pid = NIS, cbproxy = CBP}) -> - Info = [{server, server_info(GCT, CBP)}, + Info = [{server, server_info(GCT, CBP, NIS)}, {config, config_info()}, {net_if, net_if_info(NI, NIMod)}, {note_store, note_store_info(NS)}, {stats_counters, get_stats_counters()}], Info. -server_info(GCT, CBP) -> +server_info(GCT, CBP, NIS) -> {CBPInfo, CBPSz} = if (CBP =:= permanent) -> @@ -3689,12 +4005,20 @@ server_info(GCT, CBP) -> true -> {[], []} end, + {NISInfo, NISSz} = + case NIS of + undefined -> + {[], []}; + _ -> + {[{nis, nis_info(NIS)}], + [{nis, proc_mem(NIS)}]} + end, ProcSize = proc_mem(self()), GCTSz = proc_mem(GCT), RTSz = tab_size(snmpm_request_table), MTSz = tab_size(snmpm_monitor_table), - [{process_memory, [{server, ProcSize}, {gct, GCTSz}] ++ CBPSz}, - {db_memory, [{request, RTSz}, {monitor, MTSz}]}] ++ CBPInfo. + [{process_memory, [{server, ProcSize}, {gct, GCTSz}] ++ CBPSz ++ NISSz}, + {db_memory, [{request, RTSz}, {monitor, MTSz}]}] ++ CBPInfo ++ NISInfo. proc_mem(P) when is_pid(P) -> case (catch erlang:process_info(P, memory)) of @@ -3744,3 +4068,6 @@ note_store_info(Pid) -> %%---------------------------------------------------------------------- + +us() -> + erlang:monotonic_time(micro_seconds). diff --git a/lib/snmp/src/manager/snmpm_user.erl b/lib/snmp/src/manager/snmpm_user.erl index c0100d372f..9d0077449a 100644 --- a/lib/snmp/src/manager/snmpm_user.erl +++ b/lib/snmp/src/manager/snmpm_user.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -41,7 +41,7 @@ %% An "asynchronous" error has been detected -callback handle_error( - ReqId :: integer(), + ReqId :: netif | integer(), Reason :: {unexpected_pdu, SnmpInfo :: snmp_gen_info()} | {invalid_sec_info, SecInfo :: term(), diff --git a/lib/snmp/src/misc/snmp_verbosity.erl b/lib/snmp/src/misc/snmp_verbosity.erl index 9b2676d048..a42a1acb3a 100644 --- a/lib/snmp/src/misc/snmp_verbosity.erl +++ b/lib/snmp/src/misc/snmp_verbosity.erl @@ -138,6 +138,7 @@ image_of_sname(mns) -> "M-NOTE-STORE"; image_of_sname(mnif) -> "M-NET-IF"; image_of_sname(mnifl) -> "M-NET-IF-LOGGER"; image_of_sname(mnifw) -> io_lib:format("M-NET-IF-worker(~p)", [self()]); +image_of_sname(mnis) -> "M-NIS"; image_of_sname(mconf) -> "M-CONF"; image_of_sname(lc) -> io_lib:format("LOG-CONVERTER(~p)", [self()]); diff --git a/lib/snmp/src/misc/snmp_verbosity.hrl b/lib/snmp/src/misc/snmp_verbosity.hrl index c79f4c3e88..6aef28a854 100644 --- a/lib/snmp/src/misc/snmp_verbosity.hrl +++ b/lib/snmp/src/misc/snmp_verbosity.hrl @@ -24,39 +24,59 @@ -ifdef(VMODULE). +-define(vinfo(F), ?vinfo(F, [])). -define(vinfo(F,A), snmp_verbosity:print(get(verbosity),info, ?VMODULE,F,A)). +-define(vlog(F), ?vlog(F, [])). -define(vlog(F,A), snmp_verbosity:print(get(verbosity),log, ?VMODULE,F,A)). +-define(vdebug(F), ?vdebug(F, [])). -define(vdebug(F,A),snmp_verbosity:print(get(verbosity),debug,?VMODULE,F,A)). +-define(vtrace(F), ?vtrace(F, [])). -define(vtrace(F,A),snmp_verbosity:print(get(verbosity),trace,?VMODULE,F,A)). -else. +-define(vinfo(F), ?vinfo(F, [])). -define(vinfo(F,A), snmp_verbosity:print(get(verbosity),info, F,A)). +-define(vlog(F), ?vlog(F, [])). -define(vlog(F,A), snmp_verbosity:print(get(verbosity),log, F,A)). +-define(vdebug(F), ?vdebug(F, [])). -define(vdebug(F,A),snmp_verbosity:print(get(verbosity),debug,F,A)). +-define(vtrace(F), ?vtrace(F, [])). -define(vtrace(F,A),snmp_verbosity:print(get(verbosity),trace,F,A)). -endif. -define(vvalidate(V), snmp_verbosity:validate(V)). +-define(vinfoc(F), ?vinfoc(F, [])). -define(vinfoc(F,A), snmp_verbosity:printc(get(verbosity),info, F,A)). +-define(vlogc(F), ?vlogc(F, [])). -define(vlogc(F,A), snmp_verbosity:printc(get(verbosity),log, F,A)). +-define(vdebugc(F), ?vdebug(F, [])). -define(vdebugc(F,A),snmp_verbosity:printc(get(verbosity),debug,F,A)). +-define(vtracec(F), ?vtracec(F, [])). -define(vtracec(F,A),snmp_verbosity:printc(get(verbosity),trace,F,A)). -else. -define(vvalidate(V),ok). --define(vinfo(F,A),ok). --define(vlog(F,A),ok). --define(vdebug(F,A),ok). --define(vtrace(F,A),ok). - --define(vinfoc(F,A),ok). --define(vlogc(F,A),ok). +-define(vinfo(F), ok). +-define(vinfo(F,A), ok). +-define(vlog(F), ok). +-define(vlog(F,A), ok). +-define(vdebug(F), ok). +-define(vdebug(F,A), ok). +-define(vtrace(F), ok). +-define(vtrace(F,A), ok). + +-define(vinfoc(F), ok). +-define(vinfoc(F,A), ok). +-define(vlogc(F), ok). +-define(vlogc(F,A), ok). +-define(vdebugc(F), ok). -define(vdebugc(F,A),ok). +-define(vtracec(F), ok). -define(vtracec(F,A),ok). -endif. diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile index a9a88ccbfa..0e24506c5d 100644 --- a/lib/snmp/test/Makefile +++ b/lib/snmp/test/Makefile @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2016. All Rights Reserved. +# Copyright Ericsson AB 1997-2020. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -89,14 +89,8 @@ ifeq ($(SNMP_DEBUG),) # SNMP_DEBUG = d endif -ifeq ($(SNMP_DEBUG),e) - SNMP_FLAGS += -Dsnmp_error -endif -ifeq ($(SNMP_DEBUG),l) - SNMP_FLAGS += -Dsnmp_error -Dsnmp_log -endif ifeq ($(SNMP_DEBUG),d) - SNMP_FLAGS += -Dsnmp_error -Dsnmp_log -Dsnmp_debug + SNMP_FLAGS += -Dsnmp_debug endif ifeq ($(DONT_USE_TS),true) @@ -175,7 +169,7 @@ emakebuild: $(EMAKEFILE) targets: mib $(EMAKEFILE) erl -make -old_targets: mib $(TARGET_FILES) $(TEST_SERVER_TARGETS) +old_targets: mib $(TARGET_FILES) $(EMAKEFILE): Makefile $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' > $(EMAKEFILE) diff --git a/lib/snmp/test/modules.mk b/lib/snmp/test/modules.mk index a1554815d9..ba0aea21dd 100644 --- a/lib/snmp/test/modules.mk +++ b/lib/snmp/test/modules.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2019. All Rights Reserved. +# Copyright Ericsson AB 2004-2020. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -35,14 +35,14 @@ SUITE_MODULES = \ snmp_to_snmpnet_SUITE TEST_UTIL_MODULES = \ - snmp_agent_test_get \ + snmp_test_lib \ snmp_agent_test_lib \ + snmp_agent_test_get \ snmp_manager_user \ snmp_manager_user_old \ snmp_manager_user_test_lib \ snmp_test_global_sys_monitor \ snmp_test_sys_monitor \ - snmp_test_lib \ snmp_test_manager \ snmp_test_mgr \ snmp_test_mgr_misc \ @@ -52,10 +52,6 @@ TEST_UTIL_MODULES = \ test1 \ test2 -TEST_SERVER_MODULES = \ - snmp_test_server \ - snmp_test_suite - MODULES = \ $(TEST_UTIL_MODULES) \ $(SUITE_MODULES) diff --git a/lib/snmp/test/snmp_agent_SUITE.erl b/lib/snmp/test/snmp_agent_SUITE.erl index 609ac6cea8..2a6cfbedbe 100644 --- a/lib/snmp/test/snmp_agent_SUITE.erl +++ b/lib/snmp/test/snmp_agent_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -481,22 +481,22 @@ -define(expect1(What), - snmp_agent_test_lib:expect(?MODULE, ?LINE, + ?ALIB:expect(?MODULE, ?LINE, What)). -define(expect2(What, ExpVBs), - snmp_agent_test_lib:expect(?MODULE, ?LINE, + ?ALIB:expect(?MODULE, ?LINE, What, ExpVBs)). -define(expect3(Err, Idx, ExpVBs), - snmp_agent_test_lib:expect(?MODULE, ?LINE, + ?ALIB:expect(?MODULE, ?LINE, Err, Idx, ExpVBs)). -define(expect4(Err, Idx, ExpVBs, To), - snmp_agent_test_lib:expect(?MODULE, ?LINE, + ?ALIB:expect(?MODULE, ?LINE, Err, Idx, ExpVBs, To)). -define(expect5(Type, Ent, Gen, Spec, ExpVBs), - snmp_agent_test_lib:expect(?MODULE, ?LINE, + ?ALIB:expect(?MODULE, ?LINE, Type, Ent, Gen, Spec, ExpVBs)). -define(expect6(Type, Ent, Gen, Spec, ExpVBs, To), - snmp_agent_test_lib:expect(?MODULE, ?LINE, + ?ALIB:expect(?MODULE, ?LINE, Type, Ent, Gen, Spec, ExpVBs, To)). @@ -578,9 +578,9 @@ all_cases() -> init_per_suite(Config0) when is_list(Config0) -> - p("init_per_suite -> entry with" - "~n Config: ~p" - "~n Nodes: ~p", [Config0, erlang:nodes()]), + ?IPRINT("init_per_suite -> entry with" + "~n Config: ~p" + "~n Nodes: ~p", [Config0, erlang:nodes()]), case ?LIB:init_per_suite(Config0) of {skip, _} = SKIP -> @@ -601,33 +601,34 @@ init_per_suite(Config0) when is_list(Config0) -> snmp_test_mgr_counter_server:start(), - p("init_per_suite -> end when" - "~n Config: ~p" - "~n Nodes: ~p", [Config4, erlang:nodes()]), + ?IPRINT("init_per_suite -> end when" + "~n Config: ~p" + "~n Nodes: ~p", [Config4, erlang:nodes()]), Config4 end. end_per_suite(Config0) when is_list(Config0) -> - p("end_per_suite -> entry with" - "~n Config0: ~p" - "~n Nodes: ~p", [Config0, erlang:nodes()]), + ?IPRINT("end_per_suite -> entry with" + "~n Config0: ~p" + "~n Nodes: ~p", [Config0, erlang:nodes()]), case snmp_test_mgr_counter_server:stop() of {ok, Counters} -> - p("end_per_suite -> sucessfully stopped counter server" - "~n Counters: ~p", [Counters]); + ?IPRINT("end_per_suite -> sucessfully stopped counter server" + "~n Counters: ~p", [Counters]); {error, Reason} -> - p("end_per_suite -> failed stopping counter server" - "~n Reason: ~p", [Reason]) + ?IPRINT("end_per_suite -> failed stopping counter server" + "~n Reason: ~p", [Reason]) end, snmp_test_sys_monitor:stop(), Config1 = ?LIB:end_per_suite(Config0), - p("end_per_suite -> end when" - "~n Nodes: ~p", [erlang:nodes()]), + ?IPRINT("end_per_suite -> end when" + "~n Nodes: ~p", [erlang:nodes()]), + Config1. @@ -813,18 +814,35 @@ end_per_group(_GroupName, Config) -> %% ----- Init Per TestCase ----- %% +%% T is in number of minutes +wd_start(T, Config) -> + Factor = case ?config(snmp_factor, Config) of + F when (F > 0) -> + F-1; + _ -> + 0 + end, + Dog = ?WD_START(?MINS(T + Factor)), + [{watchdog, Dog} | Config ]. + + +wd_stop(Config) -> + Dog = ?config(watchdog, Config), + ?WD_STOP(Dog), + lists:keydelete(Dog, 2, Config). + init_per_testcase(Case, Config) when is_list(Config) -> - p("init_per_testcase -> entry with" - "~n Config: ~p" - "~n Nodes: ~p", [Config, erlang:nodes()]), + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p" + "~n Nodes: ~p", [Config, erlang:nodes()]), Result = init_per_testcase1(Case, Config), snmp_test_global_sys_monitor:reset_events(), - p("init_per_testcase -> done when" - "~n Result: ~p" - "~n Nodes: ~p", [Result, erlang:nodes()]), + ?IPRINT("init_per_testcase -> done when" + "~n Result: ~p" + "~n Nodes: ~p", [Result, erlang:nodes()]), Result. init_per_testcase1(otp8395 = Case, Config) when is_list(Config) -> @@ -841,8 +859,7 @@ init_per_testcase1(otp_7157 = _Case, Config) when is_list(Config) -> ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), - Dog = ?WD_START(?MINS(1)), - [{watchdog, Dog} | Config ]; + wd_start(1, Config); init_per_testcase1(Case, Config) when ((Case =:= otp_16092_simple_start_and_stop1) orelse (Case =:= otp_16092_simple_start_and_stop2) orelse @@ -852,30 +869,26 @@ init_per_testcase1(Case, Config) ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), - Dog = ?WD_START(?MINS(1)), - init_per_testcase2(Case, [{watchdog, Dog} | Config]); + init_per_testcase2(Case, wd_start(1, Config)); init_per_testcase1(v2_inform_i = _Case, Config) when is_list(Config) -> ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), - Dog = ?WD_START(?MINS(10)), - [{watchdog, Dog} | Config ]; + wd_start(10, Config); init_per_testcase1(v3_inform_i = _Case, Config) when is_list(Config) -> ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), - Dog = ?WD_START(?MINS(10)), - [{watchdog, Dog} | Config ]; + wd_start(10, Config); init_per_testcase1(_Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), - Dog = ?WD_START(?MINS(6)), - [{watchdog, Dog}| Config ]. + wd_start(6, Config). init_per_testcase2(Case, Config) -> - ?DBG("end_per_testcase2 -> entry with" + ?DBG("init_per_testcase2 -> entry with" "~n Case: ~p" "~n Config: ~p", [Case, Config]), @@ -911,20 +924,48 @@ init_per_testcase2(Case, Config) -> %% ---- End Per TestCase ---- end_per_testcase(Case, Config) when is_list(Config) -> - p("end_per_testcase -> entry with" - "~n Config: ~p" - "~n Nodes: ~p", [Config, erlang:nodes()]), - display_log(Config), + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p" + "~n Nodes: ~p", + [Config, erlang:nodes()]), + + ?IPRINT("system events during test: " + "~n ~p", [snmp_test_global_sys_monitor:events()]), + + %% On some hosts, this operation can take a long time. + %% So long, that the timetrap expires and the test case + %% will be "failed". + %% So, wrap it in a process and for a successful test case, + %% give it 30 seconds, then kill it. If the test case has + %% already failed, we will want to get as much of the logs + %% as possible. So, set no timeout (infinity) and let the + %% test framework take care of things... + DisplayLogTimeout = + case ?config(tc_status, Config) of + ok -> + ?SECS(30); + _ -> + infinity + end, + Flag = process_flag(trap_exit, true), + Pid = spawn_link(fun() -> display_log(Config), exit(normal) end), + receive + {'EXIT', Pid, _} -> + process_flag(trap_exit, Flag), + ok + after DisplayLogTimeout -> + ?WPRINT("Display Log process fail to complete in time (~w msec): " + "kill it", [DisplayLogTimeout]), + process_flag(trap_exit, Flag), + exit(Pid, kill) + end, - p("system events during test: " - "~n ~p", [snmp_test_global_sys_monitor:events()]), - Result = end_per_testcase1(Case, Config), - p("end_per_testcase -> done with" - "~n Result: ~p" - "~n Nodes: ~p", [Result, erlang:nodes()]), + ?IPRINT("end_per_testcase -> done with" + "~n Result: ~p" + "~n Nodes: ~p", [Result, erlang:nodes()]), Result. end_per_testcase1(otp8395, Config) when is_list(Config) -> @@ -935,9 +976,7 @@ end_per_testcase1(_Case, Config) when is_list(Config) -> ?DBG("end_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), - Dog = ?config(watchdog, Config), - ?WD_STOP(Dog), - Config. + wd_stop(Config). @@ -975,37 +1014,37 @@ end_per_testcase1(_Case, Config) when is_list(Config) -> init_all(Conf) -> ?DISPLAY_SUITE_INFO(), - snmp_agent_test_lib:init_all(Conf). + ?ALIB:init_all(Conf). finish_all(Conf) -> - snmp_agent_test_lib:finish_all(Conf). + ?ALIB:finish_all(Conf). start_v1_agent(Config) -> - snmp_agent_test_lib:start_v1_agent(Config). + ?ALIB:start_v1_agent(Config). start_v1_agent(Config, Opts) -> - snmp_agent_test_lib:start_v1_agent(Config, Opts). + ?ALIB:start_v1_agent(Config, Opts). start_v2_agent(Config) -> - snmp_agent_test_lib:start_v2_agent(Config). + ?ALIB:start_v2_agent(Config). start_v2_agent(Config, Opts) -> - snmp_agent_test_lib:start_v2_agent(Config, Opts). + ?ALIB:start_v2_agent(Config, Opts). %% start_v3_agent(Config) -> -%% snmp_agent_test_lib:start_v3_agent(Config). +%% ?ALIB:start_v3_agent(Config). start_v3_agent(Config, Opts) -> - snmp_agent_test_lib:start_v3_agent(Config, Opts). + ?ALIB:start_v3_agent(Config, Opts). start_bilingual_agent(Config) -> - snmp_agent_test_lib:start_bilingual_agent(Config). + ?ALIB:start_bilingual_agent(Config). start_multi_threaded_agent(Config) when is_list(Config) -> - snmp_agent_test_lib:start_mt_agent(Config). + ?ALIB:start_mt_agent(Config). stop_agent(Config) -> - snmp_agent_test_lib:stop_agent(Config). + ?ALIB:stop_agent(Config). create_tables(SaNode) -> @@ -1148,28 +1187,28 @@ varm_mib_storage_mnesia_cases() -> [msm_varm_mib_start]. init_mib_storage_ets(Config) when is_list(Config) -> - ?LOG("init_mib_storage_ets -> entry", []), + ?IPRINT("init_mib_storage_ets -> entry"), MibStorage = {mib_storage, [{module, snmpa_mib_storage_ets}]}, init_ms(Config, [MibStorage]). init_mib_storage_dets(Config) when is_list(Config) -> - ?LOG("init_mib_storage_dets -> entry", []), + ?IPRINT("init_mib_storage_dets -> entry"), ?line AgentDbDir = ?GCONF(agent_db_dir, Config), MibStorage = {mib_storage, [{module, snmpa_mib_storage_dets}, {options, [{dir, AgentDbDir}]}]}, init_ms(Config, [MibStorage]). init_mib_storage_mnesia(Config) when is_list(Config) -> - ?LOG("init_mib_storage_mnesia -> entry", []), + ?IPRINT("init_mib_storage_mnesia -> entry"), ?line AgentNode = ?GCONF(snmp_master, Config), MibStorage = {mib_storage, [{module, snmpa_mib_storage_mnesia}, {options, [{nodes, [AgentNode]}]}]}, init_ms(Config, [MibStorage]). init_ms(Config, Opts) when is_list(Config) -> - ?LOG("init_ms -> entry with" - "~n Config: ~p" - "~n Opts: ~p", [Config, Opts]), + ?IPRINT("init_ms -> entry with" + "~n Config: ~p" + "~n Opts: ~p", [Config, Opts]), ?line SaNode = ?GCONF(snmp_sa, Config), ?line create_tables(SaNode), ?line AgentConfDir = ?GCONF(agent_conf_dir, Config), @@ -1206,11 +1245,16 @@ init_size_check_ms(Config, Opts) when is_list(Config) -> ok -> case ?CRYPTO_SUPPORT() of {no, Reason} -> + ?WPRINT("crypto support not sufficient:" + "~n ~p", [Reason]), ?SKIP({unsupported_encryption, Reason}); yes -> + ?IPRINT("crypto started"), ok end; {error, Reason} -> + ?IPRINT("crypto not started:" + "~n ~p", [Reason]), ?SKIP({failed_starting_crypto, Reason}) end, create_tables(SaNode), @@ -1222,7 +1266,7 @@ init_size_check_ms(Config, Opts) when is_list(Config) -> [{vsn, v3} | start_v3_agent(Config, Opts)]. init_varm_mib_storage_dets(Config) when is_list(Config) -> - ?LOG("init_varm_mib_storage_dets -> entry", []), + ?IPRINT("init_varm_mib_storage_dets -> entry"), ?line SaNode = ?GCONF(snmp_sa, Config), ?line create_tables(SaNode), ?line AgentDbDir = ?GCONF(agent_db_dir, Config), @@ -1243,7 +1287,7 @@ init_varm_mib_storage_dets(Config) when is_list(Config) -> [{vsn, v1}, {agent_opts, Opts} | Config]. init_varm_mib_storage_mnesia(Config) when is_list(Config) -> - ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?IPRINT("init_varm_mib_storage_mnesia -> entry"), ?line SaNode = ?GCONF(snmp_sa, Config), ?line create_tables(SaNode), ?line AgentConfDir = ?GCONF(agent_conf_dir, Config), @@ -1264,7 +1308,7 @@ init_varm_mib_storage_mnesia(Config) when is_list(Config) -> [{vsn, v1}, {agent_opts, Opts} | Config]. finish_mib_storage_ets(Config) when is_list(Config) -> - ?LOG("finish_mib_storage_ets -> entry", []), + ?IPRINT("finish_mib_storage_ets -> entry"), delete_tables(), C1 = stop_agent(Config), delete_files(C1), @@ -1272,7 +1316,7 @@ finish_mib_storage_ets(Config) when is_list(Config) -> lists:keydelete(agent_opts, 1, C2). finish_mib_storage_dets(Config) when is_list(Config) -> - ?LOG("finish_mib_storage_dets -> entry", []), + ?IPRINT("finish_mib_storage_dets -> entry"), delete_tables(), C1 = stop_agent(Config), delete_files(C1), @@ -1280,7 +1324,7 @@ finish_mib_storage_dets(Config) when is_list(Config) -> lists:keydelete(agent_opts, 1, C2). finish_mib_storage_mnesia(Config) when is_list(Config) -> - ?LOG("finish_mib_storage_mnesia -> entry", []), + ?IPRINT("finish_mib_storage_mnesia -> entry"), delete_tables(), delete_mib_storage_mnesia_tables(), C1 = stop_agent(Config), @@ -1289,7 +1333,7 @@ finish_mib_storage_mnesia(Config) when is_list(Config) -> lists:keydelete(agent_opts, 1, C2). finish_varm_mib_storage_dets(Config) when is_list(Config) -> - ?LOG("finish_varm_mib_storage_dets -> entry", []), + ?IPRINT("finish_varm_mib_storage_dets -> entry"), delete_tables(), %% C1 = stop_agent(Config), % In case something went wrong... delete_files(Config), @@ -1297,7 +1341,7 @@ finish_varm_mib_storage_dets(Config) when is_list(Config) -> lists:keydelete(agent_opts, 1, C2). finish_varm_mib_storage_mnesia(Config) when is_list(Config) -> - ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + ?IPRINT("finish_varm_mib_storage_mnesia -> entry"), delete_tables(), delete_mib_storage_mnesia_tables(), %% C1 = stop_agent(Config), % In case something went wrong... @@ -1408,7 +1452,7 @@ ms_size_check(suite) -> []; ms_size_check(Config) when is_list(Config) -> ?P(ms_size_check), init_case(Config), - ?LOG("mib server size check...", []), + ?IPRINT("mib server size check..."), ?line load_master("Test2"), ?line load_master("TestTrap"), @@ -1449,7 +1493,7 @@ ms_size_check(Config) when is_list(Config) -> varm_mib_start(suite) -> []; varm_mib_start(Config) when is_list(Config) -> ?P(varm_mib_start), - ?LOG("varm_mib_start -> entry", []), + ?IPRINT("varm_mib_start -> entry"), init_case(Config), %% Start the agent @@ -1694,24 +1738,64 @@ app_dir(App) -> end. create_local_db_dir(Config) when is_list(Config) -> - ?P(create_local_db_dir), - DataDir = snmp_test_lib:lookup(data_dir, Config), - UName = erlang:unique_integer([positive]), - T = {UName, UName, UName}, - [As,Bs,Cs] = [integer_to_list(I) || I <- tuple_to_list(T)], - DbDir = filename:join([DataDir, As, Bs, Cs]), - ok = del_dir(DbDir, 3), - Name = list_to_atom(atom_to_list(create_local_db_dir) - ++"-"++As++"-"++Bs++"-"++Cs), - Pa = filename:dirname(code:which(?MODULE)), - {ok,Node} = ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]), + Pre = fun() -> + DataDir = snmp_test_lib:lookup(data_dir, Config), + T = {erlang:unique_integer([positive]), + erlang:unique_integer([positive]), + erlang:unique_integer([positive])}, + [As,Bs,Cs] = [integer_to_list(I) || I <- tuple_to_list(T)], + DbDir = filename:join([DataDir, As, Bs, Cs]), + Name = list_to_atom(atom_to_list(create_local_db_dir) + ++"_"++As++"_"++Bs++"_"++Cs), + ?IPRINT("try ensuring db-dir does not exist"), + try del_dir(DbDir, 3) of + ok -> + ok + catch + C:E:S -> + ?WPRINT("Failed pre db-dir delete: " + "~n Class: ~p" + "~n Error: ~p" + "~n Stack: ~p", [C, E, S]), + throw({skip, "Failed pre db-dir cleanup"}) + end, + ?IPRINT("try start node ~p", [Name]), + case ?ALIB:start_node(Name) of + {ok, Node} -> + {DbDir, Node}; + {error, Reason} -> + ?WPRINT("Failed starting node ~p:" + "~n ~p", [Reason]), + throw({skip, ?F("Failed starting node ~p", [Name])}) + end + end, + Case = fun do_create_local_db_dir/1, + Post = fun({DbDir, Node}) -> + ?IPRINT("try stop node ~p", [Node]), + ?ALIB:stop_node(Node), + ?IPRINT("try delete db-dir"), + try del_dir(DbDir, 3) + catch + C:E:S -> + ?WPRINT("Failed post db-dir delete: " + "~n DbDir ~s" + "~n Class: ~p" + "~n Error: ~p" + "~n Stack: ~p", [DbDir, C, E, S]), + ok + end + end, + ?TC_TRY(create_local_db_dir, Pre, Case, Post). +do_create_local_db_dir({DbDir, Node}) -> + ?P(create_local_db_dir), %% first start with a nonexisting DbDir Fun1 = fun() -> false = filelib:is_dir(DbDir), process_flag(trap_exit,true), {error, {error, {failed_open_dets, {file_error, _, _}}}} = - snmpa_local_db:start_link(normal, DbDir, [{verbosity,trace}]), + snmpa_local_db:start_link(normal, DbDir, + [{verbosity, trace}]), false = filelib:is_dir(DbDir), {ok, not_found} end, @@ -1729,21 +1813,21 @@ create_local_db_dir(Config) when is_list(Config) -> {ok, found} end, {ok, found} = nodecall(Node, Fun2), - %% cleanup - ?t:stop_node(Node), - ok = del_dir(DbDir, 3), ok. nodecall(Node, Fun) -> Parent = self(), - Ref = make_ref(), - spawn_link(Node, - fun() -> - Res = Fun(), - unlink(Parent), - Parent ! {Ref, Res} - end), + Ref = make_ref(), + Pid = spawn_link(Node, + fun() -> + Res = Fun(), + unlink(Parent), + Parent ! {Ref, Res} + end), receive + %% Just so we are not left hanging + {'EXIT', Pid, Reason} -> + Reason; {Ref, Res} -> Res end. @@ -1992,11 +2076,16 @@ init_v3(Config) when is_list(Config) -> ok -> case ?CRYPTO_SUPPORT() of {no, Reason} -> + ?WPRINT("crypto support not sufficient:" + "~n ~p", [Reason]), ?SKIP({unsupported_encryption, Reason}); yes -> + ?IPRINT("crypto started"), ok end; {error, Reason} -> + ?IPRINT("crypto not started:" + "~n ~p", [Reason]), ?SKIP({failed_starting_crypto, Reason}) end, SaNode = ?config(snmp_sa, Config), @@ -2046,7 +2135,7 @@ finish_mt(Config) when is_list(Config) -> %% This one *must* be run first in each case. init_case(Config) -> - snmp_agent_test_lib:init_case(Config). + ?ALIB:init_case(Config). load_master(Mib) -> @@ -2079,10 +2168,10 @@ unload_mibs(Mibs) -> ok = snmpa:unload_mibs(snmp_master_agent, Mibs). start_subagent(SaNode, RegTree, Mib) -> - snmp_agent_test_lib:start_subagent(SaNode, RegTree, Mib). + ?ALIB:start_subagent(SaNode, RegTree, Mib). stop_subagent(SA) -> - snmp_agent_test_lib:stop_subagent(SA). + ?ALIB:stop_subagent(SA). %%----------------------------------------------------------------- @@ -2116,7 +2205,7 @@ simple(Config) when is_list(Config) -> try_test(simple_standard_test), - p("done"), + ?IPRINT("done"), ok. simple_2(X) -> ?P(simple_2), simple(X). @@ -2143,7 +2232,7 @@ big(Config) when is_list(Config) -> {SaNode, _MgrNode, _MibDir} = init_case(Config), - ?P1("Starting subagent..."), + ?NPRINT("Starting subagent..."), ?line pong = net_adm:ping(SaNode), ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), @@ -2172,7 +2261,7 @@ big2(Config) when is_list(Config) -> %% v2 equivalent of the mibs. {SaNode, _MgrNode, _MibDir} = init_case(Config), - ?P1("Starting subagent..."), + ?NPRINT("Starting subagent..."), ?line pong = net_adm:ping(SaNode), ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), @@ -2278,7 +2367,7 @@ opaque_3(X) -> ?P(opaque_2), opaque(X). change_target_addr_config(suite) -> []; change_target_addr_config(Config) when is_list(Config) -> ?P(change_target_addr_config), - ?LOG("change_target_addr_config -> entry",[]), + ?IPRINT("change_target_addr_config -> entry"), init_case(Config), put(sname,snmp_suite), @@ -2286,43 +2375,43 @@ change_target_addr_config(Config) when is_list(Config) -> MA = whereis(snmp_master_agent), - ?LOG("change_target_addr_config -> load TestTrap",[]), + ?IPRINT("change_target_addr_config -> load TestTrap"), ?line load_master("TestTrap"), - ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?IPRINT("change_target_addr_config -> set trace verbosity for local_db"), ?line snmpa:verbosity(local_db,trace), %% First send some traps that will arive att the original manager - ?LOG("change_target_addr_config -> send trap",[]), + ?IPRINT("change_target_addr_config -> send trap"), try_test(ma_trap1, [MA]), - ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?IPRINT("change_target_addr_config -> set silence verbosity for local_db"), ?line snmpa:verbosity(local_db, silence), %% Start new dummy listener - ?LOG("change_target_addr_config -> start dummy manager",[]), + ?IPRINT("change_target_addr_config -> start dummy manager"), ?line {ok,Pid,NewPort} = dummy_manager_start(MA), %% Reconfigure - ?LOG("change_target_addr_config -> reconfigure",[]), + ?IPRINT("change_target_addr_config -> reconfigure"), AgentConfDir = ?config(agent_conf_dir, Config), ?line rewrite_target_addr_conf(AgentConfDir, NewPort), ?line snmp_target_mib:reconfigure(AgentConfDir), %% Send the trap again - ?LOG("change_target_addr_config -> send trap again",[]), + ?IPRINT("change_target_addr_config -> send trap again"), catch dummy_manager_send_trap2(Pid), - ?LOG("change_target_addr_config -> await trap ack",[]), + ?IPRINT("change_target_addr_config -> await trap ack"), catch dummy_manager_await_trap2_ack(), - ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?IPRINT("change_target_addr_config -> stop dummy manager"), ?line ok = dummy_manager_stop(Pid), - ?LOG("change_target_addr_config -> reset target address config",[]), + ?IPRINT("change_target_addr_config -> reset target address config"), ?line reset_target_addr_conf(AgentConfDir), - ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?IPRINT("change_target_addr_config -> unload TestTrap"), ?line unload_master("TestTrap"). @@ -2338,11 +2427,15 @@ await_dummy_manager_started(Pid) -> ?DBG("dummy_manager_start -> acknowledge received with" "~n Port: ~p",[Port]), {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + ?EPRINT("dummy manager terminated: " + "~n ~p", [Reason]), {error, Pid, Reason}; + _O -> - ?LOG("dummy_manager_start -> received unknown message:" - "~n ~p",[_O]), + ?NPRINT("dummy_manager_start -> received unknown message:" + "~n ~p", [_O]), await_dummy_manager_started(Pid) end. @@ -2354,7 +2447,7 @@ dummy_manager_stop(Pid) -> ?DBG("dummy_manager_stop -> acknowledge received",[]), ok after 10000 -> - ?ERR("dummy_manager_stop -> timeout",[]), + ?EPRINT("dummy_manager_stop -> timeout"), timeout end. @@ -2366,7 +2459,7 @@ dummy_manager_await_trap2_ack() -> ?DBG("dummy_manager_await_trap2 -> entry",[]), receive {received_trap, _Trap} -> - ?LOG("dummy_manager_await_trap2 -> received trap: ~p", [_Trap]), + ?IPRINT("dummy_manager_await_trap2 -> received trap: ~p", [_Trap]), %% Note: %% Without this sleep the v2_inform_i testcase failes! There %% is no relation between these two test cases as far as I @@ -2374,10 +2467,10 @@ dummy_manager_await_trap2_ack() -> ?SLEEP(60000), ok; _O -> - ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[_O]), + ?WPRINT("dummy_manager_await_trap2 -> unexpected message: ~p",[_O]), ok after 10000 -> - ?ERR("dummy_manager_await_trap2 -> timeout",[]), + ?EPRINT("dummy_manager_await_trap2 -> timeout",[]), timeout end. @@ -2393,18 +2486,18 @@ dummy_manager_init(Parent,MA) -> dummy_manager_loop(Parent,S,MA). dummy_manager_loop(P,S,MA) -> - ?LOG("dummy_manager_loop -> ready for receive",[]), + ?IPRINT("dummy_manager_loop -> ready for receive"), receive {send_trap,Trap} -> - ?LOG("dummy_manager_loop -> received trap send request" - "~n Trap: ~p",[Trap]), + ?IPRINT("dummy_manager_loop -> received trap send request" + "~n Trap: ~p", [Trap]), snmpa:send_trap(MA, Trap, "standard trap"), dummy_manager_loop(P,S,MA); {udp, _UdpId, _Ip, _UdpPort, Bytes} -> - ?LOG("dummy_manager_loop -> received upd message" - "~n from: ~p:~p" - "~n size: ~p", - [_Ip, _UdpPort, dummy_manager_message_sz(Bytes)]), + ?IPRINT("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [_Ip, _UdpPort, dummy_manager_message_sz(Bytes)]), R = dummy_manager_handle_message(Bytes), ?DBG("dummy_manager_loop -> R: ~p", [R]), P ! R, @@ -2415,30 +2508,31 @@ dummy_manager_loop(P,S,MA) -> gen_udp:close(S), exit(normal); _O -> - ?LOG("dummy_manager_loop -> received unknown message:" - "~n ~p", [_O]), + ?WPRINT("dummy_manager_loop -> received unknown message:" + "~n ~p", [_O]), dummy_manager_loop(P, S, MA) end. --ifdef(snmp_log). +%% -ifdef(snmp_log). dummy_manager_message_sz(B) when is_binary(B) -> size(B); dummy_manager_message_sz(L) when is_list(L) -> length(L); dummy_manager_message_sz(_) -> undefined. --endif. +%% -endif. dummy_manager_handle_message(Bytes) -> case (catch snmp_pdus:dec_message(Bytes)) of {'EXIT',Reason} -> - ?ERR("dummy_manager_handle_message -> " - "failed decoding message only:~n ~p",[Reason]), - {error,Reason}; + ?EPRINT("dummy_manager_handle_message -> " + "failed decoding message only:" + "~n ~p", [Reason]), + {error, Reason}; M -> ?DBG("dummy_manager_handle_message -> decoded message:" - "~n ~p",[M]), - {received_trap,M} + "~n ~p", [M]), + {received_trap, M} end. @@ -2465,19 +2559,20 @@ subagent(Config) when is_list(Config) -> ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), try_test(load_test_sa), - ?P1("Testing unregister subagent..."), + ?NPRINT("Testing unregister subagent..."), MA = whereis(snmp_master_agent), rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), try_test(unreg_test), - ?P1("Loading previous subagent mib in master and testing..."), + ?NPRINT("Loading previous subagent mib in master and testing..."), ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas1")), try_test(load_test), - ?P1("Unloading previous subagent mib in master and testing..."), + ?NPRINT("Unloading previous subagent mib in master and testing..."), ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas1")), try_test(unreg_test), - ?P1("Testing register subagent..."), + + ?NPRINT("Testing register subagent..."), rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), try_test(load_test_sa), @@ -2503,14 +2598,14 @@ mnesia(Config) when is_list(Config) -> ?P(mnesia), {SaNode, _MgrNode, _MibDir} = init_case(Config), - ?P1("Starting subagent with mnesia impl..."), + ?NPRINT("Starting subagent with mnesia impl..."), {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), ?line load_master("OLD-SNMPEA-MIB"), ?line init_old(), try_test(big_test_2), - ?P1("Testing unregister subagent..."), + ?NPRINT("Testing unregister subagent..."), MA = whereis(snmp_master_agent), rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), try_test(unreg_test), @@ -2577,7 +2672,7 @@ mul_get(Config) when is_list(Config) -> ?P(mul_get), init_case(Config), - ?P1("Testing multiple get..."), + ?NPRINT("Testing multiple get..."), try_test(do_mul_get). mul_get_2(X) -> ?P(mul_get_2), mul_get(X). @@ -2590,7 +2685,7 @@ mul_get_err(Config) when is_list(Config) -> ?P(mul_get_err), init_case(Config), - ?P1("Testing multiple get with error..."), + ?NPRINT("Testing multiple get with error..."), try_test(do_mul_get_err). mul_get_err_2(X) -> ?P(mul_get_err_2), mul_get_err(X). @@ -2603,7 +2698,7 @@ mul_next(Config) when is_list(Config) -> ?P(mul_next), init_case(Config), - ?P1("Testing multiple next..."), + ?NPRINT("Testing multiple next..."), try_test(do_mul_next). mul_next_2(X) -> ?P(mul_next_2), mul_next(X). @@ -2616,7 +2711,7 @@ mul_next_err(Config) when is_list(Config) -> ?P(mul_next_err), init_case(Config), - ?P1("Testing multiple next..."), + ?NPRINT("Testing multiple next..."), try_test(do_mul_next_err). mul_next_err_2(X) -> ?P(mul_next_err_2), mul_next_err(X). @@ -2629,7 +2724,7 @@ mul_set(Config) when is_list(Config) -> ?P(mul_set), init_case(Config), - ?P1("Testing multiple set..."), + ?NPRINT("Testing multiple set..."), try_test(do_mul_set). mul_set_2(X) -> ?P(mul_set_2), mul_set(X). @@ -2642,7 +2737,7 @@ mul_set_err(Config) when is_list(Config) -> ?P(mul_set_err), init_case(Config), - ?P1("Testing multiple set with error..."), + ?NPRINT("Testing multiple set with error..."), try_test(do_mul_set_err). mul_set_err_2(X) -> ?P(mul_set_err_2), mul_set_err(X). @@ -2656,30 +2751,30 @@ sa_register(Config) when is_list(Config) -> {SaNode, _MgrNode, MibDir} = init_case(Config), ?DBG("sa_register -> start subagent", []), - ?P1("start subagent..."), + ?NPRINT("start subagent..."), ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), ?DBG("sa_register -> unregister subagent", []), - ?P1("Testing unregister subagent (2)..."), + ?NPRINT("Testing unregister subagent (2)..."), MA = whereis(snmp_master_agent), rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), try_test(unreg_test), - ?P1("Unloading Klas1..."), + ?NPRINT("Unloading Klas1..."), ?DBG("sa_register -> unload mibs", []), snmpa:unload_mib(SA, join(MibDir, "Klas1")), - ?P1("Loading SA-MIB..."), + ?NPRINT("Loading SA-MIB..."), ?DBG("sa_register -> unload mibs", []), snmpa:load_mib(SA, join(MibDir, "SA-MIB")), - ?P1("register subagent..."), + ?NPRINT("register subagent..."), ?DBG("sa_register -> register subagent", []), rpc:call(SaNode, snmp, register_subagent, [MA, ?sa, SA]), try_test(sa_mib), - ?P1("stop subagent..."), + ?NPRINT("stop subagent..."), ?DBG("sa_register -> stop subagent", []), ?line stop_subagent(SA). @@ -2696,32 +2791,32 @@ v1_trap(Config) when is_list(Config) -> trap1(Config) -> {SaNode, _MgrNode, _MibDir} = init_case(Config), - ?P1("start subagent..."), + ?NPRINT("start subagent..."), ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), - ?P1("Testing trap sending from master agent..."), + ?NPRINT("Testing trap sending from master agent..."), MA = whereis(snmp_master_agent), - ?P1("load TestTrap & TestTrapv2..."), + ?NPRINT("load TestTrap & TestTrapv2..."), ?line load_master("TestTrap"), ?line load_master("TestTrapv2"), - ?P1("Testing trap sending from master-agent..."), + ?NPRINT("Testing trap sending from master-agent..."), try_test(ma_trap1, [MA]), try_test(ma_trap2, [MA]), try_test(ma_v2_2_v1_trap, [MA]), try_test(ma_v2_2_v1_trap2, [MA]), - ?P1("Testing trap sending from subagent..."), + ?NPRINT("Testing trap sending from subagent..."), try_test(sa_trap1, [SA]), try_test(sa_trap2, [SA]), try_test(sa_trap3, [SA]), - ?P1("unload TestTrap & TestTrapv2..."), + ?NPRINT("unload TestTrap & TestTrapv2..."), ?line unload_master("TestTrap"), ?line unload_master("TestTrapv2"), - ?P1("stop subagent..."), + ?NPRINT("stop subagent..."), ?line stop_subagent(SA). v2_trap(suite) -> []; @@ -2732,17 +2827,17 @@ v2_trap(Config) when is_list(Config) -> trap2(Config) -> {SaNode, _MgrNode, _MibDir} = init_case(Config), - ?P1("start subagent..."), + ?NPRINT("start subagent..."), ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), - ?P1("Testing trap sending from master agent..."), + ?NPRINT("Testing trap sending from master agent..."), MA = whereis(snmp_master_agent), - ?P1("load TestTrap & TestTrapv2..."), + ?NPRINT("load TestTrap & TestTrapv2..."), ?line load_master("TestTrap"), ?line load_master("TestTrapv2"), - ?P1("Testing trap sending from master-agent..."), + ?NPRINT("Testing trap sending from master-agent..."), try_test(ma_v2_trap1, [MA]), try_test(ma_v2_trap2, [MA]), try_test(ma_v1_2_v2_trap, [MA]), @@ -2750,16 +2845,16 @@ trap2(Config) -> try_test(sa_mib), - ?P1("Testing trap sending from subagent..."), + ?NPRINT("Testing trap sending from subagent..."), try_test(sa_v1_2_v2_trap1, [SA]), try_test(sa_v1_2_v2_trap2, [SA]), try_test(sa_v1_2_v2_trap3, [SA]), - ?P1("unload TestTrap & TestTrapv2..."), + ?NPRINT("unload TestTrap & TestTrapv2..."), ?line unload_master("TestTrap"), ?line unload_master("TestTrapv2"), - ?P1("stop subagent..."), + ?NPRINT("stop subagent..."), ?line stop_subagent(SA). v3_trap(suite) -> []; @@ -2811,18 +2906,18 @@ inform_i(Config) -> MA = whereis(snmp_master_agent), - ?P1("load TestTrap & TestTrapv2..."), + ?NPRINT("load TestTrap & TestTrapv2..."), ?line load_master("TestTrap"), ?line load_master("TestTrapv2"), - ?P1("Testing inform sending from master agent... " + ?NPRINT("Testing inform sending from master agent... " "~nNOTE! This test takes a few minutes (10) to complete."), try_test(ma_v2_inform1, [MA]), try_test(ma_v2_inform2, [MA]), try_test(ma_v2_inform3, [MA]), - ?P1("unload TestTrap & TestTrapv2..."), + ?NPRINT("unload TestTrap & TestTrapv2..."), ?line unload_master("TestTrap"), ?line unload_master("TestTrapv2"), ok. @@ -2843,26 +2938,26 @@ sa_error(Config) when is_list(Config) -> ?P(sa_error), {SaNode, _MgrNode, _MibDir} = init_case(Config), - ?P1("load OLD-SNMPEA-MIB..."), + ?NPRINT("load OLD-SNMPEA-MIB..."), ?line load_master("OLD-SNMPEA-MIB"), ?line init_old(), - ?P1("start subagent..."), + ?NPRINT("start subagent..."), ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), - ?P1("Testing sa bad value (is_set_ok)..."), + ?NPRINT("Testing sa bad value (is_set_ok)..."), try_test(sa_errs_bad_value), - ?P1("Testing sa gen err (set)..."), + ?NPRINT("Testing sa gen err (set)..."), try_test(sa_errs_gen_err), - ?P1("Testing too big..."), + ?NPRINT("Testing too big..."), try_test(sa_too_big), - ?P1("unload OLD-SNMPEA-MIB..."), + ?NPRINT("unload OLD-SNMPEA-MIB..."), ?line unload_master("OLD-SNMPEA-MIB"), - ?P1("stop subagent..."), + ?NPRINT("stop subagent..."), stop_subagent(SA). sa_error_2(X) -> @@ -2886,35 +2981,35 @@ next_across_sa(Config) when is_list(Config) -> {SaNode, _MgrNode, MibDir} = init_case(Config), MA = whereis(snmp_master_agent), - ?P1("start subagent (1)..."), + ?NPRINT("start subagent (1)..."), ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), - ?P1("Loading another subagent mib (Klas1)..."), + ?NPRINT("Loading another subagent mib (Klas1)..."), ?line ok = snmpa:load_mib(SA, MibDir ++ "Klas1"), - ?P1("register subagent..."), + ?NPRINT("register subagent..."), rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), - ?P1("Load test subagent..."), + ?NPRINT("Load test subagent..."), try_test(load_test_sa), - ?P1("Testing next across subagent (endOfMibView from SA)..."), + ?NPRINT("Testing next across subagent (endOfMibView from SA)..."), try_test(next_across_sa_test), - ?P1("Unloading mib (Klas1)"), + ?NPRINT("Unloading mib (Klas1)"), snmpa:unload_mib(SA, join(MibDir, "Klas1")), rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), try_test(unreg_test), - ?P1("Starting another subagent (2) "), + ?NPRINT("Starting another subagent (2) "), ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), - ?P1("Testing next across subagent (wrong prefix from SA)..."), + ?NPRINT("Testing next across subagent (wrong prefix from SA)..."), try_test(next_across_sa_test), - ?P1("stop subagent (1)..."), + ?NPRINT("stop subagent (1)..."), stop_subagent(SA), - ?P1("stop subagent (2)..."), + ?NPRINT("stop subagent (2)..."), stop_subagent(SA2). next_across_sa_2(X) -> @@ -2939,27 +3034,27 @@ undo(Config) when is_list(Config) -> MA = whereis(snmp_master_agent), - ?P1("start subagent (1)..."), + ?NPRINT("start subagent (1)..."), ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), - ?P1("Load Klas3 & Klas4..."), + ?NPRINT("Load Klas3 & Klas4..."), ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas3")), ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas4")), - ?P1("Testing undo phase at master agent..."), + ?NPRINT("Testing undo phase at master agent..."), try_test(undo_test), try_test(api_test2), - ?P1("Unload Klas3..."), + ?NPRINT("Unload Klas3..."), ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas3")), - ?P1("Testing bad return values from instrum. funcs..."), + ?NPRINT("Testing bad return values from instrum. funcs..."), try_test(bad_return), - ?P1("Unload Klas4..."), + ?NPRINT("Unload Klas4..."), ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas4")), - ?P1("Testing undo phase at subagent..."), + ?NPRINT("Testing undo phase at subagent..."), ?line ok = snmpa:load_mib(SA, join(MibDir, "Klas3")), ?line ok = snmpa:load_mib(SA, join(MibDir, "Klas4")), ?line ok = snmpa:register_subagent(MA, ?klas3, SA), @@ -2967,11 +3062,11 @@ undo(Config) when is_list(Config) -> try_test(undo_test), try_test(api_test3), - ?P1("Testing undo phase across master/subagents..."), + ?NPRINT("Testing undo phase across master/subagents..."), try_test(undo_test), try_test(api_test3), - ?P1("stop subagent..."), + ?NPRINT("stop subagent..."), stop_subagent(SA). undo_2(X) -> @@ -2995,12 +3090,12 @@ v1_processing(Config) when is_list(Config) -> ?DBG("v1_processing -> entry", []), init_case(Config), - ?P1("Load Test2..."), + ?NPRINT("Load Test2..."), ?line load_master("Test2"), try_test(v1_proc), - ?P1("Unload Test2..."), + ?NPRINT("Unload Test2..."), ?line unload_master("Test2"). %% Req. Test2 @@ -3009,12 +3104,12 @@ v2_processing(Config) when is_list(Config) -> ?P(v2_processing), init_case(Config), - ?P1("Load Test2..."), + ?NPRINT("Load Test2..."), ?line load_master("Test2"), try_test(v2_proc), - ?P1("Unload Test2..."), + ?NPRINT("Unload Test2..."), ?line unload_master("Test2"). %% Req. Test2 @@ -3023,12 +3118,12 @@ v3_processing(Config) when is_list(Config) -> ?P(v3_processing), init_case(Config), - ?P1("Load Test2..."), + ?NPRINT("Load Test2..."), ?line load_master("Test2"), try_test(v2_proc), % same as v2! - ?P1("Unload Test2..."), + ?NPRINT("Unload Test2..."), ?line unload_master("Test2"). @@ -3101,7 +3196,7 @@ v3_md5_auth(Config) when is_list(Config) -> ?P(v3_md5_auth), init_case(Config), - ?P1("Testing MD5 authentication...takes a few seconds..."), + ?NPRINT("Testing MD5 authentication...takes a few seconds..."), AgentConfDir = ?config(agent_conf_dir, Config), ?line rewrite_target_params_conf(AgentConfDir, "authMD5", authNoPriv), @@ -3128,7 +3223,7 @@ v3_sha_auth(Config) when is_list(Config) -> ?P(v3_sha_auth), init_case(Config), - ?P1("Testing SHA authentication...takes a few seconds..."), + ?NPRINT("Testing SHA authentication...takes a few seconds..."), AgentConfDir = ?config(agent_conf_dir, Config), ?line rewrite_target_params_conf(AgentConfDir, "authSHA", authNoPriv), @@ -3155,7 +3250,7 @@ v3_des_priv(Config) when is_list(Config) -> ?P(v3_des_priv), init_case(Config), - ?P1("Testing DES encryption...takes a few seconds..."), + ?NPRINT("Testing DES encryption...takes a few seconds..."), AgentConfDir = ?config(agent_conf_dir, Config), ?line rewrite_target_params_conf(AgentConfDir, "privDES", authPriv), @@ -3772,10 +3867,10 @@ big_test() -> %% Req. system group, Klas2, OLD-SNMPEA-MIB big_test_2() -> - ?P1("Testing simple next/get/set @ master agent (2)..."), + ?NPRINT("Testing simple next/get/set @ master agent (2)..."), simple_standard_test(), - ?P1("Testing simple next/get/set @ subagent (2)..."), + ?NPRINT("Testing simple next/get/set @ subagent (2)..."), gn([[klas2]]), ?line ?expect1([{[fname2,0], ""}]), g([[fname2,0]]), @@ -3787,7 +3882,7 @@ big_test_2() -> otp_1298_test(), - ?P1("Testing next from last object in master to subagent (2)..."), + ?NPRINT("Testing next from last object in master to subagent (2)..."), gn([[?v1_2(sysServices, sysORLastChange),0]]), ?line ?expect1([{[fname2,0], "test set"}]), gn([[1,1], [?v1_2(sysServices, sysORLastChange),0]]), @@ -3796,7 +3891,7 @@ big_test_2() -> table_test(), - ?P1("Adding one row in subagent table (2)"), + ?NPRINT("Adding one row in subagent table (2)"), _FTab = [friendsEntry2], s([{[friendsEntry2, [2, 3]], s, "kompis3"}, {[friendsEntry2, [3, 3]], i, ?createAndGo}]), @@ -3809,7 +3904,7 @@ big_test_2() -> s([{[friendsEntry2, [3, 3]], i, ?destroy}]), ?line ?expect1([{[friendsEntry2, [3, 3]], ?destroy}]), - ?P1("Adding two rows in subagent table with special INDEX (2)"), + ?NPRINT("Adding two rows in subagent table with special INDEX (2)"), s([{[kompissEntry2, [1, 3]], s, "kompis3"}, {[kompissEntry2, [2, 3]], i, ?createAndGo}]), ?line ?expect1([{[kompissEntry2, [1, 3]], "kompis3"}, @@ -3838,7 +3933,7 @@ big_test_2() -> %% Req. Test1 multi_threaded_test() -> - ?P1("Testing multi threaded agent..."), + ?NPRINT("Testing multi threaded agent..."), g([[multiStr,0]]), Pid = get_multi_pid(), g([[sysUpTime,0]]), @@ -3865,7 +3960,7 @@ multi_threaded_test() -> %% Req. Test1, TestTrapv2 mt_trap_test(MA) -> - ?P1("Testing trap-sending with multi threaded agent..."), + ?NPRINT("Testing trap-sending with multi threaded agent..."), ?DBG("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []), snmpa:send_trap(MA, testTrapv22, "standard trap"), ?DBG("mt_trap_test(02) -> await v2trap", []), @@ -3911,7 +4006,7 @@ get_multi_pid(N) -> %% Req. Test1 types_v2_test() -> - ?P1("Testing v2 types..."), + ?NPRINT("Testing v2 types..."), s([{[bits1,0], 2#10}]), ?line ?expect1([{[bits1,0], ?str(2#10)}]), @@ -3938,8 +4033,9 @@ types_v2_test() -> %% Req. Test1 implied_test(MA) -> - ?LOG("implied_test -> start",[]), - ?P1("Testing IMPLIED..."), + ?IPRINT("implied_test -> start"), + + ?NPRINT("Testing IMPLIED..."), snmpa:verbosity(MA, trace), @@ -3997,13 +4093,14 @@ implied_test(MA) -> snmpa:verbosity(MA, log), - ?LOG("implied_test -> done", []). + ?IPRINT("implied_test -> done", []), + ok. %% Req. Test1 sparse_table_test() -> - ?P1("Testing sparse table..."), + ?NPRINT("Testing sparse table..."), %% Create two rows, check that they are get-nexted in correct order. Idx1 = 1, @@ -4033,11 +4130,12 @@ sparse_table_test() -> %% Req. Test1 cnt_64_test(MA) -> - ?LOG("start cnt64 test (~p)",[MA]), + ?IPRINT("start cnt64 test (~p)", [MA]), snmpa:verbosity(MA, trace), - ?LOG("start cnt64 test",[]), - ?P1("Testing Counter64, and at the same time, " - "RowStatus is not last column"), + ?IPRINT("start cnt64 test"), + + ?NPRINT("Testing Counter64, and at the same time, " + "RowStatus is not last column"), ?DBG("get cnt64",[]), g([[cnt64,0]]), @@ -4096,7 +4194,7 @@ cnt_64_test(MA) -> %% Req. Test1 opaque_test() -> - ?P1("Testing Opaque datatype..."), + ?NPRINT("Testing Opaque datatype..."), g([[opaqueObj,0]]), ?line ?expect1([{[opaqueObj,0], "opaque-data"}]). @@ -4238,7 +4336,7 @@ do_mul_next_err() -> %% Req. system group, Klas1, OLD-SNMPEA-MIB do_mul_set() -> - ?P1("Adding one row in subagent table, and one in master table"), + ?NPRINT("Adding one row in subagent table, and one in master table"), NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], @@ -4272,7 +4370,7 @@ do_mul_set_err() -> NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], - ?P1("Adding one row in subagent table, and one in master table"), + ?NPRINT("Adding one row in subagent table, and one in master table"), s([{[friendsEntry, [2, 3]], s, "kompis3"}, {NewKeyc3, 2}, {[sysUpTime,0], 45}, % sysUpTime (readOnly) @@ -4435,14 +4533,14 @@ ma_v2_inform1(MA) -> "~n with receiver: ~p", [_Addr]), ok; {snmp_targets, T, Addrs} -> - ?ERR("ma_v2_inform1 -> " - "received unexpected snmp_targets" - "~n with receivers: ~n ~p",[Addrs]), + ?EPRINT("ma_v2_inform1 -> " + "received unexpected snmp_targets" + "~n with receivers: ~n ~p",[Addrs]), {error, {bad_addrs, Addrs}} after 5000 -> - ?ERR("ma_v2_inform1 -> " - "timeout awaiting snmp_targets [~w]",[T]), + ?EPRINT("ma_v2_inform1 -> " + "timeout awaiting snmp_targets [~w]",[T]), {error, snmp_targets_timeout} end end, @@ -4456,16 +4554,16 @@ ma_v2_inform1(MA) -> "[with manager response] from: ~n ~p", [_Addr]), ok; {snmp_notification, Tag03, {no_response, _Addr}} -> - ?ERR("ma_v2_inform1 -> " - "received unexpected snmp_notification " - "[without manager response] from: ~n ~p", - [_Addr]), + ?EPRINT("ma_v2_inform1 -> " + "received unexpected snmp_notification " + "[without manager response] from: ~n ~p", + [_Addr]), {error, no_response} after 20000 -> - ?ERR("ma_v2_inform1 -> " - "timeout awaiting snmp_notification [~p]", - [Tag03]), + ?EPRINT("ma_v2_inform1 -> " + "timeout awaiting snmp_notification [~p]", + [Tag03]), {error, snmp_notification_timeout} end end, @@ -4490,9 +4588,9 @@ ma_v2_inform1(MA) -> fun() -> receive {snmp_notification, Tag07, {got_response, _Addr}} -> - ?ERR("ma_v2_inform1 -> " - "received unexpected snmp_notification " - "[with manager response] from: ~n ~p", [_Addr]), + ?EPRINT("ma_v2_inform1 -> " + "received unexpected snmp_notification " + "[with manager response] from: ~n ~p", [_Addr]), {error, got_response}; {snmp_notification, Tag07, {no_response, _Addr}} -> ?DBG("ma_v2_inform1 -> " @@ -4502,9 +4600,9 @@ ma_v2_inform1(MA) -> ok after 240000 -> - ?ERR("ma_v2_inform1 -> " - "timeout awaiting snmp_notification [~p]", - [Tag07]), + ?EPRINT("ma_v2_inform1 -> " + "timeout awaiting snmp_notification [~p]", + [Tag07]), {error, snmp_notification_timeout} end end, @@ -4554,26 +4652,28 @@ ma_v2_inform2(MA) -> %% Await callback(s) CmdAwaitDeliveryCallback = fun(Kind, Ref, Tag) -> - io:format("CmdAwaitDeliveryCallback -> entry with" - "~n Kind: ~p" - "~n Ref: ~p" - "~n Tag: ~p" - "~n", [Kind, Ref, Tag]), + ?IPRINT("CmdAwaitDeliveryCallback -> entry with" + "~n Kind: ~p" + "~n Ref: ~p" + "~n Tag: ~p", [Kind, Ref, Tag]), receive {Kind, Ref, ok} -> - io:format("CmdAwaitDeliveryCallback(~p,~p) -> received expected result: ok" - "~n", [Tag, Ref]), + ?IPRINT("CmdAwaitDeliveryCallback(~p,~p) -> " + "received expected result: ok" + "~n", [Tag, Ref]), ok; {Kind, Ref, Error} -> - io:format("CmdAwaitDeliveryCallback(~p,~p) -> received unexpected result: " - "~n Error: ~p" - "~n", [Tag, Ref, Error]), + ?IPRINT("CmdAwaitDeliveryCallback(~p,~p) -> " + "received unexpected result: " + "~n Error: ~p" + "~n", [Tag, Ref, Error]), {error, {unexpected_response, Error}} after 240000 -> - ?ERR("ma_v2_inform2 -> " - "timeout awaiting got_response for snmp_notification [~p]", - [Tag]), + ?EPRINT("ma_v2_inform2 -> " + "timeout awaiting got_response for " + "snmp_notification [~p]", + [Tag]), {error, snmp_notification_timeout} end end, @@ -4645,25 +4745,27 @@ ma_v2_inform3(MA) -> %% Await callback(s) CmdAwaitDeliveryCallback = fun(Kind, Ref, Tag) -> - io:format("CmdAwaitDeliveryCallback -> entry with" - "~n Kind: ~p" - "~n Ref: ~p" - "~n Tag: ~p" - "~n", [Kind, Ref, Tag]), + ?IPRINT("CmdAwaitDeliveryCallback -> entry with" + "~n Kind: ~p" + "~n Ref: ~p" + "~n Tag: ~p", [Kind, Ref, Tag]), receive {Kind, Ref, ok} -> - io:format("CmdAwaitDeliveryCallback(~p,~p) -> received expected result: ok" - "~n", [Tag, Ref]), + ?IPRINT("CmdAwaitDeliveryCallback(~p,~p) -> " + "received expected result: ok" + "~n", [Tag, Ref]), ok; {Kind, Ref, Error} -> - io:format("CmdAwaitDeliveryCallback(~p,~p) -> received unexpected result: " - "~n Error: ~p" - "~n", [Tag, Ref, Error]), + ?IPRINT("CmdAwaitDeliveryCallback(~p,~p) -> " + "received unexpected result: " + "~n Error: ~p" + "~n", [Tag, Ref, Error]), {error, {unexpected_response, Error}} after 240000 -> - ?ERR("ma_v2_inform3 -> " - "timeout awaiting got_response for snmp_notification [~p]", + ?EPRINT("ma_v2_inform3 -> " + "timeout awaiting got_response for " + "snmp_notification [~p]", [Tag]), {error, snmp_notification_timeout} end @@ -4746,16 +4848,16 @@ delivery_info(Tag, Address, DeliveryResult, Extra) -> command_handler([]) -> ok; command_handler([{_No, _Desc, Cmd}|Rest]) -> - ?LOG("command_handler -> command ~w: ~n ~s", [_No, _Desc]), + ?IPRINT("command_handler -> command ~w: ~n ~s", [_No, _Desc]), case (catch Cmd()) of ok -> - ?LOG("command_handler -> ~w: ok", [_No]), + ?IPRINT("command_handler -> ~w: ok", [_No]), command_handler(Rest); {error, Reason} -> - ?ERR("command_handler -> ~w error: ~n~p", [_No, Reason]), + ?EPRINT("command_handler -> ~w error: ~n~p", [_No, Reason]), ?line ?FAIL(Reason); Error -> - ?ERR("command_handler -> ~w unexpected: ~n~p", [_No, Error]), + ?EPRINT("command_handler -> ~w unexpected: ~n~p", [_No, Error]), ?line ?FAIL({unexpected_command_result, Error}) end. @@ -5033,7 +5135,7 @@ standard_mibs2_cases() -> snmpv2_mib_2(suite) -> []; snmpv2_mib_2(Config) when is_list(Config) -> ?P(snmpv2_mib_2), - ?LOG("snmpv2_mib_2 -> start",[]), + ?IPRINT("snmpv2_mib_2 -> start"), init_case(Config), ?DBG("snmpv2_mib_2 -> standard mib init",[]), @@ -5072,7 +5174,7 @@ snmpv2_mib_2(Config) when is_list(Config) -> "then disable auth traps",[]), try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), - ?LOG("snmpv2_mib_2 -> done", []), + ?IPRINT("snmpv2_mib_2 -> done"), ok. @@ -5190,7 +5292,7 @@ snmp_community_mib_2(X) -> ?P(snmp_community_mib_2), snmp_community_mib(X). %% Req. SNMP-COMMUNITY-MIB snmp_community_mib_test() -> - ?INF("NOT YET IMPLEMENTED", []), + ?NPRINT("NOT YET IMPLEMENTED"), nyi. @@ -5215,41 +5317,69 @@ snmp_framework_mib_3(Config) when is_list(Config) -> %% Req. SNMP-FRAMEWORK-MIB +%% snmpEngineID in number of seconds. +%% In theory, the Engine Time diff of the engine, should be exactly +%% the same as the number of seconds we sleep (5 in this case). +%% But because, on some (slow or/and high loaded) hosts, the actual +%% time we sleep could be a lot larger (due to, for instance, scheduling). +%% Therefor we must take that into account when we check if the +%% Engine Time diff (between the two checks) is acceptably. snmp_framework_mib_test() -> + Sleep = 5, ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), T1 = snmp_misc:now(ms), ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), T2 = snmp_misc:now(ms), - ?SLEEP(5000), + ?SLEEP(?SECS(Sleep)), T3 = snmp_misc:now(ms), ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), T4 = snmp_misc:now(ms), - ?PRINT2("snmp_framework_mib -> time(s): " - "~n EngineTime 1: ~p" - "~n Time to acquire: ~w ms" - "~n EngineTime 2: ~p" - "~n Time to acquire: ~w ms" - "~n => (5 sec sleep between get(snmpEngineTime))" - "~n Total time to acquire: ~w ms", - [EngineTime, T2-T1, EngineTime2, T4-T3, T4-T1]), - if - (EngineTime+7) < EngineTime2 -> - ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); - (EngineTime+4) > EngineTime2 -> - ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); - true -> - ok + + %% Ok, we tried to sleep 5 seconds, but how long did we actually sleep + ASleep = ((T3-T2) + 500) div 1000, + EngineTimeDiff = EngineTime2 - EngineTime, + HighEngineTime = EngineTime + ASleep + 2, + LowEngineTime = EngineTime + ASleep - 1, + + ?IPRINT("snmp_framework_mib -> time(s): " + "~n EngineTime 1: ~p" + "~n Time to acquire: ~w msec" + "~n EngineTime 2: ~p" + "~n Time to acquire: ~w msec" + "~n => Total time to acquire: ~w msec" + "~n Sleep between get(snmpEngineTime): ~w (~w) sec" + "~n Engine Time Diff: ~w sec" + "~n Success if:" + "~n ~w (low) =< Engine Time 2 =< ~w (high)", + [EngineTime, T2-T1, + EngineTime2, T4-T3, + T4-T1, ASleep, Sleep, EngineTimeDiff, LowEngineTime, HighEngineTime]), + + if + (HighEngineTime < EngineTime2) -> + ?EPRINT("snmp_framework_mib -> (High) Engine Time diff (~w) too large: " + "~n ~w < ~w", + [EngineTimeDiff, HighEngineTime, EngineTime2]), + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + (LowEngineTime > EngineTime2) -> + ?EPRINT("snmp_framework_mib -> (Low) Engine Time diff (~w) too large: " + "~n ~w > ~w", + [EngineTimeDiff, LowEngineTime, EngineTime2]), + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> + ok end, + T5 = snmp_misc:now(ms), ?line case get_req(4, [[snmpEngineBoots,0]]) of [Boots] when is_integer(Boots) -> T6 = snmp_misc:now(ms), - ?PRINT2("snmp_framework_mib -> " + ?IPRINT("snmp_framework_mib -> " "~n boots: ~p" "~n Time to acquire: ~w ms", [Boots, T6-T5]), ok; Else -> - ?PRINT2("snmp_framework_mib -> failed get proper boots:" + ?EPRINT("snmp_framework_mib -> failed get proper boots:" "~n ~p", [Else]), ?FAIL({invalid_boots, Else}) end, @@ -5339,7 +5469,7 @@ snmp_target_mib_2(X) -> ?P(snmp_target_mib_2), snmp_target_mib(X). snmp_target_mib_3(X) -> ?P(snmp_target_mib_3), snmp_target_mib(X). snmp_target_mib_test() -> - ?INF("NOT YET IMPLEMENTED", []), + ?NPRINT("NOT YET IMPLEMENTED"), nyi. snmp_notification_mib(suite) -> []; @@ -5357,7 +5487,7 @@ snmp_notification_mib_3(X) -> ?P(snmp_notification_mib_3), snmp_notification_mib(X). snmp_notification_mib_test() -> - ?INF("NOT YET IMPLEMENTED", []), + ?NPRINT("NOT YET IMPLEMENTED"), nyi. @@ -5393,7 +5523,7 @@ snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib() -> snmpa:verbosity(net_if,trace), snmpa:verbosity(master_agent,trace), - ?LOG("start snmp_view_based_acm_mib test",[]), + ?IPRINT("start snmp_view_based_acm_mib test"), %% The user "no-rights" is present in USM, and is mapped to security %% name 'no-rights", which is not present in VACM. %% So, we'll add rights for it, try them and delete them. @@ -5790,7 +5920,7 @@ usm_bad() -> loop_mib_1(suite) -> []; loop_mib_1(Config) when is_list(Config) -> ?P(loop_mib_1), - ?LOG("loop_mib_1 -> initiate case",[]), + ?IPRINT("loop_mib_1 -> initiate case"), {_SaNode, _MgrNode, _MibDir} = init_case(Config), ?DBG("loop_mib_1 -> ~n" @@ -5827,14 +5957,14 @@ loop_mib_1(Config) when is_list(Config) -> ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), %% snmpa:verbosity(master_agent,log), %% snmpa:verbosity(mib_server,silence), - ?LOG("loop_mib_1 -> done",[]), + ?IPRINT("loop_mib_1 -> done"), ok. loop_mib_2(suite) -> []; loop_mib_2(Config) when is_list(Config) -> ?P(loop_mib_2), - ?LOG("loop_mib_2 -> initiate case",[]), + ?IPRINT("loop_mib_2 -> initiate case"), {_SaNode, _MgrNode, _MibDir} = init_case(Config), ?DBG("do_loop_mib_2 -> ~n" "\tSaNode: ~p~n" @@ -5857,14 +5987,14 @@ loop_mib_2(Config) when is_list(Config) -> ?line unload_master("SNMP-NOTIFICATION-MIB"), ?line unload_master("SNMP-FRAMEWORK-MIB"), ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), - ?LOG("loop_mib_2 -> done",[]), + ?IPRINT("loop_mib_2 -> done"), ok. loop_mib_3(suite) -> []; loop_mib_3(Config) when is_list(Config) -> ?P(loop_mib_3), - ?LOG("loop_mib_3 -> initiate case",[]), + ?IPRINT("loop_mib_3 -> initiate case"), {_SaNode, _MgrNode, _MibDir} = init_case(Config), ?DBG("loop_mib_3 -> ~n" "\tSaNode: ~p~n" @@ -5883,7 +6013,7 @@ loop_mib_3(Config) when is_list(Config) -> ?line unload_master("SNMP-NOTIFICATION-MIB"), ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), ?line unload_master("SNMP-USER-BASED-SM-MIB"), - ?LOG("loop_mib_3 -> done",[]), + ?IPRINT("loop_mib_3 -> done"), ok. @@ -6378,7 +6508,7 @@ otp_1366_2(X) -> ?P(otp_1366_2), otp_1366(X). otp_1366_3(X) -> ?P(otp_1366_3), otp_1366(X). otp_1366_test() -> - ?INF("NOT YET IMPLEMENTED", []), + ?NPRINT("NOT YET IMPLEMENTED"), 'NYI'. @@ -6397,7 +6527,7 @@ otp_2776_2(X) -> ?P(otp_2776_2), otp_2776(X). otp_2776_3(X) -> ?P(otp_2776_3), otp_2776(X). otp_2776_test() -> - io:format("Testing bug reported in ticket OTP-2776...~n"), + ?NPRINT("Testing bug reported in ticket OTP-2776..."), Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 @@ -6716,10 +6846,11 @@ otp_7157(Config) -> %% ts:run(snmp, snmp_agent_test, [batch]). otp_7157_test(MA) -> - ?LOG("start otp_7157_test test (~p)",[MA]), + ?IPRINT("start otp_7157_test test (~p)", [MA]), snmpa:verbosity(MA, trace), - ?LOG("start otp_7157_test test",[]), - ?P1("Testing that varbinds in traps/notifications are not reordered"), + ?IPRINT("start otp_7157_test test"), + + ?NPRINT("Testing that varbinds in traps/notifications are not reordered"), ?DBG("send cntTrap",[]), snmpa:send_trap(MA, cntTrap, "standard trap"), @@ -6837,8 +6968,7 @@ otp_16092_simple_start_and_stop(Config, ESO, Expected) -> ?line ConfDir = ?config(agent_conf_dir, Config), ?line DbDir = ?config(agent_db_dir, Config), - p("try start agent node~n"), - p(user, "try start agent node~n"), + ?NPRINT("try start agent node"), {ok, Node} = ?ALIB:start_node(agent_16092), Vsns = [v1], @@ -6870,27 +7000,27 @@ otp_16092_simple_start_and_stop(Config, ESO, Expected) -> otp16092_try_start_and_stop_agent(Node, Opts, Expected), - p("try stop agent node ~p~n", [Node]), - p(user, "try stop agent node ~p~n", [Node]), + ?NPRINT("try stop agent node ~p", [Node]), ?ALIB:stop_node(Node), ?SLEEP(1000), - p("done~n"), - p(user, "done~n"), + ?NPRINT("done"), ok. otp16092_try_start_and_stop_agent(Node, Opts, Expected) -> - i("try start snmp (agent) supervisor (on ~p) - expect ~p~n", [Node, Expected]), + ?IPRINT("try start snmp (agent) supervisor (on ~p) - expect ~p", + [Node, Expected]), case start_standalone_agent(Node, Opts) of Pid when is_pid(Pid) andalso (Expected =:= success) -> - i("Expected success starting snmp (agent) supervisor~n"), + ?IPRINT("Expected success starting snmp (agent) supervisor"), ?SLEEP(1000), stop_standalone_agent(Pid), ok; Pid when is_pid(Pid) andalso (Expected =:= failure) -> - e("Unexpected success starting snmp (agent) supervisor: (~p)~n", [Pid]), + ?EPRINT("Unexpected success starting snmp (agent) supervisor: (~p)", + [Pid]), ?SLEEP(1000), stop_standalone_agent(Pid), ?FAIL('unexpected-start-success'); @@ -6901,18 +7031,18 @@ otp16092_try_start_and_stop_agent(Node, Opts, Expected) -> {shutdown, {failed_to_start_child, snmpa_agent, {net_if_error, Reason}}}}} when (Expected =:= failure) -> - p("Expected (shutdown, net-if) error starting " - "snmp (agent) supervisor (on ~p):" - "~n ~p", [Node, Reason]), + ?IPRINT("Expected (shutdown, net-if) error starting " + "snmp (agent) supervisor (on ~p):" + "~n ~p", [Node, Reason]), ok; {error, {shutdown, Reason}} when (Expected =:= failure) -> - p("Expected (shutdown) error starting " - "snmp (agent) supervisor (on ~p):" - "~n ~p", [Node, Reason]), + ?IPRINT("Expected (shutdown) error starting " + "snmp (agent) supervisor (on ~p):" + "~n ~p", [Node, Reason]), ok; {error, Reason} when (Expected =:= failure) -> - p("Expected error starting snmp (agent) supervisor (on ~p):" - "~n ~p", [Node, Reason]), + ?IPRINT("Expected error starting snmp (agent) supervisor (on ~p):" + "~n ~p", [Node, Reason]), ok; {badrpc, @@ -6922,23 +7052,24 @@ otp16092_try_start_and_stop_agent(Node, Opts, Expected) -> {shutdown, {failed_to_start_child, snmpa_agent, {net_if_error, Reason}}}}}}} when (Expected =:= failure) -> - p("Expected (badrpc, shutdown, net-if) error starting " - "snmp (agent) supervisor (on ~p):" - "~n ~p", [Node, Reason]), + ?IPRINT("Expected (badrpc, shutdown, net-if) error starting " + "snmp (agent) supervisor (on ~p):" + "~n ~p", [Node, Reason]), ok; {badrpc, {'EXIT', {shutdown, Reason}}} when (Expected =:= failure) -> - p("Expected (badrpc, shutdown) error starting " - "snmp (agent) supervisor (on ~p):" - "~n ~p", [Node, Reason]), + ?IPRINT("Expected (badrpc, shutdown) error starting " + "snmp (agent) supervisor (on ~p):" + "~n ~p", [Node, Reason]), ok; {badrpc, {'EXIT', Reason}} when (Expected =:= failure) -> - p("Expected (badrpc) error starting snmp (agent) supervisor (on ~p):" - "~n ~p", [Node, Reason]), + ?IPRINT("Expected (badrpc) error starting snmp (agent) supervisor " + "(on ~p):" + "~n ~p", [Node, Reason]), ok; {badrpc, Reason} = BADRPC -> - e("Bad RPC to node ~p failed:" - "~n ~p", [Node, Reason]), + ?WPRINT("Bad RPC to node ~p failed:" + "~n ~p", [Node, Reason]), ?SKIP({BADRPC, Node}) end, @@ -7032,9 +7163,7 @@ otp8395({init, Config}) when is_list(Config) -> %% Create watchdog %% - Dog = ?WD_START(?MINS(1)), - - [{watchdog, Dog} | Config2]; + wd_start(1, Config2); otp8395({fin, Config}) when is_list(Config) -> ?DBG("otp8395(fin) -> entry with" @@ -7073,9 +7202,7 @@ otp8395({fin, Config}) when is_list(Config) -> ?DBG("otp8395(fin) -> stop manager node", []), stop_node(ManagerNode), - Dog = ?config(watchdog, Config), - ?WD_STOP(Dog), - lists:keydelete(watchdog, 1, Config); + wd_stop(Config); otp8395(doc) -> "OTP-8395 - ATL with sequence numbering. "; @@ -7153,15 +7280,15 @@ otp9884(Config) when is_list(Config) -> otp9884_backup(Node, Pid, Tag, Dir) -> - i("[~w] backup - await continue", [Tag]), + ?IPRINT("[~w] backup - await continue", [Tag]), Pid ! {otp9884_backup_started, Tag, self()}, receive {otp9884_backup_continue, Tag, Pid} -> ok end, - i("[~w] backup start", [Tag]), + ?IPRINT("[~w] backup start", [Tag]), Res = rpc:call(Node, snmpa, backup, [Dir]), - i("[~w] backup result: ~p", [Tag, Res]), + ?IPRINT("[~w] backup result: ~p", [Tag, Res]), Pid ! {otp9884_backup_complete, Tag, Res}. @@ -7170,30 +7297,30 @@ otp9884_await_backup_started() -> otp9884_await_backup_started(First, Second) when is_pid(First) andalso is_pid(Second) -> - i("otp9884_await_backup_started -> order first continue"), + ?IPRINT("otp9884_await_backup_started -> order first continue"), First ! {otp9884_backup_continue, first, self()}, - i("otp9884_await_backup_started -> order second continue"), + ?IPRINT("otp9884_await_backup_started -> order second continue"), Second ! {otp9884_backup_continue, second, self()}, ok; otp9884_await_backup_started(First, Second) -> receive {otp9884_backup_started, first, Pid} when (First =:= undefined) -> - i("otp9884_await_backup_started -> received started from first"), + ?IPRINT("otp9884_await_backup_started -> received started from first"), otp9884_await_backup_started(Pid, Second); {otp9884_backup_started, second, Pid} when (Second =:= undefined) -> - i("otp9884_await_backup_started -> received started from second"), + ?IPRINT("otp9884_await_backup_started -> received started from second"), otp9884_await_backup_started(First, Pid) end. otp9884_await_backup_completion(ok, Second) when ((Second =/= ok) andalso (Second =/= undefined)) -> - i("otp9884_await_backup_completion -> " - "first backup succeed and second failed (~p)", [Second]), + ?IPRINT("otp9884_await_backup_completion -> " + "first backup succeed and second failed (~p)", [Second]), ok; otp9884_await_backup_completion(First, ok) when ((First =/= ok) andalso (First =/= undefined)) -> - i("otp9884_await_backup_completion -> " - "second backup succeed and first failed (~p)", [First]), + ?IPRINT("otp9884_await_backup_completion -> " + "second backup succeed and first failed (~p)", [First]), ok; otp9884_await_backup_completion(First, Second) when (((First =:= undefined) andalso (Second =:= undefined)) @@ -7201,24 +7328,25 @@ otp9884_await_backup_completion(First, Second) ((First =:= undefined) andalso (Second =/= undefined)) orelse ((First =/= undefined) andalso (Second =:= undefined))) -> - i("otp9884_await_backup_completion -> await complete messages"), + ?IPRINT("otp9884_await_backup_completion -> await complete messages"), receive {otp9884_backup_complete, first, Res} -> - i("otp9884_await_backup_completion -> " - "received complete message for first: ~p", [Res]), + ?IPRINT("otp9884_await_backup_completion -> " + "received complete message for first: ~p", [Res]), otp9884_await_backup_completion(Res, Second); {otp9884_backup_complete, second, Res} -> - i("otp9884_await_backup_completion -> " - "received complete message for second: ~p", [Res]), + ?IPRINT("otp9884_await_backup_completion -> " + "received complete message for second: ~p", [Res]), otp9884_await_backup_completion(First, Res) after 10000 -> %% we have waited long enough + ?EPRINT("otp9884_await_backup_completion -> timeout"), throw({error, {timeout, First, Second}}) end; otp9884_await_backup_completion(First, Second) -> - e("Bad Completion: " - "~n First: ~p" - "~n Second: ~p", [First, Second]), + ?EPRINT("Bad Completion: " + "~n First: ~p" + "~n Second: ~p", [First, Second]), throw({error, {bad_completion, First, Second}}). @@ -7445,16 +7573,16 @@ verify_subinfo(Info0, [Key|Keys]) -> is(S) -> [length(S) | S]. try_test(Func) -> - ?P2("try test ~w...", [Func]), - snmp_agent_test_lib:try_test(?MODULE, Func). + ?NPRINT("try test ~w...", [Func]), + ?ALIB:try_test(?MODULE, Func). try_test(Func, A) -> - ?P2("try test ~w...", [Func]), - snmp_agent_test_lib:try_test(?MODULE, Func, A). + ?NPRINT("try test ~w...", [Func]), + ?ALIB:try_test(?MODULE, Func, A). try_test(Func, A, Opts) -> - ?P2("try test ~w...", [Func]), - snmp_agent_test_lib:try_test(?MODULE, Func, A, Opts). + ?NPRINT("try test ~w...", [Func]), + ?ALIB:try_test(?MODULE, Func, A, Opts). %% Test manager wrapperfunctions: @@ -7465,77 +7593,80 @@ gb(NR, MR, Oids) -> snmp_test_mgr:gb(NR, MR, Oids). s(VAV) -> snmp_test_mgr:s(VAV). get_req(Id, Vars) -> - snmp_agent_test_lib:get_req(Id, Vars). + ?ALIB:get_req(Id, Vars). get_next_req(Vars) -> - snmp_agent_test_lib:get_next_req(Vars). + ?ALIB:get_next_req(Vars). start_node(Name) -> - snmp_agent_test_lib:start_node(Name). + ?ALIB:start_node(Name). +stop_node(undefined) -> + ok; stop_node(Node) -> - snmp_agent_test_lib:stop_node(Node). + ?ALIB:stop_node(Node). %%%----------------------------------------------------------------- %%% Configuration %%%----------------------------------------------------------------- delete_files(Config) -> - snmp_agent_test_lib:delete_files(Config). + ?ALIB:delete_files(Config). config(Vsns, MgrDir, AgentDir, MIp, AIp) -> - snmp_agent_test_lib:config(Vsns, MgrDir, AgentDir, MIp, AIp). + ?ALIB:config(Vsns, MgrDir, AgentDir, MIp, AIp). config(Vsns, MgrDir, AgentDir, MIp, AIp, IpFamily) -> - snmp_agent_test_lib:config(Vsns, MgrDir, AgentDir, MIp, AIp, IpFamily). + ?ALIB:config(Vsns, MgrDir, AgentDir, MIp, AIp, IpFamily). update_usm(Vsns, Dir) -> - snmp_agent_test_lib:update_usm(Vsns, Dir). + ?ALIB:update_usm(Vsns, Dir). update_usm_mgr(Vsns, Dir) -> - snmp_agent_test_lib:update_usm_mgr(Vsns, Dir). + ?ALIB:update_usm_mgr(Vsns, Dir). rewrite_usm_mgr(Dir, ShaKey, DesKey) -> - snmp_agent_test_lib:rewrite_usm_mgr(Dir, ShaKey, DesKey). + ?ALIB:rewrite_usm_mgr(Dir, ShaKey, DesKey). reset_usm_mgr(Dir) -> - snmp_agent_test_lib:reset_usm_mgr(Dir). + ?ALIB:reset_usm_mgr(Dir). update_vacm(Vsn, Dir) -> - snmp_agent_test_lib:update_vacm(Vsn, Dir). + ?ALIB:update_vacm(Vsn, Dir). write_community_conf(Dir, Conf) -> - snmp_agent_test_lib:write_community_conf(Dir, Conf). + ?ALIB:write_community_conf(Dir, Conf). write_target_addr_conf(Dir, Conf) -> - snmp_agent_test_lib:write_target_addr_conf(Dir, Conf). + ?ALIB:write_target_addr_conf(Dir, Conf). rewrite_target_addr_conf(Dir, NewPort) -> - snmp_agent_test_lib:rewrite_target_addr_conf(Dir, NewPort). + ?ALIB:rewrite_target_addr_conf(Dir, NewPort). reset_target_addr_conf(Dir) -> - snmp_agent_test_lib:reset_target_addr_conf(Dir). + ?ALIB:reset_target_addr_conf(Dir). write_target_params_conf(Dir, Vsns) -> - snmp_agent_test_lib:write_target_params_conf(Dir, Vsns). + ?ALIB:write_target_params_conf(Dir, Vsns). rewrite_target_params_conf(Dir, SecName, SecLevel) -> - snmp_agent_test_lib:rewrite_target_params_conf(Dir, SecName, SecLevel). + ?ALIB:rewrite_target_params_conf(Dir, SecName, SecLevel). reset_target_params_conf(Dir) -> - snmp_agent_test_lib:reset_target_params_conf(Dir). + ?ALIB:reset_target_params_conf(Dir). write_notify_conf(Dir) -> - snmp_agent_test_lib:write_notify_conf(Dir). + ?ALIB:write_notify_conf(Dir). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% copy_file(From, To) -> - snmp_agent_test_lib:copy_file(From, To). + ?ALIB:copy_file(From, To). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -7548,25 +7679,25 @@ display_log(Config) -> LogDir = Dir, Mibs = [], OutFile = join(LogDir, "snmpa_log.txt"), - p("~n" - "=========================" - " < Audit Trail Log > " - "=========================" - "~n"), + ?IPRINT("~n" + "=========================" + " < Audit Trail Log > " + "=========================" + "~n"), rcall(Node, snmpa, log_to_txt, [LogDir, Mibs, OutFile]), rcall(Node, snmpa, log_to_io, [LogDir, Mibs]), - p("~n" - "=========================" - " < / Audit Trail Log > " - "=========================" - "~n", []); + ?IPRINT("~n" + "=========================" + " < / Audit Trail Log > " + "=========================" + "~n"); false -> - p("display_log -> no agent node found"), + ?IPRINT("display_log -> no agent node found"), ok end; false -> - p("display_log -> no agent log dir found: " - "~n ~p", [Config]), + ?IPRINT("display_log -> no agent log dir found: " + "~n ~p", [Config]), ok end. @@ -7581,8 +7712,7 @@ display_memory_usage() -> SSMU = display_symbolic_store_memory_usage(Info), LDBMU = display_local_db_memory_usage(Info), MSMU = display_mib_server_memory_usage(Info), - ?INF("Memory usage: ~n" ++ - AMU ++ NIMU ++ NSMU ++ SSMU ++ LDBMU ++ MSMU, []), + ?NPRINT("Memory usage: ~n" ++ AMU ++ NIMU ++ NSMU ++ SSMU ++ LDBMU ++ MSMU), ok. display_agent_memory_usage(Info) -> @@ -7599,62 +7729,57 @@ display_agent_memory_usage(Info) -> lists_key1search([db_memory,community_cache], AgentInfo), VacmSize = lists_key1search([db_memory,vacm], AgentInfo), - lists:flatten( - io_lib:format(" Agent memory usage: " - "~n Master process memory size: ~p" - "~n Worker process memory size: ~p" - "~n Set-worker process memory size: ~p" - "~n Agent tab size: ~p" - "~n Community cache size: ~p" - "~n Vacm tab size: ~p" - "~n", - [ProcMem, WProcMem, SWProcMem, - TabSize, CCSize, VacmSize])). + ?F(" Agent memory usage: " + "~n Master process memory size: ~p" + "~n Worker process memory size: ~p" + "~n Set-worker process memory size: ~p" + "~n Agent tab size: ~p" + "~n Community cache size: ~p" + "~n Vacm tab size: ~p" + "~n", + [ProcMem, WProcMem, SWProcMem, + TabSize, CCSize, VacmSize]). display_net_if_memory_usage(Info) -> NiInfo = lists_key1search(net_if, Info), ProcMem = lists_key1search(process_memory, NiInfo), - lists:flatten( - io_lib:format(" Net if memory usage: " - "~n Process memory size: ~p" - "~n",[ProcMem])). + ?F(" Net if memory usage: " + "~n Process memory size: ~p" + "~n", [ProcMem]). display_note_store_memory_usage(Info) -> NsInfo = lists_key1search(note_store, Info), ProcMem = lists_key1search([process_memory,notes], NsInfo), ProcTmrMem = lists_key1search([process_memory,timer], NsInfo), TabSize = lists_key1search([db_memory,notes], NsInfo), - lists:flatten( - io_lib:format(" Note store memory usage: " - "~n Notes process memory size: ~p" - "~n Timer process memory size: ~p" - "~n Notes tab size: ~p" - "~n", - [ProcMem, ProcTmrMem, TabSize])). + ?F(" Note store memory usage: " + "~n Notes process memory size: ~p" + "~n Timer process memory size: ~p" + "~n Notes tab size: ~p" + "~n", + [ProcMem, ProcTmrMem, TabSize]). display_symbolic_store_memory_usage(Info) -> SsInfo = lists_key1search(symbolic_store, Info), ProcMem = lists_key1search(process_memory, SsInfo), DbMem = lists_key1search(db_memory, SsInfo), - lists:flatten( - io_lib:format(" Symbolic store memory usage: " - "~n Process memory size: ~p" - "~n DB size: ~p" - "~n", - [ProcMem, DbMem])). + ?F(" Symbolic store memory usage: " + "~n Process memory size: ~p" + "~n DB size: ~p" + "~n", + [ProcMem, DbMem]). display_local_db_memory_usage(Info) -> LdInfo = lists_key1search(local_db, Info), ProcMem = lists_key1search(process_memory, LdInfo), EtsSize = lists_key1search([db_memory,ets], LdInfo), DetsSize = lists_key1search([db_memory,dets], LdInfo), - lists:flatten( - io_lib:format(" Local DB memory usage: " - "~n Process memory size: ~p" - "~n DB [ets] size: ~p" - "~n DB [dets] size: ~p" - "~n", - [ProcMem, EtsSize, DetsSize])). + ?F(" Local DB memory usage: " + "~n Process memory size: ~p" + "~n DB [ets] size: ~p" + "~n DB [dets] size: ~p" + "~n", + [ProcMem, EtsSize, DetsSize]). display_mib_server_memory_usage(Info) -> MibInfo = lists_key1search(mib_server, Info), @@ -7663,15 +7788,14 @@ display_mib_server_memory_usage(Info) -> MibDbSize = lists_key1search([db_memory,mib], MibInfo), NodeDbSize = lists_key1search([db_memory,node], MibInfo), TreeDbSize = lists_key1search([db_memory,tree], MibInfo), - lists:flatten( - io_lib:format(" MIB server memory usage: " - "~n Process memory size: ~p" - "~n Tree size: ~p" - "~n Mib db size: ~p" - "~n Node db size: ~p" - "~n Tree db size: ~p" - "~n", - [ProcMem, TreeSize, MibDbSize, NodeDbSize, TreeDbSize])). + ?F(" MIB server memory usage: " + "~n Process memory size: ~p" + "~n Tree size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p" + "~n", + [ProcMem, TreeSize, MibDbSize, NodeDbSize, TreeDbSize]). lists_key1search([], Res) -> Res; @@ -7693,56 +7817,6 @@ lists_key1search(Key, List) when is_atom(Key) -> %% ------ -join(Parts) -> - filename:join(Parts). - -join(Dir, File) -> - filename:join(Dir, File). - - -%% ------ - -rcall(Node, Mod, Func, Args) -> - case rpc:call(Node, Mod, Func, Args) of - {badrpc, nodedown} -> - ?FAIL({rpc_failure, Node}); - Else -> - Else - end. - - -%% ------ - -%% e(F) -> -%% e(F, []). - -e(F, A) -> - p(user, "<ERROR> " ++ F, A), - p(standard_io, "<ERROR> " ++ F, A). - -i(F) -> - i(F, []). -i(F, A) -> - p(user, F, A), - p(standard_io, F, A). - -p(F) -> - p(F, []). - -p(Dev, F) when is_atom(Dev) -> - p(Dev, F, []); -p(F, A) -> - p(standard_io, F, A). - -p(Dev, F, A) -> - io:format(Dev, - "*** [~s] ***" - "~n" ++ F ++ "~n", [formated_timestamp()|A]). - -formated_timestamp() -> - snmp_test_lib:formated_timestamp(). - - init_v1_agent(Config) -> %% -- %% Start nodes @@ -7813,9 +7887,7 @@ init_v1_agent(Config) -> %% Create watchdog %% - Dog = ?WD_START(?MINS(1)), - - [{watchdog, Dog} | Config2]. + wd_start(1, Config2). fin_v1_agent(Config) -> AgentNode = ?config(agent_node, Config), @@ -7850,10 +7922,7 @@ fin_v1_agent(Config) -> %% stop_node(ManagerNode), - Dog = ?config(watchdog, Config), - ?WD_STOP(Dog), - lists:keydelete(watchdog, 1, Config). - + wd_stop(Config). config_ipfamily(Config) -> @@ -7863,3 +7932,25 @@ config_ipfamily(Config) -> Value -> Value end. + + +%% ------ + +join(Parts) -> + filename:join(Parts). + +join(Dir, File) -> + filename:join(Dir, File). + + +%% ------ + +rcall(Node, Mod, Func, Args) -> + case rpc:call(Node, Mod, Func, Args) of + {badrpc, nodedown} -> + ?FAIL({rpc_failure, Node}); + Else -> + Else + end. + + diff --git a/lib/snmp/test/snmp_agent_conf_SUITE.erl b/lib/snmp/test/snmp_agent_conf_SUITE.erl index 889af630a4..1f0ad3708b 100644 --- a/lib/snmp/test/snmp_agent_conf_SUITE.erl +++ b/lib/snmp/test/snmp_agent_conf_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -101,7 +101,7 @@ init_per_testcase(_Case, Config) when is_list(Config) -> Config. end_per_testcase(_Case, Config) when is_list(Config) -> - ?PRINT2("system events during test: " + ?IPRINT("system events during test: " "~n ~p", [snmp_test_global_sys_monitor:events()]), Config. diff --git a/lib/snmp/test/snmp_agent_mibs_SUITE.erl b/lib/snmp/test/snmp_agent_mibs_SUITE.erl index 9545dfdcc9..150e015554 100644 --- a/lib/snmp/test/snmp_agent_mibs_SUITE.erl +++ b/lib/snmp/test/snmp_agent_mibs_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -67,6 +67,9 @@ ]). +-define(ALIB, snmp_agent_test_lib). + + %%====================================================================== %% Common Test interface functions %%====================================================================== @@ -166,27 +169,18 @@ init_per_testcase(Case, Config0) when is_list(Config0) -> init_per_testcase2(size_check_ets2_bad_file1, Config) when is_list(Config) -> DbDir = ?config(db_dir, Config), - %% Create a ad file + %% Create a bad file ok = file:write_file(join(DbDir, "snmpa_symbolic_store.db"), "calvin and hoppes play chess"), Config; init_per_testcase2(size_check_ets3_bad_file1, Config) when is_list(Config) -> DbDir = ?config(db_dir, Config), - %% Create a ad file + %% Create a bad file ok = file:write_file(join(DbDir, "snmpa_symbolic_store.db"), "calvin and hoppes play chess"), Config; init_per_testcase2(size_check_mnesia, Config) when is_list(Config) -> - DbDir = ?config(db_dir, Config), - try - begin - mnesia_start([{dir, DbDir}]), - Config - end - catch - throw:{skip, _} = SKIP -> - SKIP - end; + Config; init_per_testcase2(cache_test, Config) when is_list(Config) -> Min = timer:minutes(5), Timeout = @@ -205,7 +199,7 @@ init_per_testcase2(_Case, Config) when is_list(Config) -> end_per_testcase(Case, Config) when is_list(Config) -> - ?PRINT2("system events during test: " + ?IPRINT("system events during test: " "~n ~p", [snmp_test_global_sys_monitor:events()]), end_per_testcase1(Case, Config). @@ -301,7 +295,8 @@ size_check_ets1(suite) -> []; size_check_ets1(Config) when is_list(Config) -> MibStorage = [{module, snmpa_mib_storage_ets}], - do_size_check([{mib_storage, MibStorage}|Config]). + do_size_check(size_check_ets1, + [{mib_storage, MibStorage}|Config]). size_check_ets2(suite) -> []; @@ -309,7 +304,8 @@ size_check_ets2(Config) when is_list(Config) -> Dir = ?config(db_dir, Config), MibStorage = [{module, snmpa_mib_storage_ets}, {options, [{dir, Dir}]}], - do_size_check([{mib_storage, MibStorage}|Config]). + do_size_check(size_check_ets2, + [{mib_storage, MibStorage}|Config]). size_check_ets2_bad_file1(suite) -> []; @@ -319,7 +315,8 @@ size_check_ets2_bad_file1(Config) when is_list(Config) -> MibStorage = [{module, snmpa_mib_storage_ets}, {options, [{dir, Dir}, {action, clear}]}], - do_size_check([{mib_storage, MibStorage}|Config]). + do_size_check(size_check_ets2_bad_file1, + [{mib_storage, MibStorage}|Config]). size_check_ets3(suite) -> []; @@ -328,7 +325,8 @@ size_check_ets3(Config) when is_list(Config) -> MibStorage = [{module, snmpa_mib_storage_ets}, {options, [{dir, Dir}, {checksum, true}]}], - do_size_check([{mib_storage, MibStorage}|Config]). + do_size_check(size_check_ets3, + [{mib_storage, MibStorage}|Config]). size_check_ets3_bad_file1(suite) -> []; @@ -339,7 +337,8 @@ size_check_ets3_bad_file1(Config) when is_list(Config) -> {options, [{dir, Dir}, {action, clear}, {checksum, true}]}], - do_size_check([{mib_storage, MibStorage}|Config]). + do_size_check(size_check_ets3_bad_file1, + [{mib_storage, MibStorage}|Config]). size_check_dets(suite) -> []; @@ -347,18 +346,72 @@ size_check_dets(Config) when is_list(Config) -> Dir = ?config(db_dir, Config), MibStorage = [{module, snmpa_mib_storage_dets}, {options, [{dir, Dir}]}], - do_size_check([{mib_storage, MibStorage}|Config]). + do_size_check(size_check_dets, + [{mib_storage, MibStorage}|Config]). size_check_mnesia(suite) -> []; size_check_mnesia(Config) when is_list(Config) -> MibStorage = [{module, snmpa_mib_storage_mnesia}, - {options, [{nodes, [node()]}]}], - do_size_check([{mib_storage, MibStorage}|Config]). + {options, [{nodes, []}]}], + DbDir = ?config(db_dir, Config), + Init = fun() -> mnesia_start([{dir, DbDir}]), ok end, + do_size_check(size_check_mnesia, + Init, + [{mib_storage, MibStorage}|Config]). + +do_size_check(Name, Config) -> + Init = fun() -> ok end, + do_size_check(Name, Init, Config). + +do_size_check(Name, Init, Config) -> + Pre = fun() -> + {ok, Node} = ?ALIB:start_node(unique(Name)), + ok = run_on(Node, Init), + Node + end, + Case = fun(Node) -> + monitor_node(Node, true), + Pid = spawn_link(Node, fun() -> do_size_check(Config) end), + receive + {nodedown, Node} = N -> + exit(N); + {'EXIT', Pid, normal} -> + monitor_node(Node, false), + ok; + {'EXIT', Pid, ok} -> + monitor_node(Node, false), + ok; + {'EXIT', Pid, Reason} -> + monitor_node(Node, false), + exit(Reason) + end + end, + Post = fun({Node, _}) -> + ?STOP_NODE(Node) + end, + ?TC_TRY(Name, Pre, Case, Post). + +run_on(Node, F) when is_atom(Node) andalso is_function(F, 0) -> + monitor_node(Node, true), + Pid = spawn_link(Node, F), + receive + {nodedown, Node} = N -> + exit(N); + {'EXIT', Pid, normal} -> + monitor_node(Node, false), + ok; + {'EXIT', Pid, Reason} -> + monitor_node(Node, false), + Reason + end. + +unique(PreName) -> + list_to_atom(?F("~w_~w", [PreName, erlang:system_time(millisecond)])). do_size_check(Config) -> - ?DBG("do_size_check -> start with" - "~n Config: ~p", [Config]), + ?IPRINT("do_size_check -> start with" + "~n Config: ~p", [Config]), Prio = normal, Verbosity = trace, @@ -404,7 +457,7 @@ do_size_check(Config) -> ?DBG("do_size_check -> stop symbolic store", []), ?line sym_stop(), - ?DBG("do_size_check -> done", []), + ?IPRINT("do_size_check -> done", []), ok. @@ -635,7 +688,7 @@ mnesia_start(Opts, Nodes) -> %% We can accept mnesia beeing loaded but *not* started. %% If its started it *may* contain data that will invalidate %% this test case. - ?PRINT2("mnesia_start -> try load mnesia when:" + ?IPRINT("mnesia_start -> try load mnesia when:" "~n Loaded: ~p" "~n Running: ~p", [apps_loaded(), apps_running()]), ?line ok = case application:load(mnesia) of @@ -647,12 +700,12 @@ mnesia_start(Opts, Nodes) -> ERROR end, F = fun({Key, Val}) -> - ?PRINT2("mnesia_start -> try set mnesia env: " + ?IPRINT("mnesia_start -> try set mnesia env: " "~n ~p -> ~p", [Key, Val]), ?line application_controller:set_env(mnesia, Key, Val) end, lists:foreach(F, Opts), - ?PRINT2("mnesia_start -> create mnesia schema on ~p", [Nodes]), + ?IPRINT("mnesia_start -> create mnesia schema on ~p", [Nodes]), ?line case mnesia:create_schema(Nodes) of ok -> ok; @@ -662,7 +715,7 @@ mnesia_start(Opts, Nodes) -> throw({skip, ?F("Failed create mnesia schema: ~p", [SchemaReason])}) end, - ?PRINT2("mnesia_start -> start mnesia", []), + ?IPRINT("mnesia_start -> start mnesia", []), ?line case application:start(mnesia) of ok -> ok; @@ -672,19 +725,19 @@ mnesia_start(Opts, Nodes) -> throw({skip, ?F("Failed starting mnesia: ~p", [StartReason])}) end, - ?PRINT2("mnesia_start -> mnesia started", []), + ?IPRINT("mnesia_start -> mnesia started", []), ok. mnesia_stop() -> - ?PRINT2("mnesia_stop -> try stop mnesia when:" + ?IPRINT("mnesia_stop -> try stop mnesia when:" "~n Loaded: ~p" "~n Running: ~p", [apps_loaded(), apps_running()]), application:stop(mnesia), - ?PRINT2("mnesia_stop -> try unload mnesia when" + ?IPRINT("mnesia_stop -> try unload mnesia when" "~n Loaded: ~p" "~n Running: ~p", [apps_loaded(), apps_running()]), application:unload(mnesia), - ?PRINT2("mnesia_stop -> done when:" + ?IPRINT("mnesia_stop -> done when:" "~n Loaded: ~p" "~n Running: ~p", [apps_loaded(), apps_running()]), ok. @@ -856,19 +909,19 @@ display_memory_usage(MibsPid) -> MibDbSize = key1search([db_memory,mib], MibsInfo), NodeDbSize = key1search([db_memory,node], MibsInfo), TreeDbSize = key1search([db_memory,tree], MibsInfo), - ?INF("Symbolic store memory usage: " - "~n Process memory size: ~p" - "~n Db size: ~p" - "~n" - "~nMib server memory usage: " - "~n Tree size: ~p" - "~n Process memory size: ~p" - "~n Mib db size: ~p" - "~n Node db size: ~p" - "~n Tree db size: ~p" - "~n", - [SymProcSize, DbSize, - TreeSize, MibsProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + ?IPRINT("Symbolic store memory usage: " + "~n Process memory size: ~p" + "~n Db size: ~p" + "~n" + "~nMib server memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p" + "~n", + [SymProcSize, DbSize, + TreeSize, MibsProcMem, MibDbSize, NodeDbSize, TreeDbSize]). key1search([], Res) -> Res; diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index 5dc544d1a7..6a4c582f36 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2019. All Rights Reserved. +%% Copyright Ericsson AB 2005-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -122,8 +122,8 @@ init_all(Config) when is_list(Config) -> - ?LOG("init_all -> entry with" - "~n Config: ~p",[Config]), + ?IPRINT("init_all -> entry with" + "~n Config: ~p",[Config]), %% -- %% Start nodes @@ -300,7 +300,7 @@ try_test(TcRunMod, TcRunFunc, TcRunArgs, TcRunOpts) -> %% process as well. tc_try(N, M, F, A) -> - ?PRINT2("tc_try -> entry with" + ?IPRINT("tc_try -> entry with" "~n N: ~p" "~n M: ~p" "~n F: ~p" @@ -312,32 +312,32 @@ tc_try(N, M, F, A) -> get()]), case net_adm:ping(N) of pong -> - ?PRINT2("tc_try -> ~p still running - start runner~n", [N]), + ?IPRINT("tc_try -> ~p still running - start runner~n", [N]), OldFlag = trap_exit(true), % Make sure we catch it Runner = spawn_link(N, ?MODULE, tc_wait, [self(), get(), M, F, A]), await_tc_runner_started(Runner, OldFlag), await_tc_runner_done(Runner, OldFlag); pang -> - ?EPRINT2("tc_try -> ~p *not* running~n", [N]), + ?WPRINT("tc_try -> ~p *not* running~n", [N]), skip({node_not_running, N}) end. await_tc_runner_started(Runner, OldFlag) -> - ?PRINT2("await tc-runner (~p) start ack~n", [Runner]), + ?IPRINT("await tc-runner (~p) start ack~n", [Runner]), receive {'EXIT', Runner, Reason} -> - ?EPRINT2("TC runner start failed: " - "~n ~p~n", [Reason]), + ?EPRINT("TC runner start failed: " + "~n ~p~n", [Reason]), exit({tx_runner_start_failed, Reason}); {tc_runner_started, Runner} -> - ?PRINT2("TC runner start acknowledged~n"), + ?IPRINT("TC runner start acknowledged~n"), ok after 10000 -> %% We should *really* not have to wait this long, but... trap_exit(OldFlag), unlink_and_flush_exit(Runner), - RunnerInfo = process_info(Runner), - ?EPRINT2("TC runner start timeout: " - "~n ~p", [RunnerInfo]), + RunnerInfo = ?PINFO(Runner), + ?EPRINT("TC runner start timeout: " + "~n ~p", [RunnerInfo]), %% If we don't get a start ack within 10 seconds, we are f*ed exit(Runner, kill), exit({tc_runner_start, timeout, RunnerInfo}) @@ -352,18 +352,18 @@ await_tc_runner_done(Runner, OldFlag) -> SysEvs = snmp_test_global_sys_monitor:events(), if (SysEvs =:= []) -> - ?EPRINT2("TC runner failed: " - "~n ~p~n", [Reason]), + ?EPRINT("TC runner failed: " + "~n ~p~n", [Reason]), exit({tx_runner_failed, Reason}); true -> - ?EPRINT2("TC runner failed when we got system events: " - "~n Reason: ~p" - "~n Sys Events: ~p" - "~n", [Reason, SysEvs]), + ?WPRINT("TC runner failed when we got system events: " + "~n Reason: ~p" + "~n Sys Events: ~p" + "~n", [Reason, SysEvs]), skip([{reason, Reason}, {system_events, SysEvs}]) end; {tc_runner_done, Runner, {'EXIT', {skip, Reason}}, Loc} -> - ?PRINT2("call -> done with skip: " + ?WPRINT("call -> done with skip: " "~n Reason: ~p" "~n Loc: ~p" "~n", [Reason, Loc]), @@ -372,7 +372,7 @@ await_tc_runner_done(Runner, OldFlag) -> put(test_server_loc, Loc), skip(Reason); {tc_runner_done, Runner, {'EXIT', Rn}, Loc} -> - ?PRINT2("call -> done with exit: " + ?EPRINT("call -> done with exit: " "~n Rn: ~p" "~n Loc: ~p" "~n", [Rn, Loc]), @@ -409,7 +409,7 @@ unlink_and_flush_exit(Pid) -> end. tc_wait(From, Env, M, F, A) -> - ?PRINT2("tc_wait -> entry with" + ?IPRINT("tc_wait -> entry with" "~n From: ~p" "~n Env: ~p" "~n M: ~p" @@ -417,9 +417,9 @@ tc_wait(From, Env, M, F, A) -> "~n A: ~p", [From, Env, M, F, A]), From ! {tc_runner_started, self()}, lists:foreach(fun({K,V}) -> put(K,V) end, Env), - ?PRINT2("tc_wait -> env set - now run tc~n"), + ?IPRINT("tc_wait -> env set - now run tc~n"), Res = (catch apply(M, F, A)), - ?PRINT2("tc_wait -> tc run done: " + ?IPRINT("tc_wait -> tc run done: " "~n ~p" "~n", [Res]), From ! {tc_runner_done, self(), Res, get(test_server_loc)}, @@ -437,7 +437,7 @@ tc_wait(From, Env, M, F, A) -> end. tc_run(Mod, Func, Args, Opts) -> - ?PRINT2("tc_run -> entry with" + ?IPRINT("tc_run -> entry with" "~n Mod: ~p" "~n Func: ~p" "~n Args: ~p" @@ -456,7 +456,7 @@ tc_run(Mod, Func, Args, Opts) -> ?DBG("tc_run -> Crypto: ~p", [_CryptoRes]), StdM = join(code:priv_dir(snmp), "mibs") ++ "/", Vsn = get(vsn), - ?PRINT2("tc_run -> config:" + ?IPRINT("tc_run -> config:" "~n M: ~p" "~n Vsn: ~p" "~n Dir: ~p" @@ -469,7 +469,7 @@ tc_run(Mod, Func, Args, Opts) -> "~n", [M,Vsn,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, {packet_server_debug, true}, - {debug, true}, + {debug, false}, {agent, get(master_host)}, {ipfamily, get(ipfamily)}, {agent_udp, 4000}, @@ -487,7 +487,7 @@ tc_run(Mod, Func, Args, Opts) -> {ok, _Pid} -> case (catch apply(Mod, Func, Args)) of {'EXIT', {skip, Reason}} -> - ?EPRINT2("apply skip detected: " + ?WPRINT("apply skip detected: " "~n ~p", [Reason]), (catch snmp_test_mgr:stop()), ?SKIP(Reason); @@ -500,11 +500,11 @@ tc_run(Mod, Func, Args, Opts) -> (catch snmp_test_mgr:stop()), if (SysEvs =:= []) -> - ?EPRINT2("TC runner failed: " - "~n ~p~n", [Reason]), + ?EPRINT("TC runner failed: " + "~n ~p~n", [Reason]), ?FAIL({apply_failed, {Mod, Func, Args}, Reason}); true -> - ?EPRINT2("apply exit catched when we got system events: " + ?WPRINT("apply exit catched when we got system events: " "~n Reason: ~p" "~n Sys Events: ~p" "~n", [Reason, SysEvs]), @@ -516,14 +516,14 @@ tc_run(Mod, Func, Args, Opts) -> end; {error, Reason} -> - ?EPRINT2("Failed starting (test) manager: " - "~n ~p", [Reason]), + ?EPRINT("Failed starting (test) manager: " + "~n ~p", [Reason]), (catch snmp_test_mgr:stop()), ?line ?FAIL({mgr_start_error, Reason}); Err -> - ?EPRINT2("Failed starting (test) manager: " - "~n ~p", [Err]), + ?EPRINT("Failed starting (test) manager: " + "~n ~p", [Err]), (catch snmp_test_mgr:stop()), ?line ?FAIL({mgr_start_failure, Err}) end. @@ -570,10 +570,10 @@ start_agent(Config, Vsns) -> start_agent(Config, Vsns, []). start_agent(Config, Vsns, Opts) -> - ?LOG("start_agent -> entry (~p) with" - "~n Config: ~p" - "~n Vsns: ~p" - "~n Opts: ~p", [node(), Config, Vsns, Opts]), + ?IPRINT("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsns: ~p" + "~n Opts: ~p", [node(), Config, Vsns, Opts]), ?line AgentLogDir = ?config(agent_log_dir, Config), ?line AgentConfDir = ?config(agent_conf_dir, Config), @@ -603,17 +603,17 @@ start_agent(Config, Vsns, Opts) -> process_flag(trap_exit,true), - ?PRINT2("start_agent -> try start snmp app supervisor", []), + ?IPRINT("start_agent -> try start snmp app supervisor", []), {ok, AppSup} = snmp_app_sup:start_link(), unlink(AppSup), ?DBG("start_agent -> snmp app supervisor: ~p", [AppSup]), - ?PRINT2("start_agent -> try start master agent",[]), + ?IPRINT("start_agent -> try start master agent",[]), ?line Sup = start_sup(Env), ?line unlink(Sup), ?DBG("start_agent -> snmp supervisor: ~p", [Sup]), - ?PRINT2("start_agent -> try (rpc) start sub agent on ~p", [SaNode]), + ?IPRINT("start_agent -> try (rpc) start sub agent on ~p", [SaNode]), ?line SaDir = ?config(sa_dir, Config), ?line {ok, Sub} = start_sub_sup(SaNode, SaDir), ?DBG("start_agent -> done", []), @@ -813,36 +813,33 @@ merge_agent_options([{Key, _Value} = Opt|Opts], Options) -> stop_agent(Config) when is_list(Config) -> - ?PRINT2("stop_agent -> entry with" + ?IPRINT("stop_agent -> entry with" "~n Config: ~p",[Config]), %% Stop the sub-agent (the agent supervisor) {SubSup, SubPar} = ?config(snmp_sub, Config), - ?PRINT2("stop_agent -> attempt to stop sub agent (~p)" + ?IPRINT("stop_agent -> attempt to stop sub agent (~p)" "~n Sub Sup info: " "~n ~p" "~n Sub Par info: " "~n ~p", - [SubSup, - (catch process_info(SubSup)), - (catch process_info(SubPar))]), + [SubSup, ?PINFO(SubSup), ?PINFO(SubPar)]), stop_sup(SubSup, SubPar), Config2 = lists:keydelete(snmp_sub, 1, Config), %% Stop the master-agent (the top agent supervisor) {MasterSup, MasterPar} = ?config(snmp_sup, Config), - ?PRINT2("stop_agent -> attempt to stop master agent (~p)" + ?IPRINT("stop_agent -> attempt to stop master agent (~p)" "~n Master Sup: " "~n ~p" "~n Master Par: " "~n ~p" "~n Agent Info: " "~n ~p", - [MasterSup, - (catch process_info(MasterSup)), - (catch process_info(MasterPar)), + [MasterSup, + ?PINFO(MasterSup), ?PINFO(MasterPar), agent_info(MasterSup)]), stop_sup(MasterSup, MasterPar), Config3 = lists:keydelete(snmp_sup, 1, Config2), @@ -850,25 +847,24 @@ stop_agent(Config) when is_list(Config) -> %% Stop the top supervisor (of the snmp app) AppSup = ?config(snmp_app_sup, Config), - ?PRINT2("stop_agent -> attempt to app sup ~p" + ?IPRINT("stop_agent -> attempt to app sup ~p" "~n App Sup: ~p", - [AppSup, - (catch process_info(AppSup))]), + [AppSup, ?PINFO(AppSup)]), Config4 = lists:keydelete(snmp_app_sup, 1, Config3), - ?PRINT2("stop_agent -> done", []), + ?IPRINT("stop_agent -> done", []), Config4. start_sup(Env) -> case (catch snmp_app_sup:start_agent(normal, Env)) of {ok, S} -> - ?DBG("start_agent -> started, Sup: ~p",[S]), + ?DBG("start_agent -> started, Sup: ~p", [S]), S; Else -> - ?DBG("start_agent -> unknown result: ~n~p",[Else]), + ?EPRINT("start_agent -> unknown result: ~n~p", [Else]), %% Get info about the apps we depend on ?FAIL({start_failed, Else, ?IS_MNESIA_RUNNING()}) end. @@ -876,18 +872,18 @@ start_sup(Env) -> stop_sup(Pid, _) when (node(Pid) =:= node()) -> case (catch process_info(Pid)) of PI when is_list(PI) -> - ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + ?IPRINT("stop_sup -> attempt to stop ~p", [Pid]), Ref = erlang:monitor(process, Pid), exit(Pid, kill), await_stopped(Pid, Ref); {'EXIT', _Reason} -> - ?LOG("stop_sup -> ~p not running", [Pid]), + ?IPRINT("stop_sup -> ~p not running", [Pid]), ok end; stop_sup(Pid, _) -> - ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + ?IPRINT("stop_sup -> attempt to stop ~p", [Pid]), Ref = erlang:monitor(process, Pid), - ?LOG("stop_sup -> Ref: ~p", [Ref]), + ?IPRINT("stop_sup -> Ref: ~p", [Ref]), exit(Pid, kill), await_stopped(Pid, Ref). @@ -897,7 +893,7 @@ await_stopped(Pid, Ref) -> ?DBG("received down message for ~p", [Pid]), ok after 10000 -> - ?INF("await_stopped -> timeout for ~p",[Pid]), + ?EPRINT("await_stopped -> timeout for ~p",[Pid]), erlang:demonitor(Ref), ?FAIL({failed_stop,Pid}) end. @@ -1076,7 +1072,7 @@ io_format_expect(F) -> io_format_expect(F, []). io_format_expect(F, A) -> - ?PRINT2("EXPECT " ++ F, A). + ?IPRINT("EXPECT " ++ F, A). do_expect(Expect) when is_atom(Expect) -> @@ -1529,11 +1525,11 @@ get_next_req(Vars) -> %% --- start and stop nodes --- start_node(Name) -> - ?LOG("start_node -> entry with" - "~n Name: ~p" - "~n when" - "~n hostname of this node: ~p", - [Name, list_to_atom(?HOSTNAME(node()))]), + ?IPRINT("start_node -> entry with" + "~n Name: ~p" + "~n when" + "~n hostname of this node: ~p", + [Name, list_to_atom(?HOSTNAME(node()))]), Pa = filename:dirname(code:which(?MODULE)), ?DBG("start_node -> Pa: ~p", [Pa]), @@ -1547,19 +1543,19 @@ start_node(Name) -> global:sync(), {ok, Node}; {error, Reason} -> - ?ERR("start_node -> failed starting node ~p:" - "~n Reason: ~p", [Name, Reason]), + ?WPRINT("start_node -> failed starting node ~p:" + "~n Reason: ~p", [Name, Reason]), ?line ?SKIP({failed_start_node, Reason}); Else -> - ?ERR("start_node -> failed starting node ~p:" - "~n ~p", [Name, Else]), + ?EPRINT("start_node -> failed starting node ~p:" + "~n ~p", [Name, Else]), ?line ?FAIL(Else) end. stop_node(Node) -> - ?LOG("stop_node -> Node: ~p", [Node]), - rpc:cast(Node, erlang, halt, []). + ?IPRINT("stop_node -> Node: ~p", [Node]), + ?STOP_NODE(Node). %%%----------------------------------------------------------------- @@ -1570,14 +1566,14 @@ config(Vsns, MgrDir, AgentConfDir, MIp, AIp) -> config(Vsns, MgrDir, AgentConfDir, MIp, AIp, inet). config(Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily) -> - ?LOG("config -> entry with" - "~n Vsns: ~p" - "~n MgrDir: ~p" - "~n AgentConfDir: ~p" - "~n MIp: ~p" - "~n AIp: ~p" - "~n IpFamily: ~p", - [Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily]), + ?IPRINT("config -> entry with" + "~n Vsns: ~p" + "~n MgrDir: ~p" + "~n AgentConfDir: ~p" + "~n MIp: ~p" + "~n AIp: ~p" + "~n IpFamily: ~p", + [Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily]), ?line {Domain, ManagerAddr} = case IpFamily of inet6 -> @@ -1748,8 +1744,8 @@ rewrite_target_addr_conf(Dir, NewPort) -> {ok, _} -> ok; {error, _R} -> - ?ERR("failure reading file info of " - "target address config file: ~p", [_R]), + ?WPRINT("failure reading file info of " + "target address config file: ~p", [_R]), ok end, @@ -1773,10 +1769,10 @@ rewrite_target_addr_conf_check(O) -> rewrite_target_addr_conf2(NewPort, {Name, Ip, _Port, Timeout, Retry, "std_trap", EngineId}) -> - ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + ?IPRINT("rewrite_target_addr_conf2 -> entry with std_trap",[]), {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; rewrite_target_addr_conf2(_NewPort,O) -> - ?LOG("rewrite_target_addr_conf2 -> entry with " + ?IPRINT("rewrite_target_addr_conf2 -> entry with " "~n O: ~p",[O]), O. @@ -1830,12 +1826,12 @@ display_memory_usage() -> MibDbSize = key1search([db_memory,mib], Info), NodeDbSize = key1search([db_memory,node], Info), TreeDbSize = key1search([db_memory,tree], Info), - ?INF("Memory usage: " - "~n Tree size: ~p" - "~n Process memory size: ~p" - "~n Mib db size: ~p" - "~n Node db size: ~p" - "~n Tree db size: ~p", + ?IPRINT("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). key1search([], Res) -> @@ -1871,51 +1867,3 @@ join(Dir, File) -> skip(R) -> exit({skip, R}). -%% await_pdu(To) -> -%% await_response(To, pdu). -%% -%% await_trap(To) -> -%% await_response(To, trap). -%% -%% await_any(To) -> -%% await_response(To, any). -%% -%% -%% await_response(To, What) -> -%% await_response(To, What, []). -%% -%% await_response(To, What, Stuff) when is_integer(To) andalso (To >= 0) -> -%% T = t(), -%% receive -%% {snmp_pdu, PDU} when is_record(Trap, pdu) andalso (What =:= pdu) -> -%% {ok, PDU}; -%% {snmp_pdu, Trap} is_when record(Trap, trappdu) andalso (What =:= trap) -> -%% {ok, Trap}; -%% Any when What =:= any -> -%% {ok, Any}; -%% Any -> -%% %% Recalc time -%% NewTo = To - (t() - T) -%% await_reponse(NewTo, What, [{NewTo, Any}|Stuff]) -%% after To -> -%% {error, {timeout, Stuff}} -%% end; -%% await_response(_, Stuff) -> -%% {error, {timeout, Stuff}}. -%% -%% -%% t() -> -%% {A,B,C} = os:timestamp(), -%% A*1000000000+B*1000+(C div 1000). -%% -%% -%% timeout() -> -%% timeout(os:type()). -%% -%% timeout(_) -> 3500. - - -%% Time in milli seconds -%% t() -> -%% {A,B,C} = os:timestamp(), -%% A*1000000000+B*1000+(C div 1000). diff --git a/lib/snmp/test/snmp_compiler_SUITE.erl b/lib/snmp/test/snmp_compiler_SUITE.erl index aeb055742e..f4ba914919 100644 --- a/lib/snmp/test/snmp_compiler_SUITE.erl +++ b/lib/snmp/test/snmp_compiler_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -106,26 +106,48 @@ tickets_cases() -> init_per_suite(Config0) when is_list(Config0) -> - ?DBG("init_per_suite -> entry with" - "~n Config0: ~p", [Config0]), + ?IPRINT("init_per_suite -> entry with" + "~n Config: ~p" + "~n Nodes: ~p", [Config0, erlang:nodes()]), - Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0), - Config2 = snmp_test_lib:fix_data_dir(Config1), + case ?LIB:init_per_suite(Config0) of + {skip, _} = SKIP -> + SKIP; - %% Mib-dirs - %% data_dir is trashed by the test-server / common-test - %% so there is no point in fixing it... - MibDir = snmp_test_lib:lookup(data_dir, Config2), - StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]), + Config1 when is_list(Config1) -> + Config2 = snmp_test_lib:init_suite_top_dir(?MODULE, Config1), + Config3 = snmp_test_lib:fix_data_dir(Config2), - [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2]. + %% Mib-dirs + %% data_dir is trashed by the test-server / common-test + %% so there is no point in fixing it... + MibDir = snmp_test_lib:lookup(data_dir, Config3), + StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]), -end_per_suite(Config) when is_list(Config) -> + Config4 = [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config3], + + %% We need a monitor on this node also + snmp_test_sys_monitor:start(), - ?DBG("end_per_suite -> entry with" - "~n Config: ~p", [Config]), + snmp_test_mgr_counter_server:start(), - Config. + ?IPRINT("init_per_suite -> end when" + "~n Config: ~p", [Config4]), + + Config4 + end. + + +end_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("end_per_suite -> entry with" + "~n Config0: ~p", [Config0]), + + snmp_test_sys_monitor:stop(), + Config1 = ?LIB:end_per_suite(Config0), + + ?IPRINT("end_per_suite -> end"), + + Config1. %% @@ -165,7 +187,8 @@ end_per_testcase(_Case, Config) when is_list(Config) -> description(suite) -> []; description(Config) when is_list(Config) -> put(tname,desc), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), Filename = join(Dir,"test"), @@ -179,14 +202,14 @@ description(Config) when is_list(Config) -> {warnings, false}, {description, false}]), MIB1 = read_mib(MibBinName), - %% io:format("description -> MIB1: ~n~p~n", [MIB1]), + %% ?IPRINT("description -> MIB1: ~n~p~n", [MIB1]), check_mib(MIB1#mib.mes, Oid, undefined), ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir}, {group_check, false}, {warnings, false}, {description, true}]), MIB2 = read_mib(MibBinName), - %% io:format("description -> MIB2: ~n~p~n", [MIB2]), + %% ?IPRINT("description -> MIB2: ~n~p~n", [MIB2]), check_mib(MIB2#mib.mes, Oid, Desctext), %% Cleanup @@ -200,7 +223,8 @@ description(Config) when is_list(Config) -> oid_conflicts(suite) -> []; oid_conflicts(Config) when is_list(Config) -> put(tname,oid_conflicts), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), Mib = join(Dir,"TESTv2.mib"), @@ -232,7 +256,8 @@ agent_capabilities(suite) -> []; agent_capabilities(Config) when is_list(Config) -> put(tname,agent_capabilities), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), SnmpPrivDir = which_priv_dir(snmp), SnmpMibsDir = join(SnmpPrivDir, "mibs"), @@ -253,11 +278,10 @@ agent_capabilities(Config) when is_list(Config) -> ?line {ok, Mib2} = snmp_misc:read_mib(MibFile2), MEDiff = Mib2#mib.mes -- Mib1#mib.mes, %% This is a rather pathetic test, but it is somthing... - io:format("agent_capabilities -> " - "~n MEDiff: ~p" - "~n Mib1: ~p" - "~n Mib2: ~p" - "~n", [MEDiff, Mib1, Mib2]), + ?IPRINT("agent_capabilities -> " + "~n MEDiff: ~p" + "~n Mib1: ~p" + "~n Mib2: ~p", [MEDiff, Mib1, Mib2]), case length(MEDiff) of 2 -> ok; @@ -272,8 +296,9 @@ agent_capabilities(Config) when is_list(Config) -> module_compliance(suite) -> []; module_compliance(Config) when is_list(Config) -> - put(tname,module_compliance), - p("starting with Config: ~p~n", [Config]), + put(tname, module_compliance), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), SnmpPrivDir = which_priv_dir(snmp), SnmpMibsDir = join(SnmpPrivDir, "mibs"), @@ -294,11 +319,10 @@ module_compliance(Config) when is_list(Config) -> ?line {ok, Mib2} = snmp_misc:read_mib(MibFile2), MEDiff = Mib2#mib.mes -- Mib1#mib.mes, %% This is a rather pathetic test, but it is somthing... - io:format("module_compliance -> " - "~n MEDiff: ~p" - "~n Mib1: ~p" - "~n Mib2: ~p" - "~n", [MEDiff, Mib1, Mib2]), + ?IPRINT("module_compliance -> " + "~n MEDiff: ~p" + "~n Mib1: ~p" + "~n Mib2: ~p", [MEDiff, Mib1, Mib2]), case length(MEDiff) of 1 -> ok; @@ -314,7 +338,8 @@ warnings_as_errors(suite) -> ["OTP-9437"]; warnings_as_errors(Config) when is_list(Config) -> put(tname,warnings_as_errors), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP8574-MIB.mib"), @@ -338,14 +363,16 @@ otp_6150(suite) -> []; otp_6150(Config) when is_list(Config) -> put(tname, otp6150), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"), ?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]), - io:format("otp_6150 -> Mib: ~n~p~n", [Mib]), + ?IPRINT("otp_6150 -> Mib: " + "~n ~p", [Mib]), ok. @@ -355,29 +382,30 @@ otp_8574(suite) -> []; otp_8574(Config) when is_list(Config) -> put(tname, otp8574), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP8574-MIB.mib"), - p("ensure compile fail without relaxed assign check"), + ?IPRINT("ensure compile fail without relaxed assign check"), case snmpc:compile(MibFile, [{group_check, false}, {outdir, Dir}]) of {error, compilation_failed} -> - p("with relaxed assign check MIB compiles with warning"), + ?IPRINT("with relaxed assign check MIB compiles with warning"), case snmpc:compile(MibFile, [{group_check, false}, {outdir, Dir}, relaxed_row_name_assign_check]) of {ok, _Mib} -> ok; {error, Reason} -> - p("unexpected compile failure: " - "~n Reason: ~p", [Reason]), + ?EPRINT("unexpected compile failure: " + "~n Reason: ~p", [Reason]), exit({unexpected_compile_failure, Reason}) end; {ok, _} -> - p("unexpected compile success"), + ?EPRINT("unexpected compile success"), exit(unexpected_compile_success) end. @@ -388,7 +416,8 @@ otp_8595(suite) -> []; otp_8595(Config) when is_list(Config) -> put(tname, otp8595), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), @@ -397,7 +426,7 @@ otp_8595(Config) when is_list(Config) -> snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}, {group_check, false}]), - p("Mib: ~n~p~n", [Mib]), + ?IPRINT("Mib: ~n~p~n", [Mib]), ok. @@ -407,14 +436,16 @@ otp_10799(suite) -> []; otp_10799(Config) when is_list(Config) -> put(tname, otp10799), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP10799-MIB.mib"), ?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]), - p("Mib: ~n~p~n", [Mib]), + ?IPRINT("Mib: " + "~n ~p", [Mib]), ok. @@ -424,7 +455,8 @@ otp_10808(suite) -> []; otp_10808(Config) when is_list(Config) -> put(tname, otp10808), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), @@ -433,7 +465,8 @@ otp_10808(Config) when is_list(Config) -> snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}, {group_check, false}]), - p("Mib: ~n~p~n", [Mib]), + ?IPRINT("Mib: " + "~n ~p", [Mib]), ok. @@ -443,7 +476,8 @@ otp_14145(suite) -> []; otp_14145(Config) when is_list(Config) -> put(tname, otp14145), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), @@ -454,7 +488,8 @@ otp_14145(Config) when is_list(Config) -> {verbosity, trace}, {group_check, false}, module_compliance]), - p("Mib: ~n~p~n", [MibBin]), + ?IPRINT("Mib: " + "~n ~p", [MibBin]), MIB = read_mib(MibBin), Oid = [1,3,6,1,2,1,67,4], check_mib(MIB#mib.mes, Oid, undefined), @@ -467,7 +502,8 @@ otp_13014(suite) -> []; otp_13014(Config) when is_list(Config) -> put(tname, otp13014), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), @@ -478,7 +514,8 @@ otp_13014(Config) when is_list(Config) -> {verbosity, log}, {group_check, false}, module_compliance]), - p("Mib: ~n~p~n", [MibBin]), + ?IPRINT("Mib: " + "~n ~p", [MibBin]), #mib{mes = MEs} = read_mib(MibBin), Oid = [1,0,8802,1,1,2,1,1,7], #me{ @@ -494,20 +531,23 @@ otp_13014(Config) when is_list(Config) -> TableInfo, ok. + %%====================================================================== otp_14196(suite) -> []; otp_14196(Config) when is_list(Config) -> put(tname, otp14196), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP14196-MIB.mib"), ?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]), - p("Mib: ~n~p~n", [Mib]), + ?IPRINT("Mib: " + "~n ~p", [Mib]), ok. @@ -517,7 +557,8 @@ augments_extra_info(suite) -> []; augments_extra_info(Config) when is_list(Config) -> put(tname, augments_extra_info), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), @@ -527,28 +568,30 @@ augments_extra_info(Config) when is_list(Config) -> snmpc:compile(Test2File, [{outdir, Dir}, {verbosity, silence}, {group_check, false}]), - io:format("Test2BinFile: ~n~p~n", [Test2BinFile]), + ?IPRINT("Test2BinFile: " + "~n ~p", [Test2BinFile]), ?line {ok, Test3BinFile} = snmpc:compile(Test3File, [{i, [MibDir]}, {outdir, Dir}, {verbosity, silence}, {group_check, true}]), - io:format("Test3BinFile: ~n~p~n", [Test3BinFile]), + ?IPRINT("Test3BinFile: " + "~n ~p", [Test3BinFile]), {ok, Test3Mib} = snmp_misc:read_mib(Test3BinFile), - io:format("Test3Mib: ~n~p~n", [Test3Mib]), + ?IPRINT("Test3Mib: " + "~n ~p", [Test3Mib]), %% There is only one table in this mib #mib{table_infos = [{TableName, TI}]} = Test3Mib, - io:format("TableName: ~p" - "~n Table Info: ~p" - "~n", [TableName, TI]), + ?IPRINT("TableName: ~p" + "~n Table Info: ~p", [TableName, TI]), #table_info{nbr_of_cols = 4, defvals = DefVals, not_accessible = [2,4], index_types = {augments, {tEntry, undefined}}, first_accessible = 1} = TI, - io:format("Table info: ~p" - "~n DefVals: ~p" - "~n", [TableName, DefVals]), + ?IPRINT("Table info: ~p" + "~n DefVals: ~p" + "~n", [TableName, DefVals]), ok. @@ -750,21 +793,3 @@ which_priv_dir(App) -> join(A,B) -> filename:join(A,B). - -%% ------ - -%% p(F) -> -%% p(F, []). - -p(F) -> - p(F, []). - -p(F, A) -> - p(get(tname), F, A). - -p(TName, F, A) -> - io:format("*** [~w][~s] ***" - "~n" ++ F ++ "~n", [TName, formated_timestamp()|A]). - -formated_timestamp() -> - snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/test/snmp_conf_SUITE.erl b/lib/snmp/test/snmp_conf_SUITE.erl index bd8375b400..7d60485060 100644 --- a/lib/snmp/test/snmp_conf_SUITE.erl +++ b/lib/snmp/test/snmp_conf_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -97,11 +97,34 @@ groups() -> %% ----- %% -init_per_suite(Config) when is_list(Config) -> - Config. +init_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), -end_per_suite(Config) when is_list(Config) -> - Config. + case ?LIB:init_per_suite(Config0) of + {skip, _} = SKIP -> + SKIP; + + Config1 when is_list(Config1) -> + %% We need a monitor on this node also + snmp_test_sys_monitor:start(), + + ?IPRINT("init_per_suite -> end when" + "~n Config: ~p", [Config1]), + + Config1 + end. + +end_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("end_per_suite -> entry with" + "~n Config0: ~p", [Config0]), + + snmp_test_sys_monitor:stop(), + Config1 = ?LIB:end_per_suite(Config0), + + ?IPRINT("end_per_suite -> end"), + + Config1. @@ -136,7 +159,7 @@ end_per_testcase(_Case, Config) when is_list(Config) -> check_mandatory(suite) -> []; check_mandatory(Config) when is_list(Config) -> ?P(check_mandatory), - %% d("check_mandatory -> entry"), + %% ?IPRINT("check_mandatory -> entry"), A1 = [{a, hej}, {b, hopp}, {c, 10}, {d, 10101}, {f, 10.88}], B1 = [{a, {value, hejsan}}, {b, mandatory}, @@ -696,8 +719,3 @@ read_files(Config) when is_list(Config) -> %% Internal functions %%====================================================================== -% d(F) -> -% d(F, []). - -% d(F, A) -> -% io:format("~w:" ++ F ++ "~n", [?MODULE|A]). diff --git a/lib/snmp/test/snmp_log_SUITE.erl b/lib/snmp/test/snmp_log_SUITE.erl index 01a1d9ce8c..b63c9e3b34 100644 --- a/lib/snmp/test/snmp_log_SUITE.erl +++ b/lib/snmp/test/snmp_log_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -175,7 +175,7 @@ init_per_testcase(Case, Config) when is_list(Config) -> end_per_testcase(_Case, Config) when is_list(Config) -> - ?PRINT2("system events during test: " + ?IPRINT("system events during test: " "~n ~p", [snmp_test_global_sys_monitor:events()]), %% Leave the dirs created above (enable debugging of the test case(s)) @@ -191,7 +191,7 @@ end_per_testcase(_Case, Config) when is_list(Config) -> open_and_close(suite) -> []; open_and_close(Config) when is_list(Config) -> - p(open_and_close), + ?P(open_and_close), put(sname,open_and_close), put(verbosity,trace), Dir = ?config(log_dir, Config), @@ -213,7 +213,7 @@ open_write_and_close1(suite) -> open_write_and_close1(doc) -> "Open a plain (no sequence-numbering) log file"; open_write_and_close1(Config) when is_list(Config) -> - p(open_write_and_close1), + ?P(open_write_and_close1), put(sname,open_write_and_close1), put(verbosity,trace), ?DBG("open_write_and_close1 -> start", []), @@ -232,7 +232,7 @@ open_write_and_close2(suite) -> open_write_and_close2(doc) -> "Open a log file with sequence-numbering explicitly disabled"; open_write_and_close2(Config) when is_list(Config) -> - p(open_write_and_close2), + ?P(open_write_and_close2), put(sname,open_write_and_close2), put(verbosity,trace), ?DBG("open_write_and_close2 -> start", []), @@ -251,7 +251,7 @@ open_write_and_close3(suite) -> open_write_and_close3(doc) -> "Open a log file with sequence-numbering using MFA"; open_write_and_close3(Config) when is_list(Config) -> - p(open_write_and_close3), + ?P(open_write_and_close3), put(sname,open_write_and_close3), put(verbosity,trace), ?DBG("open_write_and_close2 -> start", []), @@ -272,7 +272,7 @@ open_write_and_close4(suite) -> open_write_and_close4(doc) -> "Open a log file with sequence-numbering using fun"; open_write_and_close4(Config) when is_list(Config) -> - p(open_write_and_close4), + ?P(open_write_and_close4), put(sname,open_write_and_close4), put(verbosity,trace), ?DBG("open_write_and_close2 -> start", []), @@ -371,7 +371,7 @@ log_to_io1(suite) -> []; log_to_io1(doc) -> "Log to io from the same process that opened " "and wrote the log"; log_to_io1(Config) when is_list(Config) -> - p(log_to_io1), + ?P(log_to_io1), put(sname,l2i1), put(verbosity,debug), ?DBG("log_to_io1 -> start", []), @@ -426,7 +426,7 @@ log_to_io2(doc) -> "Log to io from a different process than which " "opened and wrote the log"; log_to_io2(Config) when is_list(Config) -> process_flag(trap_exit, true), - p(log_to_io2), + ?P(log_to_io2), put(sname, l2i2), put(verbosity,debug), ?DBG("log_to_io2 -> start", []), @@ -487,7 +487,7 @@ log_to_io2(Config) when is_list(Config) -> log_to_txt1(suite) -> []; log_to_txt1(Config) when is_list(Config) -> - p(log_to_txt1), + ?P(log_to_txt1), put(sname,l2t1), put(verbosity,debug), ?DBG("log_to_txt1 -> start", []), @@ -505,7 +505,7 @@ log_to_txt1(Config) when is_list(Config) -> log_to_txt2(suite) -> []; log_to_txt2(Config) when is_list(Config) -> - p(log_to_txt2), + ?P(log_to_txt2), put(sname,l2t2), put(verbosity,debug), ?DBG("log_to_txt2 -> start", []), @@ -642,7 +642,7 @@ log_to_txt3(doc) -> "opened and wrote the log"; log_to_txt3(Config) when is_list(Config) -> process_flag(trap_exit, true), - p(log_to_txt3), + ?P(log_to_txt3), put(sname,l2t3), put(verbosity,debug), ?DBG("log_to_txt3 -> start", []), @@ -683,9 +683,7 @@ log_to_txt3(Config) when is_list(Config) -> R = snmp_log:log_to_txt(Log, LogFile, Dir, Mibs, TxtFile), T2 = snmp_misc:now(ms), - io:format(user, - "Time converting file: ~w ms~n", - [T2 - T1]), + ?IPRINT("Time converting file: ~w ms", [T2 - T1]), {R, I} end), @@ -697,9 +695,9 @@ log_to_txt3(Config) when is_list(Config) -> ?DBG("log_to_txt3 -> text file size: ~p", [FileSize]), validate_size(FileSize); {Error, Info} -> - ?DBG("log_to_txt3 -> log to txt failed: " - "~n Error: ~p" - "~n Info: ~p", [Error, Info]), + ?EPRINT("log to txt failed: " + "~n Error: ~p" + "~n Info: ~p", [Error, Info]), ?line ?FAIL({log_lo_txt_failed, Error, Info}) end, @@ -709,7 +707,7 @@ log_to_txt3(Config) when is_list(Config) -> ?DBG("log_to_txt3 -> instruct the log reader to stop", []), ?line log_reader_stop(Reader), - ?DBG("log_to_txt3 -> done", []), + ?IPRINT("log_to_txt3 -> done", []), ok. @@ -754,8 +752,7 @@ log_writer_stop(Pid) -> receive {'EXIT', Pid, normal} -> _T2 = snmp_misc:now(ms), - io:format("[~s] it took ~w ms to stop the writer~n", - [?FTS(), _T2 - _T1]), + ?IPRINT("it took ~w ms to stop the writer", [_T2 - _T1]), ok after 60000 -> Msg = receive Any -> Any after 0 -> nothing end, @@ -772,8 +769,7 @@ log_writer_sleep(Pid, Time) -> receive {sleeping, Pid} -> _T2 = snmp_misc:now(ms), - io:format("[~s] it took ~w ms to put the writer to sleep~n", - [?FTS(), _T2 - _T1]), + ?IPRINT("it took ~w ms to put the writer to sleep", [_T2 - _T1]), ok; {'EXIT', Pid, Reason} -> {error, Reason} @@ -785,8 +781,7 @@ log_writer_sleep(Pid, Time) -> log_writer_main(Name, File, Size, Repair, P, Factor) -> process_flag(trap_exit, true), - %% put(sname,log_writer), - %% put(verbosity,trace), + put(tname, "LOG-WRITER"), {ok, Log} = snmp_log:create(Name, File, Size, Repair), P ! {log, Log, self()}, Msgs = lists:flatten(lists:duplicate(if @@ -807,39 +802,34 @@ log_writer_main(Name, File, Size, Repair, P, Factor) -> log_writer(Log, BatchLogger, P). log_writer(Log, Fun, P) -> - lp("entry"), + ?IPRINT("entry"), receive {stop, P} -> - lp("received stop request"), + ?IPRINT("received stop request"), ok = snmp_log:close(Log), exit(normal); {info, P} -> - lp("received info request"), + ?IPRINT("received info request"), {ok, Info} = snmp_log:info(Log), display_info(Info), log_writer(Log, Fun, P); {sleep, Time, P} -> - lp("received sleep (~w) request", [Time]), + ?IPRINT("received sleep (~w) request", [Time]), P ! {sleeping, self()}, ?SLEEP(Time), - lp("done sleeping"), + ?IPRINT("done sleeping"), log_writer(Log, Fun, P); ELSE -> - error_logger:error_msg("ERROR:logger - received unknown message: " - "~n ~p~n", [ELSE]), + ?EPRINT("Received unknown message: " + "~n ~p", [ELSE]), log_writer(Log, Fun, P) after 1000 -> - lp("log some messages"), + ?IPRINT("log some messages"), To = lists:duplicate(100, 100), lists:foreach(Fun, To), log_writer(Log, Fun, P) end. -lp(F) -> - lp(F, []). - -lp(F, A) -> - io:format("[~s] writer [~w] " ++ F ++ "~n", [?FTS(),self()|A]). %% -- @@ -849,8 +839,7 @@ log_reader_start() -> receive {started, Pid} -> _T2 = snmp_misc:now(ms), - io:format("[~s] it took ~w ms to start the reader~n", - [?FTS(), _T2 - _T1]), + ?IPRINT("it took ~w ms to start the reader", [_T2 - _T1]), {ok, Pid}; {'EXIT', Pid, Reason} -> {error, Reason} @@ -864,8 +853,7 @@ log_reader_stop(Pid) -> receive {'EXIT', Pid, normal} -> _T2 = snmp_misc:now(ms), - io:format("[~s] it took ~w ms to stop the reader~n", - [?FTS(), _T2 - _T1]), + ?IPRINT("it took ~w ms to stop the reader", [_T2 - _T1]), ok after 1000 -> Msg = receive Any -> Any after 0 -> nothing end, @@ -880,35 +868,28 @@ log_reader_log_to(Pid, LogToFun) when is_function(LogToFun) -> end. log_reader_main(P) -> - put(sname,log_reader), - put(verbosity,trace), + put(tname, "LOG-READER"), P ! {started, self()}, log_reader(P). log_reader(P) -> - rp("entry"), + ?IPRINT("entry"), receive {stop, P} -> - rp("received stop request"), + ?IPRINT("received stop request"), exit(normal); {log_to, F, P} -> - rp("received log_to request"), + ?IPRINT("received log_to request"), Res = F(), - rp("done with log_to - sending reply"), + ?IPRINT("done with log_to - sending reply"), P ! {log_to_reply, Res, self()}, log_reader(P); ELSE -> - error_logger:error_msg("reader - received unknown message: " - "~n ~p~n", [ELSE]), + ?EPRINT("Received unknown message: " + "~n ~p", [ELSE]), log_reader(P) end. -rp(F) -> - rp(F, []). - -rp(F, A) -> - io:format("[~s] reader [~w] " ++ F ++ "~n", [?FTS(),self()|A]). - %%====================================================================== @@ -1127,23 +1108,6 @@ varbinds([{Oid, Type, Value, Idx}|T], Acc) -> org_index = Idx}, varbinds(T, [Varbind|Acc]). -% enc_message('version-3' = Vsn, Community, Pdu) -> -% ScopedPDU = #scopedPdu{contextEngineID = ContextEngineID, -% contextName = ContextName, -% data = Pdu}, -% NUsmSecParams = -% UsmSecParams#usmSecurityParameters{msgAuthenticationParameters = -% AuthParams}, -% SecBytes = snmp_pdus:enc_usm_security_parameters(NUsmSecParams), -% V3Hdr = #v3_hdr{msgID = MsgID, -% msgMaxSize = AgentMS, -% msgFlags = snmp_misc:mk_msg_flags(Type, SecLevel), -% msgSecurityParameters = SecBytes -% msgSecurityModel = MsgSecurityModel}, -% Msg = #message{version = Vsn, vsn_hdr = V3Hdr, -% data = ScopedPDUBytes}, -% snmp_pdus:enc_message_only(Message2); - enc_message(Vsn, Community, Pdu) -> PduBytes = snmp_pdus:enc_pdu(Pdu), Msg = #message{version = Vsn, @@ -1156,14 +1120,13 @@ display_info(Info) -> CurrentFile = get_info(current_file, Info, -1), NoItems = get_info(no_current_items, Info, -1), NoBytes = get_info(no_current_bytes, Info, -1), - io:format(user, "Disk log info: " - "~n Number of filled since opened: ~p" - "~n Number of filled since last info: ~p" - "~n Current file: ~p" - "~n Number of items in file: ~p" - "~n Number of bytes in file: ~p" - "~n", - [SinceOpened, SinceLastInfo, CurrentFile, NoItems, NoBytes]). + ?NPRINT("Disk log info: " + "~n Number of filled since opened: ~p" + "~n Number of filled since last info: ~p" + "~n Current file: ~p" + "~n Number of items in file: ~p" + "~n Number of bytes in file: ~p", + [SinceOpened, SinceLastInfo, CurrentFile, NoItems, NoBytes]). get_info(Key, Info, Def) -> case lists:keysearch(Key, 1, Info) of @@ -1176,5 +1139,3 @@ get_info(Key, Info, Def) -> join(D, F) -> filename:join(D, F). -p(Case) -> - io:format(user, "test case: ~w~n", [Case]). diff --git a/lib/snmp/test/snmp_manager_SUITE.erl b/lib/snmp/test/snmp_manager_SUITE.erl index bc7c5cd46d..9d8e2efacf 100644 --- a/lib/snmp/test/snmp_manager_SUITE.erl +++ b/lib/snmp/test/snmp_manager_SUITE.erl @@ -337,8 +337,8 @@ ipv6_tests() -> init_per_suite(Config0) when is_list(Config0) -> - p("init_per_suite -> entry with" - "~n Config0: ~p", [Config0]), + ?IPRINT("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), case ?LIB:init_per_suite(Config0) of {skip, _} = SKIP -> @@ -346,8 +346,8 @@ init_per_suite(Config0) when is_list(Config0) -> Config1 -> - p("init_per_suite -> common init done" - "~n Config1: ~p", [Config1]), + ?IPRINT("init_per_suite -> common init done" + "~n Config1: ~p", [Config1]), %% Preferably this test SUITE should be divided into groups %% so that if crypto does not work only v3 tests that @@ -375,15 +375,15 @@ init_per_suite(Config0) when is_list(Config0) -> end_per_suite(Config0) when is_list(Config0) -> - p("end_per_suite -> entry with" - "~n Config0: ~p" - "~n Nodes: ~p", [Config0, erlang:nodes()]), + ?IPRINT("end_per_suite -> entry with" + "~n Config0: ~p" + "~n Nodes: ~p", [Config0, erlang:nodes()]), snmp_test_sys_monitor:stop(), Config1 = ?LIB:end_per_suite(Config0), - p("end_per_suite -> end when" - "~n Nodes: ~p", [erlang:nodes()]), + ?IPRINT("end_per_suite -> end when" + "~n Nodes: ~p", [erlang:nodes()]), Config1. @@ -453,8 +453,10 @@ end_per_group(_GroupName, Config) -> %% init_per_testcase(Case, Config) when is_list(Config) -> - p(Case, "init_per_testcase begin when" - "~n Nodes: ~p~n~n", [erlang:nodes()]), + + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p" + "~n Nodes: ~p", [Config, erlang:nodes()]), snmp_test_global_sys_monitor:reset_events(), @@ -472,15 +474,19 @@ init_per_testcase(Case, Config) when is_list(Config) -> C:{skip, _} = E:_ when ((C =:= throw) orelse (C =:= exit)) -> E; + exit:{suite_failed, {{Reason, _CS},_MFA}, Mod, Line}:_ -> + {skip, {Reason, Mod, Line}}; + exit:{suite_failed, Reason, Mod, Line}:_ -> + {skip, {Reason, Mod, Line}}; C:E:_ when ((C =:= throw) orelse (C =:= exit)) -> {skip, {catched, C, E}} end end, - p(Case, "init_per_testcase end when" - "~n Nodes: ~p" - "~n Result: ~p" - "~n~n", [Result, erlang:nodes()]), + ?IPRINT("init_per_testcase end when" + "~n Nodes: ~p" + "~n Result: ~p" + "~n~n", [erlang:nodes(), Result]), Result. init_per_testcase2(Case, Config) -> @@ -527,10 +533,14 @@ init_per_testcase2(Case, Config) -> InformSwarm when (InformSwarm =:= inform_swarm_cbp_def) orelse (InformSwarm =:= inform_swarm_cbp_temp) orelse (InformSwarm =:= inform_swarm_cbp_perm) -> - ?MINS(60); + case ?config(snmp_factor, Config) of + N when is_integer(N) -> ?MINS(2*N); + _ -> ?MINS(2) + end; _ -> ?MINS(1) end, + ?IPRINT("Set test case timetrap: ~p", [TO]), ct:timetrap(TO), Conf = [{ipfamily, Family}, @@ -609,12 +619,12 @@ init_per_testcase3(Case, Config) -> (Case =:= inform_swarm_cbp_temp) orelse (Case =:= inform_swarm_cbp_perm) -> Verb = [{manager_config_verbosity, silence}, - {manager_note_store_verbosity, silence}, - {manager_server_verbosity, info}, - {manager_net_if_verbosity, info}, - {agent_verbosity, info}, - {agent_net_if_verbosity, info}], - Verb ++ Config; + {manager_note_store_verbosity, silence}, + {manager_server_verbosity, info}, + {manager_net_if_verbosity, info}, + {agent_verbosity, info}, + {agent_net_if_verbosity, info}], + Verb ++ Config; Case =:= otp8395_1 -> [{manager_atl_seqno, true} | Config]; true -> @@ -670,20 +680,21 @@ init_per_testcase_fail_agent_cleanup(Conf) -> (catch fin_agent(Conf)). end_per_testcase(Case, Config) when is_list(Config) -> - p(Case, "end_per_testcase begin when" - "~n Nodes: ~p~n~n", [erlang:nodes()]), + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p" + "~n Nodes: ~p", + [Config, erlang:nodes()]), - ?PRINT2("system events during test: " + ?IPRINT("system events during test: " "~n ~p", [snmp_test_global_sys_monitor:events()]), - %% Dog = ?config(watchdog, Config), - %% ?WD_STOP(Dog), - %% Conf1 = lists:keydelete(watchdog, 1, Config), Conf1 = Config, Conf2 = end_per_testcase2(Case, Conf1), - p(Case, "end_per_testcase end when" - "~n Nodes: ~p~n~n", [erlang:nodes()]), + ?IPRINT("end_per_testcase -> done with" + "~n Condif: ~p" + "~n Nodes: ~p", [Conf2, erlang:nodes()]), + Conf2. end_per_testcase2(Case, Config) -> @@ -763,7 +774,8 @@ simple_start_and_stop1(Config) when is_list(Config) -> fun() -> do_simple_start_and_stop1(Config) end). do_simple_start_and_stop1(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -774,12 +786,12 @@ do_simple_start_and_stop1(Config) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), - p("manager started, now try to stop"), + ?IPRINT("manager started, now try to stop"), ok = snmpm:stop(), ?SLEEP(1000), @@ -800,7 +812,9 @@ simple_start_and_stop2(Config) when is_list(Config) -> ?TC_TRY(simple_start_and_stop2, Pre, Case, Post). do_simple_start_and_stop2([ManagerNode], Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -813,23 +827,24 @@ do_simple_start_and_stop2([ManagerNode], Config) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try load snmp application"), + ?IPRINT("try load snmp application"), ?line ok = load_snmp(ManagerNode), - p("try set manager env for the snmp application"), + ?IPRINT("try set manager env for the snmp application"), ?line ok = set_mgr_env(ManagerNode, Opts), - p("try starting snmp application (with only manager)"), + ?IPRINT("try starting snmp application (with only manager)"), ?line ok = start_snmp(ManagerNode), - p("started"), + ?IPRINT("started"), ?SLEEP(1000), - p("try stopping snmp application (with only manager)"), + ?IPRINT("try stopping snmp application (with only manager)"), ?line ok = stop_snmp(ManagerNode), ?SLEEP(1000), + ?IPRINT("end"), ok. @@ -842,7 +857,9 @@ simple_start_and_stop3(Config) when is_list(Config) -> fun() -> do_simple_start_and_stop3(Config) end). do_simple_start_and_stop3(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), + ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -853,17 +870,19 @@ do_simple_start_and_stop3(Config) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), try snmpm:start_link(Opts) of ok -> + (catch snmpm:stop()), ?FAIL('unexpected-success') catch _:_:_ -> - p("expected start failure"), + ?IPRINT("expected start failure"), ok end, ?SLEEP(1000), + ?IPRINT("end"), ok. @@ -876,7 +895,8 @@ simple_start_and_monitor_crash1(Config) when is_list(Config) -> fun() -> do_simple_start_and_monitor_crash1(Config) end). do_simple_start_and_monitor_crash1(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -888,15 +908,15 @@ do_simple_start_and_monitor_crash1(Config) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start(Opts), ?SLEEP(1000), - p("create the monitor"), + ?IPRINT("create the monitor"), Ref = snmpm:monitor(), - p("make sure it has not already crashed..."), + ?IPRINT("make sure it has not already crashed..."), receive {'DOWN', Ref, process, Obj1, Reason1} -> ?FAIL({unexpected_down, Obj1, Reason1}) @@ -904,20 +924,28 @@ do_simple_start_and_monitor_crash1(Config) -> ok end, - p("stop the manager"), + ?IPRINT("stop the manager"), ok = snmpm:stop(), - p("await the down-message"), + ?IPRINT("await the down-message"), receive {'DOWN', Ref, process, Obj2, Reason2} -> - p("received expected down-message: " - "~n Obj2: ~p" - "~n Reason2: ~p", - [Obj2, Reason2]), + ?IPRINT("received expected down-message: " + "~n Obj2: ~p" + "~n Reason2: ~p", + [Obj2, Reason2]), ok after 1000 -> + %% The manager is an entire process tree and we can't + %% wait for all of them. Instead, we assume that if + %% we deal with the top supervisor, all the other procs + %% will also follow... + ?ENSURE_NOT_RUNNING(snmpm_supervisor, + fun() -> snmpm:stop() end, + 1000), ?FAIL(timeout) end, + ?IPRINT("end"), ok. @@ -926,11 +954,22 @@ do_simple_start_and_monitor_crash1(Config) -> simple_start_and_monitor_crash2(suite) -> []; simple_start_and_monitor_crash2(Config) when is_list(Config) -> + Cond = fun() -> case os:type() of + {unix, netbsd} -> + {skip, "Unstable on NetBSD"}; + _ -> + ok + end + end, + Pre = fun() -> undefined end, + Case = fun(_) -> do_simple_start_and_monitor_crash2(Config) end, + Post = fun(_) -> ok end, ?TC_TRY(simple_start_and_monitor_crash2, - fun() -> do_simple_start_and_monitor_crash2(Config) end). + Cond, Pre, Case, Post). do_simple_start_and_monitor_crash2(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -943,15 +982,15 @@ do_simple_start_and_monitor_crash2(Config) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start(Opts), ?SLEEP(1000), - p("create the monitor"), + ?IPRINT("create the monitor"), Ref = snmpm:monitor(), - p("make sure it has not already crashed..."), + ?IPRINT("make sure it has not already crashed..."), receive {'DOWN', Ref, process, Obj1, Reason1} -> ?FAIL({unexpected_down, Obj1, Reason1}) @@ -959,16 +998,16 @@ do_simple_start_and_monitor_crash2(Config) -> ok end, - p("crash the manager"), + ?IPRINT("crash the manager"), simulate_crash(), - p("await the down-message"), + ?IPRINT("await the down-message"), receive {'DOWN', Ref, process, Obj2, Reason2} -> - p("received expected down-message: " - "~n Obj2: ~p" - "~n Reason2: ~p", - [Obj2, Reason2]), + ?IPRINT("received expected down-message: " + "~n Obj2: ~p" + "~n Reason2: ~p", + [Obj2, Reason2]), ok after 1000 -> ?FAIL(timeout) @@ -995,16 +1034,17 @@ simulate_crash(?MAX_KILLS, _) -> ok end; simulate_crash(NumKills, Pid) when (NumKills < ?MAX_KILLS) and is_pid(Pid) -> - p("similate_crash -> ~w, ~p", [NumKills, Pid]), + ?IPRINT("similate_crash -> ~w, ~p", [NumKills, Pid]), Ref = erlang:monitor(process, Pid), exit(Pid, kill), receive {'DOWN', Ref, process, _Object, _Info} -> - p("received expected 'DOWN' message"), + ?IPRINT("received expected 'DOWN' message"), simulate_crash(NumKills + 1, server_pid()) after 1000 -> case server_pid() of P when is_pid(P) -> + ?EPRINT("received expected 'DOWN' message"), exit({error, {no_down_from_server, P}}); _ -> ok @@ -1023,7 +1063,8 @@ notify_started01(Config) when is_list(Config) -> fun() -> do_notify_started01(Config) end). do_notify_started01(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -1035,11 +1076,11 @@ do_notify_started01(Config) -> {note_store, [{verbosity, silence}]}, {config, [{verbosity, log}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("request start notification (1)"), + ?IPRINT("request start notification (1)"), Pid1 = snmpm:notify_started(10000), receive {snmpm_start_timeout, Pid1} -> - p("received expected start timeout"), + ?IPRINT("received expected start timeout"), ok; Any1 -> ?FAIL({unexpected_message, Any1}) @@ -1047,17 +1088,17 @@ do_notify_started01(Config) -> ?FAIL({unexpected_timeout, Pid1}) end, - p("request start notification (2)"), + ?IPRINT("request start notification (2)"), Pid2 = snmpm:notify_started(10000), - p("start the snmpm starter"), + ?IPRINT("start the snmpm starter"), Pid = snmpm_starter(Opts, 5000), - p("await the start notification"), + ?IPRINT("await the start notification"), Ref = receive {snmpm_started, Pid2} -> - p("received started message -> create the monitor"), + ?IPRINT("received started message -> create the monitor"), snmpm:monitor(); Any2 -> ?FAIL({unexpected_message, Any2}) @@ -1065,7 +1106,7 @@ do_notify_started01(Config) -> ?FAIL({unexpected_timeout, Pid2}) end, - p("[~p] make sure it has not already crashed...", [Ref]), + ?IPRINT("[~p] make sure it has not already crashed...", [Ref]), receive {'DOWN', Ref, process, Obj1, Reason1} -> ?FAIL({unexpected_down, Obj1, Reason1}) @@ -1073,22 +1114,22 @@ do_notify_started01(Config) -> ok end, - p("stop the manager"), + ?IPRINT("stop the manager"), Pid ! {stop, self()}, %ok = snmpm:stop(), - p("await the down-message"), + ?IPRINT("await the down-message"), receive {'DOWN', Ref, process, Obj2, Reason2} -> - p("received expected down-message: " - "~n Obj2: ~p" - "~n Reason2: ~p", - [Obj2, Reason2]), + ?IPRINT("received expected down-message: " + "~n Obj2: ~p" + "~n Reason2: ~p", + [Obj2, Reason2]), ok after 5000 -> ?FAIL(down_timeout) end, - p("end"), + ?IPRINT("end"), ok. @@ -1137,7 +1178,8 @@ notify_started02_cond(Config) -> ?NON_PC_TC_MAYBE_SKIP(Config, Condition). do_notify_started02(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -1149,11 +1191,11 @@ do_notify_started02(Config) -> {note_store, [{verbosity, silence}]}, {config, [{verbosity, debug}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("start snmpm client process"), + ?IPRINT("start snmpm client process"), NumIterations = 5, Pid1 = ns02_client_start(NumIterations), - p("start snmpm ctrl (starter) process"), + ?IPRINT("start snmpm ctrl (starter) process"), Pid2 = ns02_ctrl_start(Opts, NumIterations), %% On a reasonably fast machine, one iteration takes approx 4 seconds. @@ -1175,7 +1217,8 @@ do_notify_started02(Config) -> ?SKIP(Reason) end, - p("await snmpm client process exit (max ~p+10000 msec)", [ApproxStartTime]), + ?IPRINT("await snmpm client process exit (max ~p+10000 msec)", + [ApproxStartTime]), receive %% We take this opportunity to check if we got a skip from %% the ctrl process. @@ -1193,7 +1236,7 @@ do_notify_started02(Config) -> ?FAIL(timeout) end, - p("await snmpm starter process exit"), + ?IPRINT("await snmpm starter process exit"), receive {'EXIT', Pid2, normal} -> ok; @@ -1207,7 +1250,7 @@ do_notify_started02(Config) -> ?FAIL(timeout) end, - p("end"), + ?IPRINT("end"), ok. @@ -1220,8 +1263,8 @@ ns02_client_await_approx_runtime(Pid) -> {?MODULE, client_time, Time} -> {ok, Time}; {'EXIT', Pid, Reason} -> - p("client (~p) failed: " - "~n ~p", [Pid, Reason]), + ?EPRINT("client (~p) failed: " + "~n ~p", [Pid, Reason]), {error, Reason} after 30000 -> @@ -1233,48 +1276,48 @@ ns02_client_await_approx_runtime(Pid) -> ns02_client(Parent, N) when is_pid(Parent) -> put(tname, ns02_client), - p("starting"), + ?IPRINT("starting"), ns02_client_loop(Parent, dummy, snmpm:notify_started(?NS_TIMEOUT), snmp_misc:now(ms), undefined, N). ns02_client_loop(_Parent, _Ref, _Pid, _Begin, _End, 0) -> - %% p("loop -> done"), + %% ?IPRINT("loop -> done"), exit(normal); ns02_client_loop(Parent, Ref, Pid, Begin, End, N) when is_pid(Parent) andalso is_integer(Begin) andalso is_integer(End) -> - %% p("loop -> [~w] inform parent: ~w, ~w => ~w", [N, Begin, End, End-Begin]), + %% ?IPRINT("loop -> [~w] inform parent: ~w, ~w => ~w", [N, Begin, End, End-Begin]), Parent ! {?MODULE, client_time, N*(End-Begin)}, ns02_client_loop(undefined, Ref, Pid, snmp_misc:now(ms), undefined, N); ns02_client_loop(Parent, Ref, Pid, Begin, End, N) when is_integer(Begin) andalso is_integer(End) -> - %% p("loop -> [~w] entry when" + %% ?IPRINT("loop -> [~w] entry when" %% "~n Ref: ~p" %% "~n Pid: ~p" %% "~n Begin: ~p" %% "~n End: ~p", [N, Ref, Pid, Begin, End]), ns02_client_loop(Parent, Ref, Pid, snmp_misc:now(ms), undefined, N); ns02_client_loop(Parent, Ref, Pid, Begin, End, N) -> - %% p("loop(await message) -> [~w] entry when" + %% ?IPRINT("loop(await message) -> [~w] entry when" %% "~n Ref: ~p" %% "~n Pid: ~p" %% "~n Begin: ~p" %% "~n End: ~p", [N, Ref, Pid, Begin, End]), receive {snmpm_started, Pid} -> - p("received expected started message (~w)", [N]), + ?IPRINT("received expected started message (~w)", [N]), ns02_client_loop(Parent, snmpm:monitor(), dummy, Begin, End, N); {snmpm_start_timeout, Pid} -> - p("unexpected timout"), + ?EPRINT("unexpected timeout"), ?FAIL({unexpected_start_timeout, Pid}); {'DOWN', Ref, process, Obj, Reason} -> - p("received expected DOWN message (~w) with" - "~n Obj: ~p" - "~n Reason: ~p", [N, Obj, Reason]), + ?IPRINT("received expected DOWN message (~w) with" + "~n Obj: ~p" + "~n Reason: ~p", [N, Obj, Reason]), ns02_client_loop(Parent, dummy, snmpm:notify_started(?NS_TIMEOUT), Begin, snmp_misc:now(ms), @@ -1286,7 +1329,7 @@ ns02_ctrl_start(Opts, N) -> ns02_ctrl(Opts, N) -> put(tname, ns02_ctrl), - p("starting"), + ?IPRINT("starting"), ns02_ctrl_loop(Opts, N). @@ -1296,36 +1339,36 @@ ns02_ctrl(Opts, N) -> %% So, we try to monitor each start attempt. We allow 5 sec (just %% to give slow boxes a chance). ns02_ctrl_loop(_Opts, 0) -> - p("done"), + ?IPRINT("done"), exit(normal); ns02_ctrl_loop(Opts, N) -> - p("entry when N: ~p", [N]), + ?IPRINT("entry when N: ~p", [N]), ?SLEEP(2000), - p("start manager"), + ?IPRINT("start manager"), TS1 = erlang:system_time(millisecond), {StarterPid, StarterMRef} = erlang:spawn_monitor(fun() -> exit(snmpm:start(Opts)) end), receive {'DOWN', StarterMRef, process, StarterPid, ok} -> TS2 = erlang:system_time(millisecond), - p("manager started: ~w ms", [TS2-TS1]), + ?IPRINT("manager started: ~w ms", [TS2-TS1]), ok after 5000 -> - p("manager (~p) start timeout - kill", [StarterPid]), + ?EPRINT("manager (~p) start timeout - kill", [StarterPid]), exit(StarterPid, kill), exit({skip, start_timeout}) end, ?SLEEP(2000), - p("stop manager"), + ?IPRINT("stop manager"), ?SLEEP(100), % Give the verbosity to take effect... TS3 = erlang:system_time(millisecond), case snmpm:stop(5000) of ok -> TS4 = erlang:system_time(millisecond), - p("manager stopped: ~p ms", [TS4-TS3]), + ?IPRINT("manager stopped: ~p ms", [TS4-TS3]), ok; {error, timeout} -> - p("manager stop timeout - kill (cleanup) and skip"), + ?EPRINT("manager stop timeout - kill (cleanup) and skip"), exit(whereis(snmpm_supervisor), kill), exit({skip, stop_timeout}) end, @@ -1337,37 +1380,44 @@ ns02_ctrl_loop(Opts, N) -> info(suite) -> []; info(Config) when is_list(Config) -> - ?TC_TRY(info, - fun() -> do_info(Config) end). - -do_info(Config) -> - p("starting with Config: ~n~p", [Config]), - - ConfDir = ?config(manager_conf_dir, Config), - DbDir = ?config(manager_db_dir, Config), - - write_manager_conf(ConfDir), - - Opts = [{server, [{verbosity, trace}]}, - {net_if, [{verbosity, trace}]}, - {note_store, [{verbosity, trace}]}, - {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + Pre = fun() -> + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, + {dir, ConfDir}, + {db_dir, DbDir}]}], + ?IPRINT("try starting manager"), + ok = snmpm:start(Opts), + ?SLEEP(1000), + ok + end, + Case = fun(_) -> do_info(Config) end, + Post = fun(_) -> + ?IPRINT("info verified, now try to stop"), + snmpm:stop(), + ?SLEEP(1000), + ok + end, + ?TC_TRY(info, Pre, Case, Post). - p("try starting manager"), - ok = snmpm:start(Opts), - ?SLEEP(1000), +do_info(Config) -> + ?IPRINT("starting with Config: " + "~n ~p", [Config]), - p("manager started, now get info"), + ?IPRINT("get info"), Info = snmpm:info(), - p("got info, now verify: ~n~p", [Info]), + ?IPRINT("got info, now verify: " + "~n ~p", [Info]), ok = verify_info( Info ), - p("info verified, now try to stop"), - ok = snmpm:stop(), - - ?SLEEP(1000), - + ?IPRINT("end"), ok. verify_info(Info) when is_list(Info) -> @@ -1416,7 +1466,9 @@ register_user1(Config) when is_list(Config) -> ?TC_TRY(register_user1, Pre, Case, Post). do_register_user1([ManagerNode], Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -1429,56 +1481,56 @@ do_register_user1([ManagerNode], Config) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("load snmp application"), + ?IPRINT("load snmp application"), ?line ok = load_snmp(ManagerNode), - p("set manager env for the snmp application"), + ?IPRINT("set manager env for the snmp application"), ?line ok = set_mgr_env(ManagerNode, Opts), - p("starting snmp application (with only manager)"), + ?IPRINT("starting snmp application (with only manager)"), ?line ok = start_snmp(ManagerNode), - p("started"), + ?IPRINT("started"), ?SLEEP(1000), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("try register user(s)"), + ?IPRINT("try register user(s)"), ?line ok = mgr_register_user(ManagerNode, calvin, snmpm_user_default, [self(), "various misc info"]), Users1 = mgr_which_users(ManagerNode), - p("users: ~p~n", [Users1]), + ?IPRINT("users: ~p~n", [Users1]), ?line ok = verify_users(Users1, [calvin]), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), ?line ok = mgr_register_user(ManagerNode, hobbe, snmpm_user_default, {"misc info", self()}), Users2 = mgr_which_users(ManagerNode), - p("users: ~p~n", [Users2]), + ?IPRINT("users: ~p~n", [Users2]), ?line ok = verify_users(Users2, [calvin, hobbe]), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("try unregister user(s)"), + ?IPRINT("try unregister user(s)"), ?line ok = mgr_unregister_user(ManagerNode, calvin), Users3 = mgr_which_users(ManagerNode), - p("users: ~p~n", [Users3]), + ?IPRINT("users: ~p~n", [Users3]), ?line ok = verify_users(Users3, [hobbe]), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), ?line ok = mgr_unregister_user(ManagerNode, hobbe), Users4 = mgr_which_users(ManagerNode), - p("users: ~p~n", [Users4]), + ?IPRINT("users: ~p~n", [Users4]), ?line ok = verify_users(Users4, []), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), ?SLEEP(1000), - p("stop snmp application (with only manager)"), + ?IPRINT("stop snmp application (with only manager)"), ?line ok = stop_snmp(ManagerNode), ?SLEEP(1000), @@ -1514,7 +1566,9 @@ register_agent_old(Config) when is_list(Config) -> ?TC_TRY(register_agent_old, Pre, Case, Post). do_register_agent_old([ManagerNode], Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -1527,100 +1581,105 @@ do_register_agent_old([ManagerNode], Config) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("load snmp application"), + ?IPRINT("load snmp application"), ?line ok = load_snmp(ManagerNode), - p("set manager env for the snmp application"), + ?IPRINT("set manager env for the snmp application"), ?line ok = set_mgr_env(ManagerNode, Opts), - p("starting snmp application (with only manager)"), + ?IPRINT("starting snmp application (with only manager)"), ?line ok = start_snmp(ManagerNode), - p("started"), + ?IPRINT("started"), ?SLEEP(1000), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("register user(s) user_alfa & user_beta"), + ?IPRINT("register user(s) user_alfa & user_beta"), ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []), ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("register agent(s)"), + ?IPRINT("register agent(s)"), ?line ok = mgr_register_agent(ManagerNode, user_alfa, 5000, []), ?line ok = mgr_register_agent(ManagerNode, user_alfa, 5001, []), ?line ok = mgr_register_agent(ManagerNode, user_beta, 5002, []), ?line ok = mgr_register_agent(ManagerNode, user_beta, 5003, []), - p("verify all agent(s): expect 4"), + ?IPRINT("verify all agent(s): expect 4"), case mgr_which_agents(ManagerNode) of Agents1 when length(Agents1) =:= 4 -> - p("all agents: ~p~n", [Agents1]), + ?IPRINT("all agents: ~p~n", [Agents1]), ok; Agents1 -> ?FAIL({agent_registration_failure, Agents1}) end, - p("verify user_alfa agent(s)"), + ?IPRINT("verify user_alfa agent(s)"), case mgr_which_agents(ManagerNode, user_alfa) of Agents2 when length(Agents2) =:= 2 -> - p("calvin agents: ~p~n", [Agents2]), + ?IPRINT("calvin agents: ~p", [Agents2]), ok; Agents2 -> ?FAIL({agent_registration_failure, Agents2}) end, - p("verify user_beta agent(s)"), + ?IPRINT("verify user_beta agent(s)"), case mgr_which_agents(ManagerNode, user_beta) of Agents3 when length(Agents3) =:= 2 -> - p("hobbe agents: ~p~n", [Agents3]), + ?IPRINT("hobbe agents: ~p", [Agents3]), ok; Agents3 -> ?FAIL({agent_registration_failure, Agents3}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(ManagerNode)]), - p("unregister user user_alfa"), + ?IPRINT("unregister user user_alfa"), ?line ok = mgr_unregister_user(ManagerNode, user_alfa), - p("verify all agent(s): expect 2"), + ?IPRINT("verify all agent(s): expect 2"), case mgr_which_agents(ManagerNode) of Agents4 when length(Agents4) =:= 2 -> - p("all agents: ~p~n", [Agents4]), + ?IPRINT("all agents: ~p", [Agents4]), ok; Agents4 -> ?FAIL({agent_unregistration_failure, Agents4}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: " + "~n ~p~n", [mgr_info(ManagerNode)]), - p("unregister user_beta agents"), + ?IPRINT("unregister user_beta agents"), ?line ok = mgr_unregister_agent(ManagerNode, user_beta, 5002), ?line ok = mgr_unregister_agent(ManagerNode, user_beta, 5003), - p("verify all agent(s): expect 0"), + ?IPRINT("verify all agent(s): expect 0"), case mgr_which_agents(ManagerNode) of [] -> ok; Agents5 -> - p("all agents: ~p~n", [Agents5]), + ?IPRINT("all agents: ~p~n", [Agents5]), ?FAIL({agent_unregistration_failure, Agents5}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(ManagerNode)]), - p("unregister user hobbe"), + ?IPRINT("unregister user hobbe"), ?line ok = mgr_unregister_user(ManagerNode, user_beta), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(ManagerNode)]), ?SLEEP(1000), - p("stop snmp application (with only manager)"), + ?IPRINT("stop snmp application (with only manager)"), ?line ok = stop_snmp(ManagerNode), ?SLEEP(1000), + ?IPRINT("end"), ok. @@ -1641,7 +1700,8 @@ register_agent2(Config) when is_list(Config) -> ?TC_TRY(register_agent2, Pre, Case, Post). do_register_agent2([ManagerNode], Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -1654,27 +1714,27 @@ do_register_agent2([ManagerNode], Config) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("load snmp application"), + ?IPRINT("load snmp application"), ?line ok = load_snmp(ManagerNode), - p("set manager env for the snmp application"), + ?IPRINT("set manager env for the snmp application"), ?line ok = set_mgr_env(ManagerNode, Opts), - p("starting snmp application (with only manager)"), + ?IPRINT("starting snmp application (with only manager)"), ?line ok = start_snmp(ManagerNode), - p("started"), + ?IPRINT("started"), ?SLEEP(1000), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("register user(s) user_alfa & user_beta"), + ?IPRINT("register user(s) user_alfa & user_beta"), ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []), ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("register agent(s)"), + ?IPRINT("register agent(s)"), TargetName1 = "agent1", ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1, [{address, LocalHost}, @@ -1696,71 +1756,71 @@ do_register_agent2([ManagerNode], Config) -> {port, 5004}, {engine_id, "agentEngineId-4"}]), - p("verify all agent(s): expect 4"), + ?IPRINT("verify all agent(s): expect 4"), case mgr_which_agents(ManagerNode) of Agents1 when length(Agents1) =:= 4 -> - p("all agents: ~p~n", [Agents1]), + ?IPRINT("all agents: ~p~n", [Agents1]), ok; Agents1 -> ?FAIL({agent_registration_failure, Agents1}) end, - p("verify user_alfa agent(s)"), + ?IPRINT("verify user_alfa agent(s)"), case mgr_which_agents(ManagerNode, user_alfa) of Agents2 when length(Agents2) =:= 2 -> - p("calvin agents: ~p~n", [Agents2]), + ?IPRINT("calvin agents: ~p~n", [Agents2]), ok; Agents2 -> ?FAIL({agent_registration_failure, Agents2}) end, - p("verify user_beta agent(s)"), + ?IPRINT("verify user_beta agent(s)"), case mgr_which_agents(ManagerNode, user_beta) of Agents3 when length(Agents3) =:= 2 -> - p("hobbe agents: ~p~n", [Agents3]), + ?IPRINT("hobbe agents: ~p~n", [Agents3]), ok; Agents3 -> ?FAIL({agent_registration_failure, Agents3}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("unregister user user_alfa"), + ?IPRINT("unregister user user_alfa"), ?line ok = mgr_unregister_user(ManagerNode, user_alfa), - p("verify all agent(s): expect 2"), + ?IPRINT("verify all agent(s): expect 2"), case mgr_which_agents(ManagerNode) of Agents4 when length(Agents4) =:= 2 -> - p("all agents: ~p~n", [Agents4]), + ?IPRINT("all agents: ~p~n", [Agents4]), ok; Agents4 -> ?FAIL({agent_unregistration_failure, Agents4}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("unregister user_beta agents"), + ?IPRINT("unregister user_beta agents"), ?line ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName3), ?line ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName4), - p("verify all agent(s): expect 0"), + ?IPRINT("verify all agent(s): expect 0"), case mgr_which_agents(ManagerNode) of [] -> ok; Agents5 -> - p("all agents: ~p~n", [Agents5]), + ?IPRINT("all agents: ~p~n", [Agents5]), ?FAIL({agent_unregistration_failure, Agents5}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("unregister user user_beta"), + ?IPRINT("unregister user user_beta"), ?line ok = mgr_unregister_user(ManagerNode, user_beta), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), ?SLEEP(1000), - p("stop snmp application (with only manager)"), + ?IPRINT("stop snmp application (with only manager)"), ?line ok = stop_snmp(ManagerNode), ?SLEEP(1000), @@ -1785,10 +1845,11 @@ register_agent3(Config) when is_list(Config) -> ?TC_TRY(register_agent3, Pre, Case, Post). do_register_agent3([ManagerNode], Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), - ConfDir = ?config(manager_conf_dir, Config), - DbDir = ?config(manager_db_dir, Config), + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), LocalHost = snmp_test_lib:localhost(), @@ -1800,27 +1861,27 @@ do_register_agent3([ManagerNode], Config) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("load snmp application"), + ?IPRINT("load snmp application"), ?line ok = load_snmp(ManagerNode), - p("set manager env for the snmp application"), + ?IPRINT("set manager env for the snmp application"), ?line ok = set_mgr_env(ManagerNode, Opts), - p("starting snmp application (with only manager)"), + ?IPRINT("starting snmp application (with only manager)"), ?line ok = start_snmp(ManagerNode), - p("started"), + ?IPRINT("started"), ?SLEEP(1000), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("register user(s) user_alfa & user_beta"), + ?IPRINT("register user(s) user_alfa & user_beta"), ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []), ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("register agent(s)"), + ?IPRINT("register agent(s)"), TargetName1 = "agent2", ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1, [{tdomain, transportDomainUdpIpv4}, @@ -1840,7 +1901,7 @@ do_register_agent3([ManagerNode], Config) -> {address, LocalHost}, {port, 5003}, {engine_id, "agentEngineId-3"}]), - p("Expected registration failure: ~p", [Reason4]), + ?IPRINT("Expected registration failure: ~p", [Reason4]), TargetName4 = "agent5", ?line {error, {unknown_domain, _} = Reason5} = mgr_register_agent(ManagerNode, user_beta, TargetName4, @@ -1848,69 +1909,69 @@ do_register_agent3([ManagerNode], Config) -> {address, LocalHost}, {port, 5004}, {engine_id, "agentEngineId-4"}]), - p("Expected registration failure: ~p", [Reason5]), + ?IPRINT("Expected registration failure: ~p", [Reason5]), - p("verify all agent(s): expect 2"), + ?IPRINT("verify all agent(s): expect 2"), case mgr_which_agents(ManagerNode) of Agents1 when length(Agents1) =:= 2 -> - p("all agents: ~p~n", [Agents1]), + ?IPRINT("all agents: ~p~n", [Agents1]), ok; Agents1 -> ?FAIL({agent_registration_failure, Agents1}) end, - p("verify user_alfa agent(s)"), + ?IPRINT("verify user_alfa agent(s)"), case mgr_which_agents(ManagerNode, user_alfa) of Agents2 when length(Agents2) =:= 2 -> - p("calvin agents: ~p~n", [Agents2]), + ?IPRINT("calvin agents: ~p~n", [Agents2]), ok; Agents2 -> ?FAIL({agent_registration_failure, Agents2}) end, - p("verify user_beta agent(s)"), + ?IPRINT("verify user_beta agent(s)"), case mgr_which_agents(ManagerNode, user_beta) of Agents3 when length(Agents3) =:= 0 -> - p("hobbe agents: ~p~n", [Agents3]), + ?IPRINT("hobbe agents: ~p~n", [Agents3]), ok; Agents3 -> ?FAIL({agent_registration_failure, Agents3}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("unregister user user_alfa"), + ?IPRINT("unregister user user_alfa"), ?line ok = mgr_unregister_user(ManagerNode, user_alfa), - p("verify all agent(s): expect 0"), + ?IPRINT("verify all agent(s): expect 0"), case mgr_which_agents(ManagerNode) of Agents4 when length(Agents4) =:= 0 -> - p("all agents: ~p~n", [Agents4]), + ?IPRINT("all agents: ~p~n", [Agents4]), ok; Agents4 -> ?FAIL({agent_unregistration_failure, Agents4}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("verify all agent(s): expect 0"), + ?IPRINT("verify all agent(s): expect 0"), case mgr_which_agents(ManagerNode) of [] -> ok; Agents5 -> - p("all agents: ~p~n", [Agents5]), + ?EPRINT("all agents: ~p~n", [Agents5]), ?FAIL({agent_unregistration_failure, Agents5}) end, - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), - p("unregister user user_beta"), + ?IPRINT("unregister user user_beta"), ?line ok = mgr_unregister_user(ManagerNode, user_beta), - p("manager info: ~p~n", [mgr_info(ManagerNode)]), + ?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]), ?SLEEP(1000), - p("stop snmp application (with only manager)"), + ?IPRINT("stop snmp application (with only manager)"), ?line ok = stop_snmp(ManagerNode), ?SLEEP(1000), @@ -1928,7 +1989,8 @@ simple_sync_get2(Config) when is_list(Config) -> fun() -> do_simple_sync_get2(Config) end). do_simple_sync_get2(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Get = fun(Node, TargetName, Oids) -> mgr_user_sync_get(Node, TargetName, Oids) end, @@ -1938,16 +2000,17 @@ do_simple_sync_get2(Config) -> Res. do_simple_sync_get2(Config, Get, PostVerify) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Node = ?config(manager_node, Config), TargetName = ?config(manager_agent_target_name, Config), - p("issue get-request without loading the mib"), + ?IPRINT("issue get-request without loading the mib"), Oids1 = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance], ?line ok = do_simple_sync_get2(Node, TargetName, Oids1, Get, PostVerify), - p("issue get-request after first loading the mibs"), + ?IPRINT("issue get-request after first loading the mibs"), ?line ok = mgr_user_load_mib(Node, std_mib()), Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], ?line ok = do_simple_sync_get2(Node, TargetName, Oids2, Get, PostVerify), @@ -1969,17 +2032,19 @@ do_simple_sync_get2(Node, TargetName, Oids, Get, PostVerify) value = SysDescr}, #varbind{oid = ?sysUpTime_instance, value = SysUpTime}]} -> - p("expected result from get: " - "~n SysObjectID: ~p" - "~n SysDescr: ~s" - "~n SysUpTime: ~w", - [SysObjectID, SysDescr, SysUpTime]), + ?IPRINT("expected result from get: " + "~n SysObjectID: ~p" + "~n SysDescr: ~s" + "~n SysUpTime: ~w", + [SysObjectID, SysDescr, SysUpTime]), PostVerify(); {noError, 0, Vbs} -> - p("unexpected varbinds: ~n~p", [Vbs]), + ?EPRINT("unexpected varbinds: " + "~n ~p", [Vbs]), {error, {unexpected_vbs, Vbs}}; Else -> - p("unexpected reply: ~n~p", [Else]), + ?EPRINT("unexpected reply: " + "~n ~p", [Else]), {error, {unexpected_response, Else}} end, ok. @@ -1995,7 +2060,8 @@ simple_sync_get3(Config) when is_list(Config) -> fun() -> do_simple_sync_get3(Config) end). do_simple_sync_get3(Config) -> - p("starting with Config: ~n~p", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Self = self(), Msg = simple_sync_get3, Fun = fun() -> Self ! Msg end, @@ -2024,7 +2090,7 @@ do_simple_sync_get3(Config) -> %%====================================================================== sag_verify({noError, 0, _Vbs}, any) -> - p("verified [any]"), + ?IPRINT("verified [any]"), ok; sag_verify({noError, 0, Vbs}, Exp) -> ?DBG("verified first stage ok: " @@ -2042,13 +2108,13 @@ sag_verify_vbs(Vbs, []) -> sag_verify_vbs([], Exp) -> {error, {expected_vbs, Exp}}; sag_verify_vbs([#varbind{oid = Oid}|Vbs], [any|Exp]) -> - p("verified [any] oid ~w", [Oid]), + ?IPRINT("verified [any] oid ~w", [Oid]), sag_verify_vbs(Vbs, Exp); sag_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [Oid|Exp]) -> - p("verified oid ~w [~p]", [Oid, Value]), + ?IPRINT("verified oid ~w [~p]", [Oid, Value]), sag_verify_vbs(Vbs, Exp); sag_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [{Oid,Value}|Exp]) -> - p("verified oid ~w and ~p", [Oid, Value]), + ?IPRINT("verified oid ~w and ~p", [Oid, Value]), sag_verify_vbs(Vbs, Exp); sag_verify_vbs([Vb|_], [E|_]) -> {error, {unexpected_vb, Vb, E}}. @@ -2064,7 +2130,8 @@ simple_async_get2(Config) when is_list(Config) -> fun() -> do_simple_async_get2(Config) end). do_simple_async_get2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), TargetName = ?config(manager_agent_target_name, Config), @@ -2123,13 +2190,17 @@ do_simple_async_sync_get2(MgrInfo, AgentInfo, Get, PostVerify) end} ], - p("manager info when starting test: ~n~p", [MgrInfo()]), - p("agent info when starting test: ~n~p", [AgentInfo()]), + ?IPRINT("manager info when starting test: " + "~n ~p", [MgrInfo()]), + ?IPRINT("agent info when starting test: " + "~n ~p", [AgentInfo()]), ?line ok = async_exec(Requests, []), - p("manager info when ending test: ~n~p", [MgrInfo()]), - p("agent info when ending test: ~n~p", [AgentInfo()]), + ?IPRINT("manager info when ending test: " + "~n ~p", [MgrInfo()]), + ?IPRINT("agent info when ending test: " + "~n ~p", [AgentInfo()]), ok. @@ -2147,7 +2218,8 @@ simple_async_get3(Config) when is_list(Config) -> fun() -> do_simple_async_get3(Config) end). do_simple_async_get3(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), TargetName = ?config(manager_agent_target_name, Config), @@ -2215,7 +2287,8 @@ simple_sync_get_next2(Config) when is_list(Config) -> fun() -> do_simple_sync_get_next2(Config) end). do_simple_sync_get_next2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), GetNext = fun(Node, TargetName, Oids) -> mgr_user_sync_get_next(Node, TargetName, Oids) @@ -2318,7 +2391,7 @@ do_simple_sync_get_next2(Config, GetNext, PostVerify) do_simple_get_next(N, Node, TargetName, Oids, Verify, GetNext, PostVerify) -> - p("issue get-next command ~w", [N]), + ?IPRINT("issue get-next command ~w", [N]), case GetNext(Node, TargetName, Oids) of {ok, Reply, _Rem} -> ?DBG("get-next ok:" @@ -2340,7 +2413,8 @@ simple_sync_get_next3(suite) -> []; simple_sync_get_next3(Config) when is_list(Config) -> process_flag(trap_exit, true), put(tname, ssgn3), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Self = self(), Msg = simple_sync_get_next3, Fun = fun() -> Self ! Msg end, @@ -2370,7 +2444,8 @@ simple_async_get_next2(Config) when is_list(Config) -> fun() -> do_simple_async_get_next2(Config) end). do_simple_async_get_next2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2457,13 +2532,17 @@ do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify) end} ], - p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when starting test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when starting test: " + "~n ~p", [agent_info(AgentNode)]), ?line ok = async_exec(Requests, []), - p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when ending test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when ending test: " + "~n ~p", [agent_info(AgentNode)]), ok. @@ -2501,7 +2580,8 @@ simple_async_get_next3(Case, Config) when is_list(Config) -> do_simple_async_get_next3(Config) -> %% process_flag(trap_exit, true), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2559,7 +2639,8 @@ simple_sync_set2(Config) when is_list(Config) -> fun() -> do_simple_sync_set2(Config) end). do_simple_sync_set2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Set = fun(Node, TargetName, VAVs) -> mgr_user_sync_set(Node, TargetName, VAVs) @@ -2576,7 +2657,7 @@ do_simple_sync_set2(Config, Set, PostVerify) Node = ?config(manager_node, Config), TargetName = ?config(manager_agent_target_name, Config), - p("issue set-request without loading the mib"), + ?IPRINT("issue set-request without loading the mib"), Val11 = "Arne Anka", Val12 = "Stockholm", VAVs1 = [ @@ -2585,7 +2666,7 @@ do_simple_sync_set2(Config, Set, PostVerify) ], ?line ok = do_simple_set2(Node, TargetName, VAVs1, Set, PostVerify), - p("issue set-request after first loading the mibs"), + ?IPRINT("issue set-request after first loading the mibs"), ?line ok = mgr_user_load_mib(Node, std_mib()), Val21 = "Sune Anka", Val22 = "Gothenburg", @@ -2615,7 +2696,8 @@ do_simple_set2(Node, TargetName, VAVs, Set, PostVerify) -> {noError, 0, Vbs} -> {error, {unexpected_vbs, Vbs}}; Else -> - p("unexpected reply: ~n~p", [Else]), + ?EPRINT("unexpected reply: " + "~n ~p", [Else]), {error, {unexpected_response, Else}} end, ok. @@ -2631,7 +2713,8 @@ simple_sync_set3(Config) when is_list(Config) -> fun() -> do_simple_sync_set3(Config) end). do_simple_sync_set3(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p", [Config]), Self = self(), Msg = simple_sync_set3, @@ -2655,7 +2738,7 @@ do_simple_sync_set3(Config) -> %%====================================================================== sas_verify({noError, 0, _Vbs}, any) -> - p("verified [any]"), + ?IPRINT("verified [any]"), ok; sas_verify({noError, 0, Vbs}, Expected) -> ?DBG("verified stage 1: " @@ -2672,13 +2755,13 @@ sas_verify_vbs(Vbs, []) -> sas_verify_vbs([], Exp) -> {error, {expected_vbs, Exp}}; sas_verify_vbs([#varbind{oid = Oid}|Vbs], [any|Exp]) -> - p("verified [any] oid ~w", [Oid]), + ?IPRINT("verified [any] oid ~w", [Oid]), sas_verify_vbs(Vbs, Exp); sas_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [Oid|Exp]) -> - p("verified oid ~w [~p]", [Oid, Value]), + ?IPRINT("verified oid ~w [~p]", [Oid, Value]), sas_verify_vbs(Vbs, Exp); sas_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [{Oid,Value}|Exp]) -> - p("verified oid ~w and ~p", [Oid, Value]), + ?IPRINT("verified oid ~w and ~p", [Oid, Value]), sas_verify_vbs(Vbs, Exp); sas_verify_vbs([Vb|_], [E|_]) -> {error, {unexpected_vb, Vb, E}}. @@ -2694,7 +2777,9 @@ simple_async_set2(Config) when is_list(Config) -> fun() -> do_simple_async_set2(Config) end). do_simple_async_set2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2744,13 +2829,17 @@ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify) -> end} ], - p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when starting test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when starting test: " + "~n ~p", [agent_info(AgentNode)]), ?line ok = async_exec(Requests, []), - p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when ending test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when ending test: " + "~n ~p", [agent_info(AgentNode)]), ok. @@ -2784,7 +2873,8 @@ simple_async_set3(Case, Config) -> fun() -> do_simple_async_set3(Config) end). do_simple_async_set3(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2867,7 +2957,8 @@ simple_sync_get_bulk2(Config) when is_list(Config) -> fun() -> do_simple_sync_get_bulk2(Config) end). do_simple_sync_get_bulk2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2982,7 +3073,7 @@ do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify) -> %% -- 11 -- ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), - p("TCnt2: ~p", [TCnt2]), + ?IPRINT("TCnt2: ~p", [TCnt2]), VF11 = fun(X) -> verify_ssgb_reply2(X, [{fl([TCnt2,2]), 100}, @@ -3001,7 +3092,7 @@ do_simple_get_bulk2(N, when is_function(Verify, 1) andalso is_function(GetBulk, 3) andalso is_function(PostVerify) -> - p("issue get-bulk command ~w", [N]), + ?IPRINT("issue get-bulk command ~w", [N]), case GetBulk(NonRep, MaxRep, Oids) of {ok, Reply, _Rem} -> ?DBG("get-bulk ok:" @@ -3025,7 +3116,8 @@ simple_sync_get_bulk3(Config) when is_list(Config) -> fun() -> do_simple_sync_get_bulk3(Config) end). do_simple_sync_get_bulk3(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3064,7 +3156,8 @@ simple_async_get_bulk2(Config) when is_list(Config) -> fun() -> do_simple_async_get_bulk2(Config) end). do_simple_async_get_bulk2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~p ~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3196,13 +3289,17 @@ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify) -> VF10} ], - p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when starting test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when starting test: " + "~n ~p", [agent_info(AgentNode)]), ?line ok = async_exec(Requests, []), - p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when ending test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when ending test: " + "~n ~p", [agent_info(AgentNode)]), ok. @@ -3226,7 +3323,8 @@ simple_async_get_bulk3(Case, Config) -> do_simple_async_get_bulk3(Config) -> process_flag(trap_exit, true), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3292,7 +3390,9 @@ misc_async2(Config) when is_list(Config) -> fun() -> do_misc_async2(Config) end). do_misc_async2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3461,13 +3561,17 @@ do_misc_async2(Config) -> end} ], - p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when starting test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when starting test: " + "~n ~p", [agent_info(AgentNode)]), ?line ok = async_exec(Requests, []), - p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), - p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info when ending test: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info when ending test: " + "~n ~p", [agent_info(AgentNode)]), display_log(Config), ok. @@ -3493,45 +3597,47 @@ collect_traps(0, TrapInfo) -> collect_traps(N, Acc) -> receive {async_event, _From, {trap, TrapInfo}} -> - p("collect_traps -> received trap: ~n ~p", [TrapInfo]), + ?IPRINT("collect_traps -> received trap: " + "~n ~p", [TrapInfo]), collect_traps(N-1, [TrapInfo|Acc]) after 10000 -> - p("collect_traps -> still awaiting ~w trap(s) - giving up", [N]), + ?WPRINT("collect_traps -> still awaiting ~w trap(s) - giving up", [N]), Acc end. verify_traps([], []) -> - p("verify_traps -> done"), + ?IPRINT("verify_traps -> done"), ok; verify_traps([], Verifiers) -> - p("verify_traps -> done when ~w verifiers remain", [length(Verifiers)]), + ?IPRINT("verify_traps -> done when ~w verifiers remain", [length(Verifiers)]), {error, {failed_verify, [Id || {Id, _} <- Verifiers]}}; verify_traps([Trap|Traps], Verifiers0) -> - p("verify_traps -> entry"), + ?IPRINT("verify_traps -> entry"), case verify_trap(Trap, Verifiers0) of {ok, Id} -> - p("verify_traps -> trap verified: ~p", [Id]), + ?IPRINT("verify_traps -> trap verified: ~p", [Id]), Verifiers = lists:keydelete(Id, 1, Verifiers0), verify_traps(Traps, Verifiers); error -> - p("verify_traps -> failed verifying trap: ~n ~p", [Trap]), + ?EPRINT("verify_traps -> failed verifying trap: " + "~n ~p", [Trap]), {error, {failed_verifying_trap, Trap}} end. verify_trap(Trap, []) -> - p("verify_trap -> could not verify trap:" - "~n Trap: ~p", [Trap]), + ?EPRINT("verify_trap -> could not verify trap:" + "~n Trap: ~p", [Trap]), error; verify_trap(Trap, [{Id, Verifier}|Verifiers]) -> - p("verify_trap -> entry with" - "~n Id: ~p" - "~n Trap: ~p", [Id, Trap]), + ?IPRINT("verify_trap -> entry with" + "~n Id: ~p" + "~n Trap: ~p", [Id, Trap]), case Verifier(Trap) of ok -> - p("verify_trap -> verified"), + ?IPRINT("verify_trap -> verified"), {ok, Id}; {error, _} -> - p("verify_trap -> not verified"), + ?NPRINT("verify_trap -> not verified"), verify_trap(Trap, Verifiers) end. @@ -3544,7 +3650,9 @@ trap1(Config) when is_list(Config) -> fun() -> do_trap1(Config) end). do_trap1(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3565,32 +3673,33 @@ do_trap1(Config) -> fun(Ent, Gen, Spec, ExpVBs, Trap) -> case Trap of {Ent, Gen, Spec, _Timestamp, VBs} -> - p("trap info as expected"), + ?IPRINT("trap info as expected"), case (catch validate_vbs(MgrNode, ExpVBs, VBs)) of ok -> - p("valid trap"), + ?IPRINT("valid trap"), ok; Error -> - p("invalid trap: ~n Error: ~p", [Error]), + ?EPRINT("invalid trap: " + "~n ~p", [Error]), Error end; {Enteprise, Generic, Spec, Timestamp, VBs} -> - p("unepxected v1 trap info:" - "~n Enteprise: ~p" - "~n Generic: ~p" - "~n Spec: ~p" - "~n Timestamp: ~p" - "~n VBs: ~p", - [Enteprise, Generic, Spec, Timestamp, VBs]), + ?EPRINT("unepxected v1 trap info:" + "~n Enteprise: ~p" + "~n Generic: ~p" + "~n Spec: ~p" + "~n Timestamp: ~p" + "~n VBs: ~p", + [Enteprise, Generic, Spec, Timestamp, VBs]), ExpTrap = {Ent, Gen, Spec, ignore, ExpVBs}, Reason = {unexpected_trap, {ExpTrap, Trap}}, {error, Reason}; {Err, Idx, VBs} -> - p("unexpected trap info: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected trap info: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -3601,24 +3710,25 @@ do_trap1(Config) -> fun(ExpVBs, Trap) -> case Trap of {noError, 0, VBs0} -> - p("trap info as expected: ~n~p", [VBs0]), + ?IPRINT("trap info as expected: " + "~n ~p", [VBs0]), %% The first two are a timestamp and oid [_,_|VBs] = VBs0, case (catch validate_vbs(MgrNode, ExpVBs, VBs)) of ok -> - p("valid trap"), + ?IPRINT("valid trap"), ok; Error -> - p("invalid trap: ~n Error: ~p", - [Error]), + ?EPRINT("invalid trap: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -3629,8 +3739,10 @@ do_trap1(Config) -> %% Collect various info about the manager and the agent Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -3699,7 +3811,9 @@ trap2(Config) when is_list(Config) -> fun() -> do_trap2(Config) end). do_trap2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3720,32 +3834,32 @@ do_trap2(Config) -> fun(Ent, Gen, Spec, ExpVBs, Trap) -> case Trap of {Ent, Gen, Spec, _Timestamp, VBs} -> - p("trap info as expected"), + ?IPRINT("trap info as expected"), case (catch validate_vbs(MgrNode, ExpVBs, VBs)) of ok -> - p("valid trap"), + ?IPRINT("valid trap"), ok; Error -> - p("invalid trap: ~n Error: ~p", [Error]), + ?EPRINT("invalid trap: ~n Error: ~p", [Error]), Error end; {Enteprise, Generic, Spec, Timestamp, VBs} -> - p("unepxected v1 trap info:" - "~n Enteprise: ~p" - "~n Generic: ~p" - "~n Spec: ~p" - "~n Timestamp: ~p" - "~n VBs: ~p", - [Enteprise, Generic, Spec, Timestamp, VBs]), + ?EPRINT("unepxected v1 trap info:" + "~n Enteprise: ~p" + "~n Generic: ~p" + "~n Spec: ~p" + "~n Timestamp: ~p" + "~n VBs: ~p", + [Enteprise, Generic, Spec, Timestamp, VBs]), ExpTrap = {Ent, Gen, Spec, ignore, ExpVBs}, Reason = {unexpected_trap, {ExpTrap, Trap}}, {error, Reason}; {Err, Idx, VBs} -> - p("unexpected trap info: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected trap info: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -3756,24 +3870,24 @@ do_trap2(Config) -> fun(ExpVBs, Trap) -> case Trap of {noError, 0, VBs0} -> - p("trap info as expected: ~n~p", [VBs0]), + ?IPRINT("trap info as expected: ~n~p", [VBs0]), %% The first two are a timestamp and oid [_,_|VBs] = VBs0, case (catch validate_vbs(MgrNode, ExpVBs, VBs)) of ok -> - p("valid trap"), + ?IPRINT("valid trap"), ok; Error -> - p("invalid trap: ~n Error: ~p", - [Error]), + ?EPRINT("invalid trap: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -3783,8 +3897,10 @@ do_trap2(Config) -> %% Collect various info about the manager and the agent Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -3894,7 +4010,9 @@ inform1(Config) when is_list(Config) -> fun() -> do_inform1(Config) end). do_inform1(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -3913,9 +4031,12 @@ do_inform1(Config) -> Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("manager system info: ~n~p", [mgr_sys_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("manager system info: " + "~n ~p", [mgr_sys_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -3929,26 +4050,26 @@ do_inform1(Config) -> fun() -> receive {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> case (catch validate_testTrapv22_vbs(MgrNode, VBs)) of ok -> - p("valid inform"), + ?IPRINT("valid inform"), Pid ! {handle_inform_no_response, From}, ok; Error -> - p("invalid inform: ~n Error: ~p", - [Error]), + ?EPRINT("invalid inform: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -3966,25 +4087,25 @@ do_inform1(Config) -> fun() -> receive {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> case (catch validate_testTrapv22_vbs(MgrNode, VBs)) of ok -> - p("valid inform"), + ?IPRINT("valid inform"), Pid ! {handle_inform_response, From}, ok; Error -> - p("invalid inform: ~n Error: ~p", - [Error]), + ?EPRINT("invalid inform: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -4023,7 +4144,9 @@ inform2(Config) when is_list(Config) -> fun() -> do_inform2(Config) end). do_inform2(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -4043,8 +4166,10 @@ do_inform2(Config) -> Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -4062,7 +4187,7 @@ do_inform2(Config) -> fun() -> receive {snmp_targets, inform2_tag1, Addrs} -> - p("sent inform to ~p", [Addrs]), + ?IPRINT("sent inform to ~p", [Addrs]), ok after 10000 -> receive @@ -4078,26 +4203,26 @@ do_inform2(Config) -> fun() -> receive {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> case (catch validate_testTrapv22_vbs(MgrNode, VBs)) of ok -> - p("valid inform"), + ?IPRINT("valid inform"), Pid ! {handle_inform_no_response, From}, ok; Error -> - p("invalid inform: ~n Error: ~p", - [Error]), + ?IPRINT("invalid inform: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -4115,25 +4240,25 @@ do_inform2(Config) -> fun() -> receive {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> case (catch validate_testTrapv22_vbs(MgrNode, VBs)) of ok -> - p("valid inform"), + ?IPRINT("valid inform"), Pid ! {handle_inform_response, From}, ok; Error -> - p("invalid inform: ~n Error: ~p", - [Error]), + ?EPRINT("invalid inform: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -4151,14 +4276,14 @@ do_inform2(Config) -> fun() -> receive {snmp_notification, inform2_tag1, {got_response, Addr}} -> - p("received expected \"got response\" notification " - "from: " - "~n ~p", [Addr]), + ?IPRINT("received expected \"got response\" notification " + "from: " + "~n ~p", [Addr]), ok; {snmp_notification, inform2_tag1, {no_response, Addr}} -> - e("Received unexpected \"no response\" " - "notification from: " - "~n ~p", [Addr]), + ?EPRINT("Received unexpected \"no response\" " + "notification from: " + "~n ~p", [Addr]), {error, no_response} after 10000 -> receive @@ -4197,7 +4322,8 @@ inform3(Config) when is_list(Config) -> fun() -> do_inform3(Config) end). do_inform3(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -4215,8 +4341,10 @@ do_inform3(Config) -> Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -4234,7 +4362,7 @@ do_inform3(Config) -> fun() -> receive {snmp_targets, inform3_tag1, [_Addr]} -> - p("received inform-sent acknowledgement", []), + ?IPRINT("received inform-sent ack"), ok after 10000 -> receive @@ -4250,26 +4378,25 @@ do_inform3(Config) -> fun() -> receive {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> case (catch validate_testTrapv22_vbs(MgrNode, VBs)) of ok -> - p("valid inform"), - Pid ! {handle_inform_no_response, - From}, + ?IPRINT("valid inform"), + Pid ! {handle_inform_no_response, From}, ok; Error -> - p("invalid inform: ~n Error: ~p", - [Error]), + ?EPRINT("invalid inform: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -4287,15 +4414,15 @@ do_inform3(Config) -> fun() -> receive {snmp_notification, inform3_tag1, {no_response, Addr}} -> - p("received expected \"no response\" notification " - "from: " - "~n ~p", [Addr]), + ?IPRINT("received expected \"no response\" notification " + "from: " + "~n ~p", [Addr]), ok; {snmp_notification, inform3_tag1, {got_response, Addr}} -> - e("Received unexpected \"got response\" " - "notification from: " - "~n ~p", - [Addr]), + ?EPRINT("Received unexpected \"got response\" " + "notification from: " + "~n ~p", + [Addr]), {error, {got_response, Addr}} after 120000 -> receive @@ -4335,7 +4462,8 @@ inform4(Config) when is_list(Config) -> fun() -> do_inform4(Config) end). do_inform4(Config) -> - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~n ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -4353,8 +4481,10 @@ do_inform4(Config) -> Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -4368,13 +4498,13 @@ do_inform4(Config) -> fun() -> receive {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> case (catch validate_testTrapv22_vbs(MgrNode, VBs)) of ok -> - p("valid inform"), + ?IPRINT("valid inform"), %% Actually, as we have %% configured the manager in %% this test case (irb = auto) @@ -4382,15 +4512,15 @@ do_inform4(Config) -> Pid ! {handle_inform_response, From}, ok; Error -> - p("invalid inform: ~n Error: ~p", - [Error]), + ?EPRINT("invalid inform: " + "~n ~p", [Error]), Error end; {Err, Idx, VBs} -> - p("unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end @@ -4409,11 +4539,11 @@ do_inform4(Config) -> %% fun() -> %% receive %% {async_event, _ReqId, {error, Reason}} -> -%% p("received error"), +%% ?IPRINT("received error"), %% case Reason of %% {failed_processing_message, %% {securityError, usmStatsUnknownEngineIDs}} -> -%% p("expected error"), +%% ?IPRINT("expected error"), %% ok; %% _ -> %% p("unexpected error: " @@ -4469,7 +4599,8 @@ inform_swarm(Case, Config) -> do_inform_swarm(Config) -> %% process_flag(trap_exit, true), - p("starting with Config: ~p~n", [Config]), + ?IPRINT("starting with Config: " + "~p ~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -4498,7 +4629,7 @@ do_inform_swarm(Config) -> Seqs = lists:seq(1, NumInforms), lists:foreach( fun(N) -> - p("send notification ~w", [N]), + ?IPRINT("send notification ~w", [N]), agent_send_notif(AgentNode, testTrapv22, {{inform2_tag1, N}, Collector}, @@ -4509,11 +4640,11 @@ do_inform_swarm(Config) -> if N rem 100 == 0 -> Sleep = 1000, - p("sleep ~w [~w]", [Sleep, N]), + ?IPRINT("sleep ~w [~w]", [Sleep, N]), ?SLEEP(Sleep); N rem 10 == 0 -> Sleep = 100, - p("sleep ~w [~w]", [Sleep, N]), + ?IPRINT("sleep ~w [~w]", [Sleep, N]), ?SLEEP(Sleep); true -> ok @@ -4525,8 +4656,10 @@ do_inform_swarm(Config) -> Cmd1 = fun() -> - p("manager info: ~n~p", [mgr_info(MgrNode)]), - p("agent info: ~n~p", [agent_info(AgentNode)]), + ?IPRINT("manager info: " + "~n ~p", [mgr_info(MgrNode)]), + ?IPRINT("agent info: " + "~n ~p", [agent_info(AgentNode)]), ok end, @@ -4555,7 +4688,7 @@ do_inform_swarm(Config) -> inform_swarm_collector(N) -> - inform_swarm_collector(N, 0, 0, 0, 10000). + inform_swarm_collector(N, 0, 0, 0, ?SECS(60)). %% Note that we need to deal with re-transmissions! %% That is, the agent did not receive the ack in time, @@ -4571,60 +4704,65 @@ inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, _) when ((N == SentAckCnt) and (N == RespCnt) and (N =< RecvCnt)) -> - p("inform_swarm_collector -> done when" - "~n N: ~w" - "~n SentAckCnt: ~w" - "~n RecvCnt: ~w" - "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]), + ?IPRINT("inform_swarm_collector -> done when" + "~n N: ~w" + "~n SentAckCnt: ~w" + "~n RecvCnt: ~w" + "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]), ok; inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, Timeout) -> - p("inform_swarm_collector -> entry with" - "~n N: ~w" - "~n SentAckCnt: ~w" - "~n RecvCnt: ~w" - "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]), + %% ?IPRINT("inform_swarm_collector -> entry with" + %% "~n N: ~w" + %% "~n SentAckCnt: ~w" + %% "~n RecvCnt: ~w" + %% "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]), receive {snmp_targets, {inform2_tag1, Id}, [_Addr]} -> - p("received inform-sent acknowledgement for ~w", [Id]), + ?IPRINT("received inform-sent acknowledgement for ~w", [Id]), inform_swarm_collector(N, SentAckCnt+1, RecvCnt, RespCnt, Timeout); %% The manager has received the actual inform {async_event, From, {inform, Pid, Inform}} -> - p("received inform"), + ?IPRINT("received inform"), case Inform of {noError, 0, VBs} when is_list(VBs) -> Pid ! {handle_inform_response, From}, inform_swarm_collector(N, SentAckCnt, RecvCnt+1, RespCnt, Timeout); {Err, Idx, VBs} -> - e("Unexpected error status: " - "~n Err: ~p" - "~n Idx: ~p" - "~n VBs: ~p", [Err, Idx, VBs]), + ?EPRINT("Unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), Reason = {unexpected_status, {Err, Idx, VBs}}, {error, Reason} end; %% The agent has received ack from the manager {snmp_notification, {inform2_tag1, Id}, {got_response, Addr}} -> - p("received expected \"got response\" for ~w " - "notification from: " - "~n ~p", - [Id, Addr]), + ?IPRINT("received expected \"got response\" for ~w " + "notification from: " + "~n ~p", [Id, Addr]), inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt+1, Timeout); %% The agent did not received ack from the manager in time {snmp_notification, inform2_tag1, {no_response, Addr}} -> - e("Received expected \"no response\" notification " - "from: " - "~n ~p", [Addr]), + ?EPRINT("Received expected \"no response\" notification " + "from: " + "~n ~p", [Addr]), Reason = {no_response, Addr, {N, SentAckCnt, RecvCnt, RespCnt}}, {error, Reason} after Timeout -> %% Give up when we have been dead in the water for Timeout ms + ?EPRINT("timeout when" + "~n N: ~p" + "~n SentAckCnt: ~p" + "~n RecvCnt: ~p" + "~n RespCnt: ~p", + [N, SentAckCnt, RecvCnt, RespCnt]), {error, {timeout, N, SentAckCnt, RecvCnt, RespCnt}} end. @@ -4642,48 +4780,54 @@ report(Config) when is_list(Config) -> otp8015_1(doc) -> ["OTP-8015:1 - testing the new api-function."]; otp8015_1(suite) -> []; otp8015_1(Config) when is_list(Config) -> - ?TC_TRY(otp8015_1, - fun() -> do_otp8015_1(Config) end). + Pre = fun() -> + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, + {dir, ConfDir}, + {db_dir, DbDir}]}], + + ?IPRINT("starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + ok + end, + Case = fun(_) -> do_otp8015_1(Config) end, + Post = fun(_) -> + ?IPRINT("stop manager"), + ok = snmpm:stop(), + ?SLEEP(1000), + ok + end, + ?TC_TRY(otp8015_1, Pre, Case, Post). do_otp8015_1(Config) -> - p("starting with Config: ~p~n", [Config]), - - ConfDir = ?config(manager_conf_dir, Config), - DbDir = ?config(manager_db_dir, Config), - - write_manager_conf(ConfDir), - - Opts = [{server, [{verbosity, trace}]}, - {net_if, [{verbosity, trace}]}, - {note_store, [{verbosity, trace}]}, - {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - - p("starting manager"), - ok = snmpm:start_link(Opts), - - ?SLEEP(1000), + ?IPRINT("starting with Config: " + "~n ~p" + "~n", [Config]), snmpm:load_mib(std_mib()), snmpm:load_mib(test_trap_mib(Config)), - p("manager started, now sleep some"), + ?IPRINT("manager started, now sleep some"), ?SLEEP(1000), - p("loaded mibs: ~p", [snmpm:which_mibs()]), + ?IPRINT("loaded mibs: ~p", [snmpm:which_mibs()]), - p("get some type(s) from the mibs"), + ?IPRINT("get some type(s) from the mibs"), {ok, 'Counter32'} = snmpm:oid_to_type(?snmpOutTraps), - {ok, [IfIndex]} = snmpm:name_to_oid(ifIndex), - {ok, 'INTEGER'} = snmpm:oid_to_type(IfIndex), + {ok, [IfIndex]} = snmpm:name_to_oid(ifIndex), + {ok, 'INTEGER'} = snmpm:oid_to_type(IfIndex), - - p("stop manager"), - ok = snmpm:stop(), - - ?SLEEP(1000), - - p("end"), + ?IPRINT("end"), ok. @@ -4704,27 +4848,30 @@ do_otp8395_1(Config) -> %%====================================================================== async_exec([], Acc) -> - p("all async request's sent => now await reponses"), + ?IPRINT("all async request's sent => now await responses"), async_verify(async_collector(Acc, [])); async_exec([{Id, Data, Exec, Ver}|Reqs], Acc) -> - p("issue async request ~w", [Id]), + ?IPRINT("issue async request ~w", [Id]), ?line {ok, ReqId} = Exec(Data), async_exec(Reqs, [{ReqId, Id, Ver}|Acc]). async_collector([], Acc) -> - p("received replies for all requests - now sort"), + ?IPRINT("received replies for all requests - now sort"), lists:keysort(1, Acc); async_collector(Expected, Acc) -> receive {async_event, ReqId, Reply} -> - p("received async event with request-id ~w", [ReqId]), + ?IPRINT("received async event with request-id ~w", [ReqId]), case lists:keysearch(ReqId, 1, Expected) of {value, {_, Id, Ver}} -> - p("event was for request ~w", [Id]), + ?IPRINT("event was for request ~w", [Id]), Expected2 = lists:keydelete(ReqId, 1, Expected), async_collector(Expected2, [{Id, Ver, Reply}|Acc]); false -> % Duplicate reply? + ?EPRINT("unexpected async event: " + "~n ReqId: ~p" + "~n Reply: ~p", [ReqId, Reply]), ?FAIL({unexpected_async_event, ReqId, Reply}) end after 10000 -> @@ -4734,7 +4881,7 @@ async_collector(Expected, Acc) -> async_verify([]) -> ok; async_verify([{Id, Verify, Reply}|Replies]) -> - p("verify reply ~w", [Id]), + ?IPRINT("verify reply ~w", [Id]), Verify(Reply), async_verify(Replies). @@ -4791,17 +4938,19 @@ purify_oid(Node, Oid) -> command_handler([]) -> ok; command_handler([{No, Desc, Cmd}|Cmds]) -> - p("command_handler -> command ~w: " - "~n ~s", [No, Desc]), + ?IPRINT("command_handler -> command ~w: " + "~n ~s", [No, Desc]), case (catch Cmd()) of ok -> - p("command_handler -> ~w: ok",[No]), + ?IPRINT("command_handler -> ~w: ok", [No]), command_handler(Cmds); {error, Reason} -> - e("Command_handler -> ~w error: ~n~p",[No, Reason]), + ?EPRINT("Command_handler -> ~w error: " + "~n ~p", [No, Reason]), ?line ?FAIL({command_failed, No, Reason}); Error -> - e("Command_handler -> ~w unexpected: ~n~p",[No, Error]), + ?EPRINT("Command_handler -> ~w unexpected: " + "~n ~p", [No, Error]), ?line ?FAIL({unexpected_command_result, No, Error}) end. @@ -4810,9 +4959,9 @@ command_handler([{No, Desc, Cmd}|Cmds]) -> init_manager(AutoInform, Config) -> - ?LOG("init_manager -> entry with" - "~n AutoInform: ~p" - "~n Config: ~p", [AutoInform, Config]), + ?IPRINT("init_manager -> entry with" + "~n AutoInform: ~p" + "~n Config: ~p", [AutoInform, Config]), %% -- %% Start node @@ -4852,11 +5001,18 @@ init_manager(AutoInform, Config) -> start_manager(Node, Vsns, Conf) end catch + C:{suite_failed, Reason, _M, _L} = E:S when (C =:= exit) -> + ?EPRINT("Failure during manager start (suite-failed):" + "~n Reason: ~p" + "~n StackTrace: ~p", [Reason, S]), + %% And now, *try* to cleanup + (catch stop_node(Node)), + erlang:raise(C, E, S); C:E:S -> - p("Failure during manager start: " - "~n Error Class: ~p" - "~n Error: ~p" - "~n StackTrace: ~p", [C, E, S]), + ?EPRINT("Failure during manager start: " + "~n Error Class: ~p" + "~n Error: ~p" + "~n StackTrace: ~p", [C, E, S]), %% And now, *try* to cleanup (catch stop_node(Node)), ?FAIL({failed_starting_manager, C, E, S}) @@ -4867,19 +5023,19 @@ fin_manager(Config) -> StopMgrRes = stop_manager(Node), StopCryptoRes = fin_crypto(Node), StopNode = stop_node(Node), - p("fin_manager -> stop apps and (mgr node ~p) node results: " - "~n SNMP Mgr: ~p" - "~n Crypto: ~p" - "~n Node: ~p", - [Node, StopMgrRes, StopCryptoRes, StopNode]), + ?IPRINT("fin_manager -> stop apps and (mgr node ~p) node results: " + "~n SNMP Mgr: ~p" + "~n Crypto: ~p" + "~n Node: ~p", + [Node, StopMgrRes, StopCryptoRes, StopNode]), Config. %% -- Misc agent functions -- init_agent(Config) -> - ?LOG("init_agent -> entry with" - "~n Config: ~p", [Config]), + ?IPRINT("init_agent -> entry with" + "~n Config: ~p", [Config]), %% -- %% Retrieve some dir's @@ -4933,11 +5089,18 @@ init_agent(Config) -> start_agent(Node, Vsns, Conf) end catch + C:{suite_failed, Reason, _M, _L} = E:S when (C =:= exit) -> + ?EPRINT("Failure during agent start (suite-failed):" + "~n Reason: ~p" + "~n StackTrace: ~p", [Reason, S]), + %% And now, *try* to cleanup + (catch stop_node(Node)), + erlang:raise(C, E, S); C:E:S -> - p("Failure during agent start: " - "~n Error Class: ~p" - "~n Error: ~p" - "~n StackTrace: ~p", [C, E, S]), + ?EPRINT("Failure during agent start: " + "~n Error Class: ~p" + "~n Error: ~p" + "~n StackTrace: ~p", [C, E, S]), %% And now, *try* to cleanup (catch stop_node(Node)), ?FAIL({failed_starting_agent, C, E, S}) @@ -4945,17 +5108,17 @@ init_agent(Config) -> fin_agent(Config) -> - Node = ?config(agent_node, Config), + Node = ?config(agent_node, Config), StopAgentRes = stop_agent(Node), StopCryptoRes = fin_crypto(Node), StopMnesiaRes = fin_mnesia(Node), StopNode = stop_node(Node), - p("fin_agent -> stop apps and (agent node ~p) node results: " - "~n SNMP Agent: ~p" - "~n Crypto: ~p" - "~n Mnesia: ~p" - "~n Node: ~p", - [Node, StopAgentRes, StopCryptoRes, StopMnesiaRes, StopNode]), + ?IPRINT("fin_agent -> stop apps and (agent node ~p) node results: " + "~n SNMP Agent: ~p" + "~n Crypto: ~p" + "~n Mnesia: ~p" + "~n Node: ~p", + [Node, StopAgentRes, StopCryptoRes, StopMnesiaRes, StopNode]), Config. init_mnesia(Node, Dir, MnesiaDebug) @@ -5021,8 +5184,8 @@ load_app(Node, App) -> ({error, {already_loaded, LoadedApp}}) when (LoadedApp =:= App) -> ok; ({error, Reason}) -> - p("failed loading app ~w on ~p: " - "~n ~p", [App, Node, Reason]), + ?EPRINT("failed loading app ~w on ~p: " + "~n ~p", [App, Node, Reason]), ?FAIL({failed_load, Node, App, Reason}) end, do_load_app(Node, App, VerifySuccess). @@ -5042,8 +5205,8 @@ start_app(Node, App) -> ({error, {already_started, LoadedApp}}) when (LoadedApp =:= App) -> ok; ({error, Reason}) -> - p("failed starting app ~w on ~p: " - "~n ~p", [App, Node, Reason]), + ?EPRINT("failed starting app ~w on ~p: " + "~n Reason: ~p", [App, Node, Reason]), ?FAIL({failed_start, Node, App, Reason}) end, start_app(Node, App, VerifySuccess). @@ -5061,8 +5224,8 @@ stop_app(Node, App) -> ({error, {not_started, LoadedApp}}) when (LoadedApp =:= App) -> ok; ({error, Reason}) -> - p("failed stopping app ~w on ~p: " - "~n ~p", [App, Node, Reason]), + ?EPRINT("failed stopping app ~w on ~p: " + "~n ~p", [App, Node, Reason]), ?FAIL({failed_stop, Node, App, Reason}) end, stop_app(Node, App, VerifySuccess). @@ -5078,11 +5241,11 @@ set_app_env(Node, App, Key, Val) -> VerifySuccess = fun(ok) -> ok; ({error, Reason}) -> - p("failed setting app ~w env on ~p" - "~n Key: ~p" - "~n Val: ~p" - "~n Reason: ~p" - "~n ~p", [App, Node, Key, Val, Reason]), + ?EPRINT("failed setting app ~w env on ~p" + "~n Key: ~p" + "~n Val: ~p" + "~n Reason: ~p", + [App, Node, Key, Val, Reason]), ?FAIL({failed_set_app_env, Node, App, Key, Val, Reason}) end, @@ -5484,12 +5647,13 @@ start_manager(Node, Vsns, Conf0, _Opts) -> ConfigVerbosity = get_opt(manager_config_verbosity, Conf0, trace), NoteStoreVerbosity = get_opt(manager_note_store_verbosity, Conf0, log), - ServerVerbosity = get_opt(manager_server_verbosity, Conf0, trace), NetIfVerbosity = get_opt(manager_net_if_verbosity, Conf0, trace), AtlSeqNo = get_opt(manager_atl_seqno, Conf0, false), + ServerVerbosity = get_opt(manager_server_verbosity, Conf0, trace), CBP = get_opt(manager_server_cbproxy, Conf0, temporary), + NIS = get_opt(manager_server_nis, Conf0, none), NetIfConf = case get_opt(manager_net_if_module, Conf0, no_module) of @@ -5512,12 +5676,22 @@ start_manager(Node, Vsns, Conf0, _Opts) -> {verbosity, ConfigVerbosity}]}, {note_store, [{verbosity, NoteStoreVerbosity}]}, {server, [{verbosity, ServerVerbosity}, - {cbproxy, CBP}]}, + {cbproxy, CBP}, + {netif_sup, NIS}]}, {net_if, NetIfConf}], ?line ok = set_mgr_env(Node, Env), - ?line ok = start_snmp(Node), - + ?line ok = try start_snmp(Node) of + ok -> + ok; + {error, Reason} -> + ?FAIL({failed_start_manager, Reason}) + catch + exit:{suite_failed, {failed_start, _, _, Reason}, _M, _L}:_ -> + ?FAIL({failed_start_manager, Reason}); + C:E:S -> + erlang:raise(C, E, S) + end, Conf0. stop_manager(Node) -> @@ -5573,7 +5747,17 @@ start_agent(Node, Vsns, Conf0, _Opts) -> {multi_threaded, true}], ?line ok = set_agent_env(Node, Env), - ?line ok = start_snmp(Node), + ?line try start_snmp(Node) of + ok -> + ok; + {error, Reason} -> + ?FAIL({failed_start_agent, Reason}) + catch + exit:{suite_failed, {failed_start, _, _, Reason}, _M, _L}:_ -> + ?FAIL({failed_start_agent, Reason}); + C:E:S -> + erlang:raise(C, E, S) + end, Conf0. stop_agent(Node) -> @@ -5637,7 +5821,7 @@ start_node(Name, Retry) -> global:sync(), Node; {error, timeout} -> - e("Failed starting node ~p: timeout", [Name]), + ?EPRINT("Failed starting node ~p: timeout", [Name]), ?line ?FAIL({error_starting_node, Name, timeout}); {error, {already_running, Node}} when (Retry =:= true) -> %% Ouch @@ -5646,24 +5830,24 @@ start_node(Name, Retry) -> %% timeout) but actually succeeded. Regardless, we don't know %% the state of this node, so (try) stop it and then (re-) try %% start again. - e("Failed starting node ~p: Already Running - try stop", [Node]), + ?WPRINT("Failed starting node ~p: Already Running - try stop", [Node]), case ?STOP_NODE(Node) of true -> - p("Successfully stopped old node ~p", [Node]), + ?IPRINT("Successfully stopped old node ~p", [Node]), start_node(Name, false); false -> - e("Failed stop old node ~p", [Node]), + ?EPRINT("Failed stop old node ~p", [Node]), ?line ?FAIL({error_starting_node, Node, Retry, already_running}) end; {error, {already_running, Node}} -> - e("Failed starting node ~p: Already Running", [Node]), + ?EPRINT("Failed starting node ~p: Already Running", [Node]), ?line ?FAIL({error_starting_node, Node, Retry, already_running}); {error, Reason} -> - e("Failed starting node ~p: ~p", [Name, Reason]), + ?EPRINT("Failed starting node ~p: ~p", [Name, Reason]), ?line ?FAIL({error_starting_node, Name, Reason}) catch exit:{suite_failed, Reason} -> - e("(suite) Failed starting node ~p: ~p", [Name, Reason]), + ?EPRINT("(suite) Failed starting node ~p: ~p", [Name, Reason]), ?line ?FAIL({failed_starting_node, Name, Reason}) end. @@ -5842,24 +6026,24 @@ display_log(Config) -> LogDir = Dir, Mibs = [], OutFile = j(LogDir, "snmpm_log.txt"), - p("~n" - "=========================" - " < Audit Trail Log > " - "=========================" - "~n"), + ?IPRINT("~n" + "=========================" + " < Audit Trail Log > " + "=========================" + "~n"), rcall(Node, snmpm, log_to_txt, [LogDir, Mibs, OutFile]), rcall(Node, snmpm, log_to_io, [LogDir, Mibs]), - p("~n" - "=========================" - " < / Audit Trail Log > " - "=========================" - "~n"); + ?IPRINT("~n" + "=========================" + " < / Audit Trail Log > " + "=========================" + "~n"); false -> - p("display_log -> no manager node found"), + ?IPRINT("display_log -> no manager node found"), ok end; false -> - p("display_log -> no manager log dir found"), + ?IPRINT("display_log -> no manager log dir found"), ok end. @@ -5910,35 +6094,5 @@ rcall(Node, Mod, Func, Args) -> %% ------ -%% Time in milli sec -%% t() -> -%% {A,B,C} = os:timestamp(), -%% A*1000000000+B*1000+(C div 1000). - - -%% ------ - -e(F, A) -> - p("<ERROR> " ++ F, A). - -p(F) -> - p(F, []). - -p(F, A) -> - p(get(tname), F, A). - -p(undefined, F, A) -> - io:format("*** [~s] ***" - "~n " ++ F ++ "~n", [formated_timestamp()|A]); -p(TName, F, A) -> - io:format("*** [~s][~w] ***" - "~n " ++ F ++ "~n", [formated_timestamp(),TName|A]). - -formated_timestamp() -> - snmp_test_lib:formated_timestamp(). - -%% p(TName, F, A) -> -%% io:format("~w -> " ++ F ++ "~n", [TName|A]). - ipv6_init(Config) when is_list(Config) -> [{ipfamily, inet6} | Config]. diff --git a/lib/snmp/test/snmp_manager_config_SUITE.erl b/lib/snmp/test/snmp_manager_config_SUITE.erl index b5c1894294..9a7b485a60 100644 --- a/lib/snmp/test/snmp_manager_config_SUITE.erl +++ b/lib/snmp/test/snmp_manager_config_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2019. All Rights Reserved. +%% Copyright Ericsson AB 2004-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ %%---------------------------------------------------------------------- -module(snmp_manager_config_SUITE). + %%---------------------------------------------------------------------- %% Include files %%---------------------------------------------------------------------- @@ -97,6 +98,7 @@ ]). + %%---------------------------------------------------------------------- %% Internal exports %%---------------------------------------------------------------------- @@ -219,24 +221,40 @@ otp_8395_cases() -> otp_8395_4 ]. + init_per_suite(Config0) when is_list(Config0) -> - ?DBG("init_per_suite -> entry with" - "~n Config0: ~p", [Config0]), + ?IPRINT("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), - Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0), + case ?LIB:init_per_suite(Config0) of + {skip, _} = SKIP -> + SKIP; - ?DBG("init_per_suite -> done when" - "~n Config1: ~p", [Config1]), + Config1 -> - Config1. + Config2 = snmp_test_lib:init_suite_top_dir(?MODULE, Config1), -end_per_suite(Config) when is_list(Config) -> + %% We need one on this node also + snmp_test_sys_monitor:start(), - ?DBG("end_per_suite -> entry with" - "~n Config: ~p", [Config]), + ?IPRINT("init_per_suite -> end when" + "~n Config: ~p", [Config2]), - Config. + Config2 + end. + +end_per_suite(Config0) when is_list(Config0) -> + + ?IPRINT("end_per_suite -> entry with" + "~n Config0: ~p", [Config0]), + + snmp_test_sys_monitor:stop(), + Config1 = ?LIB:end_per_suite(Config0), + + ?IPRINT("end_per_suite -> end"), + + Config1. init_per_group(_GroupName, Config) -> @@ -247,11 +265,16 @@ end_per_group(_GroupName, Config) -> init_per_testcase(Case, Config) when is_list(Config) -> - p("init_per_testcase -> Case: ~p", [Case]), + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + snmp_test_global_sys_monitor:reset_events(), + SuiteTopDir = ?config(snmp_suite_top_dir, Config), CaseTopDir = filename:join(SuiteTopDir, atom_to_list(Case)), ?line ok = file:make_dir(CaseTopDir), - p("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]), + + ?IPRINT("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]), MgrTopDir = filename:join(CaseTopDir, "manager/"), ?line ok = file:make_dir(MgrTopDir), MgrConfDir = filename:join(MgrTopDir, "conf/"), @@ -265,15 +288,26 @@ init_per_testcase(Case, Config) when is_list(Config) -> end, MgrLogDir = filename:join(MgrTopDir, "log/"), ?line ok = file:make_dir(MgrLogDir), - [{case_top_dir, CaseTopDir}, - {manager_dir, MgrTopDir}, - {manager_conf_dir, MgrConfDir}, - {manager_db_dir, MgrDbDir}, - {manager_log_dir, MgrLogDir} | Config]. + Config1 = [{case_top_dir, CaseTopDir}, + {manager_dir, MgrTopDir}, + {manager_conf_dir, MgrConfDir}, + {manager_db_dir, MgrDbDir}, + {manager_log_dir, MgrLogDir} | Config], + + ?IPRINT("init_per_testcase -> done when" + "~n Config1: ~p", [Config1]), + Config1. + + +end_per_testcase(_Case, Config) when is_list(Config) -> + + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + ?IPRINT("system events during test: " + "~n ~p", [snmp_test_global_sys_monitor:events()]), -end_per_testcase(Case, Config) when is_list(Config) -> - p("end_per_testcase -> Case: ~p", [Case]), %% The cleanup is removed due to some really discusting NFS behaviour... %% Also, it can always be useful to retain "all the stuff" after %% the test case in case of debugging... @@ -293,8 +327,8 @@ simple_start_and_stop(doc) -> "Start the snmp manager config process with the \n" "minimum setof options (config dir)."; simple_start_and_stop(Conf) when is_list(Conf) -> - put(tname,ssas), - p("start"), + put(tname, "SIME-START_AND_STOP"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -319,9 +353,9 @@ start_without_mandatory_opts1(doc) -> "Start the snmp manager config process with some of the \n" "mandatory options missing."; start_without_mandatory_opts1(Conf) when is_list(Conf) -> - put(tname,swomo1), - put(verbosity,trace), - p("start"), + put(tname, "START-WO-MAND-OPTS-1"), + put(verbosity, trace), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -330,12 +364,12 @@ start_without_mandatory_opts1(Conf) when is_list(Conf) -> %% config, but no dir: - p("config option, but no dir"), + ?IPRINT("config option, but no dir"), Opts = [{priority, normal}, {config, [{verbosity, trace}, {db_dir, DbDir}]}, {mibs, []}], ?line {error, {missing_mandatory,dir}} = config_start(Opts), - p("done"), + ?IPRINT("done"), ok. @@ -348,9 +382,9 @@ start_without_mandatory_opts2(doc) -> "Start the snmp manager config process with some of the \n" "mandatory options missing."; start_without_mandatory_opts2(Conf) when is_list(Conf) -> - put(tname,swomo2), + put(tname, "START-WO-MAND-OPTS-2"), put(verbosity,trace), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -358,13 +392,13 @@ start_without_mandatory_opts2(Conf) when is_list(Conf) -> %% Second set of options (no config): - p("no config option"), + ?IPRINT("no config option"), Opts = [{priority, normal}, {mibs, []}], ?line {error, {missing_mandatory,config,[dir, db_dir]}} = config_start(Opts), - p("done"), + ?IPRINT("done"), ok. @@ -377,8 +411,9 @@ start_with_all_valid_opts(doc) -> "Start the snmp manager config process with the \n" "complete set of all the valid options."; start_with_all_valid_opts(Conf) when is_list(Conf) -> + put(tname, "START-W-ALL-VALID-OPTS"), put(tname,swavo), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -389,16 +424,22 @@ start_with_all_valid_opts(Conf) when is_list(Conf) -> %% Third set of options (no versions): - p("all options"), + ?IPRINT("all options"), NetIfOpts = [{module, snmpm_net_if}, {verbosity, trace}, {options, [{recbuf, 30000}, {bind_to, false}, {no_reuse, false}]}], - ServerOpts = [{timeout, 10000}, {verbosity, trace}], - NoteStoreOpts = [{timeout, 20000}, {verbosity, trace}], - ConfigOpts = [{dir, ConfDir}, {verbosity, trace}, - {db_dir, DbDir}, {db_init_error, create}], + ServerOpts = [{timeout, ?SECS(10)}, + {verbosity, trace}, + {cbproxy, permanent}, + {netif_sup, {?SECS(60), ?SECS(5)}}], + NoteStoreOpts = [{timeout, ?SECS(20)}, + {verbosity, trace}], + ConfigOpts = [{dir, ConfDir}, + {verbosity, trace}, + {db_dir, DbDir}, + {db_init_error, create}], Mibs = [join(StdMibDir, "SNMP-NOTIFICATION-MIB"), join(StdMibDir, "SNMP-USER-BASED-SM-MIB")], Prio = normal, @@ -418,7 +459,7 @@ start_with_all_valid_opts(Conf) when is_list(Conf) -> ?line {ok, _Pid} = config_start(Opts), ?line ok = config_stop(), - p("done"), + ?IPRINT("done"), ok. @@ -431,8 +472,8 @@ start_with_unknown_opts(doc) -> "Start the snmp manager config process when some of\n" "the options are unknown."; start_with_unknown_opts(Conf) when is_list(Conf) -> - put(tname,swuo), - p("start"), + put(tname, "START-W-UNKNOWN-OPTS"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -443,7 +484,7 @@ start_with_unknown_opts(Conf) when is_list(Conf) -> %% Third set of options (no versions): - p("all options"), + ?IPRINT("all options"), NetIfOpts = [{module, snmpm_net_if}, {verbosity, trace}, {options, [{recbuf, 30000}, @@ -471,7 +512,10 @@ start_with_unknown_opts(Conf) when is_list(Conf) -> {versions, Vsns}], ?line {ok, _Pid} = config_start(Opts), - p("done"), + ?IPRINT("(config) started - now stop"), + ?line ok = config_stop(), + + ?IPRINT("done"), ok. @@ -484,8 +528,8 @@ start_with_incorrect_opts(doc) -> "Start the snmp manager config process when some of\n" "the options has incorrect values."; start_with_incorrect_opts(Conf) when is_list(Conf) -> - put(tname,swio), - p("start"), + put(tname, "START-W-INCORRECT-OPTS"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -496,135 +540,135 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> ConfigOpts = [{verbosity,trace}, {dir, ConfDir}, {db_dir, DbDir}], - p("net-if - incorrect module"), + ?IPRINT("net-if - incorrect module"), NetIfOpts1 = [{module, snmpm_user}], %% Behaviour check will fail Opts01 = [{config, ConfigOpts}, {versions, [v1]}, {net_if, NetIfOpts1}], ?line {error, Reason01} = config_start(Opts01), - p("net-if (module) res: ~p", [Reason01]), + ?IPRINT("net-if (module) res: ~p", [Reason01]), - p("net-if - incorrect verbosity"), + ?IPRINT("net-if - incorrect verbosity"), NetIfOpts2 = [{verbosity, invalid_verbosity}], Opts02 = [{config, ConfigOpts}, {versions, [v1]}, {net_if, NetIfOpts2}], ?line {error, Reason02} = config_start(Opts02), - p("net-if (verbosity) res: ~p", [Reason02]), + ?IPRINT("net-if (verbosity) res: ~p", [Reason02]), - p("net-if - incorrect options"), + ?IPRINT("net-if - incorrect options"), NetIfOpts3 = [{options, invalid_options}], Opts03 = [{config, ConfigOpts}, {versions, [v1]}, {net_if, NetIfOpts3}], ?line {error, Reason03} = config_start(Opts03), - p("net-if (options) res: ~p", [Reason03]), + ?IPRINT("net-if (options) res: ~p", [Reason03]), - p("server - incorrect timeout (1)"), + ?IPRINT("server - incorrect timeout (1)"), ServerOpts1 = [{timeout, invalid_timeout}], Opts08 = [{config, ConfigOpts}, {versions, [v1]}, {server, ServerOpts1}], ?line {error, Reason08} = config_start(Opts08), - p("server (timeout) res: ~p", [Reason08]), + ?IPRINT("server (timeout) res: ~p", [Reason08]), - p("server - incorrect timeout (2)"), + ?IPRINT("server - incorrect timeout (2)"), ServerOpts2 = [{timeout, 0}], Opts09 = [{config, ConfigOpts}, {versions, [v1]}, {server, ServerOpts2}], ?line {error, Reason09} = config_start(Opts09), - p("server (timeout) res: ~p", [Reason09]), + ?IPRINT("server (timeout) res: ~p", [Reason09]), - p("server - incorrect timeout (3)"), + ?IPRINT("server - incorrect timeout (3)"), ServerOpts3 = [{timeout, -1000}], Opts10 = [{config, ConfigOpts}, {versions, [v1]}, {server, ServerOpts3}], ?line {error, Reason10} = config_start(Opts10), - p("server (timeout) res: ~p", [Reason10]), + ?IPRINT("server (timeout) res: ~p", [Reason10]), - p("server - incorrect verbosity"), + ?IPRINT("server - incorrect verbosity"), ServerOpts4 = [{verbosity, invalid_verbosity}], Opts11 = [{config, ConfigOpts}, {versions, [v1]}, {server, ServerOpts4}], ?line {error, Reason11} = config_start(Opts11), - p("server (verbosity) res: ~p", [Reason11]), + ?IPRINT("server (verbosity) res: ~p", [Reason11]), - p("note-store - incorrect timeout (1)"), + ?IPRINT("note-store - incorrect timeout (1)"), NoteStoreOpts1 = [{timeout, invalid_timeout}], Opts12 = [{config, ConfigOpts}, {versions, [v1]}, {note_store, NoteStoreOpts1}], ?line {error, Reason12} = config_start(Opts12), - p("note-store (timeout) res: ~p", [Reason12]), + ?IPRINT("note-store (timeout) res: ~p", [Reason12]), - p("note-store - incorrect timeout (2)"), + ?IPRINT("note-store - incorrect timeout (2)"), NoteStoreOpts2 = [{timeout, 0}], Opts13 = [{config, ConfigOpts}, {versions, [v1]}, {note_store, NoteStoreOpts2}], ?line {error, Reason13} = config_start(Opts13), - p("note-store (timeout) res: ~p", [Reason13]), + ?IPRINT("note-store (timeout) res: ~p", [Reason13]), - p("note-store - incorrect timeout (3)"), + ?IPRINT("note-store - incorrect timeout (3)"), NoteStoreOpts3 = [{timeout, -2000}], Opts14 = [{config, ConfigOpts}, {versions, [v1]}, {note_store, NoteStoreOpts3}], ?line {error, Reason14} = config_start(Opts14), - p("note-store (timeout) res: ~p", [Reason14]), + ?IPRINT("note-store (timeout) res: ~p", [Reason14]), - p("note-store - incorrect verbosity"), + ?IPRINT("note-store - incorrect verbosity"), NoteStoreOpts4 = [{timeout, 20000}, {verbosity, invalid_verbosity}], Opts15 = [{config, ConfigOpts}, {versions, [v1]}, {note_store, NoteStoreOpts4}], ?line {error, Reason15} = config_start(Opts15), - p("note-store (verbosity) res: ~p", [Reason15]), + ?IPRINT("note-store (verbosity) res: ~p", [Reason15]), - p("config - incorrect dir (1)"), + ?IPRINT("config - incorrect dir (1)"), ConfigOpts1 = [{dir, invalid_dir}], Opts16 = [{config, ConfigOpts1}, {versions, [v1]}], ?line {error, Reason16} = config_start(Opts16), - p("config (dir) res: ~p", [Reason16]), + ?IPRINT("config (dir) res: ~p", [Reason16]), - p("config - incorrect dir (2)"), + ?IPRINT("config - incorrect dir (2)"), ConfigOpts2 = [{dir, "/invalid/dir"}], Opts17 = [{config, ConfigOpts2}, {versions, [v1]}], ?line {error, Reason17} = config_start(Opts17), - p("config (dir) res: ~p", [Reason17]), + ?IPRINT("config (dir) res: ~p", [Reason17]), - p("config - incorrect verbosity"), + ?IPRINT("config - incorrect verbosity"), ConfigOpts3 = [{dir, ConfDir}, {verbosity, invalid_verbosity}], Opts18 = [{config, ConfigOpts3}, {versions, [v1]}], ?line {error, Reason18} = config_start(Opts18), - p("config (verbosity) res: ~p", [Reason18]), + ?IPRINT("config (verbosity) res: ~p", [Reason18]), - p("mibs - incorrect mibs (1)"), + ?IPRINT("mibs - incorrect mibs (1)"), Mibs1 = invalid_mibs, Opts19 = [{config, ConfigOpts}, {versions, [v1]}, {mibs, Mibs1}], ?line {error, Reason19} = config_start(Opts19), - p("mibs (mibs) res: ~p", [Reason19]), + ?IPRINT("mibs (mibs) res: ~p", [Reason19]), - p("mibs - incorrect mibs (2)"), + ?IPRINT("mibs - incorrect mibs (2)"), Mibs2 = [join(StdMibDir, "INVALID-MIB")], Opts20 = [{config, ConfigOpts}, {versions, [v1]}, {mibs, Mibs2}], ?line {error, Reason20} = config_start(Opts20), - p("mibs (mibs) res: ~p", [Reason20]), + ?IPRINT("mibs (mibs) res: ~p", [Reason20]), - p("prio - incorrect prio"), + ?IPRINT("prio - incorrect prio"), Prio1 = invalid_prio, Opts21 = [{config, ConfigOpts}, {versions, [v1]}, {priority, Prio1}], ?line {error, Reason21} = config_start(Opts21), - p("prio (prio) res: ~p", [Reason21]), + ?IPRINT("prio (prio) res: ~p", [Reason21]), - p("atl - incorrect type"), + ?IPRINT("atl - incorrect type"), ATL1 = [{type, invalid_type}, {dir, LogDir}, {size, {10,10240}}, @@ -633,9 +677,9 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL1}], ?line {error, Reason22} = config_start(Opts22), - p("atl (type) res: ~p", [Reason22]), + ?IPRINT("atl (type) res: ~p", [Reason22]), - p("atl - incorrect dir (1)"), + ?IPRINT("atl - incorrect dir (1)"), ATL2 = [{type, read_write}, {dir, invalid_dir}, {size, {10,10240}}, @@ -644,9 +688,9 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL2}], ?line {error, Reason23} = config_start(Opts23), - p("atl (dir) res: ~p", [Reason23]), + ?IPRINT("atl (dir) res: ~p", [Reason23]), - p("atl - incorrect dir (2)"), + ?IPRINT("atl - incorrect dir (2)"), ATL3 = [{type, read_write}, {dir, "/invalid/dir"}, {size, {10,10240}}, @@ -655,9 +699,9 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL3}], ?line {error, Reason24} = config_start(Opts24), - p("atl (dir) res: ~p", [Reason24]), + ?IPRINT("atl (dir) res: ~p", [Reason24]), - p("atl - incorrect size (1)"), + ?IPRINT("atl - incorrect size (1)"), ATL4 = [{type, read_write}, {dir, LogDir}, {size, invalid_size}, @@ -666,9 +710,9 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL4}], ?line {error, Reason25} = config_start(Opts25), - p("atl (size) res: ~p", [Reason25]), + ?IPRINT("atl (size) res: ~p", [Reason25]), - p("atl - incorrect size (2)"), + ?IPRINT("atl - incorrect size (2)"), ATL5 = [{type, read_write}, {dir, LogDir}, {size, {10,invalid_file_size}}, @@ -677,9 +721,9 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL5}], ?line {error, Reason26} = config_start(Opts26), - p("atl (size) res: ~p", [Reason26]), + ?IPRINT("atl (size) res: ~p", [Reason26]), - p("atl - incorrect size (3)"), + ?IPRINT("atl - incorrect size (3)"), ATL6 = [{type, read_write}, {dir, LogDir}, {size, {invalid_file_num,10240}}, @@ -688,9 +732,9 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL6}], ?line {error, Reason27} = config_start(Opts27), - p("atl (size) res: ~p", [Reason27]), + ?IPRINT("atl (size) res: ~p", [Reason27]), - p("atl - incorrect repair"), + ?IPRINT("atl - incorrect repair"), ATL7 = [{type, read_write}, {dir, LogDir}, {size, {10,10240}}, @@ -699,23 +743,23 @@ start_with_incorrect_opts(Conf) when is_list(Conf) -> {versions, [v1]}, {audit_trail_log, ATL7}], ?line {error, Reason28} = config_start(Opts28), - p("atl (repair) res: ~p", [Reason28]), + ?IPRINT("atl (repair) res: ~p", [Reason28]), - p("version - incorrect versions (1)"), + ?IPRINT("version - incorrect versions (1)"), Vsns1 = invalid_vsns, Opts29 = [{config, ConfigOpts}, {versions, Vsns1}], ?line {error, Reason29} = config_start(Opts29), - p("versions (versions) res: ~p", [Reason29]), + ?IPRINT("versions (versions) res: ~p", [Reason29]), - p("version - incorrect versions (2)"), + ?IPRINT("version - incorrect versions (2)"), Vsns2 = [v1,v2,v3,v9], Opts30 = [{config, ConfigOpts}, {versions, Vsns2}], ?line {error, Reason30} = config_start(Opts30), - p("versions (versions) res: ~p", [Reason30]), + ?IPRINT("versions (versions) res: ~p", [Reason30]), - p("done"), + ?IPRINT("done"), ok. @@ -727,8 +771,8 @@ start_with_invalid_manager_conf_file1(suite) -> []; start_with_invalid_manager_conf_file1(doc) -> "Start with invalid manager config file (1)."; start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> - put(tname,swimcf), - p("start"), + put(tname, "START-W-INV-MGR-CONF-FILE-1"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -737,142 +781,142 @@ start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], %% -- - p("write manager config file with invalid IP address (1)"), + ?IPRINT("write manager config file with invalid IP address (1)"), write_manager_conf(ConfDir, "arne-anka", "4001", "500", "\"bmkEngine\""), ?line {error, Reason11} = config_start(Opts), - p("start failed (as expected): ~p", [Reason11]), + ?IPRINT("start failed (as expected): ~p", [Reason11]), ?line {failed_reading, _, _, 1, {parse_error, _}} = Reason11, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid IP address (2)"), + ?IPRINT("write manager config file with invalid IP address (2)"), write_manager_conf(ConfDir, "arne_anka", "4001", "500", "\"bmkEngine\""), ?line {error, Reason12} = config_start(Opts), - p("start failed (as expected): ~p", [Reason12]), + ?IPRINT("start failed (as expected): ~p", [Reason12]), ?line {failed_check, _, _, 2, {bad_address, _}} = Reason12, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid IP address (3)"), + ?IPRINT("write manager config file with invalid IP address (3)"), write_manager_conf(ConfDir, "9999", "4001", "500", "\"bmkEngine\""), ?line {error, Reason13} = config_start(Opts), - p("start failed (as expected): ~p", [Reason13]), + ?IPRINT("start failed (as expected): ~p", [Reason13]), ?line {failed_check, _, _, 2, {bad_address, _}} = Reason13, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid port (2)"), + ?IPRINT("write manager config file with invalid port (2)"), write_manager_conf(ConfDir, "[134,138,177,189]", "kalle-anka", "500", "\"bmkEngine\""), ?line {error, Reason21} = config_start(Opts), - p("start failed (as expected): ~p", [Reason21]), + ?IPRINT("start failed (as expected): ~p", [Reason21]), ?line {failed_reading, _, _, 2, {parse_error, _}} = Reason21, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid port (1)"), + ?IPRINT("write manager config file with invalid port (1)"), write_manager_conf(ConfDir, "[134,138,177,189]", "-1", "500", "\"bmkEngine\""), ?line {error, Reason22} = config_start(Opts), - p("start failed (as expected): ~p", [Reason22]), + ?IPRINT("start failed (as expected): ~p", [Reason22]), io:format("Reason22: ~p~n", [Reason22]), ?line {failed_check, _, _, 3, {bad_port, _}} = Reason22, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid port (3)"), + ?IPRINT("write manager config file with invalid port (3)"), write_manager_conf(ConfDir, "[134,138,177,189]", "\"kalle-anka\"", "500", "\"bmkEngine\""), ?line {error, Reason23} = config_start(Opts), - p("start failed (as expected): ~p", [Reason23]), + ?IPRINT("start failed (as expected): ~p", [Reason23]), ?line {failed_check, _, _, 3, {bad_port, _}} = Reason23, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid EngineID (1)"), + ?IPRINT("write manager config file with invalid EngineID (1)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "500", "bmkEngine"), ?line {error, Reason31} = config_start(Opts), - p("start failed (as expected): ~p", [Reason31]), + ?IPRINT("start failed (as expected): ~p", [Reason31]), ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason31, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid EngineID (2)"), + ?IPRINT("write manager config file with invalid EngineID (2)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "500", "{1,2,3}"), ?line {error, Reason32} = config_start(Opts), - p("start failed (as expected): ~p", [Reason32]), + ?IPRINT("start failed (as expected): ~p", [Reason32]), ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason32, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid EngineID (3)"), + ?IPRINT("write manager config file with invalid EngineID (3)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "500", "10101"), ?line {error, Reason33} = config_start(Opts), - p("start failed (as expected): ~p", [Reason33]), + ?IPRINT("start failed (as expected): ~p", [Reason33]), ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason33, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid MMS (1)"), + ?IPRINT("write manager config file with invalid MMS (1)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "483", "\"bmkEngine\""), ?line {error, Reason41} = config_start(Opts), - p("start failed (as expected): ~p", [Reason41]), + ?IPRINT("start failed (as expected): ~p", [Reason41]), ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason41, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid MMS (2)"), + ?IPRINT("write manager config file with invalid MMS (2)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "-1", "\"bmkEngine\""), ?line {error, Reason42} = config_start(Opts), - p("start failed (as expected): ~p", [Reason42]), + ?IPRINT("start failed (as expected): ~p", [Reason42]), ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason42, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid MMS (3)"), + ?IPRINT("write manager config file with invalid MMS (3)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "\"kalle-anka\"", "\"bmkEngine\""), ?line {error, Reason43} = config_start(Opts), - p("start failed (as expected): ~p", [Reason43]), + ?IPRINT("start failed (as expected): ~p", [Reason43]), ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason43, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with invalid MMS (4)"), + ?IPRINT("write manager config file with invalid MMS (4)"), write_manager_conf(ConfDir, "[134,138,177,189]", "4001", "kalle_anka", "\"bmkEngine\""), ?line {error, Reason44} = config_start(Opts), - p("start failed (as expected): ~p", [Reason44]), + ?IPRINT("start failed (as expected): ~p", [Reason44]), ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason44, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with unknown option"), + ?IPRINT("write manager config file with unknown option"), write_manager_conf(ConfDir, "{kalle, anka}."), ?line {error, Reason51} = config_start(Opts), - p("start failed (as expected): ~p", [Reason51]), + ?IPRINT("start failed (as expected): ~p", [Reason51]), ?line {failed_check, _, _, 1, {unknown_config, _}} = Reason51, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write manager config file with unknown option"), + ?IPRINT("write manager config file with unknown option"), write_manager_conf(ConfDir, "kalle_anka."), ?line {error, Reason52} = config_start(Opts), - p("start failed (as expected): ~p", [Reason52]), + ?IPRINT("start failed (as expected): ~p", [Reason52]), ?line {failed_check, _, _, 1, {unknown_config, _}} = Reason52, - await_config_not_running(), + config_ensure_not_running(), - p("done"), + ?IPRINT("done"), ok. @@ -884,8 +928,8 @@ start_with_invalid_users_conf_file1(suite) -> []; start_with_invalid_users_conf_file1(doc) -> "Start with invalid users config file."; start_with_invalid_users_conf_file1(Conf) when is_list(Conf) -> - put(tname,swiucf), - p("start"), + put(tname, "START-W-INV-USER-CONF-FILE-1"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -899,74 +943,74 @@ start_with_invalid_users_conf_file1(Conf) when is_list(Conf) -> write_manager_conf(ConfDir), %% -- - p("write users config file with invalid module (1)"), + ?IPRINT("write users config file with invalid module (1)"), write_users_conf(ConfDir, [{"kalle", "kalle", "dummy"}]), ?line {error, Reason11} = config_start(Opts), - p("start failed (as expected): ~p", [Reason11]), + ?IPRINT("start failed (as expected): ~p", [Reason11]), ?line {failed_check, _, _, _, {bad_module, kalle}} = Reason11, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid module (1)"), + ?IPRINT("write users config file with invalid module (1)"), write_users_conf(ConfDir, [{"kalle", "snmpm", "dummy"}]), ?line {error, Reason12} = config_start(Opts), - p("start failed (as expected): ~p", [Reason12]), + ?IPRINT("start failed (as expected): ~p", [Reason12]), ?line {failed_check, _, _, _, {bad_module, _}} = Reason12, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid module (2)"), + ?IPRINT("write users config file with invalid module (2)"), write_users_conf(ConfDir, [{"kalle1", "10101", "dummy"}]), ?line {error, Reason13} = config_start(Opts), - p("start failed (as expected): ~p", [Reason13]), + ?IPRINT("start failed (as expected): ~p", [Reason13]), ?line {failed_check, _, _, _, {bad_module, _}} = Reason13, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid user tuple (1)"), + ?IPRINT("write users config file with invalid user tuple (1)"), write_users_conf2(ConfDir, "{kalle, snmpm_user_default}."), ?line {error, Reason21} = config_start(Opts), - p("start failed (as expected): ~p", [Reason21]), + ?IPRINT("start failed (as expected): ~p", [Reason21]), ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason21, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid user tuple (2)"), + ?IPRINT("write users config file with invalid user tuple (2)"), write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, [], olle}."), ?line {error, Reason22} = config_start(Opts), - p("start failed (as expected): ~p", [Reason22]), + ?IPRINT("start failed (as expected): ~p", [Reason22]), ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason22, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid user tuple (3)"), + ?IPRINT("write users config file with invalid user tuple (3)"), write_users_conf2(ConfDir, "snmpm_user_default."), ?line {error, Reason23} = config_start(Opts), - p("start failed (as expected): ~p", [Reason23]), + ?IPRINT("start failed (as expected): ~p", [Reason23]), ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason23, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid user tuple (4)"), + ?IPRINT("write users config file with invalid user tuple (4)"), write_users_conf2(ConfDir, "[kalle, snmpm_user_default, kalle]."), ?line {error, Reason24} = config_start(Opts), - p("start failed (as expected): ~p", [Reason24]), + ?IPRINT("start failed (as expected): ~p", [Reason24]), ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason24, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid user agent default config (1)"), + ?IPRINT("write users config file with invalid user agent default config (1)"), write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, olle}."), ?line {error, Reason31} = config_start(Opts), - p("start failed (as expected): ~p", [Reason31]), + ?IPRINT("start failed (as expected): ~p", [Reason31]), ?line {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason31, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("write users config file with invalid user agent default config (2)"), + ?IPRINT("write users config file with invalid user agent default config (2)"), write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, [olle]}."), ?line {error, Reason32} = config_start(Opts), - p("start failed (as expected): ~p", [Reason32]), + ?IPRINT("start failed (as expected): ~p", [Reason32]), %% ?line {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason32, case Reason32 of {failed_check, _, _, _, {bad_default_agent_config, _}} -> @@ -974,9 +1018,9 @@ start_with_invalid_users_conf_file1(Conf) when is_list(Conf) -> {A, B, C, D} -> exit({bad_error, A, B, C, D}) end, - await_config_not_running(), + config_ensure_not_running(), - p("done"), + ?IPRINT("done"), ok. @@ -988,8 +1032,8 @@ start_with_invalid_agents_conf_file1(suite) -> []; start_with_invalid_agents_conf_file1(doc) -> "Start with invalid agents config file."; start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> - put(tname, swiacf), - p("start"), + put(tname, "START-W-INV-AGS-CONF-FILE-1"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -1009,375 +1053,391 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> "any", "\"initial\"", "noAuthNoPriv"}, %% -- - p("[test 11] write agents config file with invalid user (1)"), + ?IPRINT("[test 11] write agents config file with invalid user (1)"), Agent11 = setelement(1, Agent0, "kalle-anka"), write_agents_conf(ConfDir, [Agent11]), case config_start(Opts) of {error, Reason11} -> - p("start failed (as expected): ~p", [Reason11]), + ?IPRINT("start failed (as expected): ~p", [Reason11]), ?line {failed_reading, _, _, _, {parse_error, _}} = Reason11, - await_config_not_running(); + config_ensure_not_running(); OK_11 -> + config_ensure_not_running(), exit({error, {unexpected_success, "11", OK_11}}) end, %% -- - p("[test 21] write agents config file with invalid target name (1)"), + ?IPRINT("[test 21] write agents config file with invalid target name (1)"), Agent21 = setelement(2, Agent0, "targ-hobbes"), write_agents_conf(ConfDir, [Agent21]), case config_start(Opts) of {error, Reason21} -> - p("start failed (as expected): ~p", [Reason21]), + ?IPRINT("start failed (as expected): ~p", [Reason21]), ?line {failed_reading, _, _, _, {parse_error, _}} = Reason21, - await_config_not_running(); + config_ensure_not_running(); OK_21 -> + config_ensure_not_running(), exit({error, {unexpected_success, "21", OK_21}}) end, %% -- - p("[test 22] write agents config file with invalid target name (2)"), + ?IPRINT("[test 22] write agents config file with invalid target name (2)"), Agent22 = setelement(2, Agent0, "targ_hobbes"), write_agents_conf(ConfDir, [Agent22]), case config_start(Opts) of {error, Reason22} -> - p("start failed (as expected): ~p", [Reason22]), + ?IPRINT("start failed (as expected): ~p", [Reason22]), ?line {failed_check, _, _, _, {invalid_string, _}} = Reason22, - await_config_not_running(); + config_ensure_not_running(); OK_22 -> + config_ensure_not_running(), exit({error, {unexpected_success, "22", OK_22}}) end, %% -- - p("[test 23] write agents config file with invalid target name (3)"), + ?IPRINT("[test 23] write agents config file with invalid target name (3)"), Agent23 = setelement(2, Agent0, "10101"), write_agents_conf(ConfDir, [Agent23]), case config_start(Opts) of {error, Reason23} -> - p("start failed (as expected): ~p", [Reason23]), + ?IPRINT("start failed (as expected): ~p", [Reason23]), ?line {failed_check, _, _, _, {invalid_string, _}} = Reason23, - await_config_not_running(); + config_ensure_not_running(); OK_23 -> + config_ensure_not_running(), exit({error, {unexpected_success, "23", OK_23}}) end, %% -- - p("[test 31] write agents config file with invalid community (1)"), + ?IPRINT("[test 31] write agents config file with invalid community (1)"), Agent31 = setelement(3, Agent0, "targ-hobbes"), write_agents_conf(ConfDir, [Agent31]), case config_start(Opts) of {error, Reason31} -> - p("start failed (as expected): ~p", [Reason31]), + ?IPRINT("start failed (as expected): ~p", [Reason31]), ?line {failed_reading, _, _, _, {parse_error, _}} = Reason31, - await_config_not_running(); + config_ensure_not_running(); OK_31 -> + config_ensure_not_running(), exit({error, {unexpected_success, "31", OK_31}}) end, %% -- - p("[test 32] write agents config file with invalid community (2)"), + ?IPRINT("[test 32] write agents config file with invalid community (2)"), Agent32 = setelement(3, Agent0, "targ_hobbes"), write_agents_conf(ConfDir, [Agent32]), case config_start(Opts) of {error, Reason32} -> - p("start failed (as expected): ~p", [Reason32]), + ?IPRINT("start failed (as expected): ~p", [Reason32]), ?line {failed_check, _, _, _, {invalid_string, _}} = Reason32, - await_config_not_running(); + config_ensure_not_running(); OK_32 -> + config_ensure_not_running(), exit({error, {unexpected_success, "32", OK_32}}) end, %% -- - p("[test 33] write agents config file with invalid community (3)"), + ?IPRINT("[test 33] write agents config file with invalid community (3)"), Agent33 = setelement(3, Agent0, "10101"), write_agents_conf(ConfDir, [Agent33]), case config_start(Opts) of {error, Reason33} -> - p("start failed (as expected): ~p", [Reason33]), + ?IPRINT("start failed (as expected): ~p", [Reason33]), ?line {failed_check, _, _, _, {invalid_string, _}} = Reason33, - await_config_not_running(); + config_ensure_not_running(); OK_33 -> + config_ensure_not_running(), exit({error, {unexpected_success, "33", OK_33}}) end, %% -- - p("[test 51] write agents config file with invalid ip (1)"), + ?IPRINT("[test 51] write agents config file with invalid ip (1)"), Agent51 = setelement(4, Agent0, "kalle_anka"), write_agents_conf(ConfDir, [Agent51]), case config_start(Opts) of {error, Reason51} -> - p("start failed (as expected): ~p", [Reason51]), + ?IPRINT("start failed (as expected): ~p", [Reason51]), ?line {failed_check, _, _, _, {bad_domain, _}} = Reason51, - await_config_not_running(); + config_ensure_not_running(); OK_51 -> + config_ensure_not_running(), exit({error, {unexpected_success, "51", OK_51}}) end, %% -- - p("[test 52] write agents config file with invalid ip (2)"), + ?IPRINT("[test 52] write agents config file with invalid ip (2)"), Agent52 = setelement(4, Agent0, "10101"), write_agents_conf(ConfDir, [Agent52]), case config_start(Opts) of {error, Reason52} -> - p("start failed (as expected): ~p", [Reason52]), + ?IPRINT("start failed (as expected): ~p", [Reason52]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason52, - await_config_not_running(); + config_ensure_not_running(); OK_52 -> + config_ensure_not_running(), exit({error, {unexpected_success, "52", OK_52}}) end, %% -- - p("[test 53] write agents config file with invalid ip (3)"), + ?IPRINT("[test 53] write agents config file with invalid ip (3)"), Agent53 = setelement(4, Agent0, "[192,168,0]"), write_agents_conf(ConfDir, [Agent53]), case config_start(Opts) of {error, Reason53} -> - p("start failed (as expected): ~p", [Reason53]), + ?IPRINT("start failed (as expected): ~p", [Reason53]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason53, - await_config_not_running(); + config_ensure_not_running(); OK_53 -> + config_ensure_not_running(), exit({error, {unexpected_success, "53", OK_53}}) end, %% -- - p("[test 54] write agents config file with invalid ip (4)"), + ?IPRINT("[test 54] write agents config file with invalid ip (4)"), Agent54 = setelement(4, Agent0, "[192,168,0,100,99]"), write_agents_conf(ConfDir, [Agent54]), case config_start(Opts) of {error, Reason54} -> - p("start failed (as expected): ~p", [Reason54]), + ?IPRINT("start failed (as expected): ~p", [Reason54]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason54, - await_config_not_running(); + config_ensure_not_running(); OK_54 -> + config_ensure_not_running(), exit({error, {unexpected_success, "54", OK_54}}) end, %% -- - p("[test 55] write agents config file with invalid ip (5)"), + ?IPRINT("[test 55] write agents config file with invalid ip (5)"), Agent55 = setelement(4, Agent0, "[192,168,0,arne]"), write_agents_conf(ConfDir, [Agent55]), ?line {error, Reason55} = config_start(Opts), - p("start failed (as expected): ~p", [Reason55]), + ?IPRINT("start failed (as expected): ~p", [Reason55]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason55, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 61] write agents config file with invalid port (1)"), + ?IPRINT("[test 61] write agents config file with invalid port (1)"), Agent61 = setelement(5, Agent0, "kalle_anka"), write_agents_conf(ConfDir, [Agent61]), ?line {error, Reason61} = config_start(Opts), - p("start failed (as expected): ~p", [Reason61]), + ?IPRINT("start failed (as expected): ~p", [Reason61]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason61, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 62] write agents config file with invalid port (2)"), + ?IPRINT("[test 62] write agents config file with invalid port (2)"), Agent62 = setelement(5, Agent0, "-1"), write_agents_conf(ConfDir, [Agent62]), ?line {error, Reason62} = config_start(Opts), - p("start failed (as expected): ~p", [Reason62]), + ?IPRINT("start failed (as expected): ~p", [Reason62]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason62, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 63] write agents config file with invalid port (3)"), + ?IPRINT("[test 63] write agents config file with invalid port (3)"), Agent63 = setelement(5, Agent0, "\"100\""), write_agents_conf(ConfDir, [Agent63]), ?line {error, Reason63} = config_start(Opts), - p("start failed (as expected): ~p", [Reason63]), + ?IPRINT("start failed (as expected): ~p", [Reason63]), ?line {failed_check, _, _, _, {bad_address, _}} = Reason63, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 71] write agents config file with invalid engine-id (1)"), + ?IPRINT("[test 71] write agents config file with invalid engine-id (1)"), Agent71 = setelement(6, Agent0, "kalle_anka"), write_agents_conf(ConfDir, [Agent71]), ?line {error, Reason71} = config_start(Opts), - p("start failed (as expected): ~p", [Reason71]), + ?IPRINT("start failed (as expected): ~p", [Reason71]), ?line {failed_check, _, _, _, {invalid_string, _}} = Reason71, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 72] write agents config file with invalid engine-id (2)"), + ?IPRINT("[test 72] write agents config file with invalid engine-id (2)"), Agent72 = setelement(6, Agent0, "10101"), write_agents_conf(ConfDir, [Agent72]), ?line {error, Reason72} = config_start(Opts), - p("start failed (as expected): ~p", [Reason72]), + ?IPRINT("start failed (as expected): ~p", [Reason72]), ?line {failed_check, _, _, _, {invalid_string, _}} = Reason72, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 81] write agents config file with invalid timeout (1)"), + ?IPRINT("[test 81] write agents config file with invalid timeout (1)"), Agent81 = setelement(7, Agent0, "kalle_anka"), write_agents_conf(ConfDir, [Agent81]), ?line {error, Reason81} = config_start(Opts), - p("start failed (as expected): ~p", [Reason81]), + ?IPRINT("start failed (as expected): ~p", [Reason81]), ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason81, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 82] write agents config file with invalid timeout (2)"), + ?IPRINT("[test 82] write agents config file with invalid timeout (2)"), Agent82 = setelement(7, Agent0, "-1"), write_agents_conf(ConfDir, [Agent82]), ?line {error, Reason82} = config_start(Opts), - p("start failed (as expected): ~p", [Reason82]), + ?IPRINT("start failed (as expected): ~p", [Reason82]), ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason82, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 83] write agents config file with invalid timeout (3)"), + ?IPRINT("[test 83] write agents config file with invalid timeout (3)"), Agent83 = setelement(7, Agent0, "{1000, 1, 10, kalle}"), write_agents_conf(ConfDir, [Agent83]), ?line {error, Reason83} = config_start(Opts), - p("start failed (as expected): ~p", [Reason83]), + ?IPRINT("start failed (as expected): ~p", [Reason83]), ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason83, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 84] write agents config file with invalid timeout (4)"), + ?IPRINT("[test 84] write agents config file with invalid timeout (4)"), Agent84 = setelement(7, Agent0, "{1000, -1, 10, 10}"), write_agents_conf(ConfDir, [Agent84]), ?line {error, Reason84} = config_start(Opts), - p("start failed (as expected): ~p", [Reason84]), + ?IPRINT("start failed (as expected): ~p", [Reason84]), ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason84, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 85] write agents config file with invalid timeout (5)"), + ?IPRINT("[test 85] write agents config file with invalid timeout (5)"), Agent85 = setelement(7, Agent0, "{1000, 1, -100, 10}"), write_agents_conf(ConfDir, [Agent85]), ?line {error, Reason85} = config_start(Opts), - p("start failed (as expected): ~p", [Reason85]), + ?IPRINT("start failed (as expected): ~p", [Reason85]), ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason85, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 86] write agents config file with invalid timeout (6)"), + ?IPRINT("[test 86] write agents config file with invalid timeout (6)"), Agent86 = setelement(7, Agent0, "{1000, 1, 100, -1}"), write_agents_conf(ConfDir, [Agent86]), ?line {error, Reason86} = config_start(Opts), - p("start failed (as expected): ~p", [Reason86]), + ?IPRINT("start failed (as expected): ~p", [Reason86]), ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason86, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 91] write agents config file with invalid max-message-size (1)"), + ?IPRINT("[test 91] write agents config file with invalid max-message-size (1)"), Agent91 = setelement(8, Agent0, "483"), write_agents_conf(ConfDir, [Agent91]), ?line {error, Reason91} = config_start(Opts), - p("start failed (as expected): ~p", [Reason91]), + ?IPRINT("start failed (as expected): ~p", [Reason91]), ?line {failed_check, _, _, _, {invalid_packet_size, _}} = Reason91, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 92] write agents config file with invalid max-message-size (2)"), + ?IPRINT("[test 92] write agents config file with invalid max-message-size (2)"), Agent92 = setelement(8, Agent0, "kalle_anka"), write_agents_conf(ConfDir, [Agent92]), ?line {error, Reason92} = config_start(Opts), - p("start failed (as expected): ~p", [Reason92]), + ?IPRINT("start failed (as expected): ~p", [Reason92]), ?line {failed_check, _, _, _, {invalid_packet_size, _}} = Reason92, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test A1] write agents config file with invalid version (1)"), + ?IPRINT("[test A1] write agents config file with invalid version (1)"), AgentA1 = setelement(9, Agent0, "1"), write_agents_conf(ConfDir, [AgentA1]), ?line {error, ReasonA1} = config_start(Opts), - p("start failed (as expected): ~p", [ReasonA1]), + ?IPRINT("start failed (as expected): ~p", [ReasonA1]), ?line {failed_check, _, _, _, {bad_version, _}} = ReasonA1, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test A2] write agents config file with invalid version (2)"), + ?IPRINT("[test A2] write agents config file with invalid version (2)"), AgentA2 = setelement(9, Agent0, "v30"), write_agents_conf(ConfDir, [AgentA2]), ?line {error, ReasonA2} = config_start(Opts), - p("start failed (as expected): ~p", [ReasonA2]), + ?IPRINT("start failed (as expected): ~p", [ReasonA2]), ?line {failed_check, _, _, _, {bad_version, _}} = ReasonA2, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test B1] write agents config file with invalid sec-model (1)"), + ?IPRINT("[test B1] write agents config file with invalid sec-model (1)"), AgentB1 = setelement(10, Agent0, "\"any\""), write_agents_conf(ConfDir, [AgentB1]), ?line {error, ReasonB1} = config_start(Opts), - p("start failed (as expected): ~p", [ReasonB1]), + ?IPRINT("start failed (as expected): ~p", [ReasonB1]), ?line {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB1, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test B2] write agents config file with invalid sec-model (2)"), + ?IPRINT("[test B2] write agents config file with invalid sec-model (2)"), AgentB2 = setelement(10, Agent0, "v3"), write_agents_conf(ConfDir, [AgentB2]), ?line {error, ReasonB2} = config_start(Opts), - p("start failed (as expected): ~p", [ReasonB2]), + ?IPRINT("start failed (as expected): ~p", [ReasonB2]), ?line {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB2, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test C1] write agents config file with invalid sec-name (1)"), + ?IPRINT("[test C1] write agents config file with invalid sec-name (1)"), AgentC1 = setelement(11, Agent0, "initial"), write_agents_conf(ConfDir, [AgentC1]), case config_start(Opts) of {error, ReasonC1} -> - p("start failed (as expected): ~p", [ReasonC1]), + ?IPRINT("start failed (as expected): ~p", [ReasonC1]), ?line {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC1, - await_config_not_running(); + config_ensure_not_running(); OK_C1 -> + config_ensure_not_running(), exit({error, {unexpected_success, "C1", OK_C1}}) end, %% -- - p("[test C2] write agents config file with invalid sec-name (2)"), + ?IPRINT("[test C2] write agents config file with invalid sec-name (2)"), AgentC2 = setelement(11, Agent0, "10101"), write_agents_conf(ConfDir, [AgentC2]), case config_start(Opts) of {error, ReasonC2} -> - p("start failed (as expected): ~p", [ReasonC2]), + ?IPRINT("start failed (as expected): ~p", [ReasonC2]), ?line {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC2, - await_config_not_running(); + config_ensure_not_running(); OK_C2 -> + config_ensure_not_running(), exit({error, {unexpected_success, "C2", OK_C2}}) end, %% -- - p("[test D1] write agents config file with invalid sec-level (1)"), + ?IPRINT("[test D1] write agents config file with invalid sec-level (1)"), AgentD1 = setelement(12, Agent0, "\"noAuthNoPriv\""), write_agents_conf(ConfDir, [AgentD1]), case config_start(Opts) of {error, ReasonD1} -> - p("start failed (as expected): ~p", [ReasonD1]), + ?IPRINT("start failed (as expected): ~p", [ReasonD1]), ?line {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD1, - await_config_not_running(); + config_ensure_not_running(); OK_D1 -> + config_ensure_not_running(), exit({error, {unexpected_success, "D1", OK_D1}}) end, %% -- - p("[test D2] write agents config file with invalid sec-level (2)"), + ?IPRINT("[test D2] write agents config file with invalid sec-level (2)"), AgentD2 = setelement(12, Agent0, "99"), write_agents_conf(ConfDir, [AgentD2]), case config_start(Opts) of {error, ReasonD2} -> - p("start failed (as expected): ~p", [ReasonD2]), + ?IPRINT("start failed (as expected): ~p", [ReasonD2]), ?line {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD2, - await_config_not_running(); + config_ensure_not_running(); OK_D2 -> + config_ensure_not_running(), exit({error, {unexpected_success, "D2", OK_D2}}) end, %% -- - p("[test E1] write agents config file with invalid agent (1)"), + ?IPRINT("[test E1] write agents config file with invalid agent (1)"), write_agents_conf2(ConfDir, "{swiacf, \"targ-hobbes\"}."), case config_start(Opts) of {error, ReasonE1} -> - p("start failed (as expected): ~p", [ReasonE1]), + ?IPRINT("start failed (as expected): ~p", [ReasonE1]), ?line {failed_check, _, _, _, {bad_agent_config, _}} = ReasonE1, - await_config_not_running(); + config_ensure_not_running(); OK_E1 -> + config_ensure_not_running(), exit({error, {unexpected_success, "E1", OK_E1}}) end, - p("done"), + ?IPRINT("done"), ok. @@ -1389,8 +1449,8 @@ start_with_invalid_usm_conf_file1(suite) -> []; start_with_invalid_usm_conf_file1(doc) -> "Start with invalid usm config file."; start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> - put(tname,swiusmcf), - p("start"), + put(tname, "START-W-INV-USM-CONF-FILE-1"), + ?IPRINT("start"), process_flag(trap_exit, true), case ?CRYPTO_START() of @@ -1424,179 +1484,179 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> "usmNoPrivProtocol", "[]"}, %% -- - p("[test 11] write usm config file with invalid engine-id (1)"), + ?IPRINT("[test 11] write usm config file with invalid engine-id (1)"), Usm11 = setelement(1, Usm0, "kalle-anka"), write_usm_conf(ConfDir, [Usm11]), ?line {error, Reason11} = config_start(Opts), - p("start failed (as expected): ~p", [Reason11]), + ?IPRINT("start failed (as expected): ~p", [Reason11]), ?line {failed_reading, _, _, _, {parse_error, _}} = Reason11, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 12] write usm config file with invalid engine-id (2)"), + ?IPRINT("[test 12] write usm config file with invalid engine-id (2)"), Usm12 = setelement(1, Usm0, "kalle_anka"), write_usm_conf(ConfDir, [Usm12]), ?line {error, Reason12} = config_start(Opts), - p("start failed (as expected): ~p", [Reason12]), + ?IPRINT("start failed (as expected): ~p", [Reason12]), ?line {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason12, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 13] write usm config file with invalid engine-id (3)"), + ?IPRINT("[test 13] write usm config file with invalid engine-id (3)"), Usm13 = setelement(1, Usm1, "10101"), write_usm_conf(ConfDir, [Usm13]), ?line {error, Reason13} = config_start(Opts), - p("start failed (as expected): ~p", [Reason13]), + ?IPRINT("start failed (as expected): ~p", [Reason13]), ?line {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason13, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 21] write usm config file with invalid user-name (1)"), + ?IPRINT("[test 21] write usm config file with invalid user-name (1)"), Usm21 = setelement(2, Usm0, "kalle_anka"), write_usm_conf(ConfDir, [Usm21]), ?line {error, Reason21} = config_start(Opts), - p("start failed (as expected): ~p", [Reason21]), + ?IPRINT("start failed (as expected): ~p", [Reason21]), ?line {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason21, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 22] write usm config file with invalid user-name (1)"), + ?IPRINT("[test 22] write usm config file with invalid user-name (1)"), Usm22 = setelement(2, Usm1, "10101"), write_usm_conf(ConfDir, [Usm22]), ?line {error, Reason22} = config_start(Opts), - p("start failed (as expected): ~p", [Reason22]), + ?IPRINT("start failed (as expected): ~p", [Reason22]), ?line {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason22, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 31] write usm config file with invalid sec-name (1)"), + ?IPRINT("[test 31] write usm config file with invalid sec-name (1)"), Usm31 = setelement(3, Usm1, "kalle_anka"), write_usm_conf(ConfDir, [Usm31]), ?line {error, Reason31} = config_start(Opts), - p("start failed (as expected): ~p", [Reason31]), + ?IPRINT("start failed (as expected): ~p", [Reason31]), ?line {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason31, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 32] write usm config file with invalid sec-name (2)"), + ?IPRINT("[test 32] write usm config file with invalid sec-name (2)"), Usm32 = setelement(3, Usm1, "10101"), write_usm_conf(ConfDir, [Usm32]), ?line {error, Reason32} = config_start(Opts), - p("start failed (as expected): ~p", [Reason32]), + ?IPRINT("start failed (as expected): ~p", [Reason32]), ?line {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason32, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 41] write usm config file with invalid auth-protocol (1)"), + ?IPRINT("[test 41] write usm config file with invalid auth-protocol (1)"), Usm41 = setelement(3, Usm0, "\"usmNoAuthProtocol\""), write_usm_conf(ConfDir, [Usm41]), ?line {error, Reason41} = config_start(Opts), - p("start failed (as expected): ~p", [Reason41]), + ?IPRINT("start failed (as expected): ~p", [Reason41]), ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason41, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 42] write usm config file with invalid auth-protocol (2)"), + ?IPRINT("[test 42] write usm config file with invalid auth-protocol (2)"), Usm42 = setelement(3, Usm0, "kalle"), write_usm_conf(ConfDir, [Usm42]), ?line {error, Reason42} = config_start(Opts), - p("start failed (as expected): ~p", [Reason42]), + ?IPRINT("start failed (as expected): ~p", [Reason42]), ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason42, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 43] write usm config file with invalid auth-protocol (3)"), + ?IPRINT("[test 43] write usm config file with invalid auth-protocol (3)"), Usm43 = setelement(3, Usm0, "10101"), write_usm_conf(ConfDir, [Usm43]), ?line {error, Reason43} = config_start(Opts), - p("start failed (as expected): ~p", [Reason43]), + ?IPRINT("start failed (as expected): ~p", [Reason43]), ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason43, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 51] write usm config file with invalid auth-key (1)"), + ?IPRINT("[test 51] write usm config file with invalid auth-key (1)"), Usm51 = setelement(3, Usm0, "usmHMACMD5AuthProtocol"), write_usm_conf(ConfDir, [Usm51]), ?line {error, Reason51} = config_start(Opts), - p("start failed (as expected): ~p", [Reason51]), + ?IPRINT("start failed (as expected): ~p", [Reason51]), ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason51, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 52] write usm config file with invalid auth-key (2)"), + ?IPRINT("[test 52] write usm config file with invalid auth-key (2)"), Usm52 = setelement(4, Usm51, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]"), write_usm_conf(ConfDir, [Usm52]), ?line {error, Reason52} = config_start(Opts), - p("start failed (as expected): ~p", [Reason52]), + ?IPRINT("start failed (as expected): ~p", [Reason52]), ?line {failed_check, _, _, _, {invalid_auth_key, _, 15}} = Reason52, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 53] write usm config file with invalid auth-key (3)"), + ?IPRINT("[test 53] write usm config file with invalid auth-key (3)"), Usm53 = setelement(4, Usm51, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"), write_usm_conf(ConfDir, [Usm53]), ?line {error, Reason53} = config_start(Opts), - p("start failed (as expected): ~p", [Reason53]), + ?IPRINT("start failed (as expected): ~p", [Reason53]), ?line {failed_check, _, _, _, {invalid_auth_key, _, 17}} = Reason53, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 54] write usm config file with invalid auth-key (4)"), + ?IPRINT("[test 54] write usm config file with invalid auth-key (4)"), Usm54 = setelement(4, Usm51, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,kalle]"), write_usm_conf(ConfDir, [Usm54]), ?line maybe_start_crypto(), %% Make sure it's started... ?line {error, Reason54} = config_start(Opts), ?line ok = maybe_stop_crypto(), - p("start failed (as expected): ~p", [Reason54]), + ?IPRINT("start failed (as expected): ~p", [Reason54]), ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason54, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 55] write usm config file with invalid auth-key (5)"), + ?IPRINT("[test 55] write usm config file with invalid auth-key (5)"), Usm55 = setelement(4, Usm51, "arne_anka"), write_usm_conf(ConfDir, [Usm55]), ?line {error, Reason55} = config_start(Opts), - p("start failed (as expected): ~p", [Reason55]), + ?IPRINT("start failed (as expected): ~p", [Reason55]), ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason55, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 56] write usm config file with invalid auth-key (6)"), + ?IPRINT("[test 56] write usm config file with invalid auth-key (6)"), Usm56 = setelement(4, Usm51, "10101"), write_usm_conf(ConfDir, [Usm56]), ?line {error, Reason56} = config_start(Opts), - p("start failed (as expected): ~p", [Reason56]), + ?IPRINT("start failed (as expected): ~p", [Reason56]), ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason56, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 57] write usm config file with invalid auth-key (7)"), + ?IPRINT("[test 57] write usm config file with invalid auth-key (7)"), Usm57 = setelement(3, Usm0, "usmHMACSHAAuthProtocol"), write_usm_conf(ConfDir, [Usm57]), ?line {error, Reason57} = config_start(Opts), - p("start failed (as expected): ~p", [Reason57]), + ?IPRINT("start failed (as expected): ~p", [Reason57]), ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason57, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 58] write usm config file with invalid auth-key (8)"), + ?IPRINT("[test 58] write usm config file with invalid auth-key (8)"), Usm58 = setelement(4, Usm57, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]"), write_usm_conf(ConfDir, [Usm58]), ?line {error, Reason58} = config_start(Opts), - p("start failed (as expected): ~p", [Reason58]), + ?IPRINT("start failed (as expected): ~p", [Reason58]), ?line {failed_check, _, _, _, {invalid_auth_key, _, 16}} = Reason58, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 59] write usm config file with invalid auth-key (9)"), + ?IPRINT("[test 59] write usm config file with invalid auth-key (9)"), Usm59 = setelement(4, Usm57, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,ka]"), write_usm_conf(ConfDir, [Usm59]), ?line ok = maybe_start_crypto(), ?line {error, Reason59} = config_start(Opts), ?line ok = maybe_stop_crypto(), - p("start failed (as expected): ~p", [Reason59]), + ?IPRINT("start failed (as expected): ~p", [Reason59]), ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason59, - await_config_not_running(), + config_ensure_not_running(), %% -- %% <CRYPTO-MODIFICATIONS> @@ -1604,16 +1664,16 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> %% explicitly (all of it is as of R14 implemented with NIFs). case (catch crypto:version()) of {'EXIT', {undef, _}} -> - p("[test 5A] write usm config file with valid auth-key " + ?IPRINT("[test 5A] write usm config file with valid auth-key " "when crypto not started (10)"), Usm5A = setelement(4, Usm57, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]"), write_usm_conf(ConfDir, [Usm5A]), ?line {error, Reason5A} = config_start(Opts), - p("start failed (as expected): ~p", [Reason5A]), + ?IPRINT("start failed (as expected): ~p", [Reason5A]), ?line {failed_check, _, _, _, {unsupported_crypto, _}} = Reason5A, - await_config_not_running(); + config_ensure_not_running(); _ -> %% This function is only present in version 2.0 or greater. %% The crypto app no longer needs to be explicitly started @@ -1622,87 +1682,87 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> %% </CRYPTO-MODIFICATIONS> %% -- - p("[test 61] write usm config file with invalid priv-protocol (1)"), + ?IPRINT("[test 61] write usm config file with invalid priv-protocol (1)"), Usm61 = setelement(5, Usm0, "\"usmNoPrivProtocol\""), write_usm_conf(ConfDir, [Usm61]), ?line {error, Reason61} = config_start(Opts), - p("start failed (as expected): ~p", [Reason61]), + ?IPRINT("start failed (as expected): ~p", [Reason61]), ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason61, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 62] write usm config file with invalid priv-protocol (2)"), + ?IPRINT("[test 62] write usm config file with invalid priv-protocol (2)"), Usm62 = setelement(5, Usm0, "kalle"), write_usm_conf(ConfDir, [Usm62]), ?line {error, Reason62} = config_start(Opts), - p("start failed (as expected): ~p", [Reason62]), + ?IPRINT("start failed (as expected): ~p", [Reason62]), ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason62, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 63] write usm config file with invalid priv-protocol (3)"), + ?IPRINT("[test 63] write usm config file with invalid priv-protocol (3)"), Usm63 = setelement(5, Usm0, "10101"), write_usm_conf(ConfDir, [Usm63]), ?line {error, Reason63} = config_start(Opts), - p("start failed (as expected): ~p", [Reason63]), + ?IPRINT("start failed (as expected): ~p", [Reason63]), ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason63, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 71] write usm config file with invalid priv-key (1)"), + ?IPRINT("[test 71] write usm config file with invalid priv-key (1)"), Usm71 = setelement(5, Usm0, "usmDESPrivProtocol"), write_usm_conf(ConfDir, [Usm71]), ?line {error, Reason71} = config_start(Opts), - p("start failed (as expected): ~p", [Reason71]), + ?IPRINT("start failed (as expected): ~p", [Reason71]), ?line {failed_check, _, _, _, {invalid_priv_key, _, _}} = Reason71, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 72] write usm config file with invalid priv-key (2)"), + ?IPRINT("[test 72] write usm config file with invalid priv-key (2)"), Usm72 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]"), write_usm_conf(ConfDir, [Usm72]), ?line {error, Reason72} = config_start(Opts), - p("start failed (as expected): ~p", [Reason72]), + ?IPRINT("start failed (as expected): ~p", [Reason72]), ?line {failed_check, _, _, _, {invalid_priv_key, _, 15}} = Reason72, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 73] write usm config file with invalid priv-key (3)"), + ?IPRINT("[test 73] write usm config file with invalid priv-key (3)"), Usm73 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"), write_usm_conf(ConfDir, [Usm73]), ?line {error, Reason73} = config_start(Opts), - p("start failed (as expected): ~p", [Reason73]), + ?IPRINT("start failed (as expected): ~p", [Reason73]), ?line {failed_check, _, _, _, {invalid_priv_key, _, 17}} = Reason73, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 74] write usm config file with invalid priv-key (4)"), + ?IPRINT("[test 74] write usm config file with invalid priv-key (4)"), Usm74 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,kalle]"), write_usm_conf(ConfDir, [Usm74]), ?line ok = maybe_start_crypto(), ?line {error, Reason74} = config_start(Opts), ?line ok = maybe_stop_crypto(), - p("start failed (as expected): ~p", [Reason74]), + ?IPRINT("start failed (as expected): ~p", [Reason74]), ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason74, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 75] write usm config file with invalid priv-key (5)"), + ?IPRINT("[test 75] write usm config file with invalid priv-key (5)"), Usm75 = setelement(6, Usm71, "arne_anka"), write_usm_conf(ConfDir, [Usm75]), ?line {error, Reason75} = config_start(Opts), - p("start failed (as expected): ~p", [Reason75]), + ?IPRINT("start failed (as expected): ~p", [Reason75]), ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason75, - await_config_not_running(), + config_ensure_not_running(), %% -- - p("[test 76] write usm config file with invalid priv-key (6)"), + ?IPRINT("[test 76] write usm config file with invalid priv-key (6)"), Usm76 = setelement(6, Usm71, "10101"), write_usm_conf(ConfDir, [Usm76]), ?line {error, Reason76} = config_start(Opts), - p("start failed (as expected): ~p", [Reason76]), + ?IPRINT("start failed (as expected): ~p", [Reason76]), ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason76, - await_config_not_running(), + config_ensure_not_running(), %% -- %% <CRYPTO-MODIFICATIONS> @@ -1710,14 +1770,14 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> %% explicitly (all of it is as of R14 implemented with NIFs). case (catch crypto:version()) of {'EXIT', {undef, _}} -> - p("[test 77] write usm config file with valid priv-key " + ?IPRINT("[test 77] write usm config file with valid priv-key " "when crypto not started (7)"), Usm77 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]"), write_usm_conf(ConfDir, [Usm77]), ?line {error, Reason77} = config_start(Opts), - p("start failed (as expected): ~p", [Reason77]), + ?IPRINT("start failed (as expected): ~p", [Reason77]), ?line {failed_check, _, _, _, {unsupported_crypto, _}} = Reason77, - await_config_not_running(); + config_ensure_not_running(); _ -> %% This function is only present in version 2.0 or greater. %% The crypto app no longer needs to be explicitly started @@ -1726,14 +1786,14 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> %% </CRYPTO-MODIFICATIONS> %% -- - p("[test 78] write usm config file with invalid usm (1)"), + ?IPRINT("[test 78] write usm config file with invalid usm (1)"), write_usm_conf2(ConfDir, "{\"bmkEngine\", \"swiusmcf\"}."), ?line {error, Reason81} = config_start(Opts), - p("start failed (as expected): ~p", [Reason81]), + ?IPRINT("start failed (as expected): ~p", [Reason81]), ?line {failed_check, _, _, _, {bad_usm_config, _}} = Reason81, - await_config_not_running(), + config_ensure_not_running(), - p("done"), + ?IPRINT("done"), ok. @@ -1746,28 +1806,28 @@ start_with_create_db_and_dir_opt(doc) -> "Start the snmp manager config process with the\n" "create_db_and_dir option."; start_with_create_db_and_dir_opt(Conf) when is_list(Conf) -> - put(tname, swcdado), - p("start"), + put(tname, "START-W-CRE-DB-AND-DIR-OPT"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), true = not filelib:is_dir(DbDir) and not filelib:is_file(DbDir), write_manager_conf(ConfDir), - p("verify nonexistent db_dir"), + ?IPRINT("verify nonexistent db_dir"), ConfigOpts01 = [{verbosity,trace}, {dir, ConfDir}, {db_dir, DbDir}], {error, Reason01} = config_start([{config, ConfigOpts01}]), - p("nonexistent db_dir res: ~p", [Reason01]), + ?IPRINT("nonexistent db_dir res: ~p", [Reason01]), {invalid_conf_db_dir, _, not_found} = Reason01, - p("verify nonexistent db_dir gets created"), + ?IPRINT("verify nonexistent db_dir gets created"), ConfigOpts02 = [{db_init_error, create_db_and_dir} | ConfigOpts01], {ok, _Pid} = config_start([{config, ConfigOpts02}]), true = filelib:is_dir(DbDir), - p("verified: nonexistent db_dir was correctly created"), + ?IPRINT("verified: nonexistent db_dir was correctly created"), ok = config_stop(), - p("done"), + ?IPRINT("done"), ok. %% @@ -1780,8 +1840,8 @@ simple_system_op(doc) -> "Access some of the known system info and some \n" "system info that does not exist."; simple_system_op(Conf) when is_list(Conf) -> - put(tname,sso), - p("start"), + put(tname, "SIMPLE-SYS-OP"), + ?IPRINT("start"), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -1790,21 +1850,21 @@ simple_system_op(Conf) when is_list(Conf) -> Opts = [{versions, [v1]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("start config"), + ?IPRINT("start config"), ?line {ok, _Pid} = config_start(Opts), - p("retreive various configs"), + ?IPRINT("retreive various configs"), ?line {ok, _Time} = snmpm_config:system_start_time(), ?line {ok, _EngineId} = snmpm_config:get_engine_id(), ?line {ok, _MMS} = snmpm_config:get_engine_max_message_size(), - p("attempt to retreive nonexisting"), + ?IPRINT("attempt to retreive nonexisting"), ?line {error, not_found} = snmpm_config:system_info(kalle), ?line ok = config_stop(), - await_config_not_running(), + config_ensure_not_running(), - p("done"), + ?IPRINT("done"), ok. @@ -1822,8 +1882,8 @@ register_user_using_file(suite) -> []; register_user_using_file(doc) -> "Register user using the 'users.conf' file."; register_user_using_file(Conf) when is_list(Conf) -> - put(tname,ruufi), - p("start"), + put(tname, "REG-USER-USING-FILE"), + ?IPRINT("start"), process_flag(trap_exit, true), _ConfDir = ?config(manager_conf_dir, Conf), _DbDir = ?config(manager_db_dir, Conf), @@ -1838,8 +1898,8 @@ register_user_using_function(suite) -> []; register_user_using_function(doc) -> "Register user using the API (function)."; register_user_using_function(Conf) when is_list(Conf) -> - put(tname,ruufu), - p("start"), + put(tname, "REG-USER-USING-FUNC"), + ?IPRINT("start"), process_flag(trap_exit, true), _ConfDir = ?config(manager_conf_dir, Conf), _DbDir = ?config(manager_db_dir, Conf), @@ -1854,8 +1914,8 @@ register_user_failed_using_function1(suite) -> []; register_user_failed_using_function1(doc) -> "Register user failed using incorrect arguments to API (function)."; register_user_failed_using_function1(Conf) when is_list(Conf) -> - put(tname,rufufu1), - p("start"), + put(tname, "REG-USER-FAIL-USING-FUNC-1"), + ?IPRINT("start"), process_flag(trap_exit, true), _ConfDir = ?config(manager_conf_dir, Conf), _DbDir = ?config(manager_db_dir, Conf), @@ -1872,13 +1932,29 @@ register_user_failed_using_function1(Conf) when is_list(Conf) -> %% --- %% +%% This test case tests that we can "register" agents using a config file. +%% So, starting the config process is part of the actual test, but even +%% if the test fails, we want to make sure the config process is actually +%% stop'ed. So, we put config stop in the post. + register_agent_using_file(suite) -> []; register_agent_using_file(doc) -> "Register agents using the 'agents'conf' file."; register_agent_using_file(Conf) when is_list(Conf) -> - put(tname,raufi), - p("start"), + put(tname, "REG-AG-USING-FILE"), process_flag(trap_exit, true), + Pre = fun() -> ok end, + Case = fun(_) -> do_register_agent_using_file(Conf) end, + Post = fun(_) -> + ?IPRINT("stop config process"), + ?line ok = snmpm_config:stop(), + config_ensure_not_running(), + ok + end, + ?TC_TRY(register_agent_using_file, Pre, Case, Post). + +do_register_agent_using_file(Conf) -> + ?IPRINT("start"), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -1887,11 +1963,11 @@ register_agent_using_file(Conf) when is_list(Conf) -> %% -- - p("write manager config file"), + ?IPRINT("write manager config file"), write_manager_conf(ConfDir), %% -- - p("write users config file"), + ?IPRINT("write users config file"), UserId1 = raufi1, UserId1Str = str(UserId1), UserId2 = raufi2, @@ -1901,7 +1977,7 @@ register_agent_using_file(Conf) when is_list(Conf) -> write_users_conf(ConfDir, [User1, User2]), %% -- - p("write agents config file"), + ?IPRINT("write agents config file"), AgentAddr1 = [192,168,0,101], AgentAddr1Str = str(AgentAddr1), AgentPort1 = 162, @@ -1929,38 +2005,38 @@ register_agent_using_file(Conf) when is_list(Conf) -> write_agents_conf(ConfDir, [Agent1Str, Agent2Str]), %% -- - p("start the config process"), + ?IPRINT("start the config process"), ?line {ok, _Pid} = config_start(Opts), %% -- - p("which agents"), + ?IPRINT("which agents"), ?line [_, _] = All = snmpm_config:which_agents(), - p("all agents: ~n ~p", [All]), + ?IPRINT("all agents: ~n ~p", [All]), ?line [A1] = snmpm_config:which_agents(UserId1), - p("agents belonging to ~w: ~n ~p", [UserId1, A1]), + ?IPRINT("agents belonging to ~w: ~n ~p", [UserId1, A1]), ?line [A2] = snmpm_config:which_agents(UserId2), - p("agents belonging to ~w: ~n ~p", [UserId2, A2]), + ?IPRINT("agents belonging to ~w: ~n ~p", [UserId2, A2]), %% -- - p("All info for agent <~w,~w>", [AgentAddr1, AgentPort1]), + ?IPRINT("All info for agent <~w,~w>", [AgentAddr1, AgentPort1]), ?line {ok, AllInfo1} = snmpm_config:agent_info(AgentAddr1, AgentPort1, all), - p("all agent info for agent: ~n ~p", [AllInfo1]), + ?IPRINT("all agent info for agent: ~n ~p", [AllInfo1]), %% -- - p("EngineID (~p) for agent <~w,~w>", [EngineID1, AgentAddr1, AgentPort1]), + ?IPRINT("EngineID (~p) for agent <~w,~w>", [EngineID1, AgentAddr1, AgentPort1]), ?line {ok, EngineID1} = snmpm_config:agent_info(AgentAddr1, AgentPort1, engine_id), %% -- - p("All info for agent <~w,~w>", [AgentAddr2, AgentPort2]), + ?IPRINT("All info for agent <~w,~w>", [AgentAddr2, AgentPort2]), ?line {ok, AllInfo2} = snmpm_config:agent_info(AgentAddr2, AgentPort2, all), - p("all agent info for agent: ~n ~p", [AllInfo2]), + ?IPRINT("all agent info for agent: ~n ~p", [AllInfo2]), %% -- - p("EngineID (~p) for agent <~w,~w>", [EngineID2, AgentAddr2, AgentPort2]), + ?IPRINT("EngineID (~p) for agent <~w,~w>", [EngineID2, AgentAddr2, AgentPort2]), ?line {ok, EngineID2} = snmpm_config:agent_info(AgentAddr2, AgentPort2, engine_id), @@ -1968,7 +2044,7 @@ register_agent_using_file(Conf) when is_list(Conf) -> ?line {ok, MMS2} = snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size), NewMMS21 = 2048, - p("try update agent info max-message-size to ~w for agent <~w,~w>", + ?IPRINT("try update agent info max-message-size to ~w for agent <~w,~w>", [NewMMS21, AgentAddr2, AgentPort2]), ?line ok = snmpm_config:update_agent_info(UserId2, AgentAddr2, AgentPort2, max_message_size, NewMMS21), @@ -1976,34 +2052,29 @@ register_agent_using_file(Conf) when is_list(Conf) -> snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size), %% -- - p("try (and fail) to update agent info max-message-size to ~w " + ?IPRINT("try (and fail) to update agent info max-message-size to ~w " "for agent <~w,~w> " "with user ~w (not owner)", [NewMMS21, AgentAddr2, AgentPort2, UserId1]), ?line {error, Reason01} = snmpm_config:update_agent_info(UserId1, AgentAddr2, AgentPort2, max_message_size, NewMMS21), - p("expected failure. Reason01: ~p", [Reason01]), + ?IPRINT("expected failure. Reason01: ~p", [Reason01]), ?line {ok, NewMMS21} = snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size), %% -- NewMMS22 = 400, - p("try (and fail) to update agent info max-message-size to ~w " + ?IPRINT("try (and fail) to update agent info max-message-size to ~w " "for agent <~w,~w>", [NewMMS22, AgentAddr2, AgentPort2]), ?line {error, Reason02} = snmpm_config:update_agent_info(UserId1, AgentAddr2, AgentPort2, max_message_size, NewMMS22), - p("expected failure. Reason02: ~p", [Reason02]), + ?IPRINT("expected failure. Reason02: ~p", [Reason02]), %% -- - p("stop config process"), - ?line ok = snmpm_config:stop(), - await_config_not_running(), - - %% -- - p("done"), + ?IPRINT("done"), ok. @@ -2015,8 +2086,8 @@ register_agent_using_function(suite) -> []; register_agent_using_function(doc) -> "Register agents using the API (function)."; register_agent_using_function(Conf) when is_list(Conf) -> - put(tname,raufu), - p("start"), + put(tname, "REG-AG-USING-FUNC"), + ?IPRINT("start"), process_flag(trap_exit, true), _ConfDir = ?config(manager_conf_dir, Conf), _DbDir = ?config(manager_db_dir, Conf), @@ -2032,8 +2103,8 @@ register_agent_failed_using_function1(doc) -> "Register agents failng using the API (function) with incorrect " "config (1)."; register_agent_failed_using_function1(Conf) when is_list(Conf) -> - put(tname,rafuf1), - p("start"), + put(tname, "REG-AG-FAIL-USING-FUNC-1"), + ?IPRINT("start"), process_flag(trap_exit, true), _ConfDir = ?config(manager_conf_dir, Conf), _DbDir = ?config(manager_db_dir, Conf), @@ -2054,8 +2125,8 @@ register_usm_user_using_file(suite) -> []; register_usm_user_using_file(doc) -> "Register usm user using the 'usm.conf' file."; register_usm_user_using_file(Conf) when is_list(Conf) -> - put(tname,ruuufi), - p("start"), + put(tname, "REG-USM-USER-USING-FILE"), + ?IPRINT("start"), process_flag(trap_exit, true), case ?CRYPTO_START() of @@ -2077,11 +2148,11 @@ register_usm_user_using_file(Conf) when is_list(Conf) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], %% -- - p("write manager config file"), + ?IPRINT("write manager config file"), write_manager_conf(ConfDir), %% -- - p("write usm user config file"), + ?IPRINT("write usm user config file"), SecEngineID = "loctzp's engine", SecName1 = "samu_auth1", UserName1 = SecName1, @@ -2101,31 +2172,31 @@ register_usm_user_using_file(Conf) when is_list(Conf) -> write_usm_conf(ConfDir, [UsmUser1, UsmUser2]), %% -- - p("start the config process"), + ?IPRINT("start the config process"), ?line {ok, _Pid} = config_start(Opts), %% -- - p("lookup 1 (ok)"), + ?IPRINT("lookup 1 (ok)"), ?line {ok, #usm_user{name = UserName1} = User1} = snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName1), - p("User: ~p", [User1]), + ?IPRINT("User: ~p", [User1]), - p("lookup 2 (ok)"), + ?IPRINT("lookup 2 (ok)"), ?line {ok, #usm_user{name = UserName2} = User2} = snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName2), - p("User: ~p", [User2]), + ?IPRINT("User: ~p", [User2]), - p("lookup 3 (error)"), + ?IPRINT("lookup 3 (error)"), ?line {error, not_found} = snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName2 ++ "_1"), %% -- - p("stop config process"), + ?IPRINT("stop config process"), ?line ok = snmpm_config:stop(), - await_config_not_running(), + config_ensure_not_running(), %% -- - p("done"), + ?IPRINT("done"), ok. @@ -2137,8 +2208,8 @@ register_usm_user_using_function(suite) -> []; register_usm_user_using_function(doc) -> "Register usm user using the API (function)."; register_usm_user_using_function(Conf) when is_list(Conf) -> - put(tname,ruuufu), - p("start"), + put(tname, "REG-USM-USER-USING-FUNC"), + ?IPRINT("start"), process_flag(trap_exit, true), case ?CRYPTO_START() of @@ -2160,18 +2231,18 @@ register_usm_user_using_function(Conf) when is_list(Conf) -> {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], %% -- - p("write manager config file"), + ?IPRINT("write manager config file"), write_manager_conf(ConfDir), %% -- - p("start the config process"), + ?IPRINT("start the config process"), ?line {ok, _Pid} = config_start(Opts), %% -- - p("register usm user's"), + ?IPRINT("register usm user's"), EngineID = "loctzp's engine", - p("register user 1 (ok)"), + ?IPRINT("register user 1 (ok)"), UserName1 = "samu_auth1", SecName1 = UserName1, UsmConfig1 = [{sec_name, SecName1}, @@ -2179,11 +2250,11 @@ register_usm_user_using_function(Conf) when is_list(Conf) -> {auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]}, {priv, usmNoPrivProtocol}], ?line ok = snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1), - p("try register user 1 again (error)"), + ?IPRINT("try register user 1 again (error)"), ?line {error, {already_registered, EngineID, UserName1}} = snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1), - p("register user 2 (ok)"), + ?IPRINT("register user 2 (ok)"), UserName2 = "samu_auth2", SecName2 = UserName2, UsmConfig2 = [{auth, usmHMACMD5AuthProtocol}, @@ -2191,7 +2262,7 @@ register_usm_user_using_function(Conf) when is_list(Conf) -> {priv, usmNoPrivProtocol}], ?line ok = snmpm_config:register_usm_user(EngineID, UserName2, UsmConfig2), - p("register user 3 (ok)"), + ?IPRINT("register user 3 (ok)"), UserName3 = "samu3", SecName3 = "samu_auth3", UsmConfig3 = [{sec_name, SecName3}, @@ -2200,32 +2271,32 @@ register_usm_user_using_function(Conf) when is_list(Conf) -> {priv, usmNoPrivProtocol}], ?line ok = snmpm_config:register_usm_user(EngineID, UserName3, UsmConfig3), - p("lookup 1 (ok)"), + ?IPRINT("lookup 1 (ok)"), ?line {ok, #usm_user{name = UserName1} = User1} = snmpm_config:get_usm_user_from_sec_name(EngineID, SecName1), - p("User: ~p", [User1]), + ?IPRINT("User: ~p", [User1]), - p("lookup 2 (ok)"), + ?IPRINT("lookup 2 (ok)"), ?line {ok, #usm_user{name = UserName2} = User2} = snmpm_config:get_usm_user_from_sec_name(EngineID, SecName2), - p("User: ~p", [User2]), + ?IPRINT("User: ~p", [User2]), - p("lookup 3 (ok)"), + ?IPRINT("lookup 3 (ok)"), ?line {ok, #usm_user{name = UserName3} = User3} = snmpm_config:get_usm_user_from_sec_name(EngineID, SecName3), - p("User: ~p", [User3]), + ?IPRINT("User: ~p", [User3]), - p("lookup 4 (error)"), + ?IPRINT("lookup 4 (error)"), ?line {error, not_found} = snmpm_config:get_usm_user_from_sec_name(EngineID, SecName3 ++ "_1"), %% -- - p("stop config process"), + ?IPRINT("stop config process"), ?line ok = snmpm_config:stop(), - await_config_not_running(), + config_ensure_not_running(), %% -- - p("done"), + ?IPRINT("done"), ok. @@ -2237,8 +2308,8 @@ register_usm_user_failed_using_function1(suite) -> []; register_usm_user_failed_using_function1(doc) -> "Register usm user failed using incorrect arguments to API (function)."; register_usm_user_failed_using_function1(Conf) when is_list(Conf) -> - put(tname,ruufufu1), - p("start"), + put(tname, "REG-USM-USER-FAIL-USING-FUNC"), + ?IPRINT("start"), process_flag(trap_exit, true), case ?CRYPTO_START() of @@ -2266,8 +2337,8 @@ update_usm_user_info(suite) -> []; update_usm_user_info(doc) -> "Update usm user info."; update_usm_user_info(Conf) when is_list(Conf) -> - put(tname,ruufufu1), - p("start"), + put(tname, "UPD-USM-USER-INFO"), + ?IPRINT("start"), process_flag(trap_exit, true), case ?CRYPTO_START() of @@ -2301,8 +2372,8 @@ create_and_increment(suite) -> []; create_and_increment(doc) -> "Craete and increment counters."; create_and_increment(Conf) when is_list(Conf) -> - put(tname,cai), - p("start"), + put(tname, "CRE-AND-INC"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -2317,10 +2388,6 @@ create_and_increment(Conf) when is_list(Conf) -> %% Random init ?SNMP_RAND_SEED(), - %% rand:seed(exrop, - %% {erlang:phash2([node()]), - %% erlang:monotonic_time(), - %% erlang:unique_integer()}), StartVal = rand:uniform(2147483647), IncVal = 42, @@ -2330,7 +2397,7 @@ create_and_increment(Conf) when is_list(Conf) -> ?line EndVal = snmpm_config:incr_counter(test_id, IncVal), ?line ok = snmpm_config:stop(), - await_config_not_running(), + config_ensure_not_running(), ok. @@ -2348,8 +2415,8 @@ stats_create_and_increment(suite) -> []; stats_create_and_increment(doc) -> "Create and increment statistics counters."; stats_create_and_increment(Conf) when is_list(Conf) -> - put(tname,scai), - p("start"), + put(tname, "STATS-CRE-AND-INC"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -2362,26 +2429,26 @@ stats_create_and_increment(Conf) when is_list(Conf) -> ?line {ok, _Pid} = snmpm_config:start_link(Opts), - p("stats table (1): ~p", [ets:tab2list(snmpm_stats_table)]), + ?IPRINT("stats table (1): ~p", [ets:tab2list(snmpm_stats_table)]), ?line 0 = snmpm_config:maybe_cre_stats_counter(stats1, 0), - p("stats table (2): ~p", [ets:tab2list(snmpm_stats_table)]), + ?IPRINT("stats table (2): ~p", [ets:tab2list(snmpm_stats_table)]), ?line ok = snmpm_config:maybe_cre_stats_counter(stats1, 0), - p("stats table (3): ~p", [ets:tab2list(snmpm_stats_table)]), + ?IPRINT("stats table (3): ~p", [ets:tab2list(snmpm_stats_table)]), ?line 1 = snmpm_config:maybe_cre_stats_counter(stats2, 1), - p("stats table (4): ~p", [ets:tab2list(snmpm_stats_table)]), + ?IPRINT("stats table (4): ~p", [ets:tab2list(snmpm_stats_table)]), ?line 10 = snmpm_config:cre_stats_counter(stats3, 10), - p("stats table (5): ~p", [ets:tab2list(snmpm_stats_table)]), + ?IPRINT("stats table (5): ~p", [ets:tab2list(snmpm_stats_table)]), Stats1Inc = fun() -> snmpm_config:incr_stats_counter(stats1, 1) end, ?line 10 = loop(10, -1, Stats1Inc), - p("stats table (6): ~p", [ets:tab2list(snmpm_stats_table)]), + ?IPRINT("stats table (6): ~p", [ets:tab2list(snmpm_stats_table)]), ?line ok = snmpm_config:reset_stats_counter(stats1), ?line 10 = loop(10, -1, Stats1Inc), ?line ok = snmpm_config:stop(), - await_config_not_running(), + config_ensure_not_running(), ok. @@ -2403,46 +2470,46 @@ otp_7219(suite) -> otp_7219(doc) -> "Test-case for ticket OTP-7219"; otp_7219(Config) when is_list(Config) -> - put(tname, otp7219), - p("start"), + put(tname, "OTP-7219"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), - p("write manager configuration"), + ?IPRINT("write manager configuration"), write_manager_conf(ConfDir), Opts1 = [{versions, [v1]}, {inform_request_behaviour, user}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("start manager config"), + ?IPRINT("start manager config"), ?line {ok, _Pid1} = snmpm_config:start_link(Opts1), - p("get some manager config"), + ?IPRINT("get some manager config"), {ok, {user, _}} = snmpm_config:system_info(net_if_irb), - p("stop manager config"), + ?IPRINT("stop manager config"), ?line ok = snmpm_config:stop(), - await_config_not_running(), + config_ensure_not_running(), IRB_TO = 15322, Opts2 = [{versions, [v1]}, {inform_request_behaviour, {user, IRB_TO}}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("start manager config"), + ?IPRINT("start manager config"), ?line {ok, _Pid2} = snmpm_config:start_link(Opts2), - p("get some manager config"), + ?IPRINT("get some manager config"), {ok, {user, IRB_TO}} = snmpm_config:system_info(net_if_irb), - p("stop manager config"), + ?IPRINT("stop manager config"), ?line ok = snmpm_config:stop(), - await_config_not_running(), + config_ensure_not_running(), - p("done"), + ?IPRINT("done"), ok. @@ -2452,8 +2519,8 @@ otp_8395_1(suite) -> []; otp_8395_1(doc) -> "OTP-8395(1)"; otp_8395_1(Conf) when is_list(Conf) -> - put(tname, otp_8395_1), - p("start"), + put(tname, "OTP-8395-1"), + ?IPRINT("start"), process_flag(trap_exit, true), otp8395(Conf, false, ok), ok. @@ -2462,8 +2529,8 @@ otp_8395_2(suite) -> []; otp_8395_2(doc) -> "OTP-8395(2)"; otp_8395_2(Conf) when is_list(Conf) -> - put(tname, otp_8395_2), - p("start"), + put(tname, "OTP-8395-2"), + ?IPRINT("start"), process_flag(trap_exit, true), otp8395(Conf, true, ok), ok. @@ -2472,8 +2539,8 @@ otp_8395_3(suite) -> []; otp_8395_3(doc) -> "OTP-8395(3)"; otp_8395_3(Conf) when is_list(Conf) -> - put(tname, otp_8395_3), - p("start"), + put(tname, "OTP-8395-3"), + ?IPRINT("start"), process_flag(trap_exit, true), otp8395(Conf, gurka, error), ok. @@ -2487,7 +2554,7 @@ otp8395(Conf, SeqNoVal, Expect) -> write_manager_conf(ConfDir), %% Third set of options (no versions): - p("all options"), + ?IPRINT("all options"), NetIfOpts = [{module, snmpm_net_if}, {verbosity, trace}, {options, [{recbuf, 30000}, @@ -2526,7 +2593,7 @@ otp8395(Conf, SeqNoVal, Expect) -> Error when (Expect =:= ok) -> exit({unexpected_failed_starting_config, SeqNoVal, Error}) end, - p("done"), + ?IPRINT("done"), ok. @@ -2534,8 +2601,8 @@ otp_8395_4(suite) -> []; otp_8395_4(doc) -> "OTP-8395(4)"; otp_8395_4(Conf) when is_list(Conf) -> - put(tname, otp_8395_4), - p("start"), + put(tname, "OTP-8395-4"), + ?IPRINT("start"), process_flag(trap_exit, true), snmp:print_version_info(), @@ -2548,7 +2615,7 @@ otp_8395_4(Conf) when is_list(Conf) -> write_manager_conf(ConfDir), %% Third set of options (no versions): - p("all options"), + ?IPRINT("all options"), NetIfOpts = [{module, snmpm_net_if}, {verbosity, trace}, {options, [{recbuf, 30000}, @@ -2595,7 +2662,7 @@ otp_8395_4(Conf) when is_list(Conf) -> ?line ok = config_stop(), - p("done"), + ?IPRINT("done"), ok. @@ -2607,52 +2674,17 @@ otp8395_incr_counter(Counter, Initial, Increment, Max) -> %% Internal functions %%====================================================================== -await_config_not_running() -> - await_not_running(snmpm_config, 5). - -await_not_running(Name, 0) -> - p("await_not_running -> done waiting for ~w to die - try kill it", [Name]), - %% Ok, we tried it the nice way, now use brute force - await_killed(Name, 5); -await_not_running(Name, N) when N > 0 -> - p("await_not_running -> is process ~w still running (~w)", [Name, N]), - case erlang:whereis(Name) of - undefined -> - p("await_not_running -> no such (~w) process - sleep some",[Name]), - ?SLEEP(1000), - p("await_not_running -> no such (~w) process - done", [Name]), - ok; - Pid when is_pid(Pid) -> - p("~w process still running", [Name]), - ?SLEEP(500), - await_not_running(Name, N-1) - end. - -await_killed(Name, 0) -> - p("await_killed -> could not kill ~w => giving up", [Name]), - exit({error, {failed_terminating, Name}}); -await_killed(Name, N) when N > 0 -> - p("await_killed -> is process ~w still running (~w)", [Name, N]), - case whereis(Name) of - undefined -> - p("await_killed -> no such (~w) process - sleep some", [Name]), - ?SLEEP(1000), - p("await_killed -> no such (~w) process - done", [Name]), - ok; - Pid when is_pid(Pid) -> - p("await_killed -> ~w still running - try kill it", [Name]), - exit(Pid, kill), - ?SLEEP(1000), - await_killed(Name, N-1) - end. - - config_start(Opts) -> (catch snmpm_config:start_link(Opts)). config_stop() -> (catch snmpm_config:stop()). +config_ensure_not_running() -> + ?ENSURE_NOT_RUNNING(snmpm_config, + fun() -> snmpm_config:stop() end, + 1000). + %% ------ @@ -2809,20 +2841,5 @@ verify_dir_existing(DirName, Dir) -> %% ------ str(X) -> - lists:flatten(io_lib:format("~w", [X])). - - -%% ------ - -p(F) -> - p(F, []). - -p(F, A) -> - p(get(tname), F, A). - -p(TName, F, A) -> - io:format("*** [~s] ***" - " ~w -> " ++ F ++ "~n", [formated_timestamp(),TName|A]). + ?F("~w", [X]). -formated_timestamp() -> - snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/test/snmp_manager_user_SUITE.erl b/lib/snmp/test/snmp_manager_user_SUITE.erl index 353f1b21f3..eca0d8a4f9 100644 --- a/lib/snmp/test/snmp_manager_user_SUITE.erl +++ b/lib/snmp/test/snmp_manager_user_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2019. All Rights Reserved. +%% Copyright Ericsson AB 2004-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -143,8 +143,8 @@ tickets_cases() -> init_per_suite(Config0) when is_list(Config0) -> - p("init_per_suite -> entry with" - "~n Config0: ~p", [Config0]), + ?IPRINT("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), case ?LIB:init_per_suite(Config0) of {skip, _} = SKIP -> @@ -153,19 +153,23 @@ init_per_suite(Config0) when is_list(Config0) -> snmp_test_sys_monitor:start(), Config2 = snmp_test_lib:init_suite_top_dir(?MODULE, Config1), - p("init_per_suite -> done when" - "~n Config: ~p", [Config2]), + ?IPRINT("init_per_suite -> done when" + "~n Config: ~p", [Config2]), Config2 end. end_per_suite(Config) when is_list(Config) -> - p("end_per_suite -> entry with" - "~n Config: ~p", [Config]), + ?IPRINT("end_per_suite -> entry with" + "~n Config: ~p", [Config]), snmp_test_sys_monitor:stop(), - ?LIB:end_per_suite(Config). + Config1 = ?LIB:end_per_suite(Config), + + ?IPRINT("end_per_suite -> end"), + + Config1. @@ -186,14 +190,15 @@ end_per_group(_GroupName, Config) -> %% init_per_testcase(Case, Config) when is_list(Config) -> - p("init_per_testcase -> Case: ~p", [Case]), + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), snmp_test_global_sys_monitor:reset_events(), SuiteTopDir = ?config(snmp_suite_top_dir, Config), CaseTopDir = filename:join(SuiteTopDir, atom_to_list(Case)), ?line ok = file:make_dir(CaseTopDir), - p("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]), + ?IPRINT("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]), MgrTopDir = filename:join(CaseTopDir, "manager/"), ?line ok = file:make_dir(MgrTopDir), MgrConfDir = filename:join(MgrTopDir, "conf/"), @@ -202,18 +207,27 @@ init_per_testcase(Case, Config) when is_list(Config) -> ?line ok = file:make_dir(MgrDbDir), MgrLogDir = filename:join(MgrTopDir, "log/"), ?line ok = file:make_dir(MgrLogDir), - [{case_top_dir, CaseTopDir}, - {manager_dir, MgrTopDir}, - {manager_conf_dir, MgrConfDir}, - {manager_db_dir, MgrDbDir}, - {manager_log_dir, MgrLogDir} | Config]. + Config1 = [{case_top_dir, CaseTopDir}, + {manager_dir, MgrTopDir}, + {manager_conf_dir, MgrConfDir}, + {manager_db_dir, MgrDbDir}, + {manager_log_dir, MgrLogDir} | Config], + + ?IPRINT("init_per_testcase -> done when" + "~n Config: ~p", [Config1]), + + Config1. + + +end_per_testcase(_Case, Config) when is_list(Config) -> -end_per_testcase(Case, Config) when is_list(Config) -> - p("end_per_testcase -> Case: ~p", [Case]), + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p", + [Config]), - p("system events during test: " - "~n ~p~n", [snmp_test_global_sys_monitor:events()]), + ?IPRINT("system events during test: ~p", + [snmp_test_global_sys_monitor:events()]), Config. @@ -228,7 +242,7 @@ simple_register_and_unregister1(doc) -> "Start a user, register and unregister the user."; simple_register_and_unregister1(Conf) when is_list(Conf) -> put(tname,srar1), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -241,7 +255,7 @@ simple_register_and_unregister1(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -251,23 +265,23 @@ simple_register_and_unregister1(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid, Id), ?line [Id] = Users2 = which_users(), - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = unregister_user(Pid), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line stop_user(Pid), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -279,7 +293,7 @@ simple_register_and_unregister2(doc) -> "register 2 users (per that process) and unregister the 2 users."; simple_register_and_unregister2(Conf) when is_list(Conf) -> put(tname,srar2), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -292,7 +306,7 @@ simple_register_and_unregister2(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -303,7 +317,7 @@ simple_register_and_unregister2(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid, Id1), ?line ok = register_user(Pid, Id2), @@ -316,20 +330,20 @@ simple_register_and_unregister2(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = unregister_user(Pid, Id1), ?line ok = unregister_user(Pid, Id2), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line stop_user(Pid), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -341,7 +355,7 @@ simple_register_and_unregister3(doc) -> "register one users per process and unregister the 2 users."; simple_register_and_unregister3(Conf) when is_list(Conf) -> put(tname,srar2), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -354,7 +368,7 @@ simple_register_and_unregister3(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -366,7 +380,7 @@ simple_register_and_unregister3(Conf) when is_list(Conf) -> ?line Pid2 = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid1, Id1), ?line ok = register_user(Pid2, Id2), @@ -379,21 +393,21 @@ simple_register_and_unregister3(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = unregister_user(Pid1, Id1), ?line ok = unregister_user(Pid2, Id2), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line stop_user(Pid1), ?line stop_user(Pid2), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -404,7 +418,7 @@ register_and_crash1(doc) -> "Start a user, register and crash user."; register_and_crash1(Conf) when is_list(Conf) -> put(tname,racau1), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -417,7 +431,7 @@ register_and_crash1(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -427,22 +441,22 @@ register_and_crash1(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid, Id), ?line [Id] = Users2 = which_users(), - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = simulate_crash(Pid), ?line [Id] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -454,7 +468,7 @@ register_and_crash2(doc) -> "register 2 users (per that process) and crash the process."; register_and_crash2(Conf) when is_list(Conf) -> put(tname,racau2), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -467,7 +481,7 @@ register_and_crash2(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -478,7 +492,7 @@ register_and_crash2(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid, Id1), ?line ok = register_user(Pid, Id2), @@ -491,7 +505,7 @@ register_and_crash2(Conf) when is_list(Conf) -> Else1 -> ?FAIL({invalid_users, Else1}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = simulate_crash(Pid), @@ -503,12 +517,12 @@ register_and_crash2(Conf) when is_list(Conf) -> Else2 -> ?FAIL({invalid_users, Else2}) end, - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -521,7 +535,7 @@ register_and_crash3(doc) -> "crash the first user process."; register_and_crash3(Conf) when is_list(Conf) -> %% put(tname,rac3), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -534,7 +548,7 @@ register_request_and_crash1(doc) -> "register user, send request and crash user."; register_request_and_crash1(Conf) when is_list(Conf) -> %% put(tname,rrac1), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -548,7 +562,7 @@ register_request_and_crash2(doc) -> "send a request for each user and crash the single user process."; register_request_and_crash2(Conf) when is_list(Conf) -> %% put(tname,rrac2), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -562,7 +576,7 @@ register_request_and_crash3(doc) -> "send a request for each user and crash the first user process."; register_request_and_crash3(Conf) when is_list(Conf) -> %% put(tname,rrac3), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -574,7 +588,7 @@ simple_register_monitor_and_unregister1(doc) -> "Start a user, register-link and unregister the user."; simple_register_monitor_and_unregister1(Conf) when is_list(Conf) -> put(tname,srlau1), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -587,41 +601,41 @@ simple_register_monitor_and_unregister1(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), Id = make_ref(), - p("start user"), + ?IPRINT("start user"), ?line Pid = start_user(), - p("get users (=0)"), + ?IPRINT("get users (=0)"), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), - p("register monitored user"), + ?IPRINT("register monitored user"), ?line ok = register_user_monitor(Pid, Id), - p("get users (=1)"), + ?IPRINT("get users (=1)"), ?line [Id] = Users2 = which_users(), - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), - p("unregister monitored user"), + ?IPRINT("unregister monitored user"), ?line unregister_user(Pid), - p("get users (=0)"), + ?IPRINT("get users (=0)"), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), - p("start user"), + ?IPRINT("start user"), ?line stop_user(Pid), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -634,7 +648,7 @@ simple_register_monitor_and_unregister2(doc) -> "unregister the 2 users."; simple_register_monitor_and_unregister2(Conf) when is_list(Conf) -> put(tname,srlau2), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -647,7 +661,7 @@ simple_register_monitor_and_unregister2(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -658,7 +672,7 @@ simple_register_monitor_and_unregister2(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user_monitor(Pid, Id1), ?line ok = register_user_monitor(Pid, Id2), @@ -671,19 +685,19 @@ simple_register_monitor_and_unregister2(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = unregister_user(Pid, Id1), ?line ok = unregister_user(Pid, Id2), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line stop_user(Pid), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -697,7 +711,7 @@ simple_register_monitor_and_unregister3(doc) -> "unregister the 2 users."; simple_register_monitor_and_unregister3(Conf) when is_list(Conf) -> put(tname,srlau3), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -710,7 +724,7 @@ simple_register_monitor_and_unregister3(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -721,7 +735,7 @@ simple_register_monitor_and_unregister3(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid, Id1), ?line ok = register_user_monitor(Pid, Id2), @@ -734,18 +748,18 @@ simple_register_monitor_and_unregister3(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line unregister_user(Pid), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line stop_user(Pid), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -756,7 +770,7 @@ register_monitor_and_crash1(doc) -> "Start a user, register-monitor and crash the user."; register_monitor_and_crash1(Conf) when is_list(Conf) -> put(tname,rlac1), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -769,7 +783,7 @@ register_monitor_and_crash1(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -779,24 +793,24 @@ register_monitor_and_crash1(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user_monitor(Pid, Id), ?line [Id] = Users2 = which_users(), - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = simulate_crash(Pid), ?SLEEP(1000), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -809,7 +823,7 @@ register_monitor_and_crash2(doc) -> "and crash the single user process."; register_monitor_and_crash2(Conf) when is_list(Conf) -> put(tname,rlac2), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -822,7 +836,7 @@ register_monitor_and_crash2(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -833,7 +847,7 @@ register_monitor_and_crash2(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user_monitor(Pid, Id1), ?line ok = register_user_monitor(Pid, Id2), @@ -846,19 +860,19 @@ register_monitor_and_crash2(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = simulate_crash(Pid), ?SLEEP(1000), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -901,7 +915,7 @@ register_monitor_and_crash3(Conf) when is_list(Conf) -> ?NON_PC_TC_MAYBE_SKIP(Conf, Condition), %% </CONDITIONAL-SKIP> - p("start"), + ?IPRINT("start"), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), @@ -913,7 +927,7 @@ register_monitor_and_crash3(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -924,7 +938,7 @@ register_monitor_and_crash3(Conf) when is_list(Conf) -> ?line Pid = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user(Pid, Id1), ?line ok = register_user_monitor(Pid, Id2), @@ -937,19 +951,19 @@ register_monitor_and_crash3(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = simulate_crash(Pid), ?SLEEP(1000), ?line [Id1] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -962,7 +976,7 @@ register_monitor_and_crash4(doc) -> "and crash the first user process."; register_monitor_and_crash4(Conf) when is_list(Conf) -> put(tname,rlac4), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -975,7 +989,7 @@ register_monitor_and_crash4(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("start manager"), + ?IPRINT("start manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -983,12 +997,12 @@ register_monitor_and_crash4(Conf) when is_list(Conf) -> Id1 = make_ref(), Id2 = make_ref(), - p("start user processes"), + ?IPRINT("start user processes"), ?line Pid1 = start_user(), ?line Pid2 = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user_monitor(Pid1, Id1), ?line ok = register_user_monitor(Pid2, Id2), @@ -1001,21 +1015,21 @@ register_monitor_and_crash4(Conf) when is_list(Conf) -> Else -> ?FAIL({invalid_users, Else}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = simulate_crash(Pid1), ?SLEEP(1000), ?line [Id2] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line stop_user(Pid2), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -1030,7 +1044,7 @@ register_monitor_and_crash5(doc) -> "and crash the first user process."; register_monitor_and_crash5(Conf) when is_list(Conf) -> put(tname,rlac4), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -1043,7 +1057,7 @@ register_monitor_and_crash5(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("start manager"), + ?IPRINT("start manager"), ?line ok = snmpm:start_link(Opts), ?SLEEP(1000), @@ -1051,12 +1065,12 @@ register_monitor_and_crash5(Conf) when is_list(Conf) -> Id1 = gurka, %% make_ref(), Id2 = tomat, %% make_ref(), - p("start user processes"), + ?IPRINT("start user processes"), ?line Pid1 = start_user(), ?line Pid2 = start_user(), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = register_user_monitor(Pid1, Id1), ?line ok = register_user_monitor(Pid2, Id2), @@ -1090,9 +1104,9 @@ register_monitor_and_crash5(Conf) when is_list(Conf) -> U3 -> ?FAIL({invalid_users, U3}) end, - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), - p("verify all agent(s): expect 2"), + ?IPRINT("verify all agent(s): expect 2"), ?line Agents1 = case which_agents() of [TargetName1, TargetName2] = A1 -> A1; @@ -1101,25 +1115,25 @@ register_monitor_and_crash5(Conf) when is_list(Conf) -> A3 -> ?FAIL({invalid_agents, A3}) end, - p("Agents1: ~p", [Agents1]), + ?IPRINT("Agents1: ~p", [Agents1]), ?line ok = simulate_crash(Pid1), - p("wait some time"), + ?IPRINT("wait some time"), ?SLEEP(1000), ?line [Id2] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line [TargetName2] = Agents2 = which_agents(), - p("Agents2: ~p", [Agents2]), + ?IPRINT("Agents2: ~p", [Agents2]), ?line stop_user(Pid2), - p("stop manager"), + ?IPRINT("stop manager"), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -1132,7 +1146,7 @@ register_monitor_request_and_crash1(doc) -> "send request and crash the user."; register_monitor_request_and_crash1(Conf) when is_list(Conf) -> %% put(tname,rlrac1), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -1146,7 +1160,7 @@ register_monitor_request_and_crash2(doc) -> "send a request for each user and crash the single user process."; register_monitor_request_and_crash2(Conf) when is_list(Conf) -> %% put(tname,rlrac2), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -1160,7 +1174,7 @@ register_monitor_request_and_crash3(doc) -> "send a request for each user and crash the single user process."; register_monitor_request_and_crash3(Conf) when is_list(Conf) -> %% put(tname,rlrac3), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -1176,7 +1190,7 @@ register_monitor_request_and_crash4(doc) -> "crash the first user process."; register_monitor_request_and_crash4(Conf) when is_list(Conf) -> %% put(tname,rlrac4), - %% p("start"), + %% ?IPRINT("start"), %% process_flag(trap_exit, true), ?SKIP(not_yet_implemented). @@ -1189,7 +1203,7 @@ otp7902(doc) -> "OTP-7902 - Start old user and make sure it wors."; otp7902(Conf) when is_list(Conf) -> put(tname, otp7902), - p("start"), + ?IPRINT("start"), process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), @@ -1202,27 +1216,27 @@ otp7902(Conf) when is_list(Conf) -> {note_store, [{verbosity, trace}]}, {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], - p("try starting manager"), + ?IPRINT("try starting manager"), ok = snmpm:start_link(Opts), ?SLEEP(1000), ?line [] = Users1 = which_users(), - p("Users1: ~p", [Users1]), + ?IPRINT("Users1: ~p", [Users1]), ?line ok = snmp_manager_user_old:start(), ?line [_] = Users2 = which_users(), - p("Users2: ~p", [Users2]), + ?IPRINT("Users2: ~p", [Users2]), ?line ok = snmp_manager_user_old:stop(), ?line [] = Users3 = which_users(), - p("Users3: ~p", [Users3]), + ?IPRINT("Users3: ~p", [Users3]), ?line ok = snmpm:stop(), - p("end"), + ?IPRINT("end"), ok. @@ -1306,15 +1320,3 @@ write_conf_file(Dir, File, Str) -> ?line ok = io:format(Fd, "~s", [Str]), file:close(Fd). - -%% ------ - -p(F) -> - p(F, []). - -p(F, A) -> - p(get(tname), F, A). - -p(TName, F, A) -> - io:format("~w -> " ++ F ++ "~n", [TName|A]). - diff --git a/lib/snmp/test/snmp_note_store_SUITE.erl b/lib/snmp/test/snmp_note_store_SUITE.erl index 832c03029e..3b6d9f9fcd 100644 --- a/lib/snmp/test/snmp_note_store_SUITE.erl +++ b/lib/snmp/test/snmp_note_store_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2019. All Rights Reserved. +%% Copyright Ericsson AB 2004-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -81,11 +81,34 @@ groups() -> %% ----- %% -init_per_suite(Config) when is_list(Config) -> - Config. +init_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("init_per_suite -> entry with" + "~n Config: ~p", [Config0]), -end_per_suite(Config) when is_list(Config) -> - Config. + case ?LIB:init_per_suite(Config0) of + {skip, _} = SKIP -> + SKIP; + + Config1 when is_list(Config1) -> + %% We need a monitor on this node also + snmp_test_sys_monitor:start(), + + ?IPRINT("init_per_suite -> end when" + "~n Config1: ~p", [Config1]), + + Config1 + end. + +end_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("end_per_suite -> entry with" + "~n Config: ~p", [Config0]), + + snmp_test_sys_monitor:stop(), + Config1 = ?LIB:end_per_suite(Config0), + + ?IPRINT("end_per_suite -> end"), + + Config1. @@ -106,9 +129,24 @@ end_per_group(_GroupName, Config) -> %% init_per_testcase(_Case, Config) when is_list(Config) -> + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + snmp_test_global_sys_monitor:reset_events(), + + ?IPRINT("init_per_testcase -> end"), + Config. end_per_testcase(_Case, Config) when is_list(Config) -> + + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p", + [Config]), + + ?IPRINT("system events during test: ~p", + [snmp_test_global_sys_monitor:events()]), + Config. @@ -143,42 +181,55 @@ notes(doc) -> ["Testing that it does what it is actually supposed to do, " "namilly to handle notes. "]; notes(Config) when is_list(Config) -> - - {ok, Handler, Pid} = note_store_handler_start(), - - io:format("sleep some before we begin the tests~n", []), - ?SLEEP(timer:seconds(1)), + Pre = fun() -> + ?IPRINT("try start note-store"), + case note_store_handler_start() of + {ok, Handler, Pid} -> + ?IPRINT("started - sleep some before we begin the tests"), + ?SLEEP(?SECS(1)), + {Handler, Pid}; + {error, Reason} -> + {skip, ?F("Failed starting note-store: ~p", [Reason])} + end + end, + Case = fun(State) -> do_notes(State, Config) end, + Post = fun({Handler, _Pid}) -> + note_store_handler_stop(Handler) + end, + ?TC_TRY(notes, Pre, Case, Post). + +do_notes({_, Pid}, _Config) -> %% Default lifetime is infinity. A note with lifetime %% infinity is permanent - io:format("create permanent note sune~n", []), + ?IPRINT("create permanent note: sune"), true = snmp_note_store:set_note(Pid, sune, 10), 10 = snmp_note_store:get_note(Pid, sune), 10 = snmp_note_store:get_note(Pid, sune), %% Lifetime is in 1/100 sec ticks, so 500 equals 5 seconds - io:format("create 5 sec note kalle~n", []), + ?IPRINT("create 5 sec note kalle"), true = snmp_note_store:set_note(Pid, 500, kalle, hobbe), - io:format("wait 1 sec~n", []), + ?IPRINT("wait 1 sec"), ?SLEEP(timer:seconds(1)), - io:format("get note kalle~n", []), + ?IPRINT("get note kalle"), hobbe = snmp_note_store:get_note(Pid, kalle), - io:format("wait 5 sec~n", []), + ?IPRINT("wait 5 sec"), ?SLEEP(timer:seconds(5)), - io:format("get note kalle again (now it should not exist)~n", []), + ?IPRINT("get note kalle again (now it should not exist)"), undefined = snmp_note_store:get_note(Pid, kalle), - io:format("create 5 sec note kalle~n", []), + ?IPRINT("create 5 sec note kalle"), true = snmp_note_store:set_note(Pid, 500, kalle, hobbe), - io:format("wait 6 sec (to allow timer to clean up note)~n", []), + ?IPRINT("wait 6 sec (to allow timer to clean up note)"), ?SLEEP(timer:seconds(6)), - io:format("get note kalle - should not exist~n", []), + ?IPRINT("get note kalle - should not exist"), undefined = snmp_note_store:get_note(Pid, kalle), - io:format("read the permanent note sune again~n", []), + ?IPRINT("read the permanent note sune again"), 10 = snmp_note_store:get_note(Pid, sune), - note_store_handler_stop(Handler), + ?IPRINT("done"), ok. @@ -190,47 +241,65 @@ info(suite) -> info(doc) -> ["Testing that we can retreive process info."]; info(Config) when is_list(Config) -> - - Prio = normal, - Mod = ?MODULE, - Opts = [{verbosity, trace}], - {ok, Pid} = snmp_note_store:start_link(Prio, Mod, Opts), + Pre = fun() -> + ?IPRINT("try start note-store"), + Prio = normal, + Mod = ?MODULE, + Opts = [{verbosity, trace}], + case snmp_note_store:start_link(Prio, Mod, Opts) of + {ok, Pid} -> + ?IPRINT("note-store started: ~p", [Pid]), + Pid; + {error, Reason} -> + {skip, ?F("Failed starting note-store: ~p", [Reason])} + end + end, + Case = fun(State) -> do_info(State, Config) end, + Post = fun(Pid) -> + ?IPRINT("attempt stop note-store"), + snmp_note_store:stop(Pid) + end, + ?TC_TRY(info, Pre, Case, Post). + +do_info(Pid, _Config) -> %% Get the info: + ?IPRINT("get initial info"), Info = snmp_note_store:info(Pid), - io:format("Info: ~p~n", [Info]), + ?IPRINT("Info: " + "~n ~p", [Info]), %% Verify content - io:format("get process memory~n", []), + ?IPRINT("verify content: get notes process memory"), {value, {process_memory, ProcMem}} = lists:keysearch(process_memory, 1, Info), - io:format("get notes process memory~n", []), + ?IPRINT("get notes process memory"), {value, {notes, NotesProcMem}} = lists:keysearch(notes, 1, ProcMem), - io:format("verify notes process memory~n", []), + ?IPRINT("verify notes process memory"), if is_integer(NotesProcMem) andalso (NotesProcMem > 0) -> ok; true -> throw({error, {bad_notes_proc_memery, NotesProcMem}}) end, - io:format("get timer process memory~n", []), + ?IPRINT("verify content: get timer process memory"), {value, {timer, TmrProcMem}} = lists:keysearch(timer, 1, ProcMem), - io:format("verify timer process memory~n", []), + ?IPRINT("verify content: timer process memory"), if is_integer(TmrProcMem) andalso (TmrProcMem > 0) -> ok; true -> throw({error, {bad_timer_proc_memery, TmrProcMem}}) end, - io:format("get db memory~n", []), + ?IPRINT("verify content: get db memory"), {value, {db_memory, DbMem}} = lists:keysearch(db_memory, 1, Info), - io:format("get notes db memory~n", []), + ?IPRINT("verify content: get notes db memory"), {value, {notes, NotesDbMem}} = lists:keysearch(notes, 1, DbMem), - io:format("verify notes db memory~n", []), + ?IPRINT("verify content: notes db memory"), if is_integer(NotesDbMem) andalso (NotesDbMem > 0) -> ok; @@ -238,9 +307,7 @@ info(Config) when is_list(Config) -> throw({error, {bad_notes_db_memery, NotesDbMem}}) end, - - snmp_note_store:stop(Pid), - + ?IPRINT("done"), ok. @@ -251,23 +318,38 @@ garbage_in(suite) -> garbage_in(doc) -> ["Test that the process handles garbage sent to it."]; garbage_in(Config) when is_list(Config) -> - - io:format("start note_store server~n", []), - Prio = normal, - Mod = ?MODULE, - Opts = [{verbosity, trace}], - {ok, Pid} = snmp_note_store:start_link(Prio, Mod, Opts), - - io:format("issue bad request~n", []), + Pre = fun() -> + ?IPRINT("try start note-store"), + Prio = normal, + Mod = ?MODULE, + Opts = [{verbosity, trace}], + case snmp_note_store:start_link(Prio, Mod, Opts) of + {ok, Pid} -> + ?IPRINT("note-store started: ~p", [Pid]), + Pid; + {error, Reason} -> + {skip, ?F("Failed starting note-store: ~p", [Reason])} + end + end, + Case = fun(State) -> do_garbage_in(State, Config) end, + Post = fun(Pid) -> + ?IPRINT("attempt stop note-store"), + snmp_note_store:stop(Pid) + end, + ?TC_TRY(garbage_in, Pre, Case, Post). + +do_garbage_in(Pid, _Config) -> + + ?IPRINT("issue bad request"), {error, _} = gen_server:call(Pid, bad_request), - io:format("cast bad message~n", []), + ?IPRINT("cast bad message"), gen_server:cast(Pid, bad_message), - io:format("bang bad info~n", []), + ?IPRINT("bang bad info"), Pid ! bad_info, - io:format("verify note_Store server still alive and kicking~n", []), + ?IPRINT("verify note-store server still alive and kicking"), Info = snmp_note_store:info(Pid), if is_list(Info) andalso (length(Info) > 0) -> @@ -276,10 +358,7 @@ garbage_in(Config) when is_list(Config) -> throw({error, {bad_info, Info}}) end, - io:format("stop note_store server~n", []), - snmp_note_store:stop(Pid), - - io:format("done~n", []), + ?IPRINT("done"), ok. diff --git a/lib/snmp/test/snmp_pdus_SUITE.erl b/lib/snmp/test/snmp_pdus_SUITE.erl index f49e2eb602..d70e7aebd0 100644 --- a/lib/snmp/test/snmp_pdus_SUITE.erl +++ b/lib/snmp/test/snmp_pdus_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2019. All Rights Reserved. +%% Copyright Ericsson AB 2003-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -75,11 +75,34 @@ tickets_cases() -> %% ----- %% -init_per_suite(Config) when is_list(Config) -> - Config. +init_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("init_per_suite -> entry with" + "~n Config: ~p", [Config0]), -end_per_suite(Config) when is_list(Config) -> - Config. + case ?LIB:init_per_suite(Config0) of + {skip, _} = SKIP -> + SKIP; + + Config1 when is_list(Config1) -> + %% We need a monitor on this node also + snmp_test_sys_monitor:start(), + + ?IPRINT("init_per_suite -> end when" + "~n Config1: ~p", [Config1]), + + Config1 + end. + +end_per_suite(Config0) when is_list(Config0) -> + ?IPRINT("end_per_suite -> entry with" + "~n Config: ~p", [Config0]), + + snmp_test_sys_monitor:stop(), + Config1 = ?LIB:end_per_suite(Config0), + + ?IPRINT("end_per_suite -> end"), + + Config1. @@ -100,9 +123,24 @@ end_per_group(_GroupName, Config) -> %% init_per_testcase(_Case, Config) when is_list(Config) -> + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + snmp_test_global_sys_monitor:reset_events(), + + ?IPRINT("init_per_testcase -> end"), + Config. end_per_testcase(_Case, Config) when is_list(Config) -> + + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p", + [Config]), + + ?IPRINT("system events during test: ~p", + [snmp_test_global_sys_monitor:events()]), + Config. @@ -114,7 +152,7 @@ end_per_testcase(_Case, Config) when is_list(Config) -> otp7575(suite) -> []; otp7575(doc) -> ["OTP-7575 - Message version"]; otp7575(Config) when is_list(Config) -> - io:format("attempt to decode message with valid version~n", []), + ?IPRINT("attempt to decode message with valid version"), MsgWithOkVersion = <<48,39,2,1,0,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, case (catch dec_message(MsgWithOkVersion)) of Msg when is_record(Msg, message) -> @@ -123,7 +161,7 @@ otp7575(Config) when is_list(Config) -> exit({unexpected_decode_result, 1, Unexpected1}) end, - io:format("attempt to decode message with bad version~n", []), + ?IPRINT("attempt to decode message with bad version"), MsgWithBadVersion = <<48,48,2,10,1,1,1,1,1,1,1,1,1,1,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, case (catch dec_message(MsgWithBadVersion)) of {'EXIT', {bad_version, BadVersion}} when is_integer(BadVersion) -> @@ -132,7 +170,7 @@ otp7575(Config) when is_list(Config) -> exit({unexpected_decode_result, 2, Unexpected2}) end, - io:format("attempt to decode message with very bad version~n", []), + ?IPRINT("attempt to decode message with very bad version"), MsgWithVeryBadVersion = <<48,49,2,11,1,1,1,1,1,1,1,1,1,1,1,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, case (catch dec_message(MsgWithVeryBadVersion)) of {'EXIT', {bad_version, {VersionSize, MaxVersionSize}}} when (VersionSize > MaxVersionSize) -> @@ -140,7 +178,7 @@ otp7575(Config) when is_list(Config) -> Unexpected3 -> exit({unexpected_decode_result, 3, Unexpected3}) end, - io:format("done~n", []), + ?IPRINT("done"), ok. @@ -148,52 +186,52 @@ otp8563(suite) -> []; otp8563(doc) -> ["OTP-8563 - Counter64"]; otp8563(Config) when is_list(Config) -> Val1 = 16#7fffffffffffffff, - io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]), + ?IPRINT("try encode and decode value 1: ~w (0x~.16b)", [Val1, Val1]), Enc1 = snmp_pdus:enc_value('Counter64', Val1), - io:format(" => ~w~n", [Enc1]), + ?IPRINT(" => ~w", [Enc1]), {{'Counter64', Val1}, []} = snmp_pdus:dec_value(Enc1), Val2 = Val1 + 1, - io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]), + ?IPRINT("try encode and decode value 2: ~w (0x~.16b)", [Val2, Val2]), Enc2 = snmp_pdus:enc_value('Counter64', Val2), - io:format(" => ~w~n", [Enc2]), + ?IPRINT(" => ~w", [Enc2]), {{'Counter64', Val2}, []} = snmp_pdus:dec_value(Enc2), Val3 = Val2 + 1, - io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]), + ?IPRINT("try encode and decode value 3: ~w (0x~.16b)", [Val3, Val3]), Enc3 = snmp_pdus:enc_value('Counter64', Val3), - io:format(" => ~w~n", [Enc3]), + ?IPRINT(" => ~w", [Enc3]), {{'Counter64', Val3}, []} = snmp_pdus:dec_value(Enc3), Val4 = 16#fffffffffffffffe, - io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]), + ?IPRINT("try encode and decode value 4: ~w (0x~.16b)", [Val4, Val4]), Enc4 = snmp_pdus:enc_value('Counter64', Val4), - io:format(" => ~w~n", [Enc4]), + ?IPRINT(" => ~w", [Enc4]), {{'Counter64', Val4}, []} = snmp_pdus:dec_value(Enc4), Val5 = Val4 + 1, - io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]), + ?IPRINT("try encode and decode value 5: ~w (0x~.16b)", [Val5, Val5]), Enc5 = snmp_pdus:enc_value('Counter64', Val5), - io:format(" => ~w~n", [Enc5]), + ?IPRINT(" => ~w", [Enc5]), {{'Counter64', Val5}, []} = snmp_pdus:dec_value(Enc5), Val6 = 16#ffffffffffffffff + 1, - io:format("try and fail to encode value 6: ~w (0x~.16b)~n", [Val6, Val6]), + ?IPRINT("try and fail to encode value 6: ~w (0x~.16b)", [Val6, Val6]), case (catch snmp_pdus:enc_value('Counter64', Val6)) of {'EXIT', {error, {bad_counter64, Val6}}} -> ok; Unexpected6 -> - io:format(" => ~w~n", [Unexpected6]), + ?IPRINT(" => ~w", [Unexpected6]), exit({unexpected_encode_result, Unexpected6, Val6}) end, Val7 = -1, - io:format("try and fail to encode value 7: ~w~n", [Val7]), + ?IPRINT("try and fail to encode value 7: ~w", [Val7]), case (catch snmp_pdus:enc_value('Counter64', Val7)) of {'EXIT', {error, {bad_counter64, Val7}}} -> ok; Unexpected7 -> - io:format(" => ~w~n", [Unexpected7]), + ?IPRINT(" => ~w", [Unexpected7]), exit({unexpected_encode_result, Unexpected7, Val7}) end, @@ -204,70 +242,70 @@ otp9022(suite) -> []; otp9022(doc) -> ["OTP-9022 - Counter32"]; otp9022(Config) when is_list(Config) -> Val0 = 2908389204, - io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]), + ?IPRINT("try encode and decode value 0: ~w (0x~.16b)", [Val0, Val0]), Enc0 = snmp_pdus:enc_value('Counter32', Val0), - io:format(" => ~w~n", [Enc0]), + ?IPRINT(" => ~w", [Enc0]), {{'Counter32', Val0}, []} = snmp_pdus:dec_value(Enc0), Val1 = 0, - io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]), + ?IPRINT("try encode and decode value 1: ~w (0x~.16b)", [Val1, Val1]), Enc1 = snmp_pdus:enc_value('Counter32', Val1), - io:format(" => ~w~n", [Enc1]), + ?IPRINT(" => ~w", [Enc1]), {{'Counter32', Val1}, []} = snmp_pdus:dec_value(Enc1), Val2 = Val1 + 1, - io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]), + ?IPRINT("try encode and decode value 2: ~w (0x~.16b)", [Val2, Val2]), Enc2 = snmp_pdus:enc_value('Counter32', Val2), - io:format(" => ~w~n", [Enc2]), + ?IPRINT(" => ~w", [Enc2]), {{'Counter32', Val2}, []} = snmp_pdus:dec_value(Enc2), Val3 = 16#7ffffffe, - io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]), + ?IPRINT("try encode and decode value 3: ~w (0x~.16b)", [Val3, Val3]), Enc3 = snmp_pdus:enc_value('Counter32', Val3), - io:format(" => ~w~n", [Enc3]), + ?IPRINT(" => ~w", [Enc3]), {{'Counter32', Val3}, []} = snmp_pdus:dec_value(Enc3), Val4 = Val3 + 1, - io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]), + ?IPRINT("try encode and decode value 4: ~w (0x~.16b)", [Val4, Val4]), Enc4 = snmp_pdus:enc_value('Counter32', Val4), - io:format(" => ~w~n", [Enc4]), + ?IPRINT(" => ~w", [Enc4]), {{'Counter32', Val4}, []} = snmp_pdus:dec_value(Enc4), Val5 = Val4 + 1, - io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]), + ?IPRINT("try encode and decode value 5: ~w (0x~.16b)", [Val5, Val5]), Enc5 = snmp_pdus:enc_value('Counter32', Val5), - io:format(" => ~w~n", [Enc5]), + ?IPRINT(" => ~w", [Enc5]), {{'Counter32', Val5}, []} = snmp_pdus:dec_value(Enc5), Val6 = 16#fffffffe, - io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]), + ?IPRINT("try encode and decode value 6: ~w (0x~.16b)", [Val6, Val6]), Enc6 = snmp_pdus:enc_value('Counter32', Val6), - io:format(" => ~w~n", [Enc6]), + ?IPRINT(" => ~w", [Enc6]), {{'Counter32', Val6}, []} = snmp_pdus:dec_value(Enc6), Val7 = Val6 + 1, - io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]), + ?IPRINT("try encode and decode value 7: ~w (0x~.16b)", [Val7, Val7]), Enc7 = snmp_pdus:enc_value('Counter32', Val7), - io:format(" => ~w~n", [Enc7]), + ?IPRINT(" => ~w", [Enc7]), {{'Counter32', Val7}, []} = snmp_pdus:dec_value(Enc7), Val8 = 16#ffffffff + 1, - io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]), + ?IPRINT("try and fail to encode value 8: ~w (0x~.16b)", [Val8, Val8]), case (catch snmp_pdus:enc_value('Counter32', Val8)) of {'EXIT', {error, {bad_counter32, Val8}}} -> ok; Unexpected8 -> - io:format(" => ~w~n", [Unexpected8]), + ?IPRINT(" => ~w", [Unexpected8]), exit({unexpected_encode_result, Unexpected8, Val8}) end, Val9 = -1, - io:format("try and fail to encode value 9: ~w~n", [Val9]), + ?IPRINT("try and fail to encode value 9: ~w", [Val9]), case (catch snmp_pdus:enc_value('Counter32', Val9)) of {'EXIT', {error, {bad_counter32, Val9}}} -> ok; Unexpected9 -> - io:format(" => ~w~n", [Unexpected9]), + ?IPRINT(" => ~w", [Unexpected9]), exit({unexpected_encode_result, Unexpected9, Val9}) end, @@ -278,74 +316,74 @@ otp10132(suite) -> []; otp10132(doc) -> ["OTP-10132 - TimeTicks"]; otp10132(Config) when is_list(Config) -> Val0 = 2159001034, - io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]), + ?IPRINT("try encode and decode value 0: ~w (0x~.16b)", [Val0, Val0]), Enc0 = snmp_pdus:enc_value('TimeTicks', Val0), - io:format(" => ~w~n", [Enc0]), + ?IPRINT(" => ~w", [Enc0]), {{'TimeTicks', Val0}, []} = snmp_pdus:dec_value(Enc0), Val1 = 0, - io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]), + ?IPRINT("try encode and decode value 1: ~w (0x~.16b)", [Val1, Val1]), Enc1 = snmp_pdus:enc_value('TimeTicks', Val1), - io:format(" => ~w~n", [Enc1]), + ?IPRINT(" => ~w", [Enc1]), {{'TimeTicks', Val1}, []} = snmp_pdus:dec_value(Enc1), Val2 = Val1 + 1, - io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]), + ?IPRINT("try encode and decode value 2: ~w (0x~.16b)", [Val2, Val2]), Enc2 = snmp_pdus:enc_value('TimeTicks', Val2), - io:format(" => ~w~n", [Enc2]), + ?IPRINT(" => ~w", [Enc2]), {{'TimeTicks', Val2}, []} = snmp_pdus:dec_value(Enc2), Val3 = 16#7ffffffe, - io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]), + ?IPRINT("try encode and decode value 3: ~w (0x~.16b)", [Val3, Val3]), Enc3 = snmp_pdus:enc_value('TimeTicks', Val3), - io:format(" => ~w~n", [Enc3]), + ?IPRINT(" => ~w", [Enc3]), {{'TimeTicks', Val3}, []} = snmp_pdus:dec_value(Enc3), Val4 = Val3 + 1, - io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]), + ?IPRINT("try encode and decode value 4: ~w (0x~.16b)", [Val4, Val4]), Enc4 = snmp_pdus:enc_value('TimeTicks', Val4), - io:format(" => ~w~n", [Enc4]), + ?IPRINT(" => ~w", [Enc4]), {{'TimeTicks', Val4}, []} = snmp_pdus:dec_value(Enc4), Val5 = Val4 + 1, - io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]), + ?IPRINT("try encode and decode value 5: ~w (0x~.16b)", [Val5, Val5]), Enc5 = snmp_pdus:enc_value('TimeTicks', Val5), - io:format(" => ~w~n", [Enc5]), + ?IPRINT(" => ~w", [Enc5]), {{'TimeTicks', Val5}, []} = snmp_pdus:dec_value(Enc5), Val6 = 16#fffffffe, - io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]), + ?IPRINT("try encode and decode value 6: ~w (0x~.16b)", [Val6, Val6]), Enc6 = snmp_pdus:enc_value('TimeTicks', Val6), - io:format(" => ~w~n", [Enc6]), + ?IPRINT(" => ~w", [Enc6]), {{'TimeTicks', Val6}, []} = snmp_pdus:dec_value(Enc6), Val7 = Val6 + 1, - io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]), + ?IPRINT("try encode and decode value 7: ~w (0x~.16b)", [Val7, Val7]), Enc7 = snmp_pdus:enc_value('TimeTicks', Val7), - io:format(" => ~w~n", [Enc7]), + ?IPRINT(" => ~w", [Enc7]), {{'TimeTicks', Val7}, []} = snmp_pdus:dec_value(Enc7), Val8 = Val7 + 1, - io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]), + ?IPRINT("try and fail to encode value 8: ~w (0x~.16b)", [Val8, Val8]), case (catch snmp_pdus:enc_value('TimeTicks', Val8)) of {'EXIT', {error, {bad_timeticks, Val8}}} -> ok; Unexpected8 -> - io:format(" => ~w~n", [Unexpected8]), + ?IPRINT(" => ~w", [Unexpected8]), exit({unexpected_encode_result, Unexpected8, Val8}) end, Val9 = -1, - io:format("try and fail to encode value 9: ~w~n", [Val9]), + ?IPRINT("try and fail to encode value 9: ~w", [Val9]), case (catch snmp_pdus:enc_value('TimeTicks', Val9)) of {'EXIT', {error, {bad_timeticks, Val9}}} -> ok; Unexpected9 -> - io:format(" => ~w~n", [Unexpected9]), + ?IPRINT(" => ~w", [Unexpected9]), exit({unexpected_encode_result, Unexpected9, Val9}) end, - io:format("done~n", []), + ?IPRINT("done"), ok. diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl index e8bcfa8a0e..3e445174ba 100644 --- a/lib/snmp/test/snmp_test_lib.erl +++ b/lib/snmp/test/snmp_test_lib.erl @@ -42,12 +42,14 @@ -export([ping/1, local_nodes/0, nodes_on/1]). -export([start_node/2, stop_node/1]). -export([is_app_running/1, - is_crypto_running/0, is_mnesia_running/0, is_snmp_running/0]). + is_crypto_running/0, is_mnesia_running/0, is_snmp_running/0, + ensure_not_running/3]). -export([crypto_start/0, crypto_support/0]). -export([watchdog/3, watchdog_start/1, watchdog_start/2, watchdog_stop/1]). -export([del_dir/1]). --export([cover/1]). --export([f/2, p/2, print1/2, print2/2, print/5, formated_timestamp/0]). +-export([f/2, formated_timestamp/0]). +-export([p/2, print1/2, print2/2, print/5]). +-export([eprint/2, wprint/2, nprint/2, iprint/2]). -define(SKIP(R), skip(R, ?MODULE, ?LINE)). @@ -97,20 +99,24 @@ tc_try(Case, TCCond, Pre, TC, Post) tc_begin(Case), try TCCond() of ok -> + tc_print("starting: try pre"), try Pre() of State -> + tc_print("pre done: try test case"), try begin TC(State), sleep(seconds(1)), + tc_print("test case done: try post"), (catch Post(State)), tc_end("ok") end catch C:{skip, _} = SKIP when (C =:= throw) orelse (C =:= exit) -> + tc_print("test case (~w) skip: try post", [C]), (catch Post(State)), - tc_end( f("skipping(catched,~w,tc)", [C]) ), + tc_end( f("skipping(catched,~w,tc)", [C]) ), SKIP; C:E:S -> %% We always check the system events @@ -119,17 +125,18 @@ tc_try(Case, TCCond, Pre, TC, Post) %% generate sys events itself... case snmp_test_global_sys_monitor:events() of [] -> + tc_print("test case failed: try post"), (catch Post(State)), tc_end( f("failed(catched,~w,tc)", [C]) ), erlang:raise(C, E, S); SysEvs -> - tc_print("System Events received: " + tc_print("System Events received during tc: " "~n ~p" "~nwhen tc failed:" "~n C: ~p" "~n E: ~p" "~n S: ~p", - [SysEvs, C, E, S], "", ""), + [SysEvs, C, E, S]), (catch Post(State)), tc_end( f("skipping(catched-sysevs,~w,tc)", [C]) ), @@ -147,16 +154,22 @@ tc_try(Case, TCCond, Pre, TC, Post) %% before we accept a failure case snmp_test_global_sys_monitor:events() of [] -> - tc_end( f("failed(catched,~w,tc-pre)", [C]) ), - erlang:raise(C, E, S); - SysEvs -> - tc_print("System Events received: " - "~n ~p" - "~nwhen tc-pre failed:" + tc_print("tc-pre failed: auto-skip" "~n C: ~p" "~n E: ~p" "~n S: ~p", - [SysEvs, C, E, S], "", ""), + [C, E, S]), + tc_end( f("auto-skip(catched,~w,tc-pre)", [C]) ), + SKIP = {skip, f("TC-Pre failure (~w)", [C])}, + SKIP; + SysEvs -> + tc_print("System Events received: " + "~n ~p" + "~nwhen tc-pre failed:" + "~n C: ~p" + "~n E: ~p" + "~n S: ~p", + [SysEvs, C, E, S], "", ""), tc_end( f("skipping(catched-sysevs,~w,tc-pre)", [C]) ), SKIP = {skip, "TC-Pre failure with system events"}, SKIP @@ -210,13 +223,19 @@ tc_end(Result) when is_list(Result) -> "", "----------------------------------------------------~n~n"), ok. +tc_print(F) -> + tc_print(F, [], "", ""). + +tc_print(F, A) -> + tc_print(F, A, "", ""). + tc_print(F, Before, After) -> tc_print(F, [], Before, After). tc_print(F, A, Before, After) -> Name = tc_which_name(), FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", - [formated_timestamp(),Name,self()|A]), + [formated_timestamp(), Name, self() | A]), io:format(user, Before ++ FStr ++ After, []), io:format(standard_io, Before ++ FStr ++ After, []). @@ -799,21 +818,24 @@ analyze_and_print_host_info() -> {unix, freebsd} -> analyze_and_print_freebsd_host_info(Version); {unix, sunos} -> - io:format("Solaris: ~s" - "~n", [Version]), - 2; + analyze_and_print_solaris_host_info(Version); + {win32, nt} -> + analyze_and_print_win_host_info(Version); _ -> io:format("OS Family: ~p" - "~n OS Type: ~p" - "~n Version: ~p" - "~n", [OsFam, OsName, Version]), + "~n OS Type: ~p" + "~n Version: ~p" + "~n Num Schedulers: ~s" + "~n", [OsFam, OsName, Version, str_num_schedulers()]), try erlang:system_info(schedulers) of 1 -> 10; 2 -> 5; + N when (N =< 6) -> + 2; _ -> - 2 + 1 catch _:_:_ -> 10 @@ -867,9 +889,11 @@ analyze_and_print_linux_host_info(Version) -> %% Check if we need to adjust the factor because of the memory try linux_which_meminfo() of AddFactor -> + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), Factor + AddFactor catch _:_:_ -> + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), Factor end. @@ -993,6 +1017,7 @@ analyze_and_print_openbsd_host_info(Version) -> "~nMemory:" "~n ~w KB" "~n", [CPU, CPUSpeed, NCPU, Memory]), + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), CPUFactor = if (CPUSpeed =:= -1) -> @@ -1033,6 +1058,7 @@ analyze_and_print_openbsd_host_info(Version) -> end catch _:_:_ -> + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), 1 end. @@ -1041,47 +1067,43 @@ analyze_and_print_freebsd_host_info(Version) -> io:format("FreeBSD:" "~n Version: ~p" "~n", [Version]), - Extract = - fun(Key) -> - string:tokens(string:trim(os:cmd("sysctl " ++ Key)), [$:]) - end, + %% This test require that the program 'sysctl' is in the path. + %% First test with 'which sysctl', if that does not work + %% try with 'which /sbin/sysctl'. If that does not work either, + %% we skip the test... try begin - CPU = - case Extract("hw.model") of - ["hw.model", Model] -> - string:trim(Model); - _ -> - "-" - end, - CPUSpeed = - case Extract("hw.clockrate") of - ["hw.clockrate", Speed] -> - list_to_integer(string:trim(Speed)); - _ -> - -1 - end, - NCPU = - case Extract("hw.ncpu") of - ["hw.ncpu", N] -> - list_to_integer(string:trim(N)); - _ -> - -1 + SysCtl = + case string:trim(os:cmd("which sysctl")) of + [] -> + case string:trim(os:cmd("which /sbin/sysctl")) of + [] -> + throw(sysctl); + SC2 -> + SC2 + end; + SC1 -> + SC1 end, - Memory = - case Extract("hw.physmem") of - ["hw.physmem", PhysMem] -> - list_to_integer(string:trim(PhysMem)) div 1024; - _ -> - -1 + Extract = + fun(Key) -> + string:tokens(string:trim(os:cmd(SysCtl ++ " " ++ Key)), + [$:]) end, + CPU = analyze_freebsd_cpu(Extract), + CPUSpeed = analyze_freebsd_cpu_speed(Extract), + NCPU = analyze_freebsd_ncpu(Extract), + Memory = analyze_freebsd_memory(Extract), io:format("CPU:" - "~n Model: ~s" - "~n Speed: ~w" - "~n N: ~w" + "~n Model: ~s" + "~n Speed: ~w" + "~n N: ~w" + "~n Num Schedulers: ~s" "~nMemory:" "~n ~w KB" - "~n", [CPU, CPUSpeed, NCPU, Memory]), + "~n", + [CPU, CPUSpeed, NCPU, str_num_schedulers(), Memory]), + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), CPUFactor = if (CPUSpeed =:= -1) -> @@ -1097,6 +1119,8 @@ analyze_and_print_freebsd_host_info(Version) -> end; true -> if + (NCPU =:= -1) -> + 1; (NCPU >= 4) -> 2; (NCPU >= 2) -> @@ -1122,9 +1146,336 @@ analyze_and_print_freebsd_host_info(Version) -> end catch _:_:_ -> + io:format("CPU:" + "~n Num Schedulers: ~s" + "~n", [str_num_schedulers()]), + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), + case erlang:system_info(schedulers) of + 1 -> + 10; + 2 -> + 5; + _ -> + 2 + end + end. + + +analyze_freebsd_cpu(Extract) -> + analyze_freebsd_item(Extract, "hw.model", fun(X) -> X end, "-"). + +analyze_freebsd_cpu_speed(Extract) -> + analyze_freebsd_item(Extract, + "hw.clockrate", + fun(X) -> list_to_integer(X) end, + -1). + +analyze_freebsd_ncpu(Extract) -> + analyze_freebsd_item(Extract, + "hw.ncpu", + fun(X) -> list_to_integer(X) end, + -1). + +analyze_freebsd_memory(Extract) -> + analyze_freebsd_item(Extract, + "hw.physmem", + fun(X) -> list_to_integer(X) div 1024 end, + -1). + +analyze_freebsd_item(Extract, Key, Process, Default) -> + try + begin + case Extract(Key) of + [Key, Model] -> + Process(string:trim(Model)); + _ -> + Default + end + end + catch + _:_:_ -> + Default + end. + + +analyze_and_print_solaris_host_info(Version) -> + Release = + case file:read_file_info("/etc/release") of + {ok, _} -> + case [string:trim(S) || S <- string:tokens(os:cmd("cat /etc/release"), [$\n])] of + [Rel | _] -> + Rel; + _ -> + "-" + end; + _ -> + "-" + end, + %% Display the firmware device tree root properties (prtconf -b) + Props = [list_to_tuple([string:trim(PS) || PS <- Prop]) || + Prop <- [string:tokens(S, [$:]) || + S <- string:tokens(os:cmd("prtconf -b"), [$\n])]], + BannerName = case lists:keysearch("banner-name", 1, Props) of + {value, {_, BN}} -> + string:trim(BN); + _ -> + "-" + end, + InstructionSet = + case string:trim(os:cmd("isainfo -k")) of + "Pseudo-terminal will not" ++ _ -> + "-"; + IS -> + IS + end, + PtrConf = [list_to_tuple([string:trim(S) || S <- Items]) || Items <- [string:tokens(S, [$:]) || S <- string:tokens(os:cmd("prtconf"), [$\n])], length(Items) > 1], + SysConf = + case lists:keysearch("System Configuration", 1, PtrConf) of + {value, {_, SC}} -> + SC; + _ -> + "-" + end, + %% Because we count the lines of the output (which may contain + %% any number of extra crap lines) we need to ensure we only + %% count the "proper" stdout. So send it to a tmp file first + %% and then count its number of lines... + NumPhysCPU = + try + begin + File1 = f("/tmp/psrinfo_p.~s.~w", [os:getpid(), os:system_time()]), + os:cmd("psrinfo -p > " ++ File1), + string:trim(os:cmd("cat " ++ File1)) + end + catch + _:_:_ -> + "-" + end, + %% Because we count the lines of the output (which may contain + %% any number of extra crap lines) we need to ensure we only + %% count the "proper" stdout. So send it to a tmp file first + %% and then count its number of lines... + NumVCPU = + try + begin + File2 = f("/tmp/psrinfo.~s.~w", [os:getpid(), os:system_time()]), + os:cmd("psrinfo > " ++ File2), + [NumVCPUStr | _] = string:tokens(os:cmd("wc -l " ++ File2), [$\ ]), + NumVCPUStr + end + catch + _:_:_ -> + "-" + end, + MemSz = + case lists:keysearch("Memory size", 1, PtrConf) of + {value, {_, MS}} -> + MS; + _ -> + "-" + end, + io:format("Solaris: ~s" + "~n Release: ~s" + "~n Banner Name: ~s" + "~n Instruction Set: ~s" + "~n CPUs: ~s (~s)" + "~n System Config: ~s" + "~n Memory Size: ~s" + "~n Num Schedulers: ~s" + "~n~n", [Version, Release, BannerName, InstructionSet, + NumPhysCPU, NumVCPU, + SysConf, MemSz, + str_num_schedulers()]), + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), + MemFactor = + try string:tokens(MemSz, [$ ]) of + [SzStr, "Mega" ++ _] -> + try list_to_integer(SzStr) of + Sz when Sz > 8192 -> + 0; + Sz when Sz > 4096 -> + 1; + Sz when Sz > 2048 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + [SzStr, "Giga" ++ _] -> + try list_to_integer(SzStr) of + Sz when Sz > 8 -> + 0; + Sz when Sz > 4 -> + 1; + Sz when Sz > 2 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + _ -> + 10 + catch + _:_:_ -> + 10 + end, + try erlang:system_info(schedulers) of + 1 -> + 10; + 2 -> + 5; + N when (N =< 6) -> + 2; + _ -> 1 + catch + _:_:_ -> + 10 + end + MemFactor. + + + +analyze_and_print_win_host_info(Version) -> + SysInfo = which_win_system_info(), + OsName = win_sys_info_lookup(os_name, SysInfo), + OsVersion = win_sys_info_lookup(os_version, SysInfo), + SysMan = win_sys_info_lookup(system_manufacturer, SysInfo), + SysMod = win_sys_info_lookup(system_model, SysInfo), + NumProcs = win_sys_info_lookup(num_processors, SysInfo), + TotPhysMem = win_sys_info_lookup(total_phys_memory, SysInfo), + io:format("Windows: ~s" + "~n OS Version: ~s (~p)" + "~n System Manufacturer: ~s" + "~n System Model: ~s" + "~n Number of Processor(s): ~s" + "~n Total Physical Memory: ~s" + "~n Num Schedulers: ~s" + "~n~n", [OsName, OsVersion, Version, + SysMan, SysMod, NumProcs, TotPhysMem, + str_num_schedulers()]), + io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]), + MemFactor = + try + begin + [MStr, MUnit|_] = + string:tokens(lists:delete($,, TotPhysMem), [$\ ]), + case string:to_lower(MUnit) of + "gb" -> + try list_to_integer(MStr) of + M when M > 8 -> + 0; + M when M > 4 -> + 1; + M when M > 2 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + "mb" -> + try list_to_integer(MStr) of + M when M > 8192 -> + 0; + M when M > 4096 -> + 1; + M when M > 2048 -> + 2; + _ -> + 5 + catch + _:_:_ -> + 10 + end; + _ -> + 10 + end + end + catch + _:_:_ -> + 10 + end, + CPUFactor = + case erlang:system_info(schedulers) of + 1 -> + 10; + 2 -> + 5; + _ -> + 2 + end, + CPUFactor + MemFactor. + +win_sys_info_lookup(Key, SysInfo) -> + win_sys_info_lookup(Key, SysInfo, "-"). + +win_sys_info_lookup(Key, SysInfo, Def) -> + case lists:keysearch(Key, 1, SysInfo) of + {value, {Key, Value}} -> + Value; + false -> + Def end. +%% This function only extracts the prop we actually care about! +which_win_system_info() -> + SysInfo = os:cmd("systeminfo"), + try process_win_system_info(string:tokens(SysInfo, [$\r, $\n]), []) + catch + _:_:_ -> + io:format("Failed process System info: " + "~s~n", [SysInfo]), + [] + end. + +process_win_system_info([], Acc) -> + Acc; +process_win_system_info([H|T], Acc) -> + case string:tokens(H, [$:]) of + [Key, Value] -> + case string:to_lower(Key) of + "os name" -> + process_win_system_info(T, + [{os_name, string:trim(Value)}|Acc]); + "os version" -> + process_win_system_info(T, + [{os_version, string:trim(Value)}|Acc]); + "system manufacturer" -> + process_win_system_info(T, + [{system_manufacturer, string:trim(Value)}|Acc]); + "system model" -> + process_win_system_info(T, + [{system_model, string:trim(Value)}|Acc]); + "processor(s)" -> + [NumProcStr|_] = string:tokens(Value, [$\ ]), + T2 = lists:nthtail(list_to_integer(NumProcStr), T), + process_win_system_info(T2, + [{num_processors, NumProcStr}|Acc]); + "total physical memory" -> + process_win_system_info(T, + [{total_phys_memory, string:trim(Value)}|Acc]); + _ -> + process_win_system_info(T, Acc) + end; + _ -> + process_win_system_info(T, Acc) + end. + + + +str_num_schedulers() -> + try erlang:system_info(schedulers) of + N -> f("~w", [N]) + catch + _:_:_ -> "-" + end. + + %% ---------------------------------------------------------------- %% Time related function @@ -1218,15 +1569,16 @@ is_snmp_running() -> is_app_running(snmp). crypto_start() -> - case (catch crypto:start()) of + try crypto:start() of ok -> ok; {error, {already_started,crypto}} -> - ok; - {'EXIT', Reason} -> - {error, {exit, Reason}}; - Else -> - Else + ok + catch + exit:{undef, [{crypto, start, [], []} | _]}:_ -> + {error, no_crypto}; + C:E:S -> + {error, {C, E, S}} end. crypto_support() -> @@ -1246,8 +1598,74 @@ crypto_support([Func|Funcs], Acc) -> is_crypto_supported(Func) -> snmp_misc:is_crypto_supported(Func). - - + + +%% This function ensures that a *named* process on the local node is not running. +%% It does so by: +%% 1) Wait for 'Timeout' msec +%% 2) If 1 did not work, issue 'stop' and then wait 'Timeout' msec +%% 3) And finally, if 2 did not work, issue exit(kill). +ensure_not_running(Name, Stopper, Timeout) + when is_atom(Name) andalso + is_function(Stopper, 0) andalso + is_integer(Timeout) -> + ensure_not_running(whereis(Name), Name, Stopper, Timeout). + +ensure_not_running(Pid, Name, Stopper, Timeout) when is_pid(Pid) -> + MRef = erlang:monitor(process, Pid), + try + begin + ensure_not_running_wait(Pid, MRef, Timeout), + ensure_not_running_stop(Pid, MRef, Stopper, Timeout), + ensure_not_running_kill(Pid, MRef, Timeout), + exit({failed_ensure_not_running, Name}) + end + catch + throw:ok -> + sleep(1000), + ok + end; +ensure_not_running(_, _, _, _) -> + iprint("ensure_not_running -> not running", []), + sleep(1000), % This should not actually be necessary! + ok. + + +ensure_not_running_wait(Pid, MRef, Timeout) -> + receive + {'DOWN', MRef, process, Pid, _Info} -> + iprint("ensure_not_running_wait -> died peacefully", []), + throw(ok) + after Timeout -> + wprint("ensure_not_running_wait -> giving up", []), + ok + end. + +ensure_not_running_stop(Pid, MRef, Stopper, Timeout) -> + %% Spawn a stop'er process + StopPid = spawn(Stopper), + receive + {'DOWN', MRef, process, Pid, _Info} -> + nprint("ensure_not_running_stop -> dead (stopped)", []), + throw(ok) + after Timeout -> + wprint("ensure_not_running_stop -> giving up", []), + exit(StopPid, kill), + ok + end. + +ensure_not_running_kill(Pid, MRef, Timeout) -> + exit(Pid, kill), + receive + {'DOWN', MRef, process, Pid, _Info} -> + nprint("ensure_not_running_kill -> dead (killed)", []), + throw(ok) + after Timeout -> + wprint("ensure_not_running_kill -> giving up", []), + ok + end. + + %% ---------------------------------------------------------------- %% Watchdog functions %% @@ -1376,19 +1794,6 @@ del_file_or_dir(FileOrDir) -> %% ---------------------------------------------------------------------- -%% cover functions -%% - -cover([Suite, Case] = Args) when is_atom(Suite) andalso is_atom(Case) -> - Mods0 = cover:compile_directory("../src"), - Mods1 = [Mod || {ok, Mod} <- Mods0], - snmp_test_server:t(Args), - Files0 = [cover:analyse_to_file(Mod) || Mod <- Mods1], - [io:format("Cover output: ~s~n", [File]) || {ok, File} <- Files0], - ok. - - -%% ---------------------------------------------------------------------- %% (debug) Print functions %% @@ -1434,3 +1839,49 @@ print(Prefix, Module, Line, Format, Args) -> formated_timestamp() -> snmp_misc:formated_timestamp(). + +%% ---------------------------------------------------------------------- +%% +%% General purpose print functions +%% ERROR, WARNING and NOTICE are written both to 'user' and 'standard_io'. +%% INFO only to 'standard_io'. +%% +%% Should we also allow for (optional) a "short name" (sname)? +%% + +%% ERROR print (both to user and standard_io) +eprint(F, A) -> + Str = format_print("ERROR", F, A), + io:format(user, "~s~n", [Str]), + io:format(standard_io, "~s~n", [Str]). + +%% WARNING print (both to user and standard_io) +wprint(F, A) -> + Str = format_print("WARNING", F, A), + io:format(user, "~s~n", [Str]), + io:format(standard_io, "~s~n", [Str]). + +%% NOTICE print (both to user and standard_io) +nprint(F, A) -> + Str = format_print("NOTICE", F, A), + io:format(user, "~s~n", [Str]), + io:format(standard_io, "~s~n", [Str]). + +%% INFO print (only to user) +iprint(F, A) -> + Str = format_print("INFO", F, A), + io:format(standard_io, "~s~n", [Str]). + +format_print(Prefix, F, A) -> + format_print(get(tname), Prefix, F, A). + +format_print(undefined, Prefix, F, A) -> + f("*** [~s] ~s ~p ~p *** ~n" ++ F ++ "~n", + [formated_timestamp(), Prefix, node(), self() | A]); +format_print(TName, Prefix, F, A) when is_atom(TName) -> + format_print(atom_to_list(TName), Prefix, F, A); +format_print(TName, Prefix, F, A) when is_list(TName) -> + f("*** [~s] ~s ~s ~p ~p *** ~n" ++ F ++ "~n", + [formated_timestamp(), Prefix, TName, node(), self() | A]). + + diff --git a/lib/snmp/test/snmp_test_lib.hrl b/lib/snmp/test/snmp_test_lib.hrl index 1e6e513d9d..f4863c9a1e 100644 --- a/lib/snmp/test/snmp_test_lib.hrl +++ b/lib/snmp/test/snmp_test_lib.hrl @@ -84,6 +84,10 @@ -define(FLUSH(), ?LIB:flush_mqueue()). -define(ETRAP_GET(), ?LIB:trap_exit()). -define(ETRAP_SET(O), ?LIB:trap_exit(O)). +-define(PINFO(__P__), try process_info(__P__) + catch _:_:_ -> + {not_running, __P__} + end). %% - Node utility macros - @@ -105,6 +109,9 @@ -define(CRYPTO_SUPPORT(), ?LIB:crypto_support()). +-define(ENSURE_NOT_RUNNING(N, S, T), ?LIB:ensure_not_running(N, S, T)). + + %% - Dir macros - -define(DEL_DIR(D), ?LIB:del_dir(D)). @@ -112,55 +119,33 @@ %% - Print macros +%% Used for indicating the start of a test case -define(P(C), ?LIB:p(?MODULE, C)). --define(P1(F), ?LIB:p(F, [])). --define(P2(F, A), ?LIB:p(F, A)). --define(F(F, A), ?LIB:f(F, A)). --ifdef(snmp_debug). --ifndef(snmp_log). --define(snmp_log,true). --endif. --ifndef(snmp_error). --define(snmp_error,true). --endif. --else. --ifdef(snmp_log). --ifndef(snmp_error). --define(snmp_error,true). --endif. --endif. --endif. +%% Takes a format call (such as io:format) and produces a printable string +-define(F(F, A), ?LIB:f(F, A)). -ifdef(snmp_debug). --define(DBG(F,A), ?PRINT("DBG", F, A)). +-define(DBG(F,A), ?IPRINT(F, A)). -else. -define(DBG(F,A), ok). -endif. --ifdef(snmp_log). --define(LOG(F,A), ?PRINT("LOG", F, A)). --else. --define(LOG(F,A), ok). --endif. - --ifdef(snmp_error). --define(ERR(F,A), ?PRINT("ERR", F, A)). --else. --define(ERR(F,A), ok). --endif. - --define(INF(F,A), ?PRINT("INF", F, A)). +%% ERROR print +-define(EPRINT(F), ?LIB:eprint(F, [])). +-define(EPRINT(F, A), ?LIB:eprint(F, A)). --define(PRINT(P,F,A), ?LIB:print(P, ?MODULE, ?LINE, F, A)). +%% WARNING print +-define(WPRINT(F), ?LIB:wprint(F, [])). +-define(WPRINT(F, A), ?LIB:wprint(F, A)). --define(PRINT1(F, A), ?LIB:print1(F, A)). --define(PRINT1(F), ?PRINT1(F, [])). --define(EPRINT1(F, A), ?PRINT1("<ERROR> " ++ F, A)). +%% NOTICE print +-define(NPRINT(F), ?LIB:nprint(F, [])). +-define(NPRINT(F, A), ?LIB:nprint(F, A)). --define(PRINT2(F, A), ?LIB:print2(F, A)). --define(PRINT2(F), ?PRINT2(F, [])). --define(EPRINT2(F, A), ?PRINT2("<ERROR> " ++ F, A)). +%% INFO print +-define(IPRINT(F), ?LIB:iprint(F, [])). +-define(IPRINT(F, A), ?LIB:iprint(F, A)). -define(FTS(), snmp_misc:formated_timestamp()). -define(FTS(TS), snmp_misc:format_timestamp(TS)). diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl index f50147a852..0a80860ed1 100644 --- a/lib/snmp/test/snmp_test_mgr.erl +++ b/lib/snmp/test/snmp_test_mgr.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2019. All Rights Reserved. +%% Copyright Ericsson AB 1996-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -191,40 +191,41 @@ receive_trap(Timeout) -> %% {mibs, List of Filenames}, {trap_udp, UDPPort (default 5000)}, %%---------------------------------------------------------------------- init({Options, CallerPid}) -> + %% This causes "verbosity printouts" to print (from level debug) + %% in the modules we "borrow" from the agent code (burr,,,) + %% With "our" name (mgr). put(sname, mgr), - put(verbosity, debug), + put(verbosity, debug), + %% Make use of the "test name" print "feature" + put(tname, "MGR"), ?SNMP_RAND_SEED(), - %% rand:seed(exrop, - %% {erlang:phash2([node()]), - %% erlang:monotonic_time(), - %% erlang:unique_integer()}), case (catch is_options_ok(Options)) of true -> put(debug, get_value(debug, Options, false)), - d("init -> (~p) extract options",[self()]), + d("init -> extract options"), PacksDbg = get_value(packet_server_debug, Options, false), - print("[~w] ~p -> PacksDbg: ~p~n", [?MODULE, self(), PacksDbg]), + ?IPRINT("init -> PacksDbg: ~p", [PacksDbg]), RecBufSz = get_value(recbuf, Options, 1024), - print("[~w] ~p -> RecBufSz: ~p~n", [?MODULE, self(), RecBufSz]), + ?IPRINT("init -> RecBufSz: ~p", [RecBufSz]), Mibs = get_value(mibs, Options, []), - print("[~w] ~p -> Mibs: ~p~n", [?MODULE, self(), Mibs]), + ?IPRINT("init -> Mibs: ~p", [Mibs]), Udp = get_value(agent_udp, Options, 4000), - print("[~w] ~p -> Udp: ~p~n", [?MODULE, self(), Udp]), + ?IPRINT("init -> Udp: ~p", [Udp]), User = get_value(user, Options, "initial"), - print("[~w] ~p -> User: ~p~n", [?MODULE, self(), User]), + ?IPRINT("init -> User: ~p", [User]), EngineId = get_value(engine_id, Options, "agentEngine"), - print("[~w] ~p -> EngineId: ~p~n", [?MODULE, self(), EngineId]), + ?IPRINT("init -> EngineId: ~p", [EngineId]), CtxEngineId = get_value(context_engine_id, Options, EngineId), - print("[~w] ~p -> CtxEngineId: ~p~n", [?MODULE, self(), CtxEngineId]), + ?IPRINT("init -> CtxEngineId: ~p", [CtxEngineId]), TrapUdp = get_value(trap_udp, Options, 5000), - print("[~w] ~p -> TrapUdp: ~p~n", [?MODULE, self(), TrapUdp]), + ?IPRINT("init -> TrapUdp: ~p", [TrapUdp]), Dir = get_value(dir, Options, "."), - print("[~w] ~p -> Dir: ~p~n", [?MODULE, self(), Dir]), + ?IPRINT("init -> Dir: ~p", [Dir]), SecLevel = get_value(sec_level, Options, noAuthNoPriv), - print("[~w] ~p -> SecLevel: ~p~n", [?MODULE, self(), SecLevel]), + ?IPRINT("init -> SecLevel: ~p", [SecLevel]), MiniMIB = snmp_mini_mib:create(Mibs), - d("[~w] ~p -> MiniMIB: " - "~n ~p", [?MODULE, self(), MiniMIB]), + d("init -> MiniMIB: " + "~n ~p", [MiniMIB]), Version = case lists:member(v2, Options) of true -> 'version-2'; false -> @@ -233,41 +234,38 @@ init({Options, CallerPid}) -> false -> 'version-1' end end, - print("[~w] ~p -> Version: ~p~n", [?MODULE, self(), Version]), + ?IPRINT("init -> Version: ~p", [Version]), Com = case Version of 'version-3' -> get_value(context, Options, ""); _ -> get_value(community, Options, "public") end, - print("[~w] ~p -> Com: ~p~n", [?MODULE, self(), Com]), + ?IPRINT("init -> Com: ~p", [Com]), VsnHdrD = {Com, User, EngineId, CtxEngineId, mk_seclevel(SecLevel)}, - print("[~w] ~p -> VsnHdrD: ~p~n", [?MODULE, self(), VsnHdrD]), + ?IPRINT("init -> VsnHdrD: ~p", [VsnHdrD]), IpFamily = get_value(ipfamily, Options, inet), - print("[~w] ~p -> IpFamily: ~p~n", [?MODULE, self(), IpFamily]), + ?IPRINT("init -> IpFamily: ~p", [IpFamily]), AgIp = case snmp_misc:assq(agent, Options) of {value, Addr} when is_tuple(Addr) andalso (size(Addr) =:= 4) andalso (IpFamily =:= inet) -> - print("[~w] ~p -> Addr: ~p~n", - [?MODULE, self(), Addr]), + ?IPRINT("init -> Addr: ~p", [Addr]), Addr; {value, Addr} when is_tuple(Addr) andalso (size(Addr) =:= 8) andalso (IpFamily =:= inet6) -> - print("[~w] ~p -> Addr: ~p~n", - [?MODULE, self(), Addr]), + ?IPRINT("init -> Addr: ~p", [Addr]), Addr; {value, Host} when is_list(Host) -> - print("[~w] ~p -> Host: ~p~n", - [?MODULE, self(), Host]), + ?IPRINT("init -> Host: ~p", [Host]), {ok, Ip} = snmp_misc:ip(Host, IpFamily), Ip end, - print("[~w] ~p -> AgIp: ~p~n", [?MODULE, self(), AgIp]), + ?IPRINT("init -> AgIp: ~p", [AgIp]), Quiet = lists:member(quiet, Options), - print("[~w] ~p -> Quiet: ~p~n", [?MODULE, self(), Quiet]), + ?IPRINT("init -> Quiet: ~p", [Quiet]), PackServ = start_packet_server( Quiet, Options, CallerPid, AgIp, Udp, TrapUdp, @@ -692,16 +690,16 @@ echo_pdu(PDU, MiniMIB) -> %% Test Sequence %%---------------------------------------------------------------------- echo_errors({error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}})-> - io:format("* Unexpected Behaviour * Id: ~w.~n" - " Expected: " ++ ExpectedFormat ++ "~n" - " Got: " ++ Format ++ "~n", - [Id] ++ ExpectedData ++ Data), + ?IPRINT("*** Unexpected Behaviour *** Id: ~w.~n" + " Expected: " ++ ExpectedFormat ++ "~n" + " Got: " ++ Format ++ "~n", + [Id] ++ ExpectedData ++ Data), {error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}}; echo_errors(ok) -> ok; echo_errors({ok, Val}) -> {ok, Val}. get_response_impl(Id, ExpVars) -> - ?PRINT2("await response ~w with" + ?IPRINT("await response ~w with" "~n Expected Varbinds: ~p", [Id, ExpVars]), PureVars = find_pure_oids2(ExpVars), @@ -710,7 +708,7 @@ get_response_impl(Id, ExpVars) -> error_status = noError, error_index = 0, varbinds = VBs} -> - ?PRINT2("received expected response pdu (~w) - match vars" + ?IPRINT("received expected response pdu (~w) - match vars" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, PureVars, VBs]), @@ -720,10 +718,10 @@ get_response_impl(Id, ExpVars) -> request_id = ReqId, error_status = Err2, error_index = Index2} -> - ?EPRINT2("received unexpected response pdu: ~w, ~w, ~w" - "~n Received Error: ~p" - "~n Received Index: ~p", - [Type2, Id, ReqId, Err2, Index2]), + ?EPRINT("received unexpected response pdu: ~w, ~w, ~w" + "~n Received Error: ~p" + "~n Received Index: ~p", + [Type2, Id, ReqId, Err2, Index2]), {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", @@ -732,8 +730,8 @@ get_response_impl(Id, ExpVars) -> [Type2, Err2, Index2]}}; {error, Reason} -> - ?EPRINT2("unexpected receive pdu error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive pdu error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end. @@ -743,81 +741,81 @@ get_response_impl(Id, ExpVars) -> %% Returns: ok | {error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}} %%---------------------------------------------------------------------- expect_impl(Id, any) -> - ?PRINT2("await ~w pdu (any)", [Id]), + ?IPRINT("await ~w pdu (any)", [Id]), case receive_response() of PDU when is_record(PDU, pdu) -> - ?PRINT2("received expected pdu (~w)", [Id]), + ?IPRINT("received expected pdu (~w)", [Id]), ok; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end; expect_impl(Id, return) -> - ?PRINT2("await ~w pdu", [Id]), + ?IPRINT("await ~w pdu", [Id]), case receive_response() of PDU when is_record(PDU, pdu) -> - ?PRINT2("received expected pdu (~w)", [Id]), + ?IPRINT("received expected pdu (~w)", [Id]), {ok, PDU}; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end; expect_impl(Id, trap) -> - ?PRINT2("await ~w trap", [Id]), + ?IPRINT("await ~w trap", [Id]), case receive_trap(3500) of PDU when is_record(PDU, trappdu) -> - ?PRINT2("received expected trap (~w)", [Id]), + ?IPRINT("received expected trap (~w)", [Id]), ok; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end; expect_impl(Id, timeout) -> - ?PRINT2("await ~w nothing", [Id]), + ?IPRINT("await ~w nothing", [Id]), receive X -> - ?EPRINT1("received unexpected message: ~w" - "~n ~p", - [Id, X]), + ?EPRINT("received unexpected message: ~w" + "~n ~p", + [Id, X]), {error, Id, {"Timeout", []}, {"Message ~w", [X]}} after 3500 -> ok end; expect_impl(Id, Err) when is_atom(Err) -> - ?PRINT2("await ~w with" + ?IPRINT("await ~w with" "~n Err: ~p", [Id, Err]), case receive_response() of #pdu{error_status = Err} -> - ?PRINT2("received pdu with expected error status (~w, ~w)", + ?IPRINT("received pdu with expected error status (~w, ~w)", [Id, Err]), ok; #pdu{type = Type2, request_id = ReqId, error_status = Err2} -> - ?EPRINT1("received pdu with unexpected error status: ~w, ~w, ~w" - "~n Expected Error: ~p" - "~n Received Error: ~p", - [Type2, Id, ReqId, Err, Err2]), + ?EPRINT("received pdu with unexpected error status: ~w, ~w, ~w" + "~n Expected Error: ~p" + "~n Received Error: ~p", + [Type2, Id, ReqId, Err, Err2]), {error, Id, {"ErrorStatus: ~w, RequestId: ~w", [Err,ReqId]}, {"ErrorStatus: ~w", [Err2]}}; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end; expect_impl(Id, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> - ?PRINT2("await ~w with" + ?IPRINT("await ~w with" "~n ExpectedVarbinds: ~p", [Id, ExpectedVarbinds]), PureVars = find_pure_oids(ExpectedVarbinds), @@ -826,7 +824,7 @@ expect_impl(Id, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> error_status = noError, error_index = 0, varbinds = VBs} -> - ?PRINT2("received expected response pdu (~w) - check varbinds" + ?IPRINT("received expected response pdu (~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, PureVars, VBs]), @@ -836,22 +834,22 @@ expect_impl(Id, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> request_id = ReqId, error_status = Err2, error_index = Index2} -> - ?EPRINT1("received unexpected pdu: ~w, ~w, ~w" - "~n Received Error: ~p" - "~n Received Index: ~p", + ?EPRINT("received unexpected pdu: ~w, ~w, ~w" + "~n Received Error: ~p" + "~n Received Index: ~p", [Type2, Id, ReqId, Err2, Index2]), {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", ['get-response', noError, 0, ReqId]}, {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end. expect_impl(Id, v2trap, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> - ?PRINT2("await v2 trap ~w with" + ?IPRINT("await v2 trap ~w with" "~n ExpectedVarbinds: ~p", [Id, ExpectedVarbinds]), PureVars = find_pure_oids(ExpectedVarbinds), @@ -860,7 +858,7 @@ expect_impl(Id, v2trap, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> error_status = noError, error_index = 0, varbinds = VBs} -> - ?PRINT2("received expected v2 trap (~w) - check varbinds" + ?IPRINT("received expected v2 trap (~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, PureVars, VBs]), @@ -870,22 +868,22 @@ expect_impl(Id, v2trap, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> request_id = ReqId, error_status = Err2, error_index = Index2} -> - ?EPRINT1("received unexpected pdu: ~w, ~w, ~w" - "~n Received Error: ~p" - "~n Received Index: ~p", - [Type2, Id, ReqId, Err2, Index2]), + ?EPRINT("received unexpected pdu: ~w, ~w, ~w" + "~n Received Error: ~p" + "~n Received Index: ~p", + [Type2, Id, ReqId, Err2, Index2]), {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", ['snmpv2-trap', noError, 0, ReqId]}, {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end; expect_impl(Id, report, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> - ?PRINT2("await report ~w with" + ?IPRINT("await report ~w with" "~n ExpectedVarbinds: ~p", [Id, ExpectedVarbinds]), PureVBs = find_pure_oids(ExpectedVarbinds), @@ -894,7 +892,7 @@ expect_impl(Id, report, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> error_status = noError, error_index = 0, varbinds = VBs} -> - ?PRINT2("received expected report (~w) - check varbinds" + ?IPRINT("received expected report (~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, PureVBs, VBs]), @@ -904,23 +902,23 @@ expect_impl(Id, report, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> request_id = ReqId, error_status = Err2, error_index = Index2} -> - ?EPRINT1("received unexpected pdu: ~w, ~w, ~w" - "~n Received Error: ~p" - "~n Received Index: ~p", - [Type2, Id, ReqId, Err2, Index2]), + ?EPRINT("received unexpected pdu: ~w, ~w, ~w" + "~n Received Error: ~p" + "~n Received Index: ~p", + [Type2, Id, ReqId, Err2, Index2]), {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", [report, noError, 0, ReqId]}, {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end; expect_impl(Id, {inform, Reply}, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> - ?PRINT2("await inform ~w with" + ?IPRINT("await inform ~w with" "~n Reply: ~p" "~n ExpectedVarbinds: ~p", [Id, Reply, ExpectedVarbinds]), @@ -931,20 +929,20 @@ expect_impl(Id, {inform, Reply}, ExpectedVarbinds) error_status = noError, error_index = 0, varbinds = VBs} -> - ?PRINT2("received inform (~w) - check varbinds" + ?IPRINT("received inform (~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, PureVBs, VBs]), case check_vars(Id, PureVBs, VBs) of ok when (Reply == true) -> - ?PRINT2("varbinds ok (~w) - send ok inform response", [Id]), + ?IPRINT("varbinds ok (~w) - send ok inform response", [Id]), RespPDU = Resp#pdu{type = 'get-response', error_status = noError, error_index = 0}, ?MODULE:rpl(RespPDU), ok; ok when (element(1, Reply) == error) -> - ?PRINT2("varbinds ok (~w) - send error inform response", [Id]), + ?IPRINT("varbinds ok (~w) - send error inform response", [Id]), {error, Status, Index} = Reply, RespPDU = Resp#pdu{type = 'get-response', error_status = Status, @@ -952,13 +950,12 @@ expect_impl(Id, {inform, Reply}, ExpectedVarbinds) ?MODULE:rpl(RespPDU), ok; ok when (Reply == false) -> - ?PRINT2("varbinds ok (~w) - don't send inform response", [Id]), + ?IPRINT("varbinds ok (~w) - don't send inform response", [Id]), ok; Else -> - ?EPRINT1("unexpected varbinds (~w)", [Id]), - io:format("expect_impl(~w, inform) -> " - "~n Else: ~p" - "~n", [Id, Else]), + ?EPRINT("unexpected (inform) varbinds (~w):" + "~n VBs: ~p" + "~n ~p", [Id, VBs, Else]), Else end; @@ -966,22 +963,22 @@ expect_impl(Id, {inform, Reply}, ExpectedVarbinds) request_id = ReqId, error_status = Err2, error_index = Index2} -> - ?EPRINT1("received unexpected pdu: ~w, ~w, ~w" - "~n Received Error: ~p" - "~n Received Index: ~p", - [Type2, Id, ReqId, Err2, Index2]), + ?EPRINT("received unexpected pdu: ~w, ~w, ~w" + "~n Received Error: ~p" + "~n Received Index: ~p", + [Type2, Id, ReqId, Err2, Index2]), {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", ['inform-request', noError, 0, ReqId]}, {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; {error, Reason} -> - ?EPRINT1("unexpected receive error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end. expect_impl(Id, Err, Index, any = _ExpectedVarbinds) -> - ?PRINT2("await response ~w with" + ?IPRINT("await response ~w with" "~n Err: ~p" "~n Index: ~p" "~n ExpectedVarbinds: ~p", @@ -990,13 +987,13 @@ expect_impl(Id, Err, Index, any = _ExpectedVarbinds) -> #pdu{type = 'get-response', error_status = Err, error_index = Index} -> - ?PRINT2("received expected response pdu (~w, ~w, ~w)", + ?IPRINT("received expected response pdu (~w, ~w, ~w)", [Id, Err, Index]), ok; #pdu{type = 'get-response', error_status = Err} when (Index == any) -> - ?PRINT2("received expected response pdu (~w, ~w)", + ?IPRINT("received expected response pdu (~w, ~w)", [Id, Err]), ok; @@ -1006,14 +1003,14 @@ expect_impl(Id, Err, Index, any = _ExpectedVarbinds) -> error_index = Idx} when is_list(Index) -> case lists:member(Idx, Index) of true -> - ?PRINT2("received expected response pdu (~w, ~w, ~w)", + ?IPRINT("received expected response pdu (~w, ~w, ~w)", [Id, Err, Idx]), ok; false -> - ?EPRINT1("received response pdu with unexpected index (~w, ~w):" - "~n Expected Index: ~p" - "~n Received Index: ~p", - [Id, Err, Index, Idx]), + ?EPRINT("received response pdu with unexpected index (~w, ~w):" + "~n Expected Index: ~p" + "~n Received Index: ~p", + [Id, Err, Index, Idx]), {error, Id, {"ErrStat: ~w, Idx: ~w, RequestId: ~w", [Err, Index, ReqId]}, {"ErrStat: ~w, Idx: ~w", [Err, Idx]}} @@ -1023,22 +1020,24 @@ expect_impl(Id, Err, Index, any = _ExpectedVarbinds) -> request_id = ReqId, error_status = Err2, error_index = Index2} -> - ?EPRINT1("received unexpected response pdu: ~w, ~w, ~w" - "~n Expected Error: ~p" - "~n Received Error: ~p" - "~n Expected Index: ~p" - "~n Received Index: ~p", - [Type2, Id, ReqId, Err, Err2, Index, Index2]), + ?EPRINT("received unexpected response pdu: ~w, ~w, ~w" + "~n Expected Error: ~p" + "~n Received Error: ~p" + "~n Expected Index: ~p" + "~n Received Index: ~p", + [Type2, Id, ReqId, Err, Err2, Index, Index2]), {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", ['get-response', Err, Index, ReqId]}, {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; {error, Reason} -> + ?EPRINT("unexpected (receive) response: " + "~n ~p", [Reason]), format_reason(Id, Reason) end; expect_impl(Id, Err, Index, ExpectedVarbinds) -> - ?PRINT2("await response ~w with" + ?IPRINT("await response ~w with" "~n Err: ~p" "~n Index: ~p" "~n ExpectedVarbinds: ~p", @@ -1049,7 +1048,7 @@ expect_impl(Id, Err, Index, ExpectedVarbinds) -> error_status = Err, error_index = Index, varbinds = VBs} -> - ?PRINT2("received expected response pdu (~w, ~w, ~w) - check varbinds" + ?IPRINT("received expected response pdu (~w, ~w, ~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, Err, Index, PureVBs, VBs]), @@ -1058,7 +1057,7 @@ expect_impl(Id, Err, Index, ExpectedVarbinds) -> #pdu{type = 'get-response', error_status = Err, varbinds = VBs} when (Index == any) -> - ?PRINT2("received expected response pdu (~w, ~w) - check varbinds" + ?IPRINT("received expected response pdu (~w, ~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, Err, PureVBs, VBs]), @@ -1071,18 +1070,18 @@ expect_impl(Id, Err, Index, ExpectedVarbinds) -> varbinds = VBs} when is_list(Index) -> case lists:member(Idx, Index) of true -> - ?PRINT2("received expected pdu (~w, ~w, ~w) - check varbinds" + ?IPRINT("received expected pdu (~w, ~w, ~w) - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [Id, Err, Idx, PureVBs, VBs]), check_vars(Id, PureVBs, VBs); false -> - ?EPRINT1("received response pdu with unexpected index (~w, ~w):" - "~n Expected Index: ~p" - "~n Received Index: ~p" - "~n Expected VBs: ~p" - "~n Received VBs: ~p", - [Id, Err, Index, Idx, PureVBs, VBs]), + ?EPRINT("received response pdu with unexpected index (~w, ~w):" + "~n Expected Index: ~p" + "~n Received Index: ~p" + "~n Expected VBs: ~p" + "~n Received VBs: ~p", + [Id, Err, Index, Idx, PureVBs, VBs]), {error,Id, {"ErrStat: ~w, Idx: ~w, Varbinds: ~w, RequestId: ~w", [Err,Index,PureVBs,ReqId]}, @@ -1095,15 +1094,15 @@ expect_impl(Id, Err, Index, ExpectedVarbinds) -> error_status = Err2, error_index = Index2, varbinds = VBs} -> - ?EPRINT1("received unexpected response pdu: ~w, ~w, ~w" - "~n Expected Error: ~p" - "~n Received Error: ~p" - "~n Expected Index: ~p" - "~n Received Index: ~p" - "~n Expected VBs: ~p" - "~n Received VBs: ~p", - [Type2, Id, ReqId, - Err, Err2, Index, Index2, PureVBs, VBs]), + ?EPRINT("received unexpected response pdu: ~w, ~w, ~w" + "~n Expected Error: ~p" + "~n Received Error: ~p" + "~n Expected Index: ~p" + "~n Received Index: ~p" + "~n Expected VBs: ~p" + "~n Received VBs: ~p", + [Type2, Id, ReqId, + Err, Err2, Index, Index2, PureVBs, VBs]), {error,Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, Varbinds: ~w, RequestId: ~w", ['get-response',Err,Index,PureVBs,ReqId]}, @@ -1111,13 +1110,13 @@ expect_impl(Id, Err, Index, ExpectedVarbinds) -> [Type2,Err2,Index2,VBs]}}; {error, Reason} -> - ?EPRINT1("unexpected receive pdu error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive pdu error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end. expect_impl(Id, trap, Enterp, Generic, Specific, ExpectedVarbinds) -> - ?PRINT2("await trap pdu ~w with" + ?IPRINT("await trap pdu ~w with" "~n Enterprise: ~p" "~n Generic: ~p" "~n Specific: ~p" @@ -1130,7 +1129,7 @@ expect_impl(Id, trap, Enterp, Generic, Specific, ExpectedVarbinds) -> generic_trap = Generic, specific_trap = Specific, varbinds = VBs} -> - ?PRINT2("received expected trap pdu - check varbinds" + ?IPRINT("received expected trap pdu - check varbinds" "~n Expected VBs: ~p" "~n Received VBs: ~p", [PureVBs, VBs]), @@ -1140,20 +1139,20 @@ expect_impl(Id, trap, Enterp, Generic, Specific, ExpectedVarbinds) -> generic_trap = G2, specific_trap = Spec2, varbinds = VBs} -> - ?EPRINT1("received unexpected trap pdu: ~w" - "~n Expected Enterprise: ~p" - "~n Received Enterprise: ~p" - "~n Expected Generic: ~p" - "~n Received Generic: ~p" - "~n Expected Specific: ~p" - "~n Received Specific: ~p" - "~n Expected VBs: ~p" - "~n Received VBs: ~p", - [Id, - PureE, Ent2, - Generic, G2, - Specific, Spec2, - PureVBs, VBs]), + ?EPRINT("received unexpected trap pdu: ~w" + "~n Expected Enterprise: ~p" + "~n Received Enterprise: ~p" + "~n Expected Generic: ~p" + "~n Received Generic: ~p" + "~n Expected Specific: ~p" + "~n Received Specific: ~p" + "~n Expected VBs: ~p" + "~n Received VBs: ~p", + [Id, + PureE, Ent2, + Generic, G2, + Specific, Spec2, + PureVBs, VBs]), {error, Id, {"Enterprise: ~w, Generic: ~w, Specific: ~w, Varbinds: ~w", [PureE, Generic, Specific, ExpectedVarbinds]}, @@ -1161,8 +1160,8 @@ expect_impl(Id, trap, Enterp, Generic, Specific, ExpectedVarbinds) -> [Ent2, G2, Spec2, VBs]}}; {error, Reason} -> - ?EPRINT1("unexpected receive trap pdu error: ~w" - "~n ~p", [Id, Reason]), + ?EPRINT("unexpected receive trap pdu error: ~w" + "~n ~p", [Id, Reason]), format_reason(Id, Reason) end. @@ -1252,15 +1251,11 @@ sizeOf(L) when is_list(L) -> sizeOf(B) when is_binary(B) -> size(B). +d(F) -> d(F, []). d(F, A) -> d(get(debug), F, A). d(true, F, A) -> - print(F, A); + ?IPRINT(F, A); d(_,_F,_A) -> ok. -print(F, A) -> - ?PRINT2("MGR " ++ F, A). - -%% formated_timestamp() -> -%% snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/test/snmp_test_mgr_misc.erl b/lib/snmp/test/snmp_test_mgr_misc.erl index 6608a88c00..738f45a1b0 100644 --- a/lib/snmp/test/snmp_test_mgr_misc.erl +++ b/lib/snmp/test/snmp_test_mgr_misc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2019. All Rights Reserved. +%% Copyright Ericsson AB 1996-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -102,13 +102,21 @@ init_packet( Parent, SnmpMgr, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, DbgOptions, IpFamily) -> + %% This causes "verbosity printouts" to print (from the + %% specified level) in the modules we "borrow" from the + %% agent code (burr,,,). + %% With "our" name (mgr_misc). put(sname, mgr_misc), init_debug(DbgOptions), + %% Make use of the "test name" print "feature" + put(tname, "MGR-MISC"), + ?IPRINT("starting"), UdpOpts = [{recbuf,BufSz}, {reuseaddr, true}, IpFamily], {ok, UdpId} = gen_udp:open(TrapUdp, UdpOpts), put(msg_id, 1), init_usm(Version, Dir), proc_lib:init_ack(Parent, self()), + ?IPRINT("started"), packet_loop(SnmpMgr, UdpId, AgentIp, UdpPort, VsnHdr, Version, []). init_debug(Dbg) when is_atom(Dbg) -> @@ -601,43 +609,51 @@ set_pdu(Msg, RePdu) -> Msg#message{data = RePdu}. +%% Disgustingly, we borrow stuff from the agent, including the +%% local-db. Also, disgustingly, the local-db may actually not +%% have died yet. But since we actually *need* a clean local-db, +%% we must make sure its dead before we try to start the new +%% instance... init_usm('version-3', Dir) -> - ?vlog("init_usm -> create (and init) fake \"agent\" table", []), + ?IPRINT("init_usm -> create (and init) fake \"agent\" table", []), ets:new(snmp_agent_table, [set, public, named_table]), ets:insert(snmp_agent_table, {agent_mib_storage, persistent}), %% The local-db process may *still* be running (from a previous %% test case), on the way down, but not yet dead. - %% Either way, before we start it, make sure its dead and *gone*! + %% Either way, before we try to start it, make sure its old instance + %% dead and *gone*! %% How do we do that without getting hung up? Calling the stop %% function, will not do since it uses Timeout=infinity. - ?vlog("init_usm -> ensure (old) fake local-db is dead", []), + ?IPRINT("init_usm -> ensure (old) fake local-db is dead", []), ensure_local_db_dead(), - ?vlog("init_usm -> try start fake local-db", []), + ?IPRINT("init_usm -> try start fake local-db", []), case snmpa_local_db:start_link(normal, Dir, [{sname, "MGR-LOCAL-DB"}, {verbosity, trace}]) of {ok, Pid} -> - ?vlog("started: ~p" - "~n ~p", [Pid, process_info(Pid)]); + ?IPRINT("init_usm -> local-db started: ~p" + "~n ~p", [Pid, process_info(Pid)]); {error, {already_started, Pid}} -> LDBInfo = process_info(Pid), - ?vlog("already started: ~p" - "~n ~p", [Pid, LDBInfo]), + ?EPRINT("init_usm -> local-db already started: ~p" + "~n ~p", [Pid, LDBInfo]), ?FAIL({still_running, snmpa_local_db, LDBInfo}); {error, Reason} -> + ?EPRINT("init_usm -> failed start local-db: " + "~n ~p", [Reason]), ?FAIL({failed_starting, snmpa_local_db, Reason}) end, NameDb = snmpa_agent:db(snmpEngineID), - ?vlog("init_usm -> try set manager engine-id", []), + ?IPRINT("init_usm -> try set manager engine-id"), R = snmp_generic:variable_set(NameDb, "mgrEngine"), snmp_verbosity:print(info, info, "init_usm -> engine-id set result: ~p", [R]), - ?vlog("init_usm -> try set engine boots (framework-mib)", []), + ?IPRINT("init_usm -> try set engine boots (framework-mib)"), snmp_framework_mib:set_engine_boots(1), - ?vlog("init_usm -> try set engine time (framework-mib)", []), + ?IPRINT("init_usm -> try set engine time (framework-mib)"), snmp_framework_mib:set_engine_time(1), - ?vlog("init_usm -> try usm (mib) reconfigure", []), + ?IPRINT("init_usm -> try usm (mib) reconfigure"), snmp_user_based_sm_mib:reconfigure(Dir), - ?vlog("init_usm -> done", []), + ?IPRINT("init_usm -> done"), ok; init_usm(_Vsn, _Dir) -> ok. @@ -659,27 +675,28 @@ ensure_dead(Pid, Timeout) when is_pid(Pid) -> ok end; ensure_dead(_, _) -> - ?vlog("ensure_dead -> already dead", []), + ?IPRINT("ensure_dead -> already dead", []), ok. ensure_dead_wait(Pid, MRef, Timeout) -> receive {'DOWN', MRef, process, Pid, _Info} -> - ?vlog("ensure_dead_wait -> died peacefully", []), + ?IPRINT("ensure_dead_wait -> died peacefully"), throw(ok) after Timeout -> - ?vlog("ensure_dead_wait -> giving up", []), + ?WPRINT("ensure_dead_wait -> giving up"), ok end. ensure_dead_stop(Pid, MRef, Timeout) -> + %% Spawn a stop'er process StopPid = spawn(fun() -> snmpa_local_db:stop() end), receive {'DOWN', MRef, process, Pid, _Info} -> - ?vlog("ensure_dead -> dead (stopped)", []), + ?NPRINT("ensure_dead -> dead (stopped)"), throw(ok) after Timeout -> - ?vlog("ensure_dead_stop -> giving up", []), + ?WPRINT("ensure_dead_stop -> giving up"), exit(StopPid, kill), ok end. @@ -688,10 +705,10 @@ ensure_dead_kill(Pid, MRef, Timeout) -> exit(Pid, kill), receive {'DOWN', MRef, process, Pid, _Info} -> - ?vlog("ensure_dead -> dead (killed)", []), + ?NPRINT("ensure_dead -> dead (killed)"), throw(ok) after Timeout -> - ?vlog("ensure_dead_kill -> giving up", []), + ?WPRINT("ensure_dead_kill -> giving up"), ok end. @@ -891,10 +908,7 @@ d(F) -> d(F, []). d(F,A) -> d(get(debug), F, A). d(true, F, A) -> - print(F, A); + ?IPRINT(F, A); d(_,_F,_A) -> ok. -print(F, A) -> - ?PRINT2("MGR_PS " ++ F, A). - diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl index 0863cf0000..76a1967513 100644 --- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2014-2018. All Rights Reserved. +%% Copyright Ericsson AB 2014-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -130,8 +130,11 @@ snmpd_cases() -> %% ----- %% -init_per_suite(Config) -> - case netsnmp_init(Config) of +init_per_suite(Config0) -> + ?IPRINT("init_per_suite -> entry with" + "~n Config: ~p", [Config0]), + + case netsnmp_init(Config0) of {skip, _} = SKIP -> SKIP; @@ -142,6 +145,10 @@ init_per_suite(Config) -> Config2 when is_list(Config2) -> snmp_test_sys_monitor:start(), + + ?IPRINT("init_per_suite -> end when" + "~n Config: ~p", [Config2]), + Config2 end end. @@ -176,9 +183,15 @@ netsnmp_check(RE) -> end_per_suite(Config) -> + ?IPRINT("end_per_suite -> entry with" + "~n Config: ~p", [Config]), + snmp_test_sys_monitor:stop(), - ?LIB:end_per_suite(Config). + ?LIB:end_per_suite(Config), + ?IPRINT("end_per_suite -> end"), + + Config. %% %% ----- @@ -260,17 +273,27 @@ end_per_group(_GroupName, Config) -> %% init_per_testcase(_Case, Config) -> + ?IPRINT("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), snmp_test_global_sys_monitor:reset_events(), - Dog = ct:timetrap(20000), + Dog = ct:timetrap(?SECS(20)), application:stop(snmp), application:unload(snmp), - [{watchdog, Dog} | Config]. + Config1 = [{watchdog, Dog} | Config], + + ?IPRINT("init_per_testcase -> done when" + "~n Config: ~p", [Config1]), + + Config1. end_per_testcase(_, Config) -> - ?PRINT2("system events during test: " + ?IPRINT("end_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + ?IPRINT("system events during test: " "~n ~p", [snmp_test_global_sys_monitor:events()]), case application:stop(snmp) of @@ -285,6 +308,10 @@ end_per_testcase(_, Config) -> E2 -> ct:pal("application:unload(snmp) -> ~p", [E2]) end, + + ?IPRINT("end_per_testcase -> done with" + "~n Config: ~p", [Config]), + Config. find_executable(Exec, Config) -> diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 1cbd48eafc..e79cbaa336 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -668,6 +668,21 @@ </section> </section> +<section><title>Ssh 4.6.9.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed possible hanging in <c>ssh_sftp:stop_channel/1</c>.</p> + <p> + Own Id: OTP-16507 Aux Id: ERIERL-470 </p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 4.6.9.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index aa0fbe376c..862f79ac56 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -1196,6 +1196,41 @@ </desc> </func> +<!-- SET_SOCK_OPTS/2 --> + <func> + <name name="set_sock_opts" arity="2" since=""/> + <fsummary>Set tcp socket options on connections</fsummary> + <desc> + <p>Sets tcp socket options on the tcp-socket below an ssh connection.</p> + <p>This function calls the + <seealso marker="kernel:inet#setopts/2">inet:setopts/2</seealso>, read that documentation and + for <seealso marker="kernel:gen_tcp#type-option">gen_tcp:option()</seealso>. + All gen_tcp socket options except <c>active</c>, <c>deliver</c>, <c>mode</c> and <c>packet</c> + are allowed. The excluded options are reserved by the SSH application. + </p> + <warning> + <p>This is an extremly dangerous function. You use it on your own risk.</p> + <p>Some options are OS and OS version dependent. + Do not use it unless you know what effect your option values will have + on an TCP stream.</p> + <p>Some values may destroy the functionality of the SSH protocol. + </p> + </warning> + </desc> + </func> + +<!-- GET_SOCK_OPTS/2 --> + <func> + <name name="get_sock_opts" arity="2" since=""/> + <fsummary>Get tcp socket options on connections</fsummary> + <desc> + <p>Get tcp socket option values of the tcp-socket below an ssh connection.</p> + <p>This function calls the + <seealso marker="kernel:inet#getopts/2">inet:getopts/2</seealso>, read that documentation. + </p> + </desc> + </func> + <!-- DEAMON/1,2,3 --> <func> <name since="">daemon(Port | TcpSocket) -> Result</name> diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index c93b796078..355b40eea8 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -35,6 +35,7 @@ channel_info/3, daemon/1, daemon/2, daemon/3, daemon_info/1, daemon_info/2, + set_sock_opts/2, get_sock_opts/2, default_algorithms/0, chk_algos_opts/1, stop_listener/1, stop_listener/2, stop_listener/3, @@ -560,6 +561,25 @@ chk_algos_opts(Opts) -> {error, {non_algo_opts_found,OtherOps}} end. + +%%-------------------------------------------------------------------- +-spec set_sock_opts(ConnectionRef, SocketOptions) -> + ok | {error, inet:posix()} when + ConnectionRef :: connection_ref(), + SocketOptions :: [gen_tcp:option()] . +%%-------------------------------------------------------------------- +set_sock_opts(ConnectionRef, SocketOptions) -> + ssh_connection_handler:set_sock_opts(ConnectionRef, SocketOptions). + +%%-------------------------------------------------------------------- +-spec get_sock_opts(ConnectionRef, SocketGetOptions) -> + ok | {error, inet:posix()} when + ConnectionRef :: connection_ref(), + SocketGetOptions :: [gen_tcp:option_name()] . +%%-------------------------------------------------------------------- +get_sock_opts(ConnectionRef, SocketGetOptions) -> + ssh_connection_handler:get_sock_opts(ConnectionRef, SocketGetOptions). + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index d200dac33c..e8c0d88e59 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -57,7 +57,8 @@ channel_info/3, adjust_window/3, close/2, disconnect/4, - get_print_info/1 + get_print_info/1, + set_sock_opts/2, get_sock_opts/2 ]). -type connection_ref() :: ssh:connection_ref(). @@ -321,6 +322,31 @@ close(ConnectionHandler, ChannelId) -> ok end. + +%%-------------------------------------------------------------------- +%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +set_sock_opts(ConnectionRef, SocketOptions) -> + try lists:foldr(fun({Name,_Val}, Acc) -> + case lists:member(Name, [active, deliver, mode, packet]) of + true -> [Name|Acc]; + false -> Acc + end + end, [], SocketOptions) + of + [] -> + call(ConnectionRef, {set_sock_opts,SocketOptions}); + Bad -> + {error, {not_allowed,Bad}} + catch + _:_ -> + {error, badarg} + end. + +%%-------------------------------------------------------------------- +%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +get_sock_opts(ConnectionRef, SocketGetOptions) -> + call(ConnectionRef, {get_sock_opts,SocketGetOptions}). + %%==================================================================== %% Test support %%==================================================================== @@ -1205,6 +1231,20 @@ handle_event({call,From}, {info, ChannelPid}, _, D) -> end, [], cache(D)), {keep_state_and_data, [{reply, From, {ok,Result}}]}; +handle_event({call,From}, {set_sock_opts,SocketOptions}, _StateName, D) -> + Result = try inet:setopts(D#data.socket, SocketOptions) + catch + _:_ -> {error, badarg} + end, + {keep_state_and_data, [{reply,From,Result}]}; + +handle_event({call,From}, {get_sock_opts,SocketGetOptions}, _StateName, D) -> + Result = try inet:getopts(D#data.socket, SocketGetOptions) + catch + _:_ -> {error, badarg} + end, + {keep_state_and_data, [{reply,From,Result}]}; + handle_event({call,From}, stop, _StateName, D0) -> {Repls,D} = send_replies(ssh_connection:handle_stop(D0#data.connection_state), D0), {stop_and_reply, normal, [{reply,From,ok}|Repls], D}; diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index f8b883c643..386730af17 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -79,7 +79,8 @@ groups() -> packet_size, ssh_info_print, {group, login_bad_pwd_no_retry}, - shell_exit_status + shell_exit_status, + setopts_getopts ]}, {ssh_renegotiate_SUITE, [?PARALLEL], [rekey0, @@ -1440,6 +1441,42 @@ shell_exit_status(Config) when is_list(Config) -> %%---------------------------------------------------------------------------- +setopts_getopts(Config) -> + process_flag(trap_exit, true), + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(priv_dir, Config), + + ShellFun = fun (_User) -> spawn(fun() -> ok end) end, + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{"vego", "morot"}]}, + {shell, ShellFun}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}]), + %% Test get_sock_opts + {ok,[{active,once},{deliver,term},{mode,binary},{packet,0}]} = + ssh:get_sock_opts(ConnectionRef, [active, deliver, mode, packet]), + + %% Test to set forbidden opts + {error,{not_allowed,[active,deliver,mode,packet]}} = + ssh:set_sock_opts(ConnectionRef, [{active,once},{deliver,term},{mode,binary},{packet,0}]), + + %% Test to set some other opt + {ok,[{delay_send,DS0}]} = + ssh:get_sock_opts(ConnectionRef, [delay_send]), + DS1 = not DS0, + ok = ssh:set_sock_opts(ConnectionRef, [{delay_send,DS1}]), + {ok,[{delay_send,DS1}]} = + ssh:get_sock_opts(ConnectionRef, [delay_send]), + + ssh:stop_daemon(Pid). + +%%---------------------------------------------------------------------------- %%% Idle timeout test rekey0() -> [{timetrap,{seconds,90}}]. rekey1() -> [{timetrap,{seconds,90}}]. diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index c45e6bcf9a..63ccaabd74 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -74,5 +74,5 @@ {applications, [crypto, public_key, kernel, stdlib]}, {env, []}, {mod, {ssl_app, []}}, - {runtime_dependencies, ["stdlib-3.5","public_key-1.5","kernel-6.0", + {runtime_dependencies, ["stdlib-3.5","public_key-@OTP-16528@","kernel-6.0", "erts-10.0","crypto-4.2", "inets-5.10.7"]}]}. diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index e24ea9ac22..b62a1c4546 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -53,7 +53,8 @@ %% Alert and close handling -export([handle_own_alert/4, handle_alert/3, handle_normal_shutdown/3, - handle_trusted_certs_db/1]). + handle_trusted_certs_db/1, + maybe_invalidate_session/6]). %% Data handling -export([read_application_data/2, internal_renegotiation/2]). @@ -325,6 +326,7 @@ dist_handshake_complete(ConnectionPid, DHandle) -> prf(ConnectionPid, Secret, Label, Seed, WantedLength) -> call(ConnectionPid, {prf, Secret, Label, Seed, WantedLength}). + %%==================================================================== %% Alert and close handling %%==================================================================== @@ -442,6 +444,13 @@ handle_alert(#alert{level = ?WARNING} = Alert, StateName, Alert#alert{role = opposite_role(Role)}), Connection:next_event(StateName, no_record, State). +maybe_invalidate_session(undefined,_, _, _, _, _) -> + ok; +maybe_invalidate_session({3, 4},_, _, _, _, _) -> + ok; +maybe_invalidate_session({3, N}, Type, Role, Host, Port, Session) when N < 4 -> + maybe_invalidate_session(Type, Role, Host, Port, Session). + %%==================================================================== %% Data handling %%==================================================================== @@ -1496,16 +1505,23 @@ handle_call(_,_,_,_,_) -> handle_info({ErrorTag, Socket, econnaborted}, StateName, #state{static_env = #static_env{role = Role, + host = Host, + port = Port, socket = Socket, transport_cb = Transport, error_tag = ErrorTag, trackers = Trackers, protocol_cb = Connection}, - start_or_recv_from = StartFrom - } = State) when StateName =/= connection -> + handshake_env = #handshake_env{renegotiation = Type}, + connection_env = #connection_env{negotiated_version = Version}, + session = Session, + start_or_recv_from = StartFrom + } = State) when StateName =/= connection -> + + maybe_invalidate_session(Version, Type, Role, Host, Port, Session), Pids = Connection:pids(State), alert_user(Pids, Transport, Trackers,Socket, - StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, StateName, Connection), + StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, StateName, Connection), {stop, {shutdown, normal}, State}; handle_info({ErrorTag, Socket, Reason}, StateName, #state{static_env = #static_env{ @@ -3013,6 +3029,11 @@ log_alert(Level, Role, ProtocolName, StateName, Alert) -> alert => Alert, alerter => peer}, Alert#alert.where). +maybe_invalidate_session({false, first}, server = Role, Host, Port, Session) -> + invalidate_session(Role, Host, Port, Session); +maybe_invalidate_session(_, _, _, _, _) -> + ok. + invalidate_session(client, Host, Port, Session) -> ssl_manager:invalidate_session(Host, Port, Session); invalidate_session(server, _, Port, Session) -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 8e53be72ed..3b33af95d0 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -402,6 +402,12 @@ certificate_verify(Signature, PublicKeyInfo, Version, %%-------------------------------------------------------------------- verify_signature(_Version, _Hash, {_HashAlgo, anon}, _Signature, _) -> true; +verify_signature({3, Minor}, Hash, {HashAlgo, rsa_pss_rsae}, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) + when Minor >= 3 -> + public_key:verify({digest, Hash}, HashAlgo, Signature, PubKey, + [{rsa_padding, rsa_pkcs1_pss_padding}, + {rsa_pss_saltlen, -1}, + {rsa_mgf1_md, HashAlgo}]); verify_signature({3, Minor}, Hash, {HashAlgo, rsa}, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) when Minor >= 3 -> public_key:verify({digest, Hash}, HashAlgo, Signature, PubKey); @@ -2356,6 +2362,20 @@ dec_server_key_params(Len, Keys, Version) -> <<Params:Len/bytes, Signature/binary>> = Keys, dec_server_key_signature(Params, Signature, Version). +dec_server_key_signature(Params, <<?BYTE(8), ?BYTE(SignAlgo), + ?UINT16(0)>>, {Major, Minor}) + when Major == 3, Minor >= 3 -> + <<?UINT16(Scheme0)>> = <<?BYTE(8), ?BYTE(SignAlgo)>>, + Scheme = ssl_cipher:signature_scheme(Scheme0), + {Hash, Sign, _} = ssl_cipher:scheme_to_components(Scheme), + {Params, {Hash, Sign}, <<>>}; +dec_server_key_signature(Params, <<?BYTE(8), ?BYTE(SignAlgo), + ?UINT16(Len), Signature:Len/binary>>, {Major, Minor}) + when Major == 3, Minor >= 3 -> + <<?UINT16(Scheme0)>> = <<?BYTE(8), ?BYTE(SignAlgo)>>, + Scheme = ssl_cipher:signature_scheme(Scheme0), + {Hash, Sign, _} = ssl_cipher:scheme_to_components(Scheme), + {Params, {Hash, Sign}, Signature}; dec_server_key_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo), ?UINT16(0)>>, {Major, Minor}) when Major == 3, Minor >= 3 -> diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 6c8553d6e0..7257e1dea5 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -734,7 +734,7 @@ hello(internal, #server_hello{} = Hello, [{next_event, internal, Hello}]} end; hello(info, Event, State) -> - gen_info(Event, ?FUNCTION_NAME, State); + handle_info(Event, ?FUNCTION_NAME, State); hello(Type, Event, State) -> gen_handshake(?FUNCTION_NAME, Type, Event, State). @@ -1200,9 +1200,22 @@ handle_info({PassiveTag, Socket}, StateName, handle_info({CloseTag, Socket}, StateName, #state{static_env = #static_env{ role = Role, + host = Host, + port = Port, socket = Socket, close_tag = CloseTag}, + handshake_env = #handshake_env{renegotiation = Type}, connection_env = #connection_env{negotiated_version = Version}, + session = Session} = State) when StateName =/= connection -> + ssl_connection:maybe_invalidate_session(Version, Type, Role, Host, Port, Session), + Alert = ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY, transport_closed), + ssl_connection:handle_normal_shutdown(Alert#alert{role = Role}, StateName, State), + {stop, {shutdown, transport_closed}, State}; +handle_info({CloseTag, Socket}, StateName, + #state{static_env = #static_env{ + role = Role, + socket = Socket, + close_tag = CloseTag}, socket_options = #socket_options{active = Active}, protocol_buffers = #protocol_buffers{tls_cipher_texts = CTs}, user_data_buffer = {_,BufferSize,_}, @@ -1215,16 +1228,16 @@ handle_info({CloseTag, Socket}, StateName, case (Active == false) andalso ((CTs =/= []) or (BufferSize =/= 0)) of false -> - case Version of - {1, N} when N >= 1 -> - ok; - _ -> - %% As invalidate_sessions here causes performance issues, - %% we will conform to the widespread implementation - %% practice and go aginst the spec - %%invalidate_session(Role, Host, Port, Session) - ok - end, + %% As invalidate_sessions here causes performance issues, + %% we will conform to the widespread implementation + %% practice and go aginst the spec + %% case Version of + %% {3, N} when N >= 1 -> + %% ok; + %% _ -> + %% invalidate_session(Role, Host, Port, Session) + %% ok + %% end, Alert = ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY, transport_closed), ssl_connection:handle_normal_shutdown(Alert#alert{role = Role}, StateName, State), {stop, {shutdown, transport_closed}, State}; diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl index 951d4302e9..790746658e 100644 --- a/lib/ssl/src/tls_sender.erl +++ b/lib/ssl/src/tls_sender.erl @@ -540,7 +540,9 @@ key_update_at(Version, #{security_parameters := ?AES_GCM -> KeyUpdateAt; ?CHACHA20_POLY1305 -> - seq_num_wrap + seq_num_wrap; + ?AES_CCM -> + KeyUpdateAt end; key_update_at(_, _, KeyUpdateAt) -> KeyUpdateAt. diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl index 381793c65d..38594151d9 100644 --- a/lib/ssl/src/tls_v1.erl +++ b/lib/ssl/src/tls_v1.erl @@ -884,7 +884,9 @@ oid_to_enum(?secp384r1) -> 24; oid_to_enum(?secp521r1) -> 25; oid_to_enum(?brainpoolP256r1) -> 26; oid_to_enum(?brainpoolP384r1) -> 27; -oid_to_enum(?brainpoolP512r1) -> 28. +oid_to_enum(?brainpoolP512r1) -> 28; +oid_to_enum(?'id-X25519') -> 29; +oid_to_enum(?'id-X448') -> 30. enum_to_oid(1) -> ?sect163k1; enum_to_oid(2) -> ?sect163r1; @@ -914,5 +916,7 @@ enum_to_oid(25) -> ?secp521r1; enum_to_oid(26) -> ?brainpoolP256r1; enum_to_oid(27) -> ?brainpoolP384r1; enum_to_oid(28) -> ?brainpoolP512r1; +enum_to_oid(29) -> ?'id-X25519'; +enum_to_oid(30) -> ?'id-X448'; enum_to_oid(_) -> undefined. diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile index 1bd4c2c910..e53f54130f 100644 --- a/lib/ssl/test/Makefile +++ b/lib/ssl/test/Makefile @@ -67,6 +67,7 @@ MODULES = \ ssl_engine_SUITE\ ssl_handshake_SUITE \ ssl_key_update_SUITE \ + openssl_key_update_SUITE \ ssl_npn_hello_SUITE \ ssl_packet_SUITE \ ssl_payload_SUITE \ @@ -74,6 +75,7 @@ MODULES = \ ssl_session_SUITE \ ssl_session_cache_SUITE \ ssl_session_ticket_SUITE \ + openssl_session_ticket_SUITE \ openssl_session_SUITE \ ssl_ECC_SUITE \ ssl_ECC_openssl_SUITE \ diff --git a/lib/ssl/test/openssl_key_update_SUITE.erl b/lib/ssl/test/openssl_key_update_SUITE.erl new file mode 100644 index 0000000000..4963f0bb30 --- /dev/null +++ b/lib/ssl/test/openssl_key_update_SUITE.erl @@ -0,0 +1,134 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2020-2020. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(openssl_key_update_SUITE). + +%% Callback functions +-export([all/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]). + +%% Testcases +-export([openssl_client_explicit_key_update/0, + openssl_client_explicit_key_update/1, + openssl_server_explicit_key_update/0, + openssl_server_explicit_key_update/1]). + +-include_lib("common_test/include/ct.hrl"). + +all() -> + [{group, 'tlsv1.3'}]. + +groups() -> + [{'tlsv1.3', [], tls_1_3_tests()}]. + +tls_1_3_tests() -> + [openssl_client_explicit_key_update, + openssl_server_explicit_key_update]. + +init_per_suite(Config0) -> + catch crypto:stop(), + try crypto:start() of + ok -> + ssl_test_lib:clean_start(), + case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of + true -> + ssl_test_lib:make_ecdsa_cert(Config0); + false -> + {skip, "Missing EC crypto support"} + end + catch _:_ -> + {skip, "Crypto did not start"} + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:unload(ssl), + application:stop(crypto). + +init_per_group(GroupName, Config) -> + ssl_test_lib:init_per_group_openssl(GroupName, Config). + +end_per_group(GroupName, Config) -> + ssl_test_lib:end_per_group(GroupName, Config). + +init_per_testcase(_TestCase, Config) -> + ssl_test_lib:ct_log_supported_protocol_versions(Config), + ct:timetrap({seconds, 10}), + Config. + +end_per_testcase(_TestCase, Config) -> + Config. + + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- + +openssl_client_explicit_key_update() -> + [{doc,"Test ssl:update_key/2 between openssl s_client and erlang server."}]. + +openssl_client_explicit_key_update(Config) -> + Data = "123456789012345", %% 15 bytes + + Server = ssl_test_lib:start_server(erlang, [{log_level, debug}], Config), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client(openssl, [{port, Port}], Config), + ssl_test_lib:send_recv_result_active(Client, Server, Data), + + %% TODO s_client can hang after sending special commands e.g "k", "K" + %% ssl_test_lib:update_keys(Client, write), + %% ssl_test_lib:update_keys(Client, read_write), + ssl_test_lib:update_keys(Server, write), + ssl_test_lib:update_keys(Server, read_write), + + ssl_test_lib:send_recv_result_active(Client, Server, Data), + + ssl_test_lib:close(Client), + ssl_test_lib:close(Server). + +openssl_server_explicit_key_update() -> + [{doc,"Test ssl:update_key/2 between ssl client and s_server."}]. + +openssl_server_explicit_key_update(Config) -> + Data = "123456789012345", %% 15 bytes + + Server = ssl_test_lib:start_server(openssl, [], Config), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client(erlang, [{port, Port}, + {log_level, debug}, + {versions, ['tlsv1.2','tlsv1.3']}],Config), + ssl_test_lib:send_recv_result_active(Server, Client, Data), + + ssl_test_lib:update_keys(Client, write), + ssl_test_lib:update_keys(Client, read_write), + ssl_test_lib:update_keys(Server, write), + ssl_test_lib:update_keys(Server, read_write), + + ssl_test_lib:send_recv_result_active(Client, Server, Data), + + ssl_test_lib:close(Client), + ssl_test_lib:close(Server). diff --git a/lib/ssl/test/openssl_session_ticket_SUITE.erl b/lib/ssl/test/openssl_session_ticket_SUITE.erl new file mode 100644 index 0000000000..775048e355 --- /dev/null +++ b/lib/ssl/test/openssl_session_ticket_SUITE.erl @@ -0,0 +1,409 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2020. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(openssl_session_ticket_SUITE). + +%% Callback functions +-export([all/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]). + +%% Testcases +-export([openssl_server_basic/0, + openssl_server_basic/1, + openssl_server_hrr/0, + openssl_server_hrr/1, + openssl_server_hrr_multiple_tickets/0, + openssl_server_hrr_multiple_tickets/1, + openssl_client_basic/0, + openssl_client_basic/1, + openssl_client_hrr/0, + openssl_client_hrr/1]). + +-include("tls_handshake.hrl"). + +-include_lib("common_test/include/ct.hrl"). + +-define(SLEEP, 500). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- +all() -> + [ + {group, 'tlsv1.3'} + ]. + +groups() -> + [{'tlsv1.3', [], [{group, stateful}, + {group, stateless}, + {group, openssl_server}]}, + {openssl_server, [], [openssl_server_basic, + openssl_server_hrr, + openssl_server_hrr_multiple_tickets + ]}, + {stateful, [], session_tests()}, + {stateless, [], session_tests()}]. + +session_tests() -> + [openssl_client_basic, + openssl_client_hrr]. + +init_per_suite(Config0) -> + catch crypto:stop(), + try crypto:start() of + ok -> + ssl_test_lib:clean_start(), + ssl_test_lib:make_rsa_cert(Config0) + catch _:_ -> + {skip, "Crypto did not start"} + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:stop(crypto). + +init_per_group(stateful, Config) -> + [{server_ticket_mode, stateful} | proplists:delete(server_ticket_mode, Config)]; +init_per_group(stateless, Config) -> + [{server_ticket_mode, stateless} | proplists:delete(server_ticket_mode, Config)]; +init_per_group(GroupName, Config) -> + ssl_test_lib:init_per_group_openssl(GroupName, Config). + +end_per_group(GroupName, Config) -> + ssl_test_lib:end_per_group(GroupName, Config). + +init_per_testcase(_TestCase, Config) -> + ssl:stop(), + application:load(ssl), + ssl:start(), + ct:timetrap({seconds, 15}), + Config. + +end_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- + +openssl_server_basic() -> + [{doc,"Test session resumption with session tickets (erlang client - openssl server)"}]. +openssl_server_basic(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + Version = 'tlsv1.3', + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + CACertFile = proplists:get_value(cacertfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + %% Configure session tickets + ClientOpts = [{session_tickets, auto}, {log_level, debug}, + {versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], + + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile,"-key", KeyFile, "-CAfile", CACertFile, "-msg", "-debug"], + + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), + + ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), + + %% Store ticket from first connection + Client0 = ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [false, no_reply]}}, + {from, self()}, {options, ClientOpts}]), + %% Wait for session ticket + ct:sleep(100), + + %% Close previous connection as s_server can only handle one at a time + ssl_test_lib:close(Client0), + + %% Use ticket + Client1 = ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [true, no_reply]}}, + {from, self()}, + {options, ClientOpts}]), + process_flag(trap_exit, false), + + %% Clean close down! Server needs to be closed first !! + ssl_test_lib:close_port(OpensslPort), + ssl_test_lib:close(Client1). + +openssl_client_basic() -> + [{doc,"Test session resumption with session tickets (openssl client - erlang server)"}]. +openssl_client_basic(Config) when is_list(Config) -> + ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + TicketFile0 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket0"]), + TicketFile1 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket1"]), + ServerTicketMode = proplists:get_value(server_ticket_mode, Config), + + Data = "Hello world", + + %% Configure session tickets + ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug}, + {versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0], + + Server0 = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [false]}}, + {options, ServerOpts}]), + + Version = 'tlsv1.3', + Port0 = ssl_test_lib:inet_port(Server0), + + Exe = "openssl", + Args0 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) + ++ ":" ++ integer_to_list(Port0), + ssl_test_lib:version_flag(Version), + "-sess_out", TicketFile0], + + OpenSslPort0 = ssl_test_lib:portable_open_port(Exe, Args0), + + true = port_command(OpenSslPort0, Data), + + ssl_test_lib:check_result(Server0, ok), + + Server0 ! {listen, {mfa, {ssl_test_lib, + verify_active_session_resumption, + [true]}}}, + + %% Wait for session ticket + ct:sleep(100), + + Args1 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) + ++ ":" ++ integer_to_list(Port0), + ssl_test_lib:version_flag(Version), + "-sess_in", TicketFile0, + "-sess_out", TicketFile1], + + OpenSslPort1 = ssl_test_lib:portable_open_port(Exe, Args1), + + true = port_command(OpenSslPort1, Data), + + ssl_test_lib:check_result(Server0, ok), + + %% Clean close down! Server needs to be closed first !! + ssl_test_lib:close(Server0), + ssl_test_lib:close_port(OpenSslPort0), + ssl_test_lib:close_port(OpenSslPort1). + +openssl_server_hrr() -> + [{doc,"Test session resumption with session tickets and hello_retry_request (erlang client - openssl server)"}]. +openssl_server_hrr(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + Version = 'tlsv1.3', + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + CACertFile = proplists:get_value(cacertfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + %% Configure session tickets + ClientOpts = [{session_tickets, auto}, {log_level, debug}, + {versions, ['tlsv1.2','tlsv1.3']}, + {supported_groups,[secp256r1, x25519]}|ClientOpts0], + + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile, + "-key", KeyFile, + "-CAfile", CACertFile, + "-groups", "X448:X25519", + "-msg", "-debug"], + + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), + + ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), + + %% Store ticket from first connection + Client0 = ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [false, no_reply]}}, + {from, self()}, {options, ClientOpts}]), + %% Wait for session ticket + ct:sleep(100), + + %% Close previous connection as s_server can only handle one at a time + ssl_test_lib:close(Client0), + + %% Use ticket + Client1 = ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [true, no_reply]}}, + {from, self()}, + {options, ClientOpts}]), + process_flag(trap_exit, false), + + %% Clean close down! Server needs to be closed first !! + ssl_test_lib:close_port(OpensslPort), + ssl_test_lib:close(Client1). + +openssl_client_hrr() -> + [{doc,"Test session resumption with session tickets and hello_retry_request (openssl client - erlang server)"}]. +openssl_client_hrr(Config) when is_list(Config) -> + ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + TicketFile0 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket0"]), + TicketFile1 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket1"]), + ServerTicketMode = proplists:get_value(server_ticket_mode, Config), + + Data = "Hello world", + + %% Configure session tickets + ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug}, + {versions, ['tlsv1.2','tlsv1.3']}, + {supported_groups,[x448, x25519]}|ServerOpts0], + + Server0 = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [false]}}, + {options, ServerOpts}]), + + Version = 'tlsv1.3', + Port0 = ssl_test_lib:inet_port(Server0), + + Exe = "openssl", + Args0 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) + ++ ":" ++ integer_to_list(Port0), + ssl_test_lib:version_flag(Version), + "-groups", "P-256:X25519", + "-sess_out", TicketFile0], + + OpenSslPort0 = ssl_test_lib:portable_open_port(Exe, Args0), + + true = port_command(OpenSslPort0, Data), + + ssl_test_lib:check_result(Server0, ok), + + Server0 ! {listen, {mfa, {ssl_test_lib, + verify_active_session_resumption, + [true]}}}, + + %% Wait for session ticket + ct:sleep(100), + + Args1 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) + ++ ":" ++ integer_to_list(Port0), + ssl_test_lib:version_flag(Version), + "-groups", "P-256:X25519", + "-sess_in", TicketFile0, + "-sess_out", TicketFile1], + + OpenSslPort1 = ssl_test_lib:portable_open_port(Exe, Args1), + + true = port_command(OpenSslPort1, Data), + + ssl_test_lib:check_result(Server0, ok), + + %% Clean close down! Server needs to be closed first !! + ssl_test_lib:close(Server0), + ssl_test_lib:close_port(OpenSslPort0), + ssl_test_lib:close_port(OpenSslPort1). + +openssl_server_hrr_multiple_tickets() -> + [{doc,"Test session resumption with multiple session tickets and hello_retry_request (erlang client - openssl server)"}]. +openssl_server_hrr_multiple_tickets(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + Version = 'tlsv1.3', + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + CACertFile = proplists:get_value(cacertfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + %% Configure session tickets + ClientOpts = [{session_tickets, manual}, {log_level, debug}, + {versions, ['tlsv1.2','tlsv1.3']}, + {supported_groups,[secp256r1, x25519]}|ClientOpts0], + + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile, + "-key", KeyFile, + "-CAfile", CACertFile, + "-groups", "X448:X25519", + "-msg", "-debug"], + + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), + + ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), + + %% Store ticket from first connection + Client0 = ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [false, no_reply, {tickets, 2}]}}, + {from, self()}, {options, ClientOpts}]), + + Tickets0 = ssl_test_lib:check_tickets(Client0), + + ct:pal("Received tickets: ~p~n", [Tickets0]), + + %% Close previous connection as s_server can only handle one at a time + ssl_test_lib:close(Client0), + + %% Use tickets + Client1 = ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, + verify_active_session_resumption, + [true, no_reply, no_tickets]}}, + {from, self()}, + {options, [{use_ticket, Tickets0}|ClientOpts]}]), + + process_flag(trap_exit, false), + + %% Clean close down! Server needs to be closed first !! + ssl_test_lib:close_port(OpensslPort), + ssl_test_lib:close(Client1). diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl index e598d662e9..855533cc3d 100644 --- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl +++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl @@ -32,6 +32,7 @@ %%-------------------------------------------------------------------- all() -> [ + {group, 'tlsv1.3'}, {group, 'tlsv1.2'}, {group, 'tlsv1.1'}, {group, 'tlsv1'}, @@ -42,6 +43,7 @@ all() -> groups() -> [ + {'tlsv1.3', [], tls_1_3_kex()}, {'tlsv1.2', [], kex()}, {'tlsv1.1', [], kex()}, {'tlsv1', [], kex()}, @@ -60,6 +62,7 @@ groups() -> ecdhe_rsa_aes_256_gcm, ecdhe_rsa_chacha20_poly1305 ]}, + {ecdhe_1_3_rsa_cert, [], tls_1_3_cipher_suites()}, {ecdhe_ecdsa, [],[ecdhe_ecdsa_rc4_128, ecdhe_ecdsa_3des_ede_cbc, ecdhe_ecdsa_aes_128_cbc, @@ -127,6 +130,17 @@ groups() -> ]} ]. + +tls_1_3_kex() -> + [{group, ecdhe_1_3_rsa_cert}]. + +tls_1_3_cipher_suites() -> + [aes_256_gcm_sha384, + aes_128_gcm_sha256, + chacha20_poly1305_sha256, + aes_128_ccm_sha256 + ]. + kex() -> rsa() ++ ecdsa() ++ dss() ++ anonymous(). @@ -186,7 +200,13 @@ end_per_suite(_Config) -> ssl:stop(), application:stop(crypto). - +init_per_group(GroupName, Config) when GroupName == ecdhe_1_3_rsa_cert -> + case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of + true -> + init_certs(GroupName, Config); + false -> + {skip, "Missing EC crypto support"} + end; init_per_group(GroupName, Config) when GroupName == ecdh_anon; GroupName == ecdhe_rsa; GroupName == ecdhe_psk -> @@ -318,6 +338,53 @@ init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8; _ -> {skip, "Missing AES_256_CCM crypto support"} end; +init_per_testcase(aes_256_gcm_sha384, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(aes_256_gcm, SupCiphers)) andalso + (lists:member(sha384, SupHashs)) + of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing AES_256_GCM_SHA384 crypto support"} + end; +init_per_testcase(aes_128_gcm_sha256, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(aes_256_gcm, SupCiphers)) andalso + (lists:member(sha256, SupHashs)) + of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing AES_128_GCM_SHA256 crypto support"} + end; +init_per_testcase(chacha20_poly1305_sha256, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(chacha20_poly1305, SupCiphers)) andalso + (lists:member(sha256, SupHashs)) + of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing chacha20_poly1305_sha256 crypto support"} + end; +init_per_testcase(aes_128_ccm_sha256, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(aes_128_ccm, SupCiphers)) andalso + (lists:member(sha256, SupHashs)) of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing AES_128_CCM_SHA256 crypto support"} + end; init_per_testcase(TestCase, Config) -> Cipher = ssl_test_lib:test_cipher(TestCase, Config), SupCiphers = proplists:get_value(ciphers, crypto:supports()), @@ -335,7 +402,6 @@ end_per_testcase(_TestCase, Config) -> %%-------------------------------------------------------------------- %% Initializtion ------------------------------------------ %%-------------------------------------------------------------------- - init_certs(srp_rsa, Config) -> DefConf = ssl_test_lib:default_cert_chain_conf(), CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf), @@ -367,6 +433,14 @@ init_certs(rsa, Config) -> [{tls_config, #{server_config => ServerOpts, client_config => ClientOpts}} | proplists:delete(tls_config, Config)]; +init_certs(ecdhe_1_3_rsa_cert, Config) -> + ClientExt = x509_test:extensions([{key_usage, [digitalSignature]}]), + {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[],[{extensions, ClientExt}]]}], + Config, "_peer_rsa_digitalsign"), + [{tls_config, #{server_config => ServerOpts, + client_config => ClientOpts}} | + proplists:delete(tls_config, Config)]; init_certs(dhe_dss, Config) -> DefConf = ssl_test_lib:default_cert_chain_conf(), CertChainConf = ssl_test_lib:gen_conf(dsa, dsa, DefConf, DefConf), @@ -427,6 +501,22 @@ init_certs(_GroupName, Config) -> %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- +aes_256_gcm_sha384(Config) when is_list(Config)-> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_AES_256_GCM_SHA384"), Version, Config). + +aes_128_gcm_sha256(Config) when is_list(Config) -> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_AES_128_GCM_SHA256"), Version, Config). + +chacha20_poly1305_sha256(Config) when is_list(Config) -> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_CHACHA20_POLY1305_SHA256"), Version, Config). + +aes_128_ccm_sha256(Config) when is_list(Config) -> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_AES_128_CCM_SHA256"), Version, Config). + %%-------------------------------------------------------------------- %% SRP -------------------------------------------------------- %%-------------------------------------------------------------------- @@ -775,3 +865,4 @@ test_ciphers(Kex, Cipher, Version) -> (_) -> false end}]). + diff --git a/lib/ssl/test/ssl_key_update_SUITE.erl b/lib/ssl/test/ssl_key_update_SUITE.erl index 32cbe0a5a1..2816f1a39e 100644 --- a/lib/ssl/test/ssl_key_update_SUITE.erl +++ b/lib/ssl/test/ssl_key_update_SUITE.erl @@ -19,7 +19,21 @@ %% -module(ssl_key_update_SUITE). --compile(export_all). +%% Callback functions +-export([all/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]). + +%% Testcases +-export([key_update_at/0, + key_update_at/1, + explicit_key_update/0, + explicit_key_update/1]). -include_lib("common_test/include/ct.hrl"). @@ -30,10 +44,8 @@ groups() -> [{'tlsv1.3', [], tls_1_3_tests()}]. tls_1_3_tests() -> - [ssl_client_ssl_server_key_update_at, - ssl_client_ssl_server_explicit_key_update, - openssl_client_ssl_server_explicit_key_update, - ssl_client_openssl_server_explicit_key_update]. + [key_update_at, + explicit_key_update]. init_per_suite(Config0) -> catch crypto:stop(), @@ -56,28 +68,10 @@ end_per_suite(_Config) -> application:stop(crypto). init_per_group(GroupName, Config) -> - case ssl_test_lib:is_tls_version(GroupName) of - true -> - case ssl_test_lib:sufficient_crypto_support(GroupName) of - true -> - [{client_type, erlang}, - {server_type, erlang}, {version, GroupName} - | ssl_test_lib:init_tls_version(GroupName, Config)]; - false -> - {skip, "Missing crypto support"} - end; - _ -> - ssl:start(), - Config - end. + ssl_test_lib:init_per_group(GroupName, Config). end_per_group(GroupName, Config) -> - case ssl_test_lib:is_tls_version(GroupName) of - true -> - ssl_test_lib:clean_tls_version(Config); - false -> - Config - end. + ssl_test_lib:end_per_group(GroupName, Config). init_per_testcase(_TestCase, Config) -> ssl_test_lib:ct_log_supported_protocol_versions(Config), @@ -92,10 +86,10 @@ end_per_testcase(_TestCase, Config) -> %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -ssl_client_ssl_server_key_update_at() -> +key_update_at() -> [{doc,"Test option 'key_update_at' between erlang client and erlang server."}]. -ssl_client_ssl_server_key_update_at(Config) -> +key_update_at(Config) -> %% {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Data = "123456789012345", %% 15 bytes @@ -117,10 +111,10 @@ ssl_client_ssl_server_key_update_at(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). -ssl_client_ssl_server_explicit_key_update() -> +explicit_key_update() -> [{doc,"Test ssl:update_key/2 between erlang client and erlang server."}]. -ssl_client_ssl_server_explicit_key_update(Config) -> +explicit_key_update(Config) -> Data = "123456789012345", %% 15 bytes Server = ssl_test_lib:start_server(erlang, [{log_level, debug}], Config), @@ -140,50 +134,3 @@ ssl_client_ssl_server_explicit_key_update(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). - -openssl_client_ssl_server_explicit_key_update() -> - [{doc,"Test ssl:update_key/2 between openssl s_client and erlang server."}]. - -openssl_client_ssl_server_explicit_key_update(Config) -> - Data = "123456789012345", %% 15 bytes - - Server = ssl_test_lib:start_server(erlang, [{log_level, debug}], Config), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client(openssl, [{port, Port}], Config), - ssl_test_lib:send_recv_result_active(Client, Server, Data), - - %% TODO s_client can hang after sending special commands e.g "k", "K" - %% ssl_test_lib:update_keys(Client, write), - %% ssl_test_lib:update_keys(Client, read_write), - ssl_test_lib:update_keys(Server, write), - ssl_test_lib:update_keys(Server, read_write), - - ssl_test_lib:send_recv_result_active(Client, Server, Data), - - ssl_test_lib:close(Client), - ssl_test_lib:close(Server). - -ssl_client_openssl_server_explicit_key_update() -> - [{doc,"Test ssl:update_key/2 between ssl client and s_server."}]. - -ssl_client_openssl_server_explicit_key_update(Config) -> - Data = "123456789012345", %% 15 bytes - - Server = ssl_test_lib:start_server(openssl, [], Config), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client(erlang, [{port, Port}, - {log_level, debug}, - {versions, ['tlsv1.2','tlsv1.3']}],Config), - ssl_test_lib:send_recv_result_active(Server, Client, Data), - - ssl_test_lib:update_keys(Client, write), - ssl_test_lib:update_keys(Client, read_write), - ssl_test_lib:update_keys(Server, write), - ssl_test_lib:update_keys(Server, read_write), - - ssl_test_lib:send_recv_result_active(Client, Server, Data), - - ssl_test_lib:close(Client), - ssl_test_lib:close(Server). diff --git a/lib/ssl/test/ssl_session_SUITE.erl b/lib/ssl/test/ssl_session_SUITE.erl index aa79698a72..f8dd633ed4 100644 --- a/lib/ssl/test/ssl_session_SUITE.erl +++ b/lib/ssl/test/ssl_session_SUITE.erl @@ -25,6 +25,7 @@ -compile(export_all). -include("tls_handshake.hrl"). +-include("ssl_record.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("public_key/include/public_key.hrl"). @@ -48,11 +49,11 @@ all() -> groups() -> [{'dtlsv1.2', [], session_tests()}, {'dtlsv1', [], session_tests()}, - {'tlsv1.3', [], session_tests()}, - {'tlsv1.2', [], session_tests()}, - {'tlsv1.1', [], session_tests()}, - {'tlsv1', [], session_tests()}, - {'sslv3', [], session_tests()} + {'tlsv1.3', [], session_tests() ++ tls_session_tests()}, + {'tlsv1.2', [], session_tests() ++ tls_session_tests()}, + {'tlsv1.1', [], session_tests() ++ tls_session_tests()}, + {'tlsv1', [], session_tests() ++ tls_session_tests()}, + {'sslv3', [], session_tests() ++ tls_session_tests()} ]. session_tests() -> @@ -62,6 +63,8 @@ session_tests() -> no_reuses_session_server_restart_new_cert, no_reuses_session_server_restart_new_cert_file]. +tls_session_tests() -> + [session_table_stable_size_on_tcp_close]. init_per_suite(Config0) -> catch crypto:stop(), @@ -372,6 +375,177 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) -> ssl_test_lib:close(Server1), ssl_test_lib:close(Client1). +session_table_stable_size_on_tcp_close() -> + [{doc, "Check that new sessions are cleanup when connection is closed abruptly during first handshake"}]. + +session_table_stable_size_on_tcp_close(Config) when is_list(Config)-> + ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + ServerCache = element(3, State), + + N = ets:info(ServerCache, size), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, [{reuseaddr, true} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + faulty_client(Hostname, Port), + check_table_did_not_grow(ServerCache, N). + + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- +check_table_did_not_grow(ServerCache, N) -> + ct:sleep(500), + check_table_did_not_grow(ServerCache, N, 10). + +check_table_did_not_grow(_, _, 0) -> + ct:fail(table_grew); +check_table_did_not_grow(ServerCache, N, Tries) -> + case ets:info(ServerCache, size) of + N -> + ok; + _ -> + ct:sleep(500), + check_table_did_not_grow(ServerCache, N, Tries -1) + end. + +faulty_client(Host, Port) -> + {ok, Sock} = gen_tcp:connect(Host, Port, [], 10000), + Random = crypto:strong_rand_bytes(32), + CH = client_hello(Random), + CHBin = encode_client_hello(CH, Random), + gen_tcp:send(Sock, CHBin), + ct:sleep(100), + gen_tcp:close(Sock). + + +server(LOpts, Port) -> + {ok, LSock} = ssl:listen(Port, LOpts), + Pid = spawn_link(?MODULE, accept_loop, [LSock]), + ssl:controlling_process(LSock, Pid), + Pid. + +accept_loop(Sock) -> + {ok, CSock} = ssl:transport_accept(Sock), + _ = ssl:handshake(CSock), + accept_loop(Sock). + + +encode_client_hello(CH, Random) -> + HSBin = tls_handshake:encode_handshake(CH, {3,3}), + CS = connection_states(Random), + {Encoded, _} = tls_record:encode_handshake(HSBin, {3,3}, CS), + Encoded. + +client_hello(Random) -> + CipherSuites = [<<0,255>>, <<"À,">>, <<"À0">>, <<"À$">>, <<"À(">>, + <<"À.">>, <<"À2">>, <<"À&">>, <<"À*">>, <<0,159>>, + <<0,163>>, <<0,107>>, <<0,106>>, <<"À+">>, <<"À/">>, + <<"À#">>, <<"À'">>, <<"À-">>, <<"À1">>, <<"À%">>, + <<"À)">>, <<0,158>>, <<0,162>>, <<0,103>>, <<0,64>>, + <<"À\n">>, <<192,20>>, <<0,57>>, <<0,56>>, <<192,5>>, + <<192,15>>, <<"À\t">>, <<192,19>>, <<0,51>>, <<0,50>>, + <<192,4>>, <<192,14>>], + Extensions = #{alpn => undefined, + ec_point_formats => + {ec_point_formats, + [0]}, + elliptic_curves => + {elliptic_curves, + [{1,3,132,0,39}, + {1,3,132,0,38}, + {1,3,132,0,35}, + {1,3,36,3,3,2, + 8,1,1,13}, + {1,3,132,0,36}, + {1,3,132,0,37}, + {1,3,36,3,3,2, + 8,1,1,11}, + {1,3,132,0,34}, + {1,3,132,0,16}, + {1,3,132,0,17}, + {1,3,36,3,3,2, + 8,1,1,7}, + {1,3,132,0,10}, + {1,2,840, + 10045,3,1,7}, + {1,3,132,0,3}, + {1,3,132,0,26}, + {1,3,132,0,27}, + {1,3,132,0,32}, + {1,3,132,0,33}, + {1,3,132,0,24}, + {1,3,132,0,25}, + {1,3,132,0,31}, + {1,2,840, + 10045,3,1,1}, + {1,3,132,0,1}, + {1,3,132,0,2}, + {1,3,132,0,15}, + {1,3,132,0,9}, + {1,3,132,0,8}, + {1,3,132,0, + 30}]}, + next_protocol_negotiation => + undefined, + renegotiation_info => + {renegotiation_info, + undefined}, + signature_algs => + {hash_sign_algos, + [{sha512,ecdsa}, + {sha512,rsa}, + {sha384,ecdsa}, + {sha384,rsa}, + {sha256,ecdsa}, + {sha256,rsa}, + {sha224,ecdsa}, + {sha224,rsa}, + {sha,ecdsa}, + {sha,rsa}, + {sha,dsa}]}, + sni => + {sni, + "localhost"}, + srp => + undefined}, + + #client_hello{client_version = {3,3}, + random = Random, + session_id = crypto:strong_rand_bytes(32), + cipher_suites = CipherSuites, + compression_methods = [0], + extensions = Extensions + }. + +connection_states(Random) -> + #{current_write => + #{beast_mitigation => one_n_minus_one,cipher_state => undefined, + client_verify_data => undefined,compression_state => undefined, + mac_secret => undefined,secure_renegotiation => undefined, + security_parameters => + #security_parameters{ + cipher_suite = <<0,0>>, + connection_end = 1, + bulk_cipher_algorithm = 0, + cipher_type = 0, + iv_size = 0, + key_size = 0, + key_material_length = 0, + expanded_key_material_length = 0, + mac_algorithm = 0, + prf_algorithm = 0, + hash_size = 0, + compression_algorithm = 0, + master_secret = undefined, + resumption_master_secret = undefined, + client_random = Random, + server_random = undefined, + exportable = undefined}, + sequence_number => 0,server_verify_data => undefined}}. diff --git a/lib/ssl/test/ssl_session_ticket_SUITE.erl b/lib/ssl/test/ssl_session_ticket_SUITE.erl index 96b0fb5c2a..3d41b59223 100644 --- a/lib/ssl/test/ssl_session_ticket_SUITE.erl +++ b/lib/ssl/test/ssl_session_ticket_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2019. All Rights Reserved. +%% Copyright Ericsson AB 2007-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -18,11 +18,27 @@ %% %CopyrightEnd% %% -%% -module(ssl_session_ticket_SUITE). -%% Note: This directive should only be used in test suites. --compile(export_all). +%% Callback functions +-export([all/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]). + +%% Testcases +-export([basic/0, + basic/1, + hello_retry_request/0, + hello_retry_request/1, + multiple_tickets/0, + multiple_tickets/1, + multiple_tickets_2hash/0, + multiple_tickets_2hash/1]). -include("tls_handshake.hrl"). @@ -40,21 +56,15 @@ all() -> ]. groups() -> - [{'tlsv1.3', [], [{group, stateful}, {group, stateless}, {group, openssl_server}]}, - {openssl_server, [], [erlang_client_openssl_server_basic, - erlang_client_openssl_server_hrr, - erlang_client_openssl_server_hrr_multiple_tickets - ]}, + [{'tlsv1.3', [], [{group, stateful}, {group, stateless}]}, {stateful, [], session_tests()}, {stateless, [], session_tests()}]. session_tests() -> - [erlang_client_erlang_server_basic, - openssl_client_erlang_server_basic, - erlang_client_erlang_server_hrr, - openssl_client_erlang_server_hrr, - erlang_client_erlang_server_multiple_tickets, - erlang_client_erlang_server_multiple_tickets_2hash]. + [basic, + hello_retry_request, + multiple_tickets, + multiple_tickets_2hash]. init_per_suite(Config0) -> catch crypto:stop(), @@ -75,27 +85,10 @@ init_per_group(stateful, Config) -> init_per_group(stateless, Config) -> [{server_ticket_mode, stateless} | proplists:delete(server_ticket_mode, Config)]; init_per_group(GroupName, Config) -> - ssl_test_lib:clean_tls_version(Config), - case ssl_test_lib:is_tls_version(GroupName) andalso ssl_test_lib:sufficient_crypto_support(GroupName) of - true -> - ssl_test_lib:init_tls_version(GroupName, Config); - _ -> - case ssl_test_lib:sufficient_crypto_support(GroupName) of - true -> - ssl:start(), - Config; - false -> - {skip, "Missing crypto support"} - end - end. + ssl_test_lib:init_per_group(GroupName, Config). end_per_group(GroupName, Config) -> - case ssl_test_lib:is_tls_version(GroupName) of - true -> - ssl_test_lib:clean_tls_version(Config); - false -> - Config - end. + ssl_test_lib:end_per_group(GroupName, Config). init_per_testcase(_, Config) -> ssl:stop(), @@ -111,10 +104,9 @@ end_per_testcase(_TestCase, Config) -> %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- - -erlang_client_erlang_server_basic() -> +basic() -> [{doc,"Test session resumption with session tickets (erlang client - erlang server)"}]. -erlang_client_erlang_server_basic(Config) when is_list(Config) -> +basic(Config) when is_list(Config) -> ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -166,127 +158,9 @@ erlang_client_erlang_server_basic(Config) when is_list(Config) -> ssl_test_lib:close(Server0), ssl_test_lib:close(Client1). - -erlang_client_openssl_server_basic() -> - [{doc,"Test session resumption with session tickets (erlang client - openssl server)"}]. -erlang_client_openssl_server_basic(Config) when is_list(Config) -> - process_flag(trap_exit, true), - ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), - ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), - {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), - - Version = 'tlsv1.3', - Port = ssl_test_lib:inet_port(node()), - CertFile = proplists:get_value(certfile, ServerOpts), - CACertFile = proplists:get_value(cacertfile, ServerOpts), - KeyFile = proplists:get_value(keyfile, ServerOpts), - - %% Configure session tickets - ClientOpts = [{session_tickets, auto}, {log_level, debug}, - {versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], - - Exe = "openssl", - Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), - "-cert", CertFile,"-key", KeyFile, "-CAfile", CACertFile, "-msg", "-debug"], - - OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), - - ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), - - %% Store ticket from first connection - Client0 = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [false, no_reply]}}, - {from, self()}, {options, ClientOpts}]), - %% Wait for session ticket - ct:sleep(100), - - %% Close previous connection as s_server can only handle one at a time - ssl_test_lib:close(Client0), - - %% Use ticket - Client1 = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [true, no_reply]}}, - {from, self()}, - {options, ClientOpts}]), - process_flag(trap_exit, false), - - %% Clean close down! Server needs to be closed first !! - ssl_test_lib:close_port(OpensslPort), - ssl_test_lib:close(Client1). - - -openssl_client_erlang_server_basic() -> - [{doc,"Test session resumption with session tickets (openssl client - erlang server)"}]. -openssl_client_erlang_server_basic(Config) when is_list(Config) -> - ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), - {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - TicketFile0 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket0"]), - TicketFile1 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket1"]), - ServerTicketMode = proplists:get_value(server_ticket_mode, Config), - - Data = "Hello world", - - %% Configure session tickets - ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug}, - {versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0], - - Server0 = - ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [false]}}, - {options, ServerOpts}]), - - Version = 'tlsv1.3', - Port0 = ssl_test_lib:inet_port(Server0), - - Exe = "openssl", - Args0 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) - ++ ":" ++ integer_to_list(Port0), - ssl_test_lib:version_flag(Version), - "-sess_out", TicketFile0], - - OpenSslPort0 = ssl_test_lib:portable_open_port(Exe, Args0), - - true = port_command(OpenSslPort0, Data), - - ssl_test_lib:check_result(Server0, ok), - - Server0 ! {listen, {mfa, {ssl_test_lib, - verify_active_session_resumption, - [true]}}}, - - %% Wait for session ticket - ct:sleep(100), - - Args1 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) - ++ ":" ++ integer_to_list(Port0), - ssl_test_lib:version_flag(Version), - "-sess_in", TicketFile0, - "-sess_out", TicketFile1], - - OpenSslPort1 = ssl_test_lib:portable_open_port(Exe, Args1), - - true = port_command(OpenSslPort1, Data), - - ssl_test_lib:check_result(Server0, ok), - - %% Clean close down! Server needs to be closed first !! - ssl_test_lib:close(Server0), - ssl_test_lib:close_port(OpenSslPort0), - ssl_test_lib:close_port(OpenSslPort1). - - -erlang_client_erlang_server_hrr() -> +hello_retry_request() -> [{doc,"Test session resumption with session tickets and hello_retry_request (erlang client - erlang server)"}]. -erlang_client_erlang_server_hrr(Config) when is_list(Config) -> +hello_retry_request(Config) when is_list(Config) -> ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -340,135 +214,9 @@ erlang_client_erlang_server_hrr(Config) when is_list(Config) -> ssl_test_lib:close(Server0), ssl_test_lib:close(Client1). - -erlang_client_openssl_server_hrr() -> - [{doc,"Test session resumption with session tickets and hello_retry_request (erlang client - openssl server)"}]. -erlang_client_openssl_server_hrr(Config) when is_list(Config) -> - process_flag(trap_exit, true), - ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), - ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), - {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), - - Version = 'tlsv1.3', - Port = ssl_test_lib:inet_port(node()), - CertFile = proplists:get_value(certfile, ServerOpts), - CACertFile = proplists:get_value(cacertfile, ServerOpts), - KeyFile = proplists:get_value(keyfile, ServerOpts), - - %% Configure session tickets - ClientOpts = [{session_tickets, auto}, {log_level, debug}, - {versions, ['tlsv1.2','tlsv1.3']}, - {supported_groups,[secp256r1, x25519]}|ClientOpts0], - - Exe = "openssl", - Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), - "-cert", CertFile, - "-key", KeyFile, - "-CAfile", CACertFile, - "-groups", "X448:X25519", - "-msg", "-debug"], - - OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), - - ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), - - %% Store ticket from first connection - Client0 = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [false, no_reply]}}, - {from, self()}, {options, ClientOpts}]), - %% Wait for session ticket - ct:sleep(100), - - %% Close previous connection as s_server can only handle one at a time - ssl_test_lib:close(Client0), - - %% Use ticket - Client1 = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [true, no_reply]}}, - {from, self()}, - {options, ClientOpts}]), - process_flag(trap_exit, false), - - %% Clean close down! Server needs to be closed first !! - ssl_test_lib:close_port(OpensslPort), - ssl_test_lib:close(Client1). - - -openssl_client_erlang_server_hrr() -> - [{doc,"Test session resumption with session tickets and hello_retry_request (openssl client - erlang server)"}]. -openssl_client_erlang_server_hrr(Config) when is_list(Config) -> - ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), - {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - TicketFile0 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket0"]), - TicketFile1 = filename:join([proplists:get_value(priv_dir, Config), "session_ticket1"]), - ServerTicketMode = proplists:get_value(server_ticket_mode, Config), - - Data = "Hello world", - - %% Configure session tickets - ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug}, - {versions, ['tlsv1.2','tlsv1.3']}, - {supported_groups,[x448, x25519]}|ServerOpts0], - - Server0 = - ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [false]}}, - {options, ServerOpts}]), - - Version = 'tlsv1.3', - Port0 = ssl_test_lib:inet_port(Server0), - - Exe = "openssl", - Args0 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) - ++ ":" ++ integer_to_list(Port0), - ssl_test_lib:version_flag(Version), - "-groups", "P-256:X25519", - "-sess_out", TicketFile0], - - OpenSslPort0 = ssl_test_lib:portable_open_port(Exe, Args0), - - true = port_command(OpenSslPort0, Data), - - ssl_test_lib:check_result(Server0, ok), - - Server0 ! {listen, {mfa, {ssl_test_lib, - verify_active_session_resumption, - [true]}}}, - - %% Wait for session ticket - ct:sleep(100), - - Args1 = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) - ++ ":" ++ integer_to_list(Port0), - ssl_test_lib:version_flag(Version), - "-groups", "P-256:X25519", - "-sess_in", TicketFile0, - "-sess_out", TicketFile1], - - OpenSslPort1 = ssl_test_lib:portable_open_port(Exe, Args1), - - true = port_command(OpenSslPort1, Data), - - ssl_test_lib:check_result(Server0, ok), - - %% Clean close down! Server needs to be closed first !! - ssl_test_lib:close(Server0), - ssl_test_lib:close_port(OpenSslPort0), - ssl_test_lib:close_port(OpenSslPort1). - - -erlang_client_erlang_server_multiple_tickets() -> +multiple_tickets() -> [{doc,"Test session resumption with multiple session tickets (erlang client - erlang server)"}]. -erlang_client_erlang_server_multiple_tickets(Config) when is_list(Config) -> +multiple_tickets(Config) when is_list(Config) -> ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -524,72 +272,9 @@ erlang_client_erlang_server_multiple_tickets(Config) when is_list(Config) -> ssl_test_lib:close(Server0), ssl_test_lib:close(Client1). - -erlang_client_openssl_server_hrr_multiple_tickets() -> - [{doc,"Test session resumption with multiple session tickets and hello_retry_request (erlang client - openssl server)"}]. -erlang_client_openssl_server_hrr_multiple_tickets(Config) when is_list(Config) -> - process_flag(trap_exit, true), - ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), - ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), - {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), - - Version = 'tlsv1.3', - Port = ssl_test_lib:inet_port(node()), - CertFile = proplists:get_value(certfile, ServerOpts), - CACertFile = proplists:get_value(cacertfile, ServerOpts), - KeyFile = proplists:get_value(keyfile, ServerOpts), - - %% Configure session tickets - ClientOpts = [{session_tickets, manual}, {log_level, debug}, - {versions, ['tlsv1.2','tlsv1.3']}, - {supported_groups,[secp256r1, x25519]}|ClientOpts0], - - Exe = "openssl", - Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), - "-cert", CertFile, - "-key", KeyFile, - "-CAfile", CACertFile, - "-groups", "X448:X25519", - "-msg", "-debug"], - - OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), - - ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), - - %% Store ticket from first connection - Client0 = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [false, no_reply, {tickets, 2}]}}, - {from, self()}, {options, ClientOpts}]), - - Tickets0 = ssl_test_lib:check_tickets(Client0), - - ct:pal("Received tickets: ~p~n", [Tickets0]), - - %% Close previous connection as s_server can only handle one at a time - ssl_test_lib:close(Client0), - - %% Use tickets - Client1 = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {mfa, {ssl_test_lib, - verify_active_session_resumption, - [true, no_reply, no_tickets]}}, - {from, self()}, - {options, [{use_ticket, Tickets0}|ClientOpts]}]), - - process_flag(trap_exit, false), - - %% Clean close down! Server needs to be closed first !! - ssl_test_lib:close_port(OpensslPort), - ssl_test_lib:close(Client1). - - -erlang_client_erlang_server_multiple_tickets_2hash() -> +multiple_tickets_2hash() -> [{doc,"Test session resumption with multiple session tickets with 2 different hash algorithms (erlang client - erlang server)"}]. -erlang_client_erlang_server_multiple_tickets_2hash(Config) when is_list(Config) -> +multiple_tickets_2hash(Config) when is_list(Config) -> ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index e7f5a59235..206c4c8b32 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -76,6 +76,43 @@ get_client_opts(Config) -> COpts = proplists:get_value(client_ecdsa_opts, Config), ssl_test_lib:ssl_options(COpts, Config). +%% Default callback functions +init_per_group(GroupName, Config) -> + clean_tls_version(Config), + case is_tls_version(GroupName) andalso sufficient_crypto_support(GroupName) of + true -> + init_tls_version(GroupName, Config); + _ -> + case sufficient_crypto_support(GroupName) of + true -> + ssl:start(), + Config; + false -> + {skip, "Missing crypto support"} + end + end. + +init_per_group_openssl(GroupName, Config) -> + case is_tls_version(GroupName) of + true -> + case check_sane_openssl_version(GroupName) of + true -> + [{version, GroupName}|init_tls_version(GroupName, Config)]; + false -> + {skip, "Missing openssl support"} + end; + _ -> + ssl:start(), + Config + end. + +end_per_group(GroupName, Config) -> + case is_tls_version(GroupName) of + true -> + clean_tls_version(Config); + false -> + Config + end. %%==================================================================== %% Internal functions diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index 39fc565ff8..c12ad2deef 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -101,10 +101,10 @@ </item> <item> In OTP 22.3 the possibility to change the callback module - with action - <seealso marker="#type-action"> - <c>change_callback_module</c> - </seealso> + with actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> and + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>, was added. </item> </list> @@ -750,8 +750,10 @@ handle_event(_, _, State, Data) -> <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso> is called when starting the <c>gen_statem</c>, after code change - and after changing the callback module with action - <seealso marker="#type-action"><c>change_callback_module</c></seealso>. + and after changing the callback module with any of the actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> or + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>. The result is cached for subsequent calls to <seealso marker="#state callback">state callbacks</seealso>. </p> @@ -1191,7 +1193,9 @@ handle_event(_, _, State, Data) -> an event inserted this way from any external event. </p> </item> - <tag><c>change_callback_module</c></tag> + <tag> + <c>change_callback_module</c> + </tag> <item> <p> Changes the callback module to @@ -1231,6 +1235,32 @@ handle_event(_, _, State, Data) -> from the old module. </p> </item> + <tag> + <c>push_callback_module</c><br /> + </tag> + <item> + <p> + Pushes the current callback module + to the top of an internal stack of callback modules + and changes the callback module to + <c><anno>NewModule</anno></c>. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </p> + </item> + <tag> + <c>pop_callback_module</c> + </tag> + <item> + Pops the top module from the internal stack of + callback modules and changes the callback module + to be the popped module. + If the stack is empty the server fails. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </item> </taglist> </desc> </datatype> @@ -2017,8 +2047,10 @@ handle_event(_, _, State, Data) -> returns. A change of the callback module happens when a <seealso marker="#state callback"><em>state callback</em></seealso> - returns the action - <seealso marker="#type-action"><c>change_callback_module</c></seealso>. + returns any of the actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> or + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>. </p> <p> The <c>CallbackMode</c> is either just @@ -2125,6 +2157,37 @@ handle_event(_, _, State, Data) -> will not be honoured, most probably causing a server crash. </p> + <p> + If the server changes callback module using any of the actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> or + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>, + be aware that it is always the current callback module that + will get this callback call. That the current callback module + handles the current state and data update should be no surprise, + but it must be able to handle even parts of + the state and data that it is not familiar with, + somehow. + </p> + <p> + In the supervisor + <seealso marker="doc/design_principles:sup_princ#child-specification">child specification</seealso> + there is a list of modules which is recommended to contain + only the callback module. + For a <c>gen_statem</c> with multiple callback modules + there is no real need to list all of them, + it may not even be possible since the list could change + after code upgrade. + If this list would contain only the start callback module, + as recommended, what is important is to upgrade <em>that</em> module + whenever a <em>synchronized code replacement</em> is done. + Then the release handler concludes that an upgrade + that upgrades <em>that</em> module needs to suspend, + code change, and resume any server whose child specification + declares that it is using <em>that</em> module. + And again; the <em>current</em> callback module will get the + <c>Module:code_change/4</c> call. + </p> </desc> </func> diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl index 3a8fe2211b..ef6d1882e6 100644 --- a/lib/stdlib/src/calendar.erl +++ b/lib/stdlib/src/calendar.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2019. All Rights Reserved. +%% Copyright Ericsson AB 1996-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -369,7 +369,7 @@ rfc3339_to_system_time(DateTimeString, Options) -> IsFractionChar = fun(C) -> C >= $0 andalso C =< $9 orelse C =:= $. end, {FractionStr, UtcOffset} = lists:splitwith(IsFractionChar, TimeStr), Time = datetime_to_system_time(DateTime), - Secs = Time - offset_adjustment(Time, second, UtcOffset), + Secs = Time - offset_string_adjustment(Time, second, UtcOffset), check(DateTimeString, Options, Secs), ScaledEpoch = erlang:convert_time_unit(Secs, second, Unit), ScaledEpoch + copy_sign(fraction(Unit, FractionStr), ScaledEpoch). @@ -689,13 +689,13 @@ offset(OffsetOption, Secs0) when OffsetOption =:= ""; offset(OffsetOption, _Secs) -> OffsetOption. +offset_adjustment(Time, Unit, "") -> + local_offset(Time, Unit); offset_adjustment(Time, Unit, OffsetString) when is_list(OffsetString) -> offset_string_adjustment(Time, Unit, OffsetString); offset_adjustment(_Time, Unit, Offset) when is_integer(Offset) -> erlang:convert_time_unit(Offset, Unit, second). -offset_string_adjustment(Time, Unit, "") -> - local_offset(Time, Unit); offset_string_adjustment(_Time, _Unit, "Z") -> 0; offset_string_adjustment(_Time, _Unit, "z") -> diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl index 885c6ef031..2cf30e10ec 100644 --- a/lib/stdlib/src/gen_statem.erl +++ b/lib/stdlib/src/gen_statem.erl @@ -150,6 +150,8 @@ EventType :: event_type(), EventContent :: term()} | {'change_callback_module', NewModule :: module()} | + {'push_callback_module', NewModule :: module()} | + 'pop_callback_module' | enter_action(). -type enter_action() :: 'hibernate' | % Set the hibernate option @@ -423,7 +425,7 @@ timeout_event_type(Type) -> {callback_mode = undefined :: callback_mode() | undefined, state_enter = false :: boolean(), parent :: pid(), - module :: atom(), + modules :: [module()], name :: atom() | pid(), hibernate_after = infinity :: timeout() }). @@ -691,7 +693,7 @@ enter( P = #params{ parent = Parent, - module = Module, + modules = [Module], name = Name, hibernate_after = HibernateAfterTimeout}, S = #state{state_data = {State,Data}}, @@ -728,7 +730,7 @@ init_it(Starter, Parent, ServerRef, Module, Args, Opts) -> proc_lib:init_ack(Starter, {error,Reason}), error_info( Class, Reason, Stacktrace, Debug, - #params{parent = Parent, name = Name, module = Module}, + #params{parent = Parent, name = Name, modules = [Module]}, #state{}, []), erlang:raise(Class, Reason, Stacktrace) end. @@ -764,7 +766,7 @@ init_result( proc_lib:init_ack(Starter, {error,Error}), error_info( error, Error, ?STACKTRACE(), Debug, - #params{parent = Parent, name = Name, module = Module}, + #params{parent = Parent, name = Name, modules = [Module]}, #state{}, []), exit(Error) end. @@ -785,7 +787,7 @@ system_terminate(Reason, Parent, Debug, {P,S}) -> update_parent(P, Parent), Debug, S, []). system_code_change( - {#params{module = Module} = P, + {#params{modules = [Module | _]} = P, #state{state_data = {State,Data}} = S}, _Mod, OldVsn, Extra) -> case @@ -816,7 +818,7 @@ system_replace_state( format_status( Opt, [PDict,SysState,Parent,Debug, - {#params{name = Name} = P, + {#params{name = Name, modules = Modules} = P, #state{postponed = Postponed, timers = Timers} = S}]) -> Header = gen:format_status_header("Status for state machine", Name), Log = sys:get_log(Debug), @@ -824,6 +826,7 @@ format_status( {data, [{"Status",SysState}, {"Parent",Parent}, + {"Modules",Modules}, {"Time-outs",list_timeouts(Timers)}, {"Logged Events",Log}, {"Postponed",Postponed}]} | @@ -1079,7 +1082,7 @@ loop_state_callback(P, Debug, S, Q, State_Data, CallbackEvent) -> StateCall, CallbackEvent). %% loop_state_callback( - #params{callback_mode = undefined, module = Module} = P, + #params{callback_mode = undefined, modules = [Module | _]} = P, Debug, S, Q, State_Data, NextEventsR, Hibernate, TimeoutsR, Postpone, StateCall, CallbackEvent) -> @@ -1105,7 +1108,7 @@ loop_state_callback( Class, Reason, Stacktrace, P, Debug, S, Q) end; loop_state_callback( - #params{callback_mode = CallbackMode, module = Module} = P, + #params{callback_mode = CallbackMode, modules = [Module | _]} = P, Debug, S, Q, {State,Data} = State_Data, NextEventsR, Hibernate, TimeoutsR, Postpone, StateCall, {Type,Content}) -> @@ -1446,13 +1449,21 @@ loop_actions_list( NextEventsR, Hibernate, TimeoutsR, Postpone, CallEnter, StateCall, Actions, Type, Content); %% - {change_callback_module, NewModule} - when is_atom(NewModule) -> + {Tag, NewModule} + when Tag =:= change_callback_module, is_atom(NewModule); + Tag =:= push_callback_module, is_atom(NewModule) -> if StateCall -> + NewModules = + case Tag of + change_callback_module -> + [NewModule | tl(P#params.modules)]; + push_callback_module -> + [NewModule | P#params.modules] + end, P_1 = P#params{ - callback_mode = undefined, module = NewModule}, + callback_mode = undefined, modules = NewModules}, loop_actions_list( P_1, Debug, S, Q, NextState_NewData, NextEventsR, Hibernate, TimeoutsR, Postpone, @@ -1467,91 +1478,40 @@ loop_actions_list( hibernate = Hibernate}, Q) end; - %% - Timeout -> - loop_actions_timeout( - P, Debug, S, Q, NextState_NewData, - NextEventsR, Hibernate, TimeoutsR, Postpone, - CallEnter, StateCall, Actions, Timeout) - end. - -%% Process a reply action -%% -loop_actions_reply( - P, Debug, S, Q, NextState_NewData, - NextEventsR, Hibernate, TimeoutsR, Postpone, - CallEnter, StateCall, Actions, - From, Reply) -> - %% - case from(From) of - true -> - %% No need for a separate ?not_sys_debug clause here - %% since the external call to erlang:'!'/2 in reply/2 - %% will cause swap out of all live registers anyway - reply(From, Reply), - Debug_1 = ?sys_debug(Debug, P#params.name, {out,Reply,From}), - loop_actions_list( - P, Debug_1, S, Q, NextState_NewData, - NextEventsR, Hibernate, TimeoutsR, Postpone, - CallEnter, StateCall, Actions); - false -> - terminate( - error, - {bad_action_from_state_function,{reply,From,Reply}}, - ?STACKTRACE(), P, Debug, - S#state{ - state_data = NextState_NewData, - hibernate = Hibernate}, - Q) - end. - -%% Process a next_event action -%% -loop_actions_next_event( - P, Debug, S, Q, NextState_NewData, - NextEventsR, Hibernate, TimeoutsR, Postpone, - CallEnter, StateCall, Actions, Type, Content) -> - case event_type(Type) of - true when StateCall -> - NextEvent = {Type,Content}, - case Debug of - ?not_sys_debug -> + pop_callback_module when tl(P#params.modules) =/= [] -> + if + StateCall -> + NewModules = tl(P#params.modules), + P_1 = + P#params{ + callback_mode = undefined, + modules = NewModules}, loop_actions_list( - P, Debug, S, Q, NextState_NewData, - [NextEvent|NextEventsR], - Hibernate, TimeoutsR, Postpone, + P_1, Debug, S, Q, NextState_NewData, + NextEventsR, Hibernate, TimeoutsR, Postpone, CallEnter, StateCall, Actions); - _ -> - Name = P#params.name, - {State,_Data} = S#state.state_data, - Debug_1 = - sys_debug(Debug, Name, {in,{Type,Content},State}), - loop_actions_list( - P, Debug_1, S, Q, NextState_NewData, - [NextEvent|NextEventsR], - Hibernate, TimeoutsR, Postpone, - CallEnter, StateCall, Actions) - end; + true -> + terminate( + error, + {bad_state_enter_action_from_state_function,Action}, + ?STACKTRACE(), P, Debug, + S#state{ + state_data = NextState_NewData, + hibernate = Hibernate}, + Q) + end; + %% _ -> - terminate( - error, - {if - StateCall -> - bad_action_from_state_function; - true -> - bad_state_enter_action_from_state_function - end, - {next_event,Type,Content}}, - ?STACKTRACE(), P, Debug, - S#state{ - state_data = NextState_NewData, - hibernate = Hibernate}, - Q) + loop_actions_list( + P, Debug, S, Q, NextState_NewData, + NextEventsR, Hibernate, TimeoutsR, Postpone, + CallEnter, StateCall, Actions, Action) end. -%% Process a timeout action, or also any unrecognized action +%% Process all other actions, i.e timeout actions, +%% all others are unrecognized %% -loop_actions_timeout( +loop_actions_list( P, Debug, S, Q, NextState_NewData, NextEventsR, Hibernate, TimeoutsR, Postpone, CallEnter, StateCall, Actions, @@ -1618,7 +1578,7 @@ loop_actions_timeout( hibernate = Hibernate}, Q) end; -loop_actions_timeout( +loop_actions_list( P, Debug, S, Q, NextState_NewData, NextEventsR, Hibernate, TimeoutsR, Postpone, CallEnter, StateCall, Actions, @@ -1643,7 +1603,7 @@ loop_actions_timeout( hibernate = Hibernate}, Q) end; -loop_actions_timeout( +loop_actions_list( P, Debug, S, Q, NextState_NewData, NextEventsR, Hibernate, TimeoutsR, Postpone, CallEnter, StateCall, Actions, @@ -1667,7 +1627,7 @@ loop_actions_timeout( hibernate = Hibernate}, Q) end; -loop_actions_timeout( +loop_actions_list( P, Debug, S, Q, NextState_NewData, NextEventsR, Hibernate, TimeoutsR, Postpone, CallEnter, StateCall, Actions, @@ -1692,6 +1652,80 @@ loop_actions_timeout( Q) end. +%% Process a reply action +%% +loop_actions_reply( + P, Debug, S, Q, NextState_NewData, + NextEventsR, Hibernate, TimeoutsR, Postpone, + CallEnter, StateCall, Actions, + From, Reply) -> + %% + case from(From) of + true -> + %% No need for a separate ?not_sys_debug clause here + %% since the external call to erlang:'!'/2 in reply/2 + %% will cause swap out of all live registers anyway + reply(From, Reply), + Debug_1 = ?sys_debug(Debug, P#params.name, {out,Reply,From}), + loop_actions_list( + P, Debug_1, S, Q, NextState_NewData, + NextEventsR, Hibernate, TimeoutsR, Postpone, + CallEnter, StateCall, Actions); + false -> + terminate( + error, + {bad_action_from_state_function,{reply,From,Reply}}, + ?STACKTRACE(), P, Debug, + S#state{ + state_data = NextState_NewData, + hibernate = Hibernate}, + Q) + end. + +%% Process a next_event action +%% +loop_actions_next_event( + P, Debug, S, Q, NextState_NewData, + NextEventsR, Hibernate, TimeoutsR, Postpone, + CallEnter, StateCall, Actions, Type, Content) -> + case event_type(Type) of + true when StateCall -> + NextEvent = {Type,Content}, + case Debug of + ?not_sys_debug -> + loop_actions_list( + P, Debug, S, Q, NextState_NewData, + [NextEvent|NextEventsR], + Hibernate, TimeoutsR, Postpone, + CallEnter, StateCall, Actions); + _ -> + Name = P#params.name, + {State,_Data} = S#state.state_data, + Debug_1 = + sys_debug(Debug, Name, {in,{Type,Content},State}), + loop_actions_list( + P, Debug_1, S, Q, NextState_NewData, + [NextEvent|NextEventsR], + Hibernate, TimeoutsR, Postpone, + CallEnter, StateCall, Actions) + end; + _ -> + terminate( + error, + {if + StateCall -> + bad_action_from_state_function; + true -> + bad_state_enter_action_from_state_function + end, + {next_event,Type,Content}}, + ?STACKTRACE(), P, Debug, + S#state{ + state_data = NextState_NewData, + hibernate = Hibernate}, + Q) + end. + %% Do the state transition %% loop_state_transition( @@ -2269,7 +2303,7 @@ do_reply_then_terminate( terminate( Class, Reason, Stacktrace, - #params{module = Module} = P, Debug, + #params{modules = [Module | _]} = P, Debug, #state{state_data = {State,Data}} = S, Q) -> case erlang:function_exported(Module, terminate, 3) of true -> @@ -2310,6 +2344,7 @@ error_info( Class, Reason, Stacktrace, Debug, #params{ name = Name, + modules = Modules, callback_mode = CallbackMode, state_enter = StateEnter} = P, #state{ @@ -2321,6 +2356,7 @@ error_info( name=>Name, queue=>Q, postponed=>Postponed, + modules=>Modules, callback_mode=>CallbackMode, state_enter=>StateEnter, state=>format_status(terminate, get(), P, S), @@ -2360,6 +2396,7 @@ format_log(#{label:={gen_statem,terminate}, name:=Name, queue:=Q, postponed:=Postponed, + modules:=Modules, callback_mode:=CallbackMode, state_enter:=StateEnter, state:=FmtData, @@ -2406,6 +2443,7 @@ format_log(#{label:={gen_statem,terminate}, end ++ "** When server state = ~tp~n" ++ "** Reason for termination = ~w:~tp~n" ++ + "** Callback modules = ~p~n" ++ "** Callback mode = ~p~n" ++ case Q of [_,_|_] -> "** Queued = ~tp~n"; @@ -2434,6 +2472,7 @@ format_log(#{label:={gen_statem,terminate}, end] ++ [error_logger:limit_term(FmtData), Class,error_logger:limit_term(FixedReason), + error_logger:limit_term(Modules), CBMode] ++ case Q of [_|[_|_] = Events] -> [error_logger:limit_term(Events)]; @@ -2471,7 +2510,7 @@ format_client_log({_Pid,{Name,Stacktrace}}) -> %% Call Module:format_status/2 or return a default value format_status( Opt, PDict, - #params{module = Module}, + #params{modules = [Module | _]}, #state{state_data = {State,Data} = State_Data}) -> case erlang:function_exported(Module, format_status, 2) of true -> diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl index 74efe5c513..2114b17a79 100644 --- a/lib/stdlib/src/ms_transform.erl +++ b/lib/stdlib/src/ms_transform.erl @@ -356,11 +356,6 @@ clause({clause,Line,H0,G0,B0},Bound) -> copy({call,Line,{remote,_Line2,{atom,_Line3,ets},{atom,_Line4,fun2ms}}, As0},Bound) -> {transform_call(ets,Line,As0,Bound),Bound}; -copy({call,Line,{remote,_Line2,{record_field,_Line3, - {atom,_Line4,''},{atom,_Line5,ets}}, - {atom,_Line6,fun2ms}}, As0},Bound) -> - %% Packages... - {transform_call(ets,Line,As0,Bound),Bound}; copy({call,Line,{remote,_Line2,{atom,_Line3,dbg},{atom,_Line4,fun2ms}}, As0},Bound) -> {transform_call(dbg,Line,As0,Bound),Bound}; diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl index 224c0d5625..bea5a217db 100644 --- a/lib/stdlib/test/calendar_SUITE.erl +++ b/lib/stdlib/test/calendar_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2019. All Rights Reserved. +%% Copyright Ericsson AB 1997-2020. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -223,6 +223,7 @@ rfc3339(Config) when is_list(Config) -> {'EXIT', _} = (catch do_format_z(253402300799+1, [])), {'EXIT', _} = (catch do_parse("9999-12-31T23:59:60Z", [])), {'EXIT', _} = (catch do_format_z(253402300799*1000000000+999999999+1, Ns)), + {'EXIT', _} = (catch do_parse("2010-04-11T22:35:41", [])), % OTP-16514 253402300799 = do_parse("9999-12-31T23:59:59Z", []), "0000-01-01T00:00:00Z" = test_parse("0000-01-01T00:00:00.0+00:00"), diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl index 0586575736..296973370c 100644 --- a/lib/stdlib/test/gen_statem_SUITE.erl +++ b/lib/stdlib/test/gen_statem_SUITE.erl @@ -69,7 +69,7 @@ tcs(sys) -> get_state, replace_state]; tcs(undef_callbacks) -> [undef_code_change, undef_terminate1, undef_terminate2, - function_clause_after_change_callback_module]. + pop_too_many]. init_per_suite(Config) -> Config. @@ -1778,7 +1778,7 @@ verify_down(Statem, MRef, Reason) -> end. -function_clause_after_change_callback_module(_Config) -> +pop_too_many(_Config) -> _ = process_flag(trap_exit, true), Machine = @@ -1790,8 +1790,17 @@ function_clause_after_change_callback_module(_Config) -> fun ({call, From}, {change_callback_module, _Module} = Action, undefined = _Data) -> {keep_state_and_data, - [{reply,From,ok}, - Action]} + [Action, + {reply,From,ok}]}; + ({call, From}, {verify, ?MODULE}, + undefined = _Data) -> + {keep_state_and_data, + [{reply,From,ok}]}; + ({call, From}, pop_callback_module = Action, + undefined = _Data) -> + {keep_state_and_data, + [Action, + {reply,From,ok}]} end}, {ok, STM} = gen_statem:start_link( @@ -1800,16 +1809,16 @@ function_clause_after_change_callback_module(_Config) -> [{debug, [trace]}]), ok = gen_statem:call(STM, {change_callback_module, oc_statem}), + ok = gen_statem:call(STM, {push_callback_module, ?MODULE}), + ok = gen_statem:call(STM, {verify, ?MODULE}), + ok = gen_statem:call(STM, pop_callback_module), + BadAction = {bad_action_from_state_function, pop_callback_module}, + {{BadAction, _}, + {gen_statem,call,[STM,pop_callback_module,infinity]}} = + ?EXPECT_FAILURE(gen_statem:call(STM, pop_callback_module), Reason), - Call = unhandled_call, - {{function_clause, - [{oc_statem, handle_event, - [{call, _From}, Call, start, _Data], _Line} - | _RestStacktrace]} = Undef, - {gen_statem, call, [STM,Call,_Timeout]}} = - ?EXPECT_FAILURE(gen_statem:call(STM, Call), Reason), receive - {'EXIT', STM, Undef} -> + {'EXIT', STM, {BadAction, _}} -> ok; Other -> ct:fail({surprise, Other}) diff --git a/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl b/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl index 1493cfb192..1bcd08867f 100644 --- a/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl +++ b/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl @@ -37,4 +37,16 @@ callback_mode() -> [handle_event_function, state_enter]. handle_event(enter, start, start, _Data) -> - keep_state_and_data. + keep_state_and_data; +handle_event( + {call,From}, {push_callback_module,NewModule} = Action, + start, _Data) -> + {keep_state_and_data, + [Action, + {reply,From,ok}]}; +handle_event( + {call,From}, pop_callback_module = Action, + start, _Data) -> + {keep_state_and_data, + [Action, + {reply,From,ok}]}. diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 2b3af417b6..80af13a4c3 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -1722,7 +1722,10 @@ bool_switch(E, T, F, AllVars, AuxVarN) -> {'case',Line,E, [{clause,Line,[{atom,Line,true}],[],[T]}, {clause,Line,[{atom,Line,false}],[],[F]}, - {clause,Line,[AuxVar],[], + %% Mark the next clause as compiler-generated to suppress + %% a warning if the case expression is an obvious boolean + %% value. + {clause,erl_anno:set_generated(true, Line),[AuxVar],[], [{call,Line, {remote,Line,{atom,Line,erlang},{atom,Line,error}}, [{tuple,Line,[{atom,Line,badarg},AuxVar]}]}]}]}. diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index 36d4828861..369fbb2d42 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -2782,6 +2782,8 @@ parsify({A, B, C}) -> {parsify(A), parsify(B), parsify(C)}; parsify(Tuple) when is_tuple(Tuple) -> list_to_tuple(parsify(tuple_to_list(Tuple))); +parsify(Map) when is_map(Map) -> + maps:from_list(parsify(maps:to_list(Map))); parsify(Pid) when is_pid(Pid) -> erlang:pid_to_list(Pid); parsify(Port) when is_port(Port) -> diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index 462767f430..0de73bc3d7 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -37,7 +37,7 @@ all() -> dont_reconnect_after_stop, stop_node_after_disconnect, export_import, otp_5031, otp_6115, otp_8270, otp_10979_hanging_node, otp_14817, - local_only, startup_race], + local_only, startup_race, otp_16476], case whereis(cover_server) of undefined -> [coverage,StartStop ++ NoStartStop]; @@ -1803,6 +1803,17 @@ startup_race_1([]) -> cover:stop(), ok. +otp_16476(Config) when is_list(Config) -> + Mod = obvious_booleans, + Dir = filename:join(proplists:get_value(data_dir, Config), + ?FUNCTION_NAME), + ok = file:set_cwd(Dir), + {ok, Mod} = compile:file(Mod, [debug_info]), + {ok, Mod} = cover:compile(Mod), + ok = Mod:Mod(), + ok = cover:stop(), + ok. + %%--Auxiliary------------------------------------------------------------ analyse_expr(Expr, Config) -> diff --git a/lib/tools/test/cover_SUITE_data/otp_16476/obvious_booleans.erl b/lib/tools/test/cover_SUITE_data/otp_16476/obvious_booleans.erl new file mode 100644 index 0000000000..1f383be0a5 --- /dev/null +++ b/lib/tools/test/cover_SUITE_data/otp_16476/obvious_booleans.erl @@ -0,0 +1,17 @@ +-module(obvious_booleans). +-export([?MODULE/0]). +-compile([warnings_as_errors]). + +?MODULE() -> + true = both_ok(ok, ok), + false = both_ok(ok, nok), + true = one_ok(ok, nok), + true = one_ok(nok, ok), + false = one_ok(nok, nok), + ok. + +both_ok(A, B) -> + A =:= ok andalso B =:= ok. + +one_ok(A, B) -> + A =:= ok orelse B =:= ok. diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl index ae0e7253ad..cdb207c1e2 100644 --- a/lib/tools/test/fprof_SUITE.erl +++ b/lib/tools/test/fprof_SUITE.erl @@ -27,7 +27,7 @@ %% Test suites -export([stack_seq/1, tail_seq/1, create_file_slow/1, spawn_simple/1, imm_tail_seq/1, imm_create_file_slow/1, imm_compile/1, - cpu_create_file_slow/1, unicode/1]). + cpu_create_file_slow/1, unicode/1, parsify_maps/1]). %% Other exports -export([create_file_slow/2]). @@ -59,7 +59,7 @@ all() -> false -> [stack_seq, tail_seq, create_file_slow, spawn_simple, imm_tail_seq, imm_create_file_slow, imm_compile, - cpu_create_file_slow, unicode] + cpu_create_file_slow, unicode, parsify_maps] end. @@ -544,6 +544,35 @@ unicode(Config) when is_list(Config) -> ok = fprof:profile(dump, AnalysisFile), ok = fprof:analyse(dest, AnalysisFile). +parsify_maps(Config) when is_list(Config) -> + Pid = self(), + Ref = make_ref(), + Port = hd(erlang:ports()), + Fun = fun () -> ok end, + M = #{pid => Pid, Pid => pid, + ref => Ref, Ref => ref, + port => Port, Port => port, + a_fun => Fun, Fun => a_fun}, + io:format("M = ~p~n", [M]), + L = [{tuple, M}, M, #{my_map => M, M => my_map}], + PL = fprof:parsify(L), + [{tuple, PM}, PM, PMap] = PL, + #{my_map := PM, PM := my_map} = PMap, + io:format("PM = ~p~n", [PM]), + LPid = pid_to_list(Pid), + LRef = ref_to_list(Ref), + LPort = port_to_list(Port), + LFun = erlang:fun_to_list(Fun), + LPid = maps:get(pid, PM), + pid = maps:get(LPid, PM), + LRef = maps:get(ref, PM), + ref = maps:get(LRef, PM), + LPort = maps:get(port, PM), + port = maps:get(LPort, PM), + LFun = maps:get(a_fun, PM), + a_fun = maps:get(LFun, PM), + ok. + %%%--------------------------------------------------------------------- %%% Functions to test %%%--------------------------------------------------------------------- diff --git a/make/otp_version_tickets_in_merge b/make/otp_version_tickets_in_merge index e2401e5757..e69de29bb2 100644 --- a/make/otp_version_tickets_in_merge +++ b/make/otp_version_tickets_in_merge @@ -1,4 +0,0 @@ -OTP-16452 -OTP-16456 -OTP-16466 -OTP-16467 diff --git a/otp_versions.table b/otp_versions.table index 30acd06214..e9547c7ead 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.2.8 : diameter-2.2.2 # asn1-5.0.9 common_test-1.18.1 compiler-7.5.2 crypto-4.6.4 debugger-4.2.8 dialyzer-4.1.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.1 erts-10.6.4 et-1.6.4 eunit-2.4 ftp-1.0.4 hipe-3.19.2 inets-7.1.2 jinterface-1.10.1 kernel-6.5.1 megaco-3.18.7 mnesia-4.16.2 observer-2.9.3 odbc-2.12.4 os_mon-2.5.1 parsetools-2.1.8 public_key-1.7.1 reltool-0.8 runtime_tools-1.14 sasl-3.4.1 snmp-5.4.5 ssh-4.8.2 ssl-9.5.3 stdlib-3.11.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3 wx-1.9 xmerl-1.3.23 : OTP-22.2.7 : compiler-7.5.2 # asn1-5.0.9 common_test-1.18.1 crypto-4.6.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.1 erts-10.6.4 et-1.6.4 eunit-2.4 ftp-1.0.4 hipe-3.19.2 inets-7.1.2 jinterface-1.10.1 kernel-6.5.1 megaco-3.18.7 mnesia-4.16.2 observer-2.9.3 odbc-2.12.4 os_mon-2.5.1 parsetools-2.1.8 public_key-1.7.1 reltool-0.8 runtime_tools-1.14 sasl-3.4.1 snmp-5.4.5 ssh-4.8.2 ssl-9.5.3 stdlib-3.11.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3 wx-1.9 xmerl-1.3.23 : OTP-22.2.6 : erts-10.6.4 # asn1-5.0.9 common_test-1.18.1 compiler-7.5.1 crypto-4.6.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.1 et-1.6.4 eunit-2.4 ftp-1.0.4 hipe-3.19.2 inets-7.1.2 jinterface-1.10.1 kernel-6.5.1 megaco-3.18.7 mnesia-4.16.2 observer-2.9.3 odbc-2.12.4 os_mon-2.5.1 parsetools-2.1.8 public_key-1.7.1 reltool-0.8 runtime_tools-1.14 sasl-3.4.1 snmp-5.4.5 ssh-4.8.2 ssl-9.5.3 stdlib-3.11.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3 wx-1.9 xmerl-1.3.23 : OTP-22.2.5 : erts-10.6.3 stdlib-3.11.2 # asn1-5.0.9 common_test-1.18.1 compiler-7.5.1 crypto-4.6.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.1 et-1.6.4 eunit-2.4 ftp-1.0.4 hipe-3.19.2 inets-7.1.2 jinterface-1.10.1 kernel-6.5.1 megaco-3.18.7 mnesia-4.16.2 observer-2.9.3 odbc-2.12.4 os_mon-2.5.1 parsetools-2.1.8 public_key-1.7.1 reltool-0.8 runtime_tools-1.14 sasl-3.4.1 snmp-5.4.5 ssh-4.8.2 ssl-9.5.3 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3 wx-1.9 xmerl-1.3.23 : @@ -24,6 +25,7 @@ OTP-22.0.3 : compiler-7.4.2 dialyzer-4.0.1 erts-10.4.2 ssl-9.3.2 stdlib-3.9.2 # OTP-22.0.2 : compiler-7.4.1 crypto-4.5.1 erts-10.4.1 stdlib-3.9.1 # asn1-5.0.9 common_test-1.17.3 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3.1 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.1 : ssl-9.3.1 # asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0 : asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3 stdlib-3.9 syntax_tools-2.2 tools-3.2 wx-1.8.8 xmerl-1.3.21 # diameter-2.2.1 et-1.6.4 eunit-2.3.7 ftp-1.0.2 parsetools-2.1.8 tftp-1.0.1 : +OTP-21.3.8.14 : erts-10.3.5.10 # asn1-5.0.8 common_test-1.17.2.1 compiler-7.3.2 crypto-4.4.2.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.7 erl_docgen-0.9 erl_interface-3.11.3 et-1.6.4 eunit-2.3.7 ftp-1.0.2.2 hipe-3.18.3 inets-7.0.7.2 jinterface-1.9.1 kernel-6.3.1.3 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.6.1 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.6.3 ssl-9.2.3.5 stdlib-3.8.2.3 syntax_tools-2.1.7.1 tftp-1.0.1 tools-3.1.0.1 wx-1.8.7 xmerl-1.3.20.1 : OTP-21.3.8.13 : erts-10.3.5.9 stdlib-3.8.2.3 # asn1-5.0.8 common_test-1.17.2.1 compiler-7.3.2 crypto-4.4.2.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.7 erl_docgen-0.9 erl_interface-3.11.3 et-1.6.4 eunit-2.3.7 ftp-1.0.2.2 hipe-3.18.3 inets-7.0.7.2 jinterface-1.9.1 kernel-6.3.1.3 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.6.1 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.6.3 ssl-9.2.3.5 syntax_tools-2.1.7.1 tftp-1.0.1 tools-3.1.0.1 wx-1.8.7 xmerl-1.3.20.1 : OTP-21.3.8.12 : crypto-4.4.2.2 erts-10.3.5.8 ssh-4.7.6.3 # asn1-5.0.8 common_test-1.17.2.1 compiler-7.3.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.7 erl_docgen-0.9 erl_interface-3.11.3 et-1.6.4 eunit-2.3.7 ftp-1.0.2.2 hipe-3.18.3 inets-7.0.7.2 jinterface-1.9.1 kernel-6.3.1.3 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.6.1 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssl-9.2.3.5 stdlib-3.8.2.2 syntax_tools-2.1.7.1 tftp-1.0.1 tools-3.1.0.1 wx-1.8.7 xmerl-1.3.20.1 : OTP-21.3.8.11 : erts-10.3.5.7 ftp-1.0.2.2 # asn1-5.0.8 common_test-1.17.2.1 compiler-7.3.2 crypto-4.4.2.1 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.7 erl_docgen-0.9 erl_interface-3.11.3 et-1.6.4 eunit-2.3.7 hipe-3.18.3 inets-7.0.7.2 jinterface-1.9.1 kernel-6.3.1.3 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.6.1 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.6.2 ssl-9.2.3.5 stdlib-3.8.2.2 syntax_tools-2.1.7.1 tftp-1.0.1 tools-3.1.0.1 wx-1.8.7 xmerl-1.3.20.1 : @@ -70,6 +72,7 @@ OTP-21.0.3 : erts-10.0.3 # asn1-5.0.6 common_test-1.16 compiler-7.2.2 crypto-4.3 OTP-21.0.2 : compiler-7.2.2 erts-10.0.2 public_key-1.6.1 stdlib-3.5.1 # asn1-5.0.6 common_test-1.16 crypto-4.3 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 inets-7.0 jinterface-1.9 kernel-6.0 megaco-3.18.3 mnesia-4.15.4 observer-2.8 odbc-2.12.1 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 snmp-5.2.11 ssh-4.7 ssl-9.0 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 : OTP-21.0.1 : compiler-7.2.1 erts-10.0.1 # asn1-5.0.6 common_test-1.16 crypto-4.3 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 inets-7.0 jinterface-1.9 kernel-6.0 megaco-3.18.3 mnesia-4.15.4 observer-2.8 odbc-2.12.1 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 public_key-1.6 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 snmp-5.2.11 ssh-4.7 ssl-9.0 stdlib-3.5 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 : OTP-21.0 : asn1-5.0.6 common_test-1.16 compiler-7.2 crypto-4.3 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 erts-10.0 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 inets-7.0 jinterface-1.9 kernel-6.0 mnesia-4.15.4 observer-2.8 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 public_key-1.6 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 ssh-4.7 ssl-9.0 stdlib-3.5 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 # megaco-3.18.3 odbc-2.12.1 snmp-5.2.11 : +OTP-20.3.8.26 : erts-9.3.3.15 ssh-4.6.9.7 # asn1-5.0.5.2 common_test-1.15.4.4 compiler-7.1.5.2 cosEvent-2.2.2 cosEventDomain-1.2.2 cosFileTransfer-1.2.2 cosNotification-1.2.3 cosProperty-1.2.3 cosTime-1.2.3 cosTransactions-1.3.3 crypto-4.2.2.4 debugger-4.2.4 dialyzer-3.2.4 diameter-2.1.4.1 edoc-0.9.2 eldap-1.2.3.1 erl_docgen-0.7.3 erl_interface-3.10.2.2 et-1.6.1 eunit-2.3.5 hipe-3.17.1 ic-4.4.4.2 inets-6.5.2.4 jinterface-1.8.1 kernel-5.4.3.2 megaco-3.18.3 mnesia-4.15.3.2 observer-2.7 odbc-2.12.1 orber-3.8.4 os_mon-2.4.4 otp_mibs-1.1.2 parsetools-2.1.6 public_key-1.5.2 reltool-0.7.5 runtime_tools-1.12.5 sasl-3.1.2 snmp-5.2.11.2 ssl-8.2.6.4 stdlib-3.4.5.1 syntax_tools-2.1.4.2 tools-2.11.2.2 wx-1.8.3 xmerl-1.3.16.1 : OTP-20.3.8.25 : crypto-4.2.2.4 erts-9.3.3.14 ssh-4.6.9.6 # asn1-5.0.5.2 common_test-1.15.4.4 compiler-7.1.5.2 cosEvent-2.2.2 cosEventDomain-1.2.2 cosFileTransfer-1.2.2 cosNotification-1.2.3 cosProperty-1.2.3 cosTime-1.2.3 cosTransactions-1.3.3 debugger-4.2.4 dialyzer-3.2.4 diameter-2.1.4.1 edoc-0.9.2 eldap-1.2.3.1 erl_docgen-0.7.3 erl_interface-3.10.2.2 et-1.6.1 eunit-2.3.5 hipe-3.17.1 ic-4.4.4.2 inets-6.5.2.4 jinterface-1.8.1 kernel-5.4.3.2 megaco-3.18.3 mnesia-4.15.3.2 observer-2.7 odbc-2.12.1 orber-3.8.4 os_mon-2.4.4 otp_mibs-1.1.2 parsetools-2.1.6 public_key-1.5.2 reltool-0.7.5 runtime_tools-1.12.5 sasl-3.1.2 snmp-5.2.11.2 ssl-8.2.6.4 stdlib-3.4.5.1 syntax_tools-2.1.4.2 tools-2.11.2.2 wx-1.8.3 xmerl-1.3.16.1 : OTP-20.3.8.24 : common_test-1.15.4.4 erts-9.3.3.13 ssh-4.6.9.5 # asn1-5.0.5.2 compiler-7.1.5.2 cosEvent-2.2.2 cosEventDomain-1.2.2 cosFileTransfer-1.2.2 cosNotification-1.2.3 cosProperty-1.2.3 cosTime-1.2.3 cosTransactions-1.3.3 crypto-4.2.2.3 debugger-4.2.4 dialyzer-3.2.4 diameter-2.1.4.1 edoc-0.9.2 eldap-1.2.3.1 erl_docgen-0.7.3 erl_interface-3.10.2.2 et-1.6.1 eunit-2.3.5 hipe-3.17.1 ic-4.4.4.2 inets-6.5.2.4 jinterface-1.8.1 kernel-5.4.3.2 megaco-3.18.3 mnesia-4.15.3.2 observer-2.7 odbc-2.12.1 orber-3.8.4 os_mon-2.4.4 otp_mibs-1.1.2 parsetools-2.1.6 public_key-1.5.2 reltool-0.7.5 runtime_tools-1.12.5 sasl-3.1.2 snmp-5.2.11.2 ssl-8.2.6.4 stdlib-3.4.5.1 syntax_tools-2.1.4.2 tools-2.11.2.2 wx-1.8.3 xmerl-1.3.16.1 : OTP-20.3.8.23 : crypto-4.2.2.3 erts-9.3.3.12 snmp-5.2.11.2 syntax_tools-2.1.4.2 # asn1-5.0.5.2 common_test-1.15.4.3 compiler-7.1.5.2 cosEvent-2.2.2 cosEventDomain-1.2.2 cosFileTransfer-1.2.2 cosNotification-1.2.3 cosProperty-1.2.3 cosTime-1.2.3 cosTransactions-1.3.3 debugger-4.2.4 dialyzer-3.2.4 diameter-2.1.4.1 edoc-0.9.2 eldap-1.2.3.1 erl_docgen-0.7.3 erl_interface-3.10.2.2 et-1.6.1 eunit-2.3.5 hipe-3.17.1 ic-4.4.4.2 inets-6.5.2.4 jinterface-1.8.1 kernel-5.4.3.2 megaco-3.18.3 mnesia-4.15.3.2 observer-2.7 odbc-2.12.1 orber-3.8.4 os_mon-2.4.4 otp_mibs-1.1.2 parsetools-2.1.6 public_key-1.5.2 reltool-0.7.5 runtime_tools-1.12.5 sasl-3.1.2 ssh-4.6.9.4 ssl-8.2.6.4 stdlib-3.4.5.1 tools-2.11.2.2 wx-1.8.3 xmerl-1.3.16.1 : diff --git a/scripts/bundle-otp b/scripts/bundle-otp index aa1f166732..df82ff4fc5 100755 --- a/scripts/bundle-otp +++ b/scripts/bundle-otp @@ -6,8 +6,8 @@ if [ "$TRAVIS_PULL_REQUEST" = "false" -a "$TRAVIS_REPO_SLUG" != "erlang/otp" ]; exit 0 fi -OTP_META_FILE=$ERL_TOP/${TRAVIS_TAG}-bundle.txt -OTP_FILE=$ERL_TOP/${TRAVIS_TAG}-bundle.tar.gz +OTP_META_FILE=$ERL_TOP/${TRAVIS_TAG}.0-bundle.txt +OTP_FILE=$ERL_TOP/${TRAVIS_TAG}.0-bundle.tar.gz REPOSITORIES="otp,$TRAVIS_TAG corba,.*" diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml index 027a71c59f..0bcd7dc1b2 100644 --- a/system/doc/design_principles/release_handling.xml +++ b/system/doc/design_principles/release_handling.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2016</year> + <year>2003</year><year>2020</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -59,7 +59,7 @@ <p><em>Step 2</em>) The release is transferred to and installed at target environment. For information of how to install the first target system, see - <seealso marker="system_principles:create_target">System Principles</seealso>.</p> + <seealso marker="doc/system_principles:create_target">System Principles</seealso>.</p> <p><em>Step 3</em>) Modifications, for example, error corrections, are made to the code in the development environment.</p> <p><em>Step 4</em>) At some point, it is time to make a new version diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml index f657e8cb00..d6d907de45 100644 --- a/system/doc/design_principles/statem.xml +++ b/system/doc/design_principles/statem.xml @@ -185,15 +185,17 @@ State(S) x Event(E) -> Actions(A), State(S')</pre> </p> <p> The <em>callback module</em> can be changed for a running server - using the - <seealso marker="#Transition Actions">transition action</seealso> - <seealso marker="stdlib:gen_statem#type-action"><c>{change_callback_module, NewModule}</c></seealso>. + using any of the + <seealso marker="#Transition Actions">transition actions</seealso> + <seealso marker="stdlib:gen_statem#type-action"><c>{change_callback_module, NewModule}</c></seealso>, + <seealso marker="stdlib:gen_statem#type-action"><c>{push_callback_module, NewModule}</c></seealso> or + <seealso marker="stdlib:gen_statem#type-action"><c>pop_callback_module</c></seealso>. Note that this is a pretty esotheric thing to do... The origin for this feature is a protocol that after version negotiation branches off into quite different state machines depending on the protocol version. There <i>might</i> be other use cases. - <i>Beware</i> that the <c>NewModule</c> + <i>Beware</i> that the new callback module completely replaces the previous behaviour module, so all relevant callback functions has to handle the state and data from the previous callback module. @@ -664,6 +666,41 @@ State(S) x Event(E) -> Actions(A), State(S')</pre> but it can <i>not</i> be done from a <seealso marker="#State Enter Calls"><em>state enter call</em></seealso>. </item> + <tag> + <seealso marker="stdlib:gen_statem#type-action"> + <c>{push_callback_module, NewModule}</c> + </seealso> + </tag> + <item> + Push the current <em>callback module</em> + to the top of an internal stack of callback modules + and set the new + <seealso marker="#Callback Module"> + <em>callback module</em> + </seealso> + for the running server. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </item> + <tag> + <seealso marker="stdlib:gen_statem#type-action"> + <c>pop_callback_module</c> + </seealso> + </tag> + <item> + Pop the top module from + the internal stack of callback modules + and set it to be the new + <seealso marker="#Callback Module"> + <em>callback module</em> + </seealso> + for the running server. + If the stack is empty the server fails. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </item> </taglist> <p> For details, see the <c>gen_statem(3)</c> |